Przejdź do treści

Kbd

Wyświetla klawisz lub skrót klawiszowy — w tekście, w menu albo w podpowiedziach.

Kod źródłowyRejestr
⌘K

Klawisz / otwiera wyszukiwanie, a Esc zamyka.

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

export default function KbdDemo() {
  return (
    <div className="flex flex-col items-center gap-4">
      <KbdGroup>
        <Kbd>⌘</Kbd>
        <Kbd>K</Kbd>
      </KbdGroup>
      <p className="text-sm text-muted-foreground">
        Klawisz <Kbd>/</Kbd> otwiera wyszukiwanie, a <Kbd>Esc</Kbd> zamyka.
      </p>
    </div>
  )
}

Instalacja

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/kbd.json

Użycie

import { Kbd, KbdGroup } from "@/components/ui/kbd"
<KbdGroup>
  <Kbd>⌘</Kbd>
  <Kbd>K</Kbd>
</KbdGroup>

Przykłady

Lista skrótów

KbdGroup ustawia obok siebie klawisze jednej kombinacji. Każdy fizyczny klawisz umieść w osobnym Kbd, w kolejności, w jakiej się je naciska.

Paleta poleceń
⌘K
Pokaż lub ukryj pasek boczny
⌘B
Znajdź w projekcie
⌘⇧F
Przejdź do wiersza
CtrlG
Usuń wiersz
⌘⌫
import { Kbd, KbdGroup } from "@/components/ui/kbd"

const shortcuts = [
  { action: "Paleta poleceń", keys: ["⌘", "K"] },
  { action: "Pokaż lub ukryj pasek boczny", keys: ["⌘", "B"] },
  { action: "Znajdź w projekcie", keys: ["⌘", "⇧", "F"] },
  { action: "Przejdź do wiersza", keys: ["Ctrl", "G"] },
  { action: "Usuń wiersz", keys: ["⌘", "⌫"] },
]

export default function KbdGroupExample() {
  return (
    <dl className="grid w-full max-w-sm grid-cols-[1fr_auto] gap-x-6 gap-y-3 text-sm">
      {shortcuts.map((shortcut) => (
        <div key={shortcut.action} className="contents">
          <dt className="text-muted-foreground">{shortcut.action}</dt>
          <dd>
            <KbdGroup>
              {shortcut.keys.map((key) => (
                <Kbd key={key}>{key}</Kbd>
              ))}
            </KbdGroup>
          </dd>
        </div>
      ))}
    </dl>
  )
}

W podpowiedziach

Ucz skrótów tam, gdzie ludzie już patrzą: w podpowiedzi przycisku, który ma swój skrót. W podpowiedzi klawisze przechodzą w półprzezroczysty styl, czytelny na odwróconej powierzchni. Zadeklaruj też skrót na samej kontrolce przez aria-keyshortcuts.

import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"

import { Button } from "@/components/ui/button"
import { Kbd, KbdGroup } from "@/components/ui/kbd"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"

const tools = [
  { label: "Pogrubienie", icon: BoldIcon, key: "B" },
  { label: "Kursywa", icon: ItalicIcon, key: "I" },
  { label: "Podkreślenie", icon: UnderlineIcon, key: "U" },
]

export default function KbdInTooltip() {
  return (
    <div className="flex items-center gap-1 rounded-lg border bg-card p-1 shadow-raised">
      {tools.map(({ label, icon: Icon, key }) => (
        <Tooltip key={label}>
          <TooltipTrigger
            render={
              <Button
                variant="ghost"
                size="icon-sm"
                aria-label={label}
                aria-keyshortcuts={`Meta+${key}`}
              />
            }
          >
            <Icon />
          </TooltipTrigger>
          <TooltipContent>
            {label}
            <KbdGroup>
              <Kbd>⌘</Kbd>
              <Kbd>{key}</Kbd>
            </KbdGroup>
          </TooltipContent>
        </Tooltip>
      ))}
    </div>
  )
}

W menu

W menu skróty trafiają do DropdownMenuShortcut, wyrównanego do końca każdej pozycji.

import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Kbd, KbdGroup } from "@/components/ui/kbd"

const items = [
  { label: "Nowy plik", keys: ["⌘", "N"] },
  { label: "Otwórz…", keys: ["⌘", "O"] },
  { label: "Zapisz", keys: ["⌘", "S"] },
  { label: "Zapisz jako…", keys: ["⌘", "⇧", "S"] },
]

export default function KbdInMenu() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="outline" />}>
        Plik
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-56">
        <DropdownMenuGroup>
          {items.map((item) => (
            <DropdownMenuItem key={item.label}>
              {item.label}
              <DropdownMenuShortcut>
                <KbdGroup>
                  {item.keys.map((key) => (
                    <Kbd key={key} className="bg-transparent">
                      {key}
                    </Kbd>
                  ))}
                </KbdGroup>
              </DropdownMenuShortcut>
            </DropdownMenuItem>
          ))}
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem>
            Zamknij okno
            <DropdownMenuShortcut>
              <KbdGroup>
                <Kbd className="bg-transparent">⌘</Kbd>
                <Kbd className="bg-transparent">W</Kbd>
              </KbdGroup>
            </DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Zależnie od platformy

