Kbd
Wyświetla klawisz lub skrót klawiszowy — w tekście, w menu albo w podpowiedziach.
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.jsonUż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
codew 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ą.
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.