Kbd
Used to display textual user input from keyboard.
⌘⇧⌥⌃Ctrl+B
import { css } from 'remix/component'
import { Kbd, KbdGroup } from '#app/ui/kbd.tsx'
export function KbdDemo() {
return () => (import { css } from 'remix/component'
import { Kbd, KbdGroup } from '#app/ui/kbd.tsx'
export function KbdDemo() {
return () => (
<div mix={css({ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '1rem' })}>
<KbdGroup>
<Kbd>⌘</Kbd>
<Kbd>⇧</Kbd>
<Kbd>⌥</Kbd>
<Kbd>⌃</Kbd>
</KbdGroup>
<KbdGroup>
<Kbd>Ctrl</Kbd>
<span>+</span>
<Kbd>B</Kbd>
</KbdGroup>
</div>
)
}Installation
$ bunx --bun shadcn@latest add https://www.shadcn-remix.com/r/kbd.json$ npx shadcn@latest add https://www.shadcn-remix.com/r/kbd.json$ pnpm dlx shadcn@latest add https://www.shadcn-remix.com/r/kbd.json$ yarn dlx shadcn@latest add https://www.shadcn-remix.com/r/kbd.jsonInstall the following dependencies:
$ bun add remix$ npm install remix$ pnpm add remix$ yarn add remixCopy and paste the following code into your project.
import { css, type Handle, type Props } from 'remix/component'
const kbdStyles = css({
pointerEvents: 'none',
display: 'inline-flex',
height: '1.25rem',
width: 'fit-content',
minWidth: '1.25rem',
alignItems: 'center',
justifyContent: 'center',
gap: '0.25rem',
borderRadius: 'calc(var(--radius) - 4px)',
backgroundColor: 'var(--muted)',
paddingInline: '0.25rem',
fontFamily: 'var(--font-sans)',
fontSize: '0.75rem',
lineHeight: 'calc(1 / 0.75)',
fontWeight: 500,
color: 'var(--muted-foreground)',
userSelect: 'none',
'& svg:not([class*="size-"])': { width: '0.75rem', height: '0.75rem' },
'[data-slot="tooltip-content"] &': {
backgroundColor: 'color-mix(in oklab, var(--background) 20%, transparent)',
color: 'var(--background)',
},
'.dark [data-slot="tooltip-content"] &': {
backgroundColor: 'color-mix(in oklab, var(--background) 10%, transparent)',
},
})
const kbdGroupStyles = css({ display: 'inline-flex', alignItems: 'center', gap: '0.25rem' })
export function Kbd(handle: Handle<Props<'kbd'>>) {
return () => {
let { mix, ...props } = handle.props
return <kbd data-slot="kbd" {...props} mix={[kbdStyles, mix]} />
}
}
export function KbdGroup(handle: Handle<Props<'kbd'>>) {
return () => {
let { mix, ...props } = handle.props
return <kbd data-slot="kbd-group" {...props} mix={[kbdGroupStyles, mix]} />
}
}Update the import paths to match your project setup.
Usage
import { Kbd } from '#app/ui/kbd.tsx'<Kbd>Ctrl</Kbd>Examples
Group
Use the KbdGroup component to group keyboard keys together.
Use Ctrl + BCtrl + K to open the command palette
import { css } from 'remix/component'
import { Kbd, KbdGroup } from '#app/ui/kbd.tsx'
export function KbdGroupExample() {
return () => (import { css } from 'remix/component'
import { Kbd, KbdGroup } from '#app/ui/kbd.tsx'
export function KbdGroupExample() {
return () => (
<div mix={css({ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '1rem' })}>
<p
mix={css({
fontSize: '0.875rem',
lineHeight: 'calc(1.25 / 0.875)',
color: 'var(--muted-foreground)',
})}
>
Use{' '}
<KbdGroup>
<Kbd>Ctrl + B</Kbd>
<Kbd>Ctrl + K</Kbd>
</KbdGroup>{' '}
to open the command palette
</p>
</div>
)
}Button
Use the Kbd component inside a Button component to display a keyboard key inside a button.
import { css } from 'remix/component'
import { Button } from '#app/ui/button.tsx'
import { Kbd } from '#app/ui/kbd.tsx'
const tightEnd = css({ paddingRight: '0.5rem' })import { css } from 'remix/component'
import { Button } from '#app/ui/button.tsx'
import { Kbd } from '#app/ui/kbd.tsx'
const tightEnd = css({ paddingRight: '0.5rem' })
export function KbdButton() {
return () => (
<div mix={css({ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: '1rem' })}>
<Button variant="outline" size="sm" mix={tightEnd}>
Accept <Kbd>⏎</Kbd>
</Button>
<Button variant="outline" size="sm" mix={tightEnd}>
Cancel <Kbd>Esc</Kbd>
</Button>
</div>
)
}Input Group
You can use the Kbd component inside a InputGroupAddon component to display a keyboard key inside an input group.
⌘K
import { css } from 'remix/component'
import { SearchIcon } from '#app/ui/icons.tsx'
import { InputGroup, InputGroupAddon, InputGroupInput } from '#app/ui/input-group.tsx'
import { Kbd } from '#app/ui/kbd.tsx'import { css } from 'remix/component'
import { SearchIcon } from '#app/ui/icons.tsx'
import { InputGroup, InputGroupAddon, InputGroupInput } from '#app/ui/input-group.tsx'
import { Kbd } from '#app/ui/kbd.tsx'
export function KbdInputGroup() {
return () => (
<div
mix={css({
display: 'flex',
width: '100%',
maxWidth: '20rem',
flexDirection: 'column',
gap: '1.5rem',
})}
>
<InputGroup>
<InputGroupInput placeholder="Search..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
<InputGroupAddon align="inline-end">
<Kbd>⌘</Kbd>
<Kbd>K</Kbd>
</InputGroupAddon>
</InputGroup>
</div>
)
}API Reference
Kbd
| Prop | Type | Default |
|---|---|---|
mix | MixValue | - |
KbdGroup
| Prop | Type | Default |
|---|---|---|
mix | MixValue | - |