A button whose label slides away to an arrow, or to a second label with an arrow, on hover and keyboard focus. Builds on Button.
Optional, and kept apart.
Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.
import { InteractiveHoverButton } from "@rdloom/react";
export default function InteractiveHoverButtonBasicExample() {
return (
<div className="flex w-full justify-center">
<InteractiveHoverButton>Get started</InteractiveHoverButton>
</div>
);
}Installation
npx rdloom add interactive-hover-buttonCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.
It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/interactive-hover-button.jsonWorks, but without upgrade tracking, and you import the motion CSS yourself.
Usage
import { InteractiveHoverButton } from "@rdloom/react";
<div className="flex w-full justify-center">
<InteractiveHoverButton>Get started</InteractiveHoverButton>
</div>With hover label
import { InteractiveHoverButton } from "@rdloom/react";
export default function InteractiveHoverButtonWithHoverLabelExample() {
return (
<div className="flex w-full flex-wrap items-center justify-center gap-4">
<InteractiveHoverButton hoverLabel="Read it" variant="secondary" size="lg">
Read the guide
</InteractiveHoverButton>
<InteractiveHoverButton hoverLabel="Open" variant="ghost">
Open the docs
</InteractiveHoverButton>
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
childrenrequiredButton label. This is the accessible name. | node | none |
hoverLabelOptional wording shown on hover and focus, next to the arrow. It is visual only and should say the same thing as the label. Without it only the arrow appears. | string | none |
variantVisual emphasis, as on Button. | "primary" | "secondary" | "ghost" | "danger" | "primary" |
sizeHeight, padding and font size, as on Button. | "sm" | "md" | "lg" | "md" |
isDisabledPrevents interaction, dims the button and turns the effect off. | boolean | false |
isLoadingShows a spinner and blocks presses; the pending state is announced. | boolean | false |
onPressCalled when the button is pressed by mouse, touch or keyboard. | () => void | none |
Accessibility
Role button, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
- Tab focuses it and shows the same effect as hover
- Enter or Space presses it
Screen readers announce
- Announced exactly as a Button: its label, as a button; the effect adds nothing to what is read
What your code must do
- The effect is the same for mouse hover and keyboard focus (focus-visible), so keyboard users see it too
- The alternate label and arrow are decoration, hidden from assistive technology; the accessible name is always the main label
- On touch screens there is no hover, so the button stays still
- Stands still for visitors who ask for less motion (prefers-reduced-motion), and inside an rdm-still container
- A disabled or loading button does not animate
- The arrow flips in right-to-left layouts
- Optional: it is a separate component, so projects that do not add it carry none of its code
Guidelines
Use it when
- A call to action on a landing page that should feel responsive
- A link-like action that leads somewhere, where the arrow adds meaning
Avoid it when
- Dense toolbars or forms, where plain Button is calmer
- Destructive actions, where a changing label could confuse
Don't
- A hover label that says something different from the main label
- A hover label much longer than the main label: it is clipped to the button's width
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-action-primary--rd-color-action-on-primary--rd-color-action-danger--rd-color-surface-default--rd-color-text-default--rd-color-border-default--rd-color-focus-ring--rd-radius-control