From ad8cf13734c4e55a1bcd4e5d6878a3f959604ef3 Mon Sep 17 00:00:00 2001 From: Chesney Julian Date: Tue, 7 Jan 2025 14:05:49 -0500 Subject: [PATCH 1/4] feat: Add flip middleware to popover and tooltip --- .../app/components/f/components/popover.gts | 19 ++++++++++++++++++ .../app/components/f/components/tooltip.gts | 11 ++++++++++ .../ember-core/src/components/popover.gts | 20 +++++++++++++++++-- .../ember-core/src/components/tooltip.gts | 2 ++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/apps/docs-app/app/components/f/components/popover.gts b/apps/docs-app/app/components/f/components/popover.gts index f8ed1a78b..a0f40ac67 100644 --- a/apps/docs-app/app/components/f/components/popover.gts +++ b/apps/docs-app/app/components/f/components/popover.gts @@ -36,6 +36,9 @@ export default class extends Component { @tracked arrow: boolean = true; + @tracked + flip: boolean = false; + @tracked isShown?: boolean; @@ -62,6 +65,7 @@ export default class extends Component { + + + { @tracked _isShown = false; + @tracked + adjustedSide: Direction = 'bottom'; + get hasArrow() { return this.args.arrow ?? true; } @@ -121,6 +125,10 @@ export default class Popover extends Component { get middleware() { const middleware = [offset(this.offset)]; + if (this.args.flip) { + middleware.push(flip()); + } + if (this.hasArrow) { middleware.push(arrow({ element: this.arrow! })); } @@ -220,6 +228,14 @@ export default class Popover extends Component { return; } + if (placement !== this.placement) { + this.adjustedSide = Object.keys(SIDE_TRANSLATION).find( + (side) => SIDE_TRANSLATION[side as Direction] === placement, + ) as Direction; + } else { + this.adjustedSide = this.side; + } + const { x: arrowX, y: arrowY } = middlewareData.arrow!; const staticSide: string = ARROW_SIDE[placement.split('-')[0] as Direction]!; @@ -245,7 +261,7 @@ export default class Popover extends Component { id={{this.id}} class={{classes (unless this.isShown "hidden") - (concat "popover bs-popover-" this.side) + (concat "popover bs-popover-" this.adjustedSide) }} {{onInsert this.initPopover}} {{! @glint-expect-error Modifier types are currently not correct }} diff --git a/packages/ember-core/src/components/tooltip.gts b/packages/ember-core/src/components/tooltip.gts index c928eb4fb..9903151ea 100644 --- a/packages/ember-core/src/components/tooltip.gts +++ b/packages/ember-core/src/components/tooltip.gts @@ -13,6 +13,7 @@ export interface TooltipSignature { Args: { alignment?: Alignment; controlElement?: HTMLElement; + flip?: boolean; isShown?: boolean; offset?: string | number; side?: Direction; @@ -80,6 +81,7 @@ const Tooltip: TOC = ); - assert.dom('.popover').hasClass('bs-popover-bottom'); - this.model.side = 'top'; - await settled(); + this.model.side = "top"; + await click('button'); assert.dom('.popover').hasClass('bs-popover-top'); this.model.side = 'start'; diff --git a/packages/ember-core/src/components/popover.gts b/packages/ember-core/src/components/popover.gts index 005c89596..fba428790 100644 --- a/packages/ember-core/src/components/popover.gts +++ b/packages/ember-core/src/components/popover.gts @@ -170,7 +170,10 @@ export default class Popover extends Component { } this._isShown = true; - await this.args.onShow?.(); + + if (this.args.onShow) { + await this.args.onShow(); + } if (evtOrInput instanceof HTMLInputElement) { this._control = evtOrInput; From 126a4530bcec4b8fb5d46c55421da37e1b6ad368 Mon Sep 17 00:00:00 2001 From: Chesney Julian Date: Tue, 14 Jan 2025 13:33:53 -0500 Subject: [PATCH 3/4] refactor: Remove isShown argument --- .../app/components/f/components/dropdown.gts | 7 ------ .../app/components/f/components/popover.gts | 19 -------------- .../integration/components/popover-test.gts | 25 ------------------- .../ember-core/src/components/dropdown.gts | 1 - .../ember-core/src/components/popover.gts | 11 +++----- .../ember-core/src/components/tooltip.gts | 1 - 6 files changed, 3 insertions(+), 61 deletions(-) diff --git a/apps/docs-app/app/components/f/components/dropdown.gts b/apps/docs-app/app/components/f/components/dropdown.gts index cd04159cb..3627b55cc 100644 --- a/apps/docs-app/app/components/f/components/dropdown.gts +++ b/apps/docs-app/app/components/f/components/dropdown.gts @@ -116,13 +116,6 @@ export default class extends Component { @value={{this.hasIcon}} @onInput={{fn this.update "hasIcon"}} /> - - - - - <:content as |Content|> - - header - - - body - - - - ); - - assert.dom('.popover').hasClass('hidden'); - - this.model.isShown = true; - - await settled(); - - assert.dom('.popover').doesNotHaveClass('hidden'); - }); - test('`direction` works', async function (this: TestContext, assert) { const { model } = this; diff --git a/packages/ember-core/src/components/dropdown.gts b/packages/ember-core/src/components/dropdown.gts index 8b65e57c0..486358032 100644 --- a/packages/ember-core/src/components/dropdown.gts +++ b/packages/ember-core/src/components/dropdown.gts @@ -92,7 +92,6 @@ export interface DropdownSignature { disabled?: boolean; fullWidth?: boolean; hasIcon?: boolean; - isShown?: boolean; loading?: boolean; offset?: string | number; scrollable?: boolean; diff --git a/packages/ember-core/src/components/popover.gts b/packages/ember-core/src/components/popover.gts index fba428790..cd404abd6 100644 --- a/packages/ember-core/src/components/popover.gts +++ b/packages/ember-core/src/components/popover.gts @@ -55,7 +55,6 @@ export interface PopoverSignature { controlElement?: HTMLElement; flip?: boolean; fullWidth?: boolean; - isShown?: boolean; offset?: string | number; side?: Direction; @@ -96,7 +95,7 @@ export default class Popover extends Component { id = `popover-${crypto.randomUUID()}`; @tracked - _isShown = false; + isShown = false; @tracked adjustedSide: Direction = 'bottom'; @@ -152,10 +151,6 @@ export default class Popover extends Component { return this.args.side ?? 'bottom'; } - get isShown() { - return this.args.isShown ?? this._isShown; - } - get control() { return this.args.controlElement ?? this._control; } @@ -169,7 +164,7 @@ export default class Popover extends Component { return; } - this._isShown = true; + this.isShown = true; if (this.args.onShow) { await this.args.onShow(); @@ -192,7 +187,7 @@ export default class Popover extends Component { return; } - this._isShown = false; + this.isShown = false; await this.args.onHide?.(); this._control = null; diff --git a/packages/ember-core/src/components/tooltip.gts b/packages/ember-core/src/components/tooltip.gts index 9903151ea..29fe46dd2 100644 --- a/packages/ember-core/src/components/tooltip.gts +++ b/packages/ember-core/src/components/tooltip.gts @@ -14,7 +14,6 @@ export interface TooltipSignature { alignment?: Alignment; controlElement?: HTMLElement; flip?: boolean; - isShown?: boolean; offset?: string | number; side?: Direction; From a4953ef4f1b3edfab76329527e946305590ae5e6 Mon Sep 17 00:00:00 2001 From: Chesney Julian Date: Thu, 23 Jan 2025 10:11:41 -0500 Subject: [PATCH 4/4] fix: Assign currentTarget to var to prevent thread nulling --- packages/ember-core/src/components/popover.gts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/ember-core/src/components/popover.gts b/packages/ember-core/src/components/popover.gts index cd404abd6..8ca5c1998 100644 --- a/packages/ember-core/src/components/popover.gts +++ b/packages/ember-core/src/components/popover.gts @@ -164,20 +164,19 @@ export default class Popover extends Component { return; } + const { currentTarget } = evtOrInput as Event; this.isShown = true; - if (this.args.onShow) { - await this.args.onShow(); - } + await this.args.onShow?.(); if (evtOrInput instanceof HTMLInputElement) { this._control = evtOrInput; this.showPopover(); } else if ( evtOrInput instanceof Event && - evtOrInput.currentTarget instanceof HTMLElement + currentTarget instanceof HTMLElement ) { - this._control = evtOrInput.currentTarget; + this._control = currentTarget; this.showPopover(); } };