Noodling on another UI experiment with @ariakitjs, this time an animated menu inspired by YouTube's settings pane.
Feels so good to navigate without ever touching the mouse ⬅️➡️⬆️⬇️. The animations could definitely use some work
Yes, I'm also considering a ShortcutInput component to capture key presses (when activated) and automatically format them correctly for use as a keyShortcuts value.
ALT The following JSX code:
const [keyShortcuts, setKeyShortcuts] = useState("Mod+B");
useShortcutCommand({
keyShortcuts,
handler: formatBold,
});
<ShortcutInput
keyShortcuts={keyShortcuts}
setKeyShortcuts={setKeyShortcuts}
/>
Here are some examples of a Shortcut module API I'm designing for @ariakitjs
From simply displaying shortcut glyphs to fully managing shortcuts across the application.
ALT The following JSX code:
// Simple use case: just display a shortcut
<button onClick={formatBold}>
Bold
<Shortcut
// Value based on aria-keyshortcuts
keyShortcuts="apple:Meta+B pc:Control+B"
// Displays Cmd+B instead of ⌘B
glyphs={{ "+": "+", apple: { Meta: "Cmd" } }}
/>
</button>
ALT The following JSX code:
// Respond and display a shortcut
<ShortcutCommand
// Equivalent to "apple:Meta+R pc:Control+R"
keyShortcuts="Mod+B"
onClick={formatBold}
>
Bold
{/* Infers props from context */}
<Shortcut />
</ShortcutCommand>
ALT The following JSX code:
// Respond and display a shortcut when target has focus
<ShortcutCommand
target={ref}
keyShortcuts="Mod+B"
onClick={formatBold}
>
Bold
<Shortcut />
</ShortcutCommand>
<div ref={ref} contentEditable />
ALT The following JSX code:
// Advanced usage
const FORMAT_BOLD = "Mod+B";
useShortcutCommand(shortcut, {
keyShortcuts: FORMAT_BOLD,
handler: formatBold,
});
// Automatically calls formatBold on click
<ShortcutCommand keyShortcuts={FORMAT_BOLD} />
// Or inside an event handler
shortcut.trigger(FORMAT_BOLD)
Some improvements we've made to the @CleeveHQ browser extension just went live.
You can now search and organize your bookmarks without leaving the page you are currently on! Working on many more of these updates!
The dialog and combobox components are built with @ariakitjs
Ariakit is about to become 490% faster at rendering multiple composite items using a simple technique that avoids the complexities of virtualized lists 😮
More on this soon.
ALT Screenshot of the following JSX code highlighting the usage of "offscreen" props:
{Array.from({ length: 1000 }).map((_, index) => (
<Ariakit.ComboboxItem
key={index}
value={`Item ${index}`}
// The size of the element when it's hidden can be set with CSS
className="empty:h-10"
// Always render the first 10 items
offscreenBehavior={index <= 10 ? "visible" : "hidden"}
offscreenRoot={ref}
// offscreenPreserveAfterVisible
/>
))}
ALT Screenshot of a combobox widget with hundreds of options, highlighting the devtools showing an Interaction to Next Paint (INP) metric of 944ms labeled "Before"
ALT Screenshot of a combobox widget with hundreds of options, highlighting the devtools showing an Interaction to Next Paint (INP) metric of 160ms labeled "After"
Ariakit has a straightforward combobox API. You simply render <ComboboxItem> elements.
Want to filter the list? Render different <ComboboxItem>'s.
Want them in a different order? Change the order of <ComboboxItem>'s.
Persistent items? <ComboboxItem>
It's simple and beautiful.
Can't wait for native customizable select to become widely available. Ariakit will benefit from all those improvements in native HTML.
The future is bright ✨
Ariakit v0.4.9 has been released with a new hook compatible with the new React Compiler:
ariakit.org/changelog#049
ALT 0.4.9
New useStoreState hook
The useStoreState hook is now part of the public API. Previously used internally by dynamic useState hooks from Ariakit store objects, it is now available in the @ariakit/react package to ensure compatibility with the new React Compiler.
The following snippets are equivalent:
const combobox = useComboboxStore();
const value = combobox.useState("value");
const combobox = useComboboxStore();
const value = useStoreState(combobox, "value");
Ariakit will include a `ComboboxValue` component in the next version, making it easier to access state from the store when using component providers.
Excited to work on more of these components soon.
ALT A ComboboxValue component is now available. This value component displays the current value of the combobox input without rendering any DOM elements or taking any HTML props. You can optionally pass a function as a child returning any React node based on the current value:
<ComboboxProvider>
<Combobox />
<ComboboxValue>
{(value) => `Current value: ${value}`}
</ComboboxValue>
</ComboboxProvider>
[WIP]
@tan_stack query makes handling all the different edge cases really trivial 🔥
There's no way I would have attempted handling them without it
Menu component from @ariakitjs