Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Buttons

Free

Kbd Button for React

A button that shows its keyboard shortcut in key caps beside the label. For React with Base UI, when power users should learn the faster way in.

Framework
UI library

The label comes first and the shortcut follows in key caps, such as Search docs ⌘K, so the faster way is visible every time someone reaches for the button. The button only shows the shortcut: your app binds the keys, as the Hotkey demo does.

Use it for actions people repeat: a command palette, Save, New issue, Send. Skip the caps on buttons without a shortcut, and on touch-first screens where nobody has a keyboard. It wraps the Button, so variant and size work as usual, and the caps are the Kbd, tinted to read on every variant. The optional hover reveal is a CSS transition that slides and fades the caps in, and only fades them with reduced motion.

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

Usage

import { KbdButton } from "@/components/ui/kbd-button";
<KbdButton shortcut={["⌘", "S"]}>Save</KbdButton>

Demos

Hotkey

shortcut takes the keys as they should read, one cap each: ["⌘", "K"], ["Ctrl", "S"], ["N"]. Binding them is your app's: here the page listens for N, skips it while someone types in a field, and runs the same action as a press. A hotkey library does the same in one line.

Preview width

Show on Hover

showShortcutOn="hover" hides the caps until the button is hovered or focused from the keyboard, then slides them in, for dense menus where shortcuts are useful to discover but shouldn't compete with the labels. The space is kept, so nothing shifts.

Preview width

Accessibility

The caps are part of the button's text, so the shortcut is read with the label. The button also gets aria-keyshortcuts from shortcut, such as Meta+K for ⌘ K, the standard way to tell assistive tech about a shortcut; pass aria-keyshortcuts yourself to spell it another way. Hover-only caps also appear on keyboard focus.

Enter
Activate the button.
Space
Activate the button.

FAQ

How do I write the shortcut?

As an array of keys, one cap each, written as they should read: ["⌘", "K"], ["Ctrl", "Shift", "P"], ["/"]. The modifier glyphs ⌘, ⌃, ⌥ and ⇧, and Cmd, Ctrl and Option, are spelled out for aria-keyshortcuts; other keys go in as written.

Why doesn't pressing the shortcut press the button?

The button only shows it, so it can't fight with your app's other shortcuts or a hotkey library you already use. Listen for the keys where your app handles shortcuts and run the same action, as the Hotkey demo does.

How do I show ⌘ on a Mac and Ctrl on Windows?

Pick the keys from the visitor's platform where you render the button, such as ["⌘", "K"] on Apple devices and ["Ctrl", "K"] elsewhere, and bind both in your listener. The button shows what you pass.

Can I hide the caps until hover?

Pass showShortcutOn="hover". They slide and fade in on hover and on keyboard focus, and keep their space so the label doesn't move.

How do I put the caps at the far end of a wide button?

They already go there: the caps take the space left after the label, so a full-width button, as in the Show on Hover demo, has the label at the start and the shortcut at the end.

What happens with reduced motion?

Hover-only caps fade in without sliding. Everything else is the same.

API Reference

KbdButton

data-slot="kbd-button-shortcut"

PropType
children?ReactNode

The label, before the shortcut.

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
shortcut?string[]

The shortcut's keys, one cap each, as they should read: ["⌘", "K"], ["Ctrl", "S"], ["/"]. It's shown only: bind the keys yourself.

Default
[]
showShortcutOn?"always" | "hover"

When the shortcut shows: always, or only while the button is hovered or has keyboard focus, sliding in. It keeps its space either way.

Type
"always" | "hover"
Default
"always"
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.

All 35 buttons