HextaUI

Kbd

ショートカット用のキーキャップです。プラットフォームごとに正しい記号を表示し、正しく読み上げ、実際のキーと同じように押し込まれます。

ShiftCommandP

Press Command K to search, or hold Shift and watch the keys.

import { Kbd, KbdGroup } from "@/components/ui/kbd"

export function KbdDemo() {
  return (
    <div className="flex flex-col items-center gap-6 text-sm text-muted-foreground">
      <KbdGroup keys="mod+shift+p" size="lg" listen />
      <p>
        Press <Kbd keys="mod+k" listen /> to search, or hold{" "}
        <Kbd keys="shift" listen /> and watch the keys.
      </p>
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/kbd.json

コンポーネント、HextaUIのテーマトークン、依存するHextaUIコンポーネントを追加します。

import { Kbd, KbdGroup } from "@/components/ui/kbd"
<KbdGroup keys="mod+k" />
<Kbd keys="escape" />
<Kbd>K</Kbd>

ショートカットは keys で一度書けば、Mac では ⌘K、Windows と Linux では Ctrl K と表示されます。完全に制御したい場合は、子要素として任意のコンテンツを渡せます。

Kbd

KbdGroup
└── Kbd

バリアント

keycap は細い縁と1pxの立体感があり、物理キーのように見えます。flat はメニューのような密な場所向けの控えめな塗りです。

import { KbdGroup } from "@/components/ui/kbd"

export function KbdVariants() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-6">
      <KbdGroup keys="mod+c" />
      <KbdGroup keys="mod+c" variant="flat" />
    </div>
  )
}

サイズ

sm は小さなテキスト内、default は本文の隣、lg は見出しや単独で使います。

import { KbdGroup } from "@/components/ui/kbd"

const sizes = ["sm", "default", "lg"] as const

export function KbdSizes() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-6">
      {sizes.map((size) => (
        <KbdGroup key={size} keys="mod+shift+z" size={size} />
      ))}
    </div>
  )
}

ショートカット

<KbdGroup /> はキーの組み合わせをキーごとのキャップに分割します。スペースでシーケンスが始まり、separator でつながれます。keys を指定した <Kbd /> は、組み合わせ全体を1つのキャップに収めます。

import { Kbd, KbdGroup } from "@/components/ui/kbd"

const shortcuts = [
  { label: "Command palette", keys: "mod+k" },
  { label: "Move line up", keys: "alt+up" },
  { label: "Close", keys: "escape" },
  { label: "Go to dashboard", keys: "g d" },
]

export function KbdShortcuts() {
  return (
    <dl className="grid w-full max-w-xs grid-cols-[1fr_auto] items-center gap-x-6 gap-y-3 text-sm">
      {shortcuts.map((shortcut) => (
        <div key={shortcut.keys} className="contents">
          <dt className="text-muted-foreground">{shortcut.label}</dt>
          <dd>
            <KbdGroup keys={shortcut.keys} />
          </dd>
        </div>
      ))}
      <dt className="text-muted-foreground">Save, as one cap</dt>
      <dd>
        <Kbd keys="mod+s" />
      </dd>
    </dl>
  )
}

ライブキー

listen を指定すると、実際のキーが押されている間キャップが押し込まれます。監視するだけなので、入力をブロックしたり、遅らせたり、変更したりすることはありません。文字は物理キーで照合されるため、Option や Shift と混同されません。

import { Kbd, KbdGroup } from "@/components/ui/kbd"

const rows = ["qwertyuiop", "asdfghjkl", "zxcvbnm"]

export function KbdListen() {
  return (
    <KbdGroup listen size="lg" className="flex-col">
      {rows.map((row) => (
        <span key={row} className="flex gap-1">
          {row.split("").map((key) => (
            <Kbd key={key}>{key.toUpperCase()}</Kbd>
          ))}
        </span>
      ))}
      <span className="flex gap-1">
        <Kbd keys="shift" />
        <Kbd keys="space" className="min-w-40" />
        <Kbd keys="enter" />
      </span>
    </KbdGroup>
  )
}

ボタン内

ボタンの中では、キャップはボタンのテキストから色を取るため、どのバリアントにもなじみます。

import { IconSearch } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"
import { Kbd } from "@/components/ui/kbd"

