New HoloCard 3D tilt component, a PromptInput token input for inline mentions and commands, HoverCard and ContextMenu rebuilt on React Aria primitives, a secondary RichTextEditor surface and slash menu fixes, a GPU-composited TextShimmer, RouterProvider navigation for ListView and Sidebar links, Safari and Glass theme fixes, and dependency bumps to HeroUI 3.2.5 and React Aria Components 1.21.0.
This release adds HoloCard, a 3D tilting card with a pointer-tracked holographic glare for membership cards, passes, and collectibles, and PromptInput.TokenInput for prompts with inline @mention and /command tokens. It rebuilds HoverCard and ContextMenu on the new React Aria PreviewTrigger and contextMenu trigger primitives, adds a secondary surface variant to the Rich Text Editor for overlays, and moves TextShimmer to a GPU-composited mask animation that substantially reduces CPU usage. ListView and Sidebar links now route through React Aria RouterProvider, and a round of fixes lands for the Rich Text Editor slash menu, Sheet overlays in Safari, Glass theme table headers, DataGrid row headers, and the Sidebar keyboard shortcut. It also bumps the @heroui/react peer to 3.2.5 and react-aria-components to 1.21.0.
⚠️ Breaking change:
@heroui/react and @heroui/styles peer dependency minimums are now >=3.2.5, and react-aria-components is now >=1.21.0.react-aria (>=3.52.0), react-stately (>=3.50.0), and @react-aria/interactions (>=3.28.1) are new peer dependencies. All three already ship with react-aria-components, so most apps only need to declare them if they use strict peer resolution.HoverCard.Content no longer accepts defaultOpen or onOpenChange (it already rejected isOpen and triggerRef). Open state lives on the HoverCard root.HoloCard is a compound component for membership cards, passes, and collectibles. The card tilts toward the pointer, scales on hover, and drifts its HoloCard.Content layers against the tilt while a holographic HoloCard.Shine overlay follows the pointer (#925).
import {HoloCard} from "@heroui-pro/react";
<HoloCard gradient="linear-gradient(140deg, #3a3730 0%, #1a1b22 78%, #12131c 100%)">
<HoloCard.Rotator>
<HoloCard.Frame>
<HoloCard.Surface>
<HoloCard.Inset />
<HoloCard.Pattern />
<HoloCard.Content className="flex-col items-center justify-center">
<span className="text-3xl font-bold text-white">Marcus Wong</span>
</HoloCard.Content>
<HoloCard.Content className="items-end justify-center pb-10">
<span className="text-sm text-white/40">Member #0999</span>
</HoloCard.Content>
<HoloCard.Shine />
</HoloCard.Surface>
</HoloCard.Frame>
</HoloCard.Rotator>
</HoloCard>;Key features:
Rotator, Frame, and Surface are required; Inset (hairline border), Pattern (static texture), Content, and Shine are optional layers you stack in any orderparallaxStrength controls how far Content layers drift, and parallax={false} pins a layer in placegradient, patternSrc, and patternSize props map to --holo-card-* CSS variables alongside width, height, radius, perspective, and overlay opacity tokens, so the holographic texture can be swapped for any CSS imageisInteractive={false} or isDisabled freezes the card flat and unlit, and it stays static automatically under prefers-reduced-motion; on touch devices horizontal drags tilt the card while vertical drags keep scrolling the pagePromptInput.TokenInput is a drop-in alternative to PromptInput.TextArea for prompts that carry inline @mention and /command tokens (#933). It is built on the React Aria Components TokenField, so the value is a TokenFieldValue segment list rather than a string, and it renders a contenteditable element in the same slot with the same box model. usePromptInputTokens owns the value and resolves the trigger the caret sits in, PromptInput.TokenSuggestions anchors a popover to that caret, PromptInput.Tokens routes arrow keys and Enter into the menu while the caret stays in the field, and PromptInput.Token renders the inline pill. The menu closes when the caret leaves the trigger or the field loses focus, and PromptInput.Send, the compact and inline layouts, and the run lock work the same as they do for the textarea.
import {Menu} from "@heroui/react";
import {PromptInput, TokenFieldValue, usePromptInputTokens} from "@heroui-pro/react";
function Composer() {
const tokens = usePromptInputTokens({triggers: ["@"]});
const items = users.filter((user) => user.username.startsWith(tokens.query));
return (
<PromptInput onSubmit={() => tokens.setValue(new TokenFieldValue([]))}>
<PromptInput.Shell>
<PromptInput.Tokens>
<PromptInput.Content>
<PromptInput.TokenInput tokens={tokens} />
</PromptInput.Content>
<PromptInput.TokenSuggestions tokens={tokens}>
<Menu items={items}>
{(item) => (
<Menu.Item id={item.id} onAction={() => tokens.insertToken(`@${item.username}`)}>
{item.name}
</Menu.Item>
)}
</Menu>
</PromptInput.TokenSuggestions>
</PromptInput.Tokens>
<PromptInput.Toolbar>
<PromptInput.ToolbarEnd>
<PromptInput.Send />
</PromptInput.ToolbarEnd>
</PromptInput.Toolbar>
</PromptInput.Shell>
</PromptInput>
);
}Key features:
PromptInput.TextArea; the token field flattens its value into a string so PromptInput.Send works unchangedPromptInput.TokenSuggestions follows the caret with full keyboard navigation (arrows, Enter, Escape) and virtual-focus announcements, and closes when the caret leaves the trigger or the field blursusePromptInputTokens exposes value, query, trigger, insertToken, and close, and TokenFieldValue is re-exported from @heroui-pro/reactTokenField is an alpha React Aria Components API; its behavior and props may change in a future release.
RichTextEditor accepts variant="primary" | "secondary" (default primary) so the editor shell can match HeroUI field surfaces when it sits on a Surface, Modal, Sheet, or Drawer (#1032). The secondary variant uses the --default fill with no shadow, exposes data-variant on the root, and switches ActionButton and CommandButton to the outline variant by default so toolbar controls stay visible on the secondary fill.
import {RichTextEditor} from "@heroui-pro/react/rich-text-editor";
<Modal.Body>
<RichTextEditor defaultValue={draft} variant="secondary">
<RichTextEditor.Shell>
<RichTextEditor.Toolbar>{/* … */}</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor.Shell>
</RichTextEditor>
</Modal.Body>;HoverCard is now built on React Aria's PreviewTrigger, replacing the hand-rolled timers and open/close state (#915). Pointer, keyboard, and touch all open the card consistently: hovering opens after openDelay with a safe area between trigger and card, focusing the trigger opens it and Tab moves into it, and long press opens it on touch. Open delays are coordinated globally with other hover cards and tooltips, so once one has opened the next opens immediately.
The root gains an isDisabled prop, Escape closes a pointer-opened card even when focus is elsewhere, and the card renders with role="dialog". See Breaking Changes for the HoverCard.Content prop change.
ContextMenu uses React Aria's trigger="contextMenu" support instead of custom right-click, long-press, and cursor-anchoring logic (#924). The compound API is unchanged. The menu now has an accessible name, focuses its first item on open, closes when you right-click the trigger again, chains a caller's own onContextMenu handler instead of replacing it, and closes submenus with the root. On iOS, long press goes through React Aria's usePress. The popover's zoom-in animation now grows from the click point via transform-origin: var(--trigger-anchor-point).
background-position animation with a GPU-composited CSS mask whose highlight layer animates only translate, substantially reducing CPU usage while keeping the same shimmer look (#1015). Text color utilities passed through className now compose with the shimmer instead of disabling it (#921)ListView.Item and Sidebar.MenuItem links route through the active React Aria RouterProvider, with native navigation as the fallback, and navigate exactly once (#944)backdrop-filter layer (#1134)isRowHeader, so toggling columns off no longer crashes the grid (#808)SuggestionMenu items now confirm with Enter, Tab, and mouse clicks (previously Enter split the block and clicks were ignored), arrow-key navigation keeps the highlighted row scrolled into view in long lists without a resting pointer or wheel scrolling disturbing the highlight, and the menu shows its "No results" state for non-matching queries and no longer clips the last row (#1145). Applying a link rejects syntactically invalid URLs, preventing window.open errors from malformed href values (#834)keydown events that carry no key (for example Microsoft Edge form autofill) instead of throwing (#1005)useSidebar exposes mobileOverlayContainer, and overlays rendered inside Sidebar.Mobile portal into the sheet so dropdowns open in view on mobile Safari instead of off screen (#978)workerUrl prop passes an explicit MapLibre worker URL for bundlers that cannot resolve the ESM worker automatically, and the docs examples use a keyless basemap provider (#1097)scrollToBottom accepts a force flag for explicit jumps@heroui/react and @heroui/styles bumped to 3.2.5; peer minimums bumped to >=3.2.5 (#887, #1195)react-aria-components bumped to 1.21.0; peer minimum bumped to >=1.21.0 (#1046)react-aria (>=3.52.0) and react-stately (>=3.50.0) added as peer dependencies for ContextMenu (#924)@react-aria/interactions (>=3.28.1) added as a peer dependency for HoverCard (#915)@internationalized/date bumped to 3.12.4 and @internationalized/number to 3.6.8maplibre-gl bumped to 6.4.1; peer minimum stays >=6.0.0@tiptap/* pins bumped to 3.31.3; peer minimums stay >=3.23.6@heroui/react and @heroui/styles now require >=3.2.5, and react-aria-components requires >=1.21.0. react-aria, react-stately, and @react-aria/interactions are declared as peers:
- "@heroui/react": ">=3.2.2"
- "@heroui/styles": ">=3.2.2"
- "react-aria-components": ">=1.19.0"
+ "@heroui/react": ">=3.2.5"
+ "@heroui/styles": ">=3.2.5"
+ "@react-aria/interactions": ">=3.28.1"
+ "react-aria": ">=3.52.0"
+ "react-aria-components": ">=1.21.0"
+ "react-stately": ">=3.50.0"Update the packages together:
npm install @heroui/react@latest @heroui/styles@latest react-aria-components@latest react-aria@latest react-stately@latest @react-aria/interactions@latestreact-aria, react-stately, and @react-aria/interactions are already dependencies of react-aria-components, so the lockfile gains no new packages. Only apps with strict peer dependency resolution need to add them explicitly.
HoverCard.Content no longer accepts defaultOpen or onOpenChange. Passing them there detached the popover from the trigger's state, so they now live on the HoverCard root alongside open:
- <HoverCard>
+ <HoverCard defaultOpen onOpenChange={handleOpenChange}>
<HoverCard.Trigger>@heroui</HoverCard.Trigger>
- <HoverCard.Content defaultOpen onOpenChange={handleOpenChange}>
+ <HoverCard.Content>
{/* … */}
</HoverCard.Content>
</HoverCard>The public API is unchanged, but a few behaviors now come from React Aria:
aria-labelledby.onContextMenu on ContextMenu.Trigger is chained with the internal handler; previously it replaced it and prevented the menu from opening.id and is not focusable by default. Pass tabIndex={0} to enable the platform keyboard shortcuts (Shift + F10, Control + Enter).npx heroui-proSelect Update HeroUI Pro React to x.x.x (latest) from the interactive menu.