Skip to content

Commit ea905f1

Browse files
authored
fix(tips): loaded floating-ui async and optimized tooltips open calc (#529)
1 parent 9117681 commit ea905f1

File tree

25 files changed

+251
-41
lines changed

25 files changed

+251
-41
lines changed

.changeset/smart-paws-stay.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@ebay/ebayui-core": minor
3+
---
4+
5+
fix(tips): only calculate position of tooltips when its open
6+
fix(floating-ui): added async loading for floating-ui library

packages/ebayui-core/src/common/dropdown/index.ts

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import {
1+
import type {
22
autoUpdate,
33
computePosition,
44
shift,
55
flip,
66
offset,
7-
type ReferenceElement,
8-
type Middleware,
7+
ReferenceElement,
8+
Middleware,
99
} from "@floating-ui/dom";
10+
import { load as floatinguiLoad } from "@internal/floating-ui";
1011

1112
interface DropdownUtilOptions {
1213
reverse?: boolean;
@@ -20,6 +21,13 @@ export class DropdownUtil {
2021
declare overlay: HTMLElement;
2122
declare cleanupFn: any;
2223
declare options: DropdownUtilOptions;
24+
declare loaded: boolean;
25+
declare triggerShow: boolean;
26+
declare computePosition: typeof computePosition;
27+
declare autoUpdate: typeof autoUpdate;
28+
declare offset: typeof offset;
29+
declare flip: typeof flip;
30+
declare shift: typeof shift;
2331

2432
constructor(
2533
host: HTMLElement,
@@ -29,28 +37,47 @@ export class DropdownUtil {
2937
this.host = host as ReferenceElement;
3038
this.overlay = overlay as HTMLElement;
3139
this.options = options ?? {};
40+
41+
floatinguiLoad().then((floatingUI) => {
42+
this.computePosition =
43+
floatingUI.computePosition as typeof computePosition;
44+
this.autoUpdate = floatingUI.autoUpdate as typeof autoUpdate;
45+
this.offset = floatingUI.offset;
46+
this.flip = floatingUI.flip;
47+
this.shift = floatingUI.shift;
48+
49+
this.loaded = true;
50+
if (this.triggerShow) {
51+
this.triggerShow = false;
52+
this.show();
53+
}
54+
});
3255
}
3356

3457
show() {
35-
this.cleanupFn = autoUpdate(
36-
this.host,
37-
this.overlay,
38-
this.update.bind(this),
39-
);
58+
if (this.loaded) {
59+
this.cleanupFn = this.autoUpdate(
60+
this.host,
61+
this.overlay,
62+
this.update.bind(this),
63+
);
64+
} else {
65+
this.triggerShow = true;
66+
}
4067
}
4168

4269
update() {
4370
const middleware = [] as Middleware[];
44-
middleware.push(offset(this.options.offset ?? 4));
71+
middleware.push(this.offset(this.options.offset ?? 4));
4572
if (this.options.flip) {
4673
middleware.push(
47-
flip({
74+
this.flip({
4875
crossAxis: true,
4976
}),
5077
);
5178
}
52-
middleware.push(shift());
53-
computePosition(this.host, this.overlay, {
79+
middleware.push(this.shift());
80+
this.computePosition(this.host, this.overlay, {
5481
placement: this.options.reverse ? "bottom-end" : "bottom-start",
5582
strategy: this.options.strategy ?? "fixed",
5683
middleware,

packages/ebayui-core/src/components/components/ebay-tooltip-base/component-browser.ts

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import Expander from "makeup-expander";
2+
import { load as floatinguiLoad } from "@internal/floating-ui";
23
import focusables from "makeup-focusables";
3-
import {
4+
import { pointerStyles } from "./constants";
5+
import type { WithNormalizedProps } from "../../../global";
6+
import type {
7+
Placement,
8+
computePosition,
49
autoUpdate,
10+
offset,
511
flip,
6-
computePosition,
712
shift,
8-
offset,
913
arrow,
10-
type Placement,
1114
inline,
1215
} from "@floating-ui/dom";
13-
import { pointerStyles } from "./constants";
14-
import type { WithNormalizedProps } from "../../../global";
1516

1617
interface TooptipBaseInput {
1718
open?: boolean;
@@ -28,31 +29,75 @@ interface TooptipBaseInput {
2829
pointer?: keyof typeof pointerStyles;
2930
"on-base-expand"?: (event: { originalEvent: Event }) => void;
3031
"on-base-collapse"?: (event: { originalEvent: Event }) => void;
32+
"on-loaded"?: () => void;
3133
}
3234
export interface Input extends WithNormalizedProps<TooptipBaseInput> {}
35+
export interface State {
36+
loaded: boolean;
37+
}
3338

34-
class TooltipBase extends Marko.Component<Input> {
39+
class TooltipBase extends Marko.Component<Input, State> {
3540
declare action: "expand" | "collapse" | null;
3641
declare _expander: any;
3742
declare cancelFocus: ReturnType<typeof focusables>;
3843
declare hostEl: HTMLElement | null;
3944
declare overlayEl: HTMLElement | null;
4045
declare arrowEl: HTMLElement | null;
4146
declare cleanup: (() => void) | undefined;
47+
declare computePosition: typeof computePosition;
48+
declare autoUpdate: typeof autoUpdate;
49+
declare offset: typeof offset;
50+
declare flip: typeof flip;
51+
declare shift: typeof shift;
52+
declare arrow: typeof arrow;
53+
declare inline: typeof inline;
4254

43-
handleExpand() {
44-
this.emit("base-expand");
55+
positionTip() {
4556
if (this.hostEl && this.overlayEl) {
57+
this.cleanup?.();
4658
this.updateTip();
59+
this.cleanup = this.autoUpdate(
60+
this.hostEl,
61+
this.overlayEl,
62+
this.updateTip.bind(this),
63+
);
4764
}
4865
}
4966

67+
onCreate() {
68+
this.state = {
69+
loaded: false,
70+
};
71+
}
72+
73+
handleExpand() {
74+
this.emit("base-expand");
75+
this.updateTip();
76+
}
77+
5078
handleCollapse() {
5179
this.emit("base-collapse");
5280
}
5381

5482
onMount() {
5583
this._setupBaseTooltip();
84+
if (!this.state.loaded) {
85+
floatinguiLoad().then((floatingUI) => {
86+
this.computePosition =
87+
floatingUI.computePosition as typeof computePosition;
88+
this.autoUpdate = floatingUI.autoUpdate as typeof autoUpdate;
89+
this.offset = floatingUI.offset;
90+
this.flip = floatingUI.flip;
91+
this.shift = floatingUI.shift;
92+
this.arrow = floatingUI.arrow;
93+
this.inline = floatingUI.inline;
94+
this.state.loaded = true;
95+
if (this.input.open !== false) {
96+
this.positionTip();
97+
}
98+
this.emit("loaded");
99+
});
100+
}
56101
}
57102

58103
onUpdate() {
@@ -114,18 +159,13 @@ class TooltipBase extends Marko.Component<Input> {
114159
host.setAttribute("aria-describedby", input.overlayId!);
115160
}
116161
}
117-
if (this.hostEl && this.overlayEl) {
118-
this.updateTip();
119-
this.cleanup = autoUpdate(
120-
this.hostEl,
121-
this.overlayEl,
122-
this.updateTip.bind(this),
123-
);
162+
if (this.input.open !== false && this.state.loaded) {
163+
this.positionTip();
124164
}
125165
}
126166

127167
updateTip() {
128-
computePosition(
168+
this.computePosition(
129169
this.hostEl as HTMLElement,
130170
this.overlayEl as HTMLElement,
131171
{
@@ -134,15 +174,15 @@ class TooltipBase extends Marko.Component<Input> {
134174
pointerStyles[this.input.pointer ?? "bottom"],
135175
strategy: "absolute",
136176
middleware: [
137-
offset(this.input.offset || 6),
138-
!this.input.notInline && inline(),
177+
this.offset(this.input.offset || 6),
178+
!this.input.notInline && this.inline(),
139179
!this.input.noFlip &&
140-
flip({
180+
this.flip({
141181
fallbackAxisSideDirection: "end",
142182
flipAlignment: false,
143183
}),
144-
!this.input.noShift && shift(),
145-
arrow({
184+
!this.input.noShift && this.shift(),
185+
this.arrow({
146186
element: this.arrowEl as HTMLElement,
147187
padding: 20,
148188
}),

packages/ebayui-core/src/components/components/ebay-tooltip-base/index.marko

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ $ const { overlayStyle, renderBody } = input;
1313
key="container"
1414
on-expander-expand("handleExpand")
1515
on-expander-collapse("handleCollapse")
16-
overlay-style=overlayStyle
17-
>
16+
overlay-style=overlayStyle>
1817
<${renderBody}/>
1918
</span>

packages/ebayui-core/src/components/ebay-infotip/component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ interface InfotipInput extends Omit<
2424
"no-shift"?: TooltipBaseInput["no-shift"];
2525
content: Marko.AttrTag<Marko.HTML.Span>;
2626
"a11y-close-button-text"?: Marko.HTMLAttributes["aria-label"];
27+
"on-loaded"?: () => void;
2728
"on-expand"?: () => void;
2829
"on-collapse"?: () => void;
2930
}

packages/ebayui-core/src/components/ebay-infotip/examples/default.marko

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ class {}
22
<ebay-infotip
33
a11yCloseButtonText="Dismiss infotip"
44
ariaLabel="Important information"
5+
on-loaded("emit", "loaded")
56
on-expand("emit", "expand")
67
on-collapse("emit", "collapse")
78
...input

packages/ebayui-core/src/components/ebay-infotip/examples/open-on-render.marko

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<ebay-infotip
22
a11yCloseButtonText="Dismiss infotip"
33
ariaLabel="Important information"
4+
on-loaded("emit", "loaded")
45
on-expand("emit", "expand")
56
on-collapse("emit", "collapse")
67
open

packages/ebayui-core/src/components/ebay-infotip/index.marko

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ $ var classPrefix = !isModal ? "infotip" : "dialog--mini";
3030
offset=input.offset
3131
pointer=input.pointer
3232
placement=input.placement
33+
on-loaded("emit", "loaded")
3334
onBase-expand(isModal ? undefined : "handleExpand")
3435
onBase-collapse(isModal ? undefined : "handleCollapse")
3536
>

packages/ebayui-core/src/components/ebay-infotip/test/test.browser.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ let component;
2323
describe("given the default infotip", () => {
2424
beforeEach(async () => {
2525
component = await render(Default);
26+
// Wait for floating-ui to load
27+
await waitFor(() => expect(component.emitted("loaded")).has.length(1));
2628
});
2729

2830
thenItCanBeOpenAndClosed();

packages/ebayui-core/src/components/ebay-tooltip/component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ interface TooltipInput extends Omit<
1818
"not-inline"?: TooltipBaseInput["not-inline"];
1919
"no-shift"?: TooltipBaseInput["no-shift"];
2020
"no-flip"?: TooltipBaseInput["no-flip"];
21+
"on-loaded"?: () => void;
2122
"on-expand"?: () => void;
2223
"on-collapse"?: () => void;
2324
}

0 commit comments

Comments
 (0)