export function KbdButton() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-3">
      <Button variant="outline">
        <IconSearch data-icon="inline-start" />
        Search
        <Kbd keys="mod+k" />
      </Button>
      <Button>
        Save
        <Kbd keys="mod+s" />
      </Button>
      <Button variant="ghost">
        Undo
        <Kbd keys="mod+z" variant="flat" />
      </Button>
    </div>
  )
}

アイコンとアクション

キー名のないアクションには、キャップにアイコンを入れ、視覚的に非表示のラベルを付けます。

import { IconArrowBackUp, IconClick } from "@tabler/icons-react"

import { Kbd, KbdGroup } from "@/components/ui/kbd"

export function KbdComposed() {
  return (
    <div className="flex flex-col items-center gap-3 text-sm text-muted-foreground">
      <p className="flex items-center gap-2">
        <KbdGroup>
          <Kbd keys="shift" />
          <Kbd>
            <IconClick aria-hidden="true" />
            <span className="sr-only">Click</span>
          </Kbd>
        </KbdGroup>
        to select a range
      </p>
      <p className="flex items-center gap-2">
        <Kbd>
          <IconArrowBackUp aria-hidden="true" />
          <span className="sr-only">Backspace</span>
        </Kbd>
        to go back
      </p>
    </div>
  )
}

右から左

ショートカットは、キーボードに印字されているのと同じように、右から左に書くテキストの中でも左から右の順序を保ちます。

import { Kbd, KbdGroup } from "@/components/ui/kbd"

export function KbdRtl() {
  return (
    <p
      dir="rtl"
      className="flex items-center gap-2 text-sm text-muted-foreground"
    >
      اضغط
      <KbdGroup keys="mod+shift+p" />
      لفتح لوحة الأوامر، أو <Kbd keys="escape" /> للإغلاق
    </p>
  )
}
  • ⌘ や ⇧ などの記号はスクリーンリーダーから隠され、名前に置き換えられるため、keys="mod+shift+p" は「Command Shift P」と読み上げられます。
  • キャップは <kbd> として描画され、グループはそれらを別の <kbd> でネストします。これは HTML でキーの組み合わせを表す方法です。
  • ショートカットを表示しても、割り当てられるわけではありません。キーハンドラーは自分で登録してください。
  • 押下エフェクトは装飾で、視差効果の軽減が有効な場合は動きの代わりに色の変化になります。ハイドレーション前は、どのプラットフォームでも Apple の記号が表示されます。

どちらのパーツも <kbd> を描画し、render とその属性を受け付けます。

プロパティ型デフォルト
keys"mod+shift+p" のように + でつないだキー。mod は Apple デバイスでは ⌘、それ以外では Ctrl です。alt、enter、escape、up、space などの名前は記号や短い語になり、スクリーンリーダー向けの読み上げ名も付きます。
string–
variant未設定の場合は KbdGroup から継承されます。
"keycap" | "flat""keycap"
size未設定の場合は KbdGroup から継承されます。
"sm" | "default" | "lg""default"
listen実際のキーが押されている間、キャップを押し込みます。keys でも、子要素としての単純なキー名でも動作します。
booleanfalse
render
ReactElement | (props, state) => ReactElement<kbd>
属性説明
data-slot="kbd"CSS でキャップを指定します。
data-variant現在のバリアント。
data-size現在のサイズ。
data-pressed実際のキーが押されている間付きます。
プロパティ型デフォルト
keys"mod+shift+p" のように + でつないだキー。mod は Apple デバイスでは ⌘、それ以外では Ctrl です。alt、enter、escape、up、space などの名前は記号や短い語になり、スクリーンリーダー向けの読み上げ名も付きます。スペースはシーケンスの各ステップを区切ります。
string–
separatorシーケンスのステップの間に表示されます。
ReactNode"then"
variant内側のすべてのキャップに渡されます。
"keycap" | "flat"–
size内側のすべてのキャップに渡されます。
"sm" | "default" | "lg"–
listen内側のすべてのキャップに渡されます。
boolean–
render
ReactElement | (props, state) => ReactElement<kbd>
属性説明
data-slot="kbd-group"CSSでグループを指定します。
data-slot="kbd-separator"シーケンスのステップ間のテキスト。

使用しているブロック

Kbd の上に構築されるブロック。