shadcn.io is not affiliated with official shadcn/ui
An arrow slides in beside the label when the pointer arrives or the button takes keyboard focus, and slides back out when it leaves.
Use it for the actions that move someone forward: Get started, Learn more, Next, Continue to checkout. It wraps the Button, so every variant and size works and Base UI handles the press. The arrow is drawn on the button itself rather than added to its content, so the label stays the button's own and it becomes a link the way the Button does. The motion is CSS transitions, with no JavaScript and no animation library: the arrow's space and the button's gap open from nothing, so the button grows smoothly, while the arrow slides out from behind the label. When the system asks for reduced motion, the arrow fades in instead of sliding.
Installation
Usage
import { ArrowButton } from "@/components/ui/arrow-button";<ArrowButton>Get started</ArrowButton>Demos
Direction
direction="left" points the arrow back and slides it in before the label, for Previous, Back to results, or the first half of a pager. The forward button keeps the default. In a right-to-left layout both arrows mirror on their own, so forward still points the way the page reads.
Always Visible
showArrow keeps the arrow out at rest, and hover still nudges it a step further. Use it where hover doesn't happen, on touch screens, or when the arrow is part of what the button says, as in Continue to checkout. It works at every size.
As a Link
Get started here is a real link with the arrow, for the calls to action that go to another page: sign up, pricing, the docs. A link shows where it goes, and people can open it in a new tab. The arrow is drawn on the link itself, so it slides in on hover and focus as on the button. The prop that makes it a link differs by library, and the link question in the FAQ names each one.
Accessibility
The arrow is decoration: it's drawn by CSS, so assistive tech never reads it, and the label has to say where the button goes. It appears on keyboard focus as well as on hover, so people who tab through the page see the same cue. As a link, Enter follows it.
- Enter
- Activate the button.
- Space
- Activate the button.
FAQ
How do I make the Arrow Button go to another page?
Give it a link, as you would the Button it wraps: the arrow is drawn on the button itself, so the link keeps it, as in the As a Link demo.
In Base UI, pass render={<a href="/pricing" />} and nativeButton={false}.
Can the arrow point back?
Yes. direction="left" flips the arrow and slides it in before the label, as in the Direction demo.
How do I keep the arrow visible on touch screens?
Pass showArrow. Touch screens have no hover, so without it the arrow only shows on a keyboard focus there. The Always Visible demo uses it.
Does the button get wider when the arrow appears?
Yes, by the arrow and the button's usual gap, and the growth is smooth: the arrow's space and the gap open from nothing together. At rest a text label is centered as on any Button; a label of several elements, such as an icon and text, keeps its gaps, so at rest it sits half a gap off center. In a row of buttons that must not move, use showArrow so the width is fixed from the start.
API Reference
ArrowButton
children?ReactNode
The label; the arrow goes after it, or before it when it points back.
direction?"left" | "right"
Which way the arrow points: forward for "Next" and "Learn more", back for "Previous". It also decides which side it slides in on.
- Type
"left" | "right"- Default
"right"
focusableWhenDisabled?boolean
Whether the button should be focusable when disabled.
- Default
false
nativeButton?boolean
Whether the component renders a native <button> element when replacing it
via the render prop.
Set to false if the rendered element is not a button (for example, <div>).
- Default
true
showArrow?boolean
Show the arrow at rest; hover still nudges it on.
- Default
false
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
Related
- Pro
Underline Button
Hover revealsA line that grows under the label
- Pro
Flip Button
Hover revealsThe label flips to its other side
- Pro
Shine Button
SurfacesLight sweeps across on hover
- Pro
Liquid Button
Hover revealsA fill rises behind the label
Magnetic Button
Motion & feedbackIt leans toward the cursor
Ripple Button
Motion & feedbackFeedback from the exact press