fix(ui): overlay fixes (responsive backdrop/select-rich/tooltip)

This commit is contained in:
Thijs Louisse 2022-12-16 01:46:05 +01:00 committed by Thomas Allmer
parent ab906fc13b
commit 7ac0a42224
6 changed files with 54 additions and 13 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
[overlays] fixes (responsive backdrop/select-rich/tooltip)

View file

@ -1,4 +1,3 @@
import { EventTargetShim } from '@lion/ui/core.js';
import { adoptStyles } from 'lit'; import { adoptStyles } from 'lit';
import { overlays } from './singleton.js'; import { overlays } from './singleton.js';
import { containFocus } from './utils/contain-focus.js'; import { containFocus } from './utils/contain-focus.js';
@ -129,7 +128,7 @@ const supportsCSSTypedObject = window.CSS?.number && document.body.attributeStyl
* bottom/top/left/right sheets etc. * bottom/top/left/right sheets etc.
* *
*/ */
export class OverlayController extends EventTargetShim { export class OverlayController extends EventTarget {
/** /**
* @constructor * @constructor
* @param {OverlayConfig} config initial config. Will be remembered as shared config * @param {OverlayConfig} config initial config. Will be remembered as shared config
@ -973,22 +972,24 @@ export class OverlayController extends EventTargetShim {
if (this.inheritsReferenceWidth) { if (this.inheritsReferenceWidth) {
this._handleInheritsReferenceWidth(); this._handleInheritsReferenceWidth();
} }
if (this.visibilityTriggerFunction) { if (this.visibilityTriggerFunction) {
this._handleUserInteraction({ phase }); this._handleVisibilityTriggers({ phase });
} }
} }
/** /**
* @param {{ phase: OverlayPhase }} config * @param {{ phase: OverlayPhase }} config
*/ */
_handleUserInteraction({ phase }) { _handleVisibilityTriggers({ phase }) {
if (typeof this.visibilityTriggerFunction === 'function') { if (typeof this.visibilityTriggerFunction === 'function') {
if (phase === 'init') { if (phase === 'init') {
this.__userInteractionHandler = this.visibilityTriggerFunction({ phase, controller: this }); this.__visibilityTriggerHandler = this.visibilityTriggerFunction({
phase,
controller: this,
});
} }
if (this.__userInteractionHandler[phase]) { if (this.__visibilityTriggerHandler[phase]) {
this.__userInteractionHandler[phase](); this.__visibilityTriggerHandler[phase]();
} }
} }
} }
@ -1053,10 +1054,14 @@ export class OverlayController extends EventTargetShim {
break; break;
} }
case 'show': case 'show':
if (this.config.hasBackdrop) {
this.backdropNode.classList.add(`overlays__backdrop--visible`); this.backdropNode.classList.add(`overlays__backdrop--visible`);
}
this.__hasActiveBackdrop = true; this.__hasActiveBackdrop = true;
break; break;
case 'hide': case 'hide':
case 'teardown':
this.backdropNode.classList.remove(`overlays__backdrop--visible`);
this.__hasActiveBackdrop = false; this.__hasActiveBackdrop = false;
break; break;
} }

View file

@ -1515,6 +1515,22 @@ describe('OverlayController', () => {
expect(ctrl.contentWrapperNode.classList.contains('overlays__overlay-container--top-right')); expect(ctrl.contentWrapperNode.classList.contains('overlays__overlay-container--top-right'));
expect(ctrl.isShown).to.be.true; expect(ctrl.isShown).to.be.true;
}); });
it('disables backdrop when switching to hasBackrop "false"', async () => {
const ctrl = new OverlayController({
...withLocalTestConfig(),
contentNode: /** @type {HTMLElement} */ (await fixture(html`<div>content1</div>`)),
hasBackdrop: true,
});
await ctrl.show(); // Popper adds inline styles
expect(ctrl.backdropNode).not.to.be.undefined;
expect(Array.from(ctrl.backdropNode.classList)).to.include('overlays__backdrop--visible');
ctrl.updateConfig({
hasBackdrop: false,
});
expect(Array.from(ctrl.backdropNode.classList)).to.not.include('overlays__backdrop--visible');
});
}); });
describe('Accessibility', () => { describe('Accessibility', () => {

View file

@ -336,6 +336,8 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
_defineOverlayConfig() { _defineOverlayConfig() {
return { return {
...withDropdownConfig(), ...withDropdownConfig(),
// Needs more advanced behavior (see `__invokerOnClick`)
visibilityTriggerFunction: undefined,
}; };
} }

View file

@ -32,6 +32,10 @@ export class LionTooltip extends ArrowMixin(OverlayMixin(LitElement)) {
:host([hidden]) { :host([hidden]) {
display: none; display: none;
} }
::slotted([slot='content']) {
width: max-content;
}
`, `,
]; ];
} }
@ -54,9 +58,19 @@ export class LionTooltip extends ArrowMixin(OverlayMixin(LitElement)) {
/** @protected */ /** @protected */
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
_defineOverlayConfig() { _defineOverlayConfig() {
const superCfg = super._defineOverlayConfig();
const tooltipCfg = withTooltipConfig({ invokerRelation: this.invokerRelation });
return /** @type {OverlayConfig} */ ({ return /** @type {OverlayConfig} */ ({
...super._defineOverlayConfig(), ...superCfg,
...withTooltipConfig({ invokerRelation: this.invokerRelation }), ...tooltipCfg,
popperConfig: {
...(superCfg.popperConfig || {}),
...(tooltipCfg.popperConfig || {}),
modifiers: [
...(superCfg.popperConfig?.modifiers || []),
...(tooltipCfg.popperConfig?.modifiers || []),
],
},
}); });
} }
} }

View file

@ -227,8 +227,7 @@ describe('lion-tooltip', () => {
expect(el._arrowNode).to.be.displayed; expect(el._arrowNode).to.be.displayed;
}); });
// TODO: promise for dynamic import popper does not resolve? it('makes sure positioning of the arrow is correct', async () => {
it.skip('makes sure positioning of the arrow is correct', async () => {
const el = /** @type {LionTooltip} */ ( const el = /** @type {LionTooltip} */ (
await fixture(html` await fixture(html`
<lion-tooltip <lion-tooltip