Skip to content

Commit

Permalink
Use Floating UI within the component instead of store (#2279)
Browse files Browse the repository at this point in the history
Closes #887
Closes #1595
Closes #2228

The primary purpose of this PR is to move the `@floating-ui/dom`
dependency from the `usePopoverStore` hook to the `Popover` component so
it can be lazy loaded.

In addition, we moved most of the Floating UI-related props to the
`Popover` component, which was the original idea, but wasn't viable
before without hacks. The only exception is the `placement` prop, to
which we need access on components other than `Popover`.

This introduces breaking changes on `Popover` and derived components.
Those are described in the changesets.

---

Finally, the `Tooltip` component has been updated, so it composes
`Hovercard` now, which also benefited from the `Popover` changes. The
specific `Tooltip` updates are related to the closed issues above.
  • Loading branch information
diegohaz committed May 13, 2023
1 parent 76ad853 commit 492cbdc
Show file tree
Hide file tree
Showing 87 changed files with 1,377 additions and 1,014 deletions.
57 changes: 57 additions & 0 deletions .changeset/__breaking-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
"@ariakit/core": minor
"@ariakit/react-core": minor
"@ariakit/react": minor
---

**BREAKING**: Moved props from the `usePopoverStore` hook to the `Popover` component: `fixed`, `gutter`, `shift`, `flip`, `slide`, `overlap`, `sameWidth`, `fitViewport`, `arrowPadding`, `overflowPadding`, `getAnchorRect`, `renderCallback` (renamed to `updatePosition`). ([#2279](https://github.com/ariakit/ariakit/pull/2279))

The exception is the `placement` prop that should still be passed to the store.

**Before**:

```jsx
const popover = usePopoverStore({
placement: "bottom",
fixed: true,
gutter: 8,
shift: 8,
flip: true,
slide: true,
overlap: true,
sameWidth: true,
fitViewport: true,
arrowPadding: 8,
overflowPadding: 8,
getAnchorRect: (anchor) => anchor?.getBoundingClientRect(),
renderCallback: (props) => props.defaultRenderCallback(),
});

<Popover store={popover} />;
```

**After**:

```jsx
const popover = usePopoverStore({ placement: "bottom" });

<Popover
store={popover}
fixed
gutter={8}
shift={8}
flip
slide
overlap
sameWidth
fitViewport
arrowPadding={8}
overflowPadding={8}
getAnchorRect={(anchor) => anchor?.getBoundingClientRect()}
updatePosition={(props) => props.updatePosition()}
/>;
```
This change affects all the hooks and components that use `usePopoverStore` and `Popover` underneath: `useComboboxStore`, `ComboboxPopover`, `useHovercardStore`, `Hovercard`, `useMenuStore`, `Menu`, `useSelectStore`, `SelectPopover`, `useTooltipStore`, `Tooltip`.
With this change, the underlying `@floating-ui/dom` dependency has been also moved to the `Popover` component, which means it can be lazy loaded. See the [Lazy Popover](https://ariakit.org/examples/popover-lazy) example.
12 changes: 12 additions & 0 deletions .changeset/curvy-taxis-shave-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@ariakit/react-core": patch
"@ariakit/react": patch
---

The `Tooltip` component now defaults to use `aria-describedby` instead of `aria-labelledby`. ([#2279](https://github.com/ariakit/ariakit/pull/2279))

If you want to use the tooltip as a label for an anchor element, you can use the `type` prop on `useTooltipStore`:

```jsx
useTooltipStore({ type: "label" });
```
8 changes: 8 additions & 0 deletions .changeset/curvy-taxis-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@ariakit/react-core": patch
"@ariakit/react": patch
---

The `Tooltip` component now supports mouse events. ([#2279](https://github.com/ariakit/ariakit/pull/2279))

It's now possible to hover over the tooltip without it disappearing, which makes it compliant with [WCAG 1.4.13](https://www.w3.org/WAI/WCAG21/Understanding/content-on-hover-or-focus.html).
6 changes: 6 additions & 0 deletions .changeset/mighty-cougars-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ariakit/react-core": patch
"@ariakit/react": patch
---

Fixed infinite loop on `Portal` with the `preserveTabOrder` prop set to `true` when the portalled element is placed right after its original position in the React tree. ([#2279](https://github.com/ariakit/ariakit/pull/2279))
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ jobs:

- name: Test
id: test
run: npm run test-chrome
run: npm run playwright -- --project chrome --project android

- name: Upload test results to GitHub
if: failure() && steps.test.outcome == 'failure'
Expand Down Expand Up @@ -341,7 +341,7 @@ jobs:

- name: Test
id: test
run: npm run playwright -- --project firefox --project safari
run: npm run playwright -- --project firefox --project safari --project ios

- name: Upload test results to GitHub
if: failure() && steps.test.outcome == 'failure'
Expand Down
13 changes: 7 additions & 6 deletions examples/combobox-animated/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import * as Ariakit from "@ariakit/react";
import "./style.css";

export default function Example() {
const combobox = Ariakit.useComboboxStore({
gutter: 4,
sameWidth: true,
animated: true,
});
const combobox = Ariakit.useComboboxStore({ animated: true });
return (
<div className="wrapper">
<label className="label">
Expand All @@ -17,7 +13,12 @@ export default function Example() {
className="combobox"
/>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={4}
sameWidth
className="popover"
>
<Ariakit.ComboboxItem className="combobox-item" value="Apple">
🍎 Apple
</Ariakit.ComboboxItem>
Expand Down
9 changes: 7 additions & 2 deletions examples/combobox-cancel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const list = [
];

export default function Example() {
const combobox = Ariakit.useComboboxStore({ gutter: 4, sameWidth: true });
const combobox = Ariakit.useComboboxStore();
return (
<div className="wrapper">
<label className="label">
Expand All @@ -30,7 +30,12 @@ export default function Example() {
/>
</div>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={4}
sameWidth
className="popover"
>
{list.map((value) => (
<Ariakit.ComboboxItem
key={value}
Expand Down
9 changes: 7 additions & 2 deletions examples/combobox-disclosure/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as Ariakit from "@ariakit/react";
import "./style.css";

export default function Example() {
const combobox = Ariakit.useComboboxStore({ gutter: 4, sameWidth: true });
const combobox = Ariakit.useComboboxStore();
return (
<div className="wrapper">
<label className="label">
Expand All @@ -19,7 +19,12 @@ export default function Example() {
/>
</div>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={4}
sameWidth
className="popover"
>
<Ariakit.ComboboxItem className="combobox-item" value="Pizza">
🍕 Pizza
</Ariakit.ComboboxItem>
Expand Down
9 changes: 7 additions & 2 deletions examples/combobox-group/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import food from "./food.js";
import "./style.css";

export default function Example() {
const combobox = Ariakit.useComboboxStore({ gutter: 4, sameWidth: true });
const combobox = Ariakit.useComboboxStore();
const value = combobox.useState("value");
const deferredValue = React.useDeferredValue(value);

Expand All @@ -27,7 +27,12 @@ export default function Example() {
autoSelect
/>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={4}
sameWidth
className="popover"
>
{!!matches.length ? (
matches.map(([type, items], i) => (
<React.Fragment key={type}>
Expand Down
9 changes: 7 additions & 2 deletions examples/combobox-inline-autocomplete/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as Ariakit from "@ariakit/react";
import "./style.css";

export default function Example() {
const combobox = Ariakit.useComboboxStore({ gutter: 8, sameWidth: true });
const combobox = Ariakit.useComboboxStore();
return (
<div>
<label className="label">
Expand All @@ -14,7 +14,12 @@ export default function Example() {
autoComplete="inline"
/>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={8}
sameWidth
className="popover"
>
<Ariakit.ComboboxItem className="combobox-item" value="Apple">
🍎 Apple
</Ariakit.ComboboxItem>
Expand Down
9 changes: 7 additions & 2 deletions examples/combobox-item-value/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "./style.css";
const fruits = ["Apple", "Grape", "Orange", "Strawberry", "Watermelon"];

export default function Example() {
const combobox = Ariakit.useComboboxStore({ gutter: 8, sameWidth: true });
const combobox = Ariakit.useComboboxStore();
return (
<div className="wrapper">
<label className="label">
Expand All @@ -15,7 +15,12 @@ export default function Example() {
className="combobox"
/>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={8}
sameWidth
className="popover"
>
{fruits.map((f) => (
<Ariakit.ComboboxItem key={f} value={f} className="combobox-item">
<Ariakit.ComboboxItemValue />
Expand Down
13 changes: 7 additions & 6 deletions examples/combobox-links/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ const links = [
];

export default function Example() {
const combobox = Ariakit.useComboboxStore({
gutter: 4,
sameWidth: true,
});

const combobox = Ariakit.useComboboxStore();
const mounted = combobox.useState("mounted");
const value = combobox.useState("value");
const deferredValue = useDeferredValue(value);
Expand Down Expand Up @@ -72,7 +68,12 @@ export default function Example() {
/>
</label>
{mounted && (
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={4}
sameWidth
className="popover"
>
{matches.length ? (
matches.map(renderItem)
) : (
Expand Down
9 changes: 7 additions & 2 deletions examples/combobox-matches/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import list from "./list.js";
import "./style.css";

export default function Example() {
const combobox = Ariakit.useComboboxStore({ gutter: 8, sameWidth: true });
const combobox = Ariakit.useComboboxStore();
const value = combobox.useState("value");
const deferredValue = useDeferredValue(value);

Expand All @@ -24,7 +24,12 @@ export default function Example() {
className="combobox"
/>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={8}
sameWidth
className="popover"
>
{matches.length ? (
matches.map((value) => (
<Ariakit.ComboboxItem
Expand Down
14 changes: 7 additions & 7 deletions examples/combobox-min-length/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ import "./style.css";

export default function Example() {
const [open, setOpen] = useState(false);
const combobox = Ariakit.useComboboxStore({
open,
setOpen,
gutter: 8,
sameWidth: true,
});
const combobox = Ariakit.useComboboxStore({ open, setOpen });

const value = combobox.useState("value");

Expand All @@ -27,7 +22,12 @@ export default function Example() {
className="combobox"
/>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={8}
sameWidth
className="popover"
>
<Ariakit.ComboboxItem className="combobox-item" value="Apple">
🍎 Apple
</Ariakit.ComboboxItem>
Expand Down
9 changes: 6 additions & 3 deletions examples/combobox-multiple/combobox-multiple.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ export const ComboboxMultiple = React.forwardRef<
// is on the combobox input, so we set `virtualFocus` to `false` to disable
// this behavior and put DOM focus on the items.
virtualFocus: false,
sameWidth: true,
gutter: 8,
defaultValue,
value,
setValue: onChange,
Expand Down Expand Up @@ -76,7 +74,12 @@ export const ComboboxMultiple = React.forwardRef<
) : (
element
)}
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={8}
sameWidth
className="popover"
>
{(popoverProps) => (
<Ariakit.SelectList
store={select}
Expand Down
15 changes: 7 additions & 8 deletions examples/combobox-textarea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,7 @@ export default function Example() {
const [trigger, setTrigger] = React.useState<string | null>(null);
const [caretOffset, setCaretOffset] = React.useState<number | null>(null);

const combobox = Ariakit.useComboboxStore({
fitViewport: true,
getAnchorRect: () => {
const textarea = ref.current;
if (!textarea) return null;
return getAnchorRect(textarea);
},
});
const combobox = Ariakit.useComboboxStore();

const searchValue = combobox.useState("value");
const mounted = combobox.useState("mounted");
Expand Down Expand Up @@ -127,6 +120,12 @@ export default function Example() {
<Ariakit.ComboboxPopover
store={combobox}
hidden={!hasMatches}
fitViewport
getAnchorRect={() => {
const textarea = ref.current;
if (!textarea) return null;
return getAnchorRect(textarea);
}}
className="popover"
>
{matches.map((value) => (
Expand Down
9 changes: 7 additions & 2 deletions examples/combobox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as Ariakit from "@ariakit/react";
import "./style.css";

export default function Example() {
const combobox = Ariakit.useComboboxStore({ gutter: 4, sameWidth: true });
const combobox = Ariakit.useComboboxStore();
return (
<div className="wrapper">
<label className="label">
Expand All @@ -13,7 +13,12 @@ export default function Example() {
className="combobox"
/>
</label>
<Ariakit.ComboboxPopover store={combobox} className="popover">
<Ariakit.ComboboxPopover
store={combobox}
gutter={4}
sameWidth
className="popover"
>
<Ariakit.ComboboxItem className="combobox-item" value="Apple">
🍎 Apple
</Ariakit.ComboboxItem>
Expand Down

1 comment on commit 492cbdc

@vercel
Copy link

@vercel vercel bot commented on 492cbdc May 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ariakit – ./

ariakit.org
ariakit-git-main-ariakit.vercel.app
ariakit-ariakit.vercel.app
www.ariakit.org

Please sign in to comment.