Pokazuj modyfikator, który ktoś naprawdę ma na klawiaturze: ⌘ na macOS i iOS, Ctrl wszędzie indziej. Wykrywaj platformę po stronie klienta, a na serwerze renderuj neutralną wartość domyślną, żeby uniknąć niezgodności podczas hydratacji.

Szukaj skrótem CtrlK

Pokazujemy skróty dla Windows i Linux — dopasowane do tego urządzenia.

"use client"

import * as React from "react"

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

function subscribe() {
  return () => {}
}

/** `true` on Apple platforms. Server-renders as `false` to avoid a mismatch. */
function useIsApple() {
  return React.useSyncExternalStore(
    subscribe,
    () => /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent),
    () => false
  )
}

export default function KbdPlatform() {
  const apple = useIsApple()
  const mod = apple ? "⌘" : "Ctrl"

  return (
    <div className="flex flex-col items-center gap-3 text-sm">
      <p className="text-muted-foreground">
        Szukaj skrótem{" "}
        <KbdGroup>
          <Kbd>{mod}</Kbd>
          <Kbd>K</Kbd>
        </KbdGroup>
      </p>
      <p className="text-xs text-muted-foreground">
        Pokazujemy skróty dla {apple ? "macOS" : "Windows i Linux"} — dopasowane do tego urządzenia.
      </p>
    </div>
  )
}
function useIsApple() {
  return React.useSyncExternalStore(
    () => () => {},
    () => /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent),
    () => false
  )
}

W tekście

Klawisze stoją na linii bazowej tekstu ciągłego, więc instrukcje mogą je wymieniać w miejscu, w którym o nich mowa.

Zaznacz wiersz i naciśnij Enter — otworzy się. Klawisze Shift↑ i Shift↓ rozszerzają zaznaczenie, a Esc je czyści.

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

export default function KbdInText() {
  return (
    <div className="max-w-md rounded-xl border bg-card p-5 text-sm leading-6 text-muted-foreground shadow-raised">
      <p>
        Zaznacz wiersz i naciśnij <Kbd>Enter</Kbd> — otworzy się. Klawisze{" "}
        <KbdGroup>
          <Kbd>Shift</Kbd>
          <Kbd>↑</Kbd>
        </KbdGroup>{" "}
        i{" "}
        <KbdGroup>
          <Kbd>Shift</Kbd>
          <Kbd>↓</Kbd>
        </KbdGroup>{" "}
        rozszerzają zaznaczenie, a <Kbd>Esc</Kbd> je czyści.
      </p>
    </div>
  )
}

Wytyczne

Kiedy używać

  • Do pokazania skrótu klawiszowego obok akcji, którą wywołuje.
  • Do wskazania klawisza w instrukcji: Naciśnij Esc, aby zamknąć.

Kiedy nie używać

  • Do kodu i poleceń — użyj formatowania code w tekście.
  • Do przycisków, które trzeba kliknąć — Kbd wygląda, jakby dało się go wcisnąć, ale to tylko pozór.

Symbole i nazwy

Używaj symboli nadrukowanych na klawiszach tam, gdzie są jednoznaczne, a słów tam, gdzie nie są.

KlawiszZapis
Command, Option, Shift, Control (macOS)⌘ ⌥ ⇧ ⌃
Control, Alt (Windows, Linux)Ctrl, Alt
Return, Delete, Escape↵ lub Enter, ⌫, Esc
Strzałki↑ ↓ ← →
LiteryWielkie: K, nie k
⌘⇧P
DobrzeKażdy klawisz osobno, w kolejności naciskania, z modyfikatorem danej platformy.
cmd+shift+p
ŹleCałą kombinację w jednym klawiszu albo mieszankę symboli i nazw trudniej odczytać.

Dostępność

  • Kbd ma znaczenie semantyczne. Renderuje <kbd>, który mówi technologiom wspomagającym, że tekst to dane wprowadzane z klawiatury. Większość czytników ekranu odczytuje symbole takie jak ⌘ („command”); w razie wątpliwości dodaj nazwę ukrytą wizualnie.
  • Deklaruj skróty na kontrolkach. Widoczna podpowiedź pomaga osobom widzącym; aria-keyshortcuts="Meta+K" na kontrolce informuje wszystkich pozostałych.
  • Nie przejmuj skrótów platformy. Unikaj jednoliterowych skrótów, które uruchamiają się podczas pisania, i nigdy nie nadpisuj skrótów przeglądarki ani czytnika ekranu.
  • Kontrast. Tekst klawisza używa muted-foreground, który na powierzchni klawisza osiąga 4,5:1 w obu trybach.

Dokumentacja API

Kbd

Renderuje element <kbd> i przyjmuje wszystkie jego propsy. Ikony w środku mają rozmiar 12 px.

KbdGroup

Renderuje <kbd>, który rozmieszcza kilka elementów Kbd z odstępem 4 px — zagnieżdżone elementy <kbd> to sposób, w jaki HTML opisuje kombinację klawiszy.