GrKbd

  • ядро
  • Данные
  • API · 6 props

Берут, когда показывается сочетание клавиш.

import { GrKbd } from '@feugene/granularity/components/GrKbd'

Обзор

Когда брать

  • показывается сочетание клавиш — в подсказке, в справке, в пункте меню;
  • сочетание зависит от платформы — platform печатает ⌘ на macOS и Ctrl на остальных;
  • клавиш несколько — keys собирает сочетание с разделителем, без ручной вёрстки;
  • нужна нативная семантика — рендерится тегом <kbd>, а не стилизованным <span>.

Когда взять другое

НужноБерите
Показывается статус или ярлыкGrBadge
Нужна подсказка о назначенииGrTooltip
Показывается фрагмент кодаразметка приложения: блоков кода в пакете нет
Сочетание вызывает палитру командGrCommandPalette

Варианты все тона и виды — настоящим компонентом

variant

  • split
  • merged
  • sequence

Размеры

  • xs
  • sm
  • md
  • lg

Playground контролы выводятся из API, а не пишутся руками

Сцена

Загружается…

0 изменено· состояние — в адресе

Примеры 3 у каждого — живое демо и его код

  • Справка по горячим клавишам

    Каждое сочетание записано один раз, как его произносят, — mod+K — и рисуется ⌘K на Mac и Ctrl+K на остальных. merged пишет сочетание так, как это делают системы, sequence говорит «G, затем I» для аккорда, а split рисует стрелки отдельными клавишами, нажимаемыми по очереди.

    Anywhere
    Search or run a commandCtrlK
    Create an issueC
    Show this sheetShift/
    Go to
    InboxGI
    My issuesGM
    SettingsGS
    In a list
    Previous / next issueстрелка вверхстрелка вниз
    Open the issueEnter
    Assign to meCtrlShiftM
  • Меню, которое учит сочетаниям

    Каждый пункт заканчивается своим сочетанием в маленьком размере xs, как подсказка, а не вторая подпись; подсказка в предложении ниже — тот же компонент. Кнопки ещё и объявляют aria-keyshortcuts: картинка клавиш — не объявление.

    Press Escape to close the menu.
  • Статья поддержки для двух систем

    Статья о конкретной системе называет платформу нарочно: platform="apple" оставляет ⌥⌘J в колонке macOS даже на ноутбуке с Windows, а platform="other" — Ctrl+Shift+J в другой. Везде остальное честнее автоматический выбор.

    Send us the browser consoleSupport article · 2 minutes
    macOS1. Open the console: OptionCommandJ2. Select all messages: CommandA3. Copy them for the ticket: CommandC
    Windows and Linux1. Open the console: CtrlShiftJ2. Select all messages: CtrlA3. Copy them for the ticket: CtrlC

API порождается из пакета · разойтись не может

Props

PropTypeпо умолчаниюОписание
keysstring | string[] | undefinedundefinedСочетание: строкой (`"mod+shift+K"`) или набором токенов (`['mod', 'K']`). Токен `mod` — Cmd на macOS, Ctrl на остальных. Пробел в строке делит её на шаги: `"g i"` рисуется как «G затем I», а `"mod+k p"` — как «⌘K затем P». Форма массива остаётся плоским аккордом: что там шаг, а что клавиша, массив не различает.
variant"split" | "merged" | "sequence" | undefined"merged"`merged` (по умолчанию) — сочетание одной плашкой, как его пишут сами системы: `⌘K` на macOS, `Ctrl+K` на прочих. `split` — по плашке на клавишу. `sequence` — аккорд «G затем I»: клавиши нажимают одну за другой.
size"xs" | "sm" | "md" | "lg" | undefinedundefinedВысота плашки и кегль — под соседний текст или кнопку. Не задан — из `GrConfigProvider`, иначе `md`.
separatorstring | undefinedundefinedРазделитель между клавишами. Не задан — авто: в общей плашке символы склеиваются (`⌘K`), а слова разделяются плюсом (`Ctrl+K`); у `split` это плюс, у `sequence` — слово из локали. Пустая строка — только зазор.
hotkeystring | undefinedundefinedИдентификатор записи в реестре (`granularityHotkeysPlugin`). Сочетание берётся оттуда, поэтому подсказка не может разойтись с привязкой. Сильнее `keys`: если задан и он, побеждает реестр — иначе два источника спорили бы молча.
platformGrKbdPlatform | undefined"auto"Чем рисовать `mod` и модификаторы: `apple` — `⌘`, `other` — `Ctrl`. По умолчанию `auto`: платформа узнаётся после монтирования, а сервер отдаёт не-Apple вид.

Слоты

SlotTypeОписание
defaultanyКлавиша или сочетание вместо пропа `keys`.

Типы

Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.

Импорт
import type { GrKbdProps, GrKbdSize, GrKbdPlatform } from '@feugene/granularity/components/GrKbd'

Файлdist/types/components/GrKbd/GrKbd.vue.d.ts

GrKbdPropsinterface
interface GrKbdProps {
    /**
     * Высота плашки и кегль — под соседний текст или кнопку.
     * Не задан — из `GrConfigProvider`, иначе `md`.
     */
    size?: GrKbdSize;
    /**
     * `merged` (по умолчанию) — сочетание одной плашкой, как его пишут сами
     * системы: `⌘K` на macOS, `Ctrl+K` на прочих. `split` — по плашке на клавишу.
     * `sequence` — аккорд «G затем I»: клавиши нажимают одну за другой.
     */
    variant?: GrKbdVariant;
    /**
     * Сочетание: строкой (`"mod+shift+K"`) или набором токенов
     * (`['mod', 'K']`). Токен `mod` — Cmd на macOS, Ctrl на остальных.
     *
     * Пробел в строке делит её на шаги: `"g i"` рисуется как «G затем I», а
     * `"mod+k p"` — как «⌘K затем P». Форма массива остаётся плоским аккордом:
     * что там шаг, а что клавиша, массив не различает.
     */
    keys?: string | string[];
    /**
     * Идентификатор записи в реестре (`granularityHotkeysPlugin`). Сочетание
     * берётся оттуда, поэтому подсказка не может разойтись с привязкой. Сильнее
     * `keys`: если задан и он, побеждает реестр — иначе два источника спорили бы
     * молча.
     */
    hotkey?: string;
    /**
     * Разделитель между клавишами. Не задан — авто: в общей плашке символы
     * склеиваются (`⌘K`), а слова разделяются плюсом (`Ctrl+K`); у `split` это
     * плюс, у `sequence` — слово из локали. Пустая строка — только зазор.
     */
    separator?: string;
    /**
     * Чем рисовать `mod` и модификаторы: `apple` — `⌘`, `other` — `Ctrl`. По умолчанию
     * `auto`: платформа узнаётся после монтирования, а сервер отдаёт не-Apple вид.
     */
    platform?: GrKbdPlatform;
}
GrKbdSizetype

GrKbd — GR-примитив для отображения клавиш и сочетаний (<kbd>). Одна клавиша — слотом: <GrKbd>Esc</GrKbd>. Сочетание — пропом: <GrKbd keys="mod+K" /> (на macOS ⌘ K, иначе Ctrl K).

type GrKbdSize = GrComponentSize;
GrKbdPlatformtype

Откуда брать платформу для токена mod.

type GrKbdPlatform = 'auto' | 'apple' | 'other';

Файлdist/types/components/GrKbd/config.d.ts

grKbdConfigconst
const grKbdConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrKbd">;

Файлdist/types/components/GrKbd/defaults.d.ts

GrKbdConfigurablePropsinterface

Пропы GrKbd, настраиваемые глобально через <GrConfigProvider :component-defaults="{ GrKbd: { … } }">. Только оформление — см. GrButton/defaults.ts.

interface GrKbdConfigurableProps {
    size: GrKbdSize;
}

Файлdist/types/components/GrKbd/safelist.d.ts

grKbdSafelistconst
const grKbdSafelist: string[];

Файлdist/types/components/shared/hotkeyTokens.d.ts

GrKbdKeyNametype

Ключи читаемых имён — gr.kbd.<name>.

type GrKbdKeyName = 'command' | 'option' | 'shift' | 'control' | 'enter' | 'escape' | 'tab' | 'backspace' | 'delete' | 'pageUp' | 'pageDown' | 'arrowUp' | 'arrowDown' | 'arrowLeft' | 'arrowRight';
GrKbdTokenGrouptype

Смысловая группа — ею витрина и дока раскладывают каталог.

type GrKbdTokenGroup = 'modifier' | 'editing' | 'navigation';
GrKbdTokenSpecinterface
interface GrKbdTokenSpec {
    /** Канонический токен: его пишут в `keys`. */
    token: string;
    /** Что ещё принимается — синонимы и сам глиф. */
    aliases: readonly string[];
    group: GrKbdTokenGroup;
    /** Вид на macOS и на остальных платформах. */
    apple: HotkeyKeyView;
    other: HotkeyKeyView;
}
GR_KBD_TOKENSconst
const GR_KBD_TOKENS: readonly GrKbdTokenSpec[];
findKbdTokenfunction

Токен или его синоним — в описание клавиши. Регистр не важен, глиф тоже принимается.

function findKbdToken(token: string): GrKbdTokenSpec | undefined;

Использование из прозы библиотеки

Одна клавиша и сочетание
vue
<GrKbd>
Esc
</GrKbd>

<GrKbd keys="mod+K" />

<GrKbd :keys="['mod', 'shift', 'P']" />

Слот остаётся рабочим для одиночной клавиши. Проп keys принимает и строку ("mod+shift+K"), и массив токенов — собирать ⌘ + K из двух GrKbd и <span>+</span> больше не нужно.

Сочетание размечается вложенными <kbd> — приём из спецификации HTML: так оно остаётся клавиатурным вводом целиком, а не набором соседних элементов. От варианта зависит только то, кто из них носит рамку.

Варианты
variantВидКогда
merged (по умолчанию)одна плашка: ⌘K, Ctrl+Kподсказка рядом с кнопкой или в поле — так сочетание пишут сами системы
splitплашка на каждую клавишу: ⌘ Kкогда нужно показать именно набор клавиш, например в справке по горячим клавишам
sequenceG затем Iаккорд: клавиши нажимают одну за другой, а не вместе
vue
<GrKbd keys="mod+K" />                      <!-- ⌘K -->

<GrKbd keys="mod+K" variant="split" />      <!-- ⌘ K -->

<GrKbd :keys="['G', 'I']" variant="sequence" />

Разделитель считается сам

separator по умолчанию не задан — это авто:

  • в merged разделитель ставится только после слова: ⌘K и ⌘⇧K на macOS, Ctrl+K и Ctrl+Shift+K на прочих. Внутри одной платформы набор однороден (macOS даёт символы, остальные — слова), поэтому правило «слева символ — склеиваем» и означает «пишем как система»;
  • в split это +, в sequence — слово из локали (gr.kbd.then).

Явный separator сильнее авто: separator="" склеит что угодно, separator="+" поставит плюс даже между символами. Разделитель декоративен (aria-hidden).

Последовательность пишется в самой строке

Пробел делит keys на шаги, плюс — клавиши внутри шага:

vue
<GrKbd keys="g i" />        <!-- G затем I -->

<GrKbd keys="mod+k p" />    <!-- ⌘K затем P -->

Так подсказка и привязка описываются одной строкой: ту же 'g i' понимает v-hotkey (keyboard.md). Раньше строка 'g+i' означала аккорд для директивы и цепочку для подсказки, а разводил их variant, которого директива не видит.

Граница шага сильнее variant: «затем» появляется между шагами независимо от него. variant="sequence" остаётся рабочим для строки без пробелов — старая запись keys="g+i" variant="sequence" даёт прежний результат.

Форма keys массивом остаётся плоским аккордом: что там шаг, а что клавиша, массив не различает.

Сочетание из реестра

hotkey берёт сочетание по id из реестра приложения (granularityHotkeysPlugin) — тогда подсказка не может разойтись с привязкой:

vue
<GrKbd hotkey="search.open" />

Проп сильнее keys: заданы оба — побеждает реестр, иначе два источника спорили бы молча. Неизвестный id в dev-сборке даёт предупреждение, а не пустую подсказку.

Словарь клавиш

Токенами задаются не только модификаторы:

Токен (и алиасы)macOSПрочие
mod⌘Ctrl
ctrl, alt, shift⌃, ⌥, ⇧Ctrl, Alt, Shift
enter / return↩Enter
esc, space, home, endсловомсловом
tab⇥Tab
backspace⌫Backspace
delete / del⌦Del
pageup / pgup, pagedown / pgdn⇞, ⇟PgUp, PgDn
up, down, left, right↑ ↓ ← →↑ ↓ ← →

Регистр не важен, глиф тоже принимается как токен (↑, ⌘). Писать стрелку литералом в разметке не нужно и не стоит: токен приносит с собой читаемое имя, а голый глиф диктор произносит как значок.

Каталог — не таблица в доке, а данные: GR_KBD_TOKENS экспортируется пакетом, по нему построена страница витрины, и он же кормит форматтер. Копия списка разошлась бы с поведением на первой же новой клавише.

ts
import { GR_KBD_TOKENS, findKbdToken } from '@feugene/granularity'

const navigation = GR_KBD_TOKENS.filter(spec => spec.group === 'navigation')
const command = findKbdToken('⌘') // тот же токен, что и `meta`
Платформа

Токен mod — Cmd на macOS и Ctrl на остальных платформах; ctrl, alt, shift тоже показываются символами на Apple (⌃, ⌥, ⇧) и словами на остальных.

vue
<GrKbd keys="mod+K" />                    <!-- определяется автоматически -->

<GrKbd keys="mod+K" platform="apple" />   <!-- всегда ⌘ -->

<GrKbd keys="mod+K" platform="other" />   <!-- всегда Ctrl -->

platform="auto" уточняет платформу после монтирования: navigator в первом рендере разошёлся бы с серверным HTML и сломал гидрацию. Поэтому с сервера всегда приходит не-Apple вариант, а ⌘ появляется на клиенте. Если аудитория известна заранее, platform убирает и эту перерисовку.

Тот же токен mod понимает директива v-hotkey, поэтому подсказка и привязка пишутся одинаково и не расходятся:

vue
<div v-hotkey="{ 'mod+K': openSearch }">
  <GrKbd keys="mod+K" />
</div>

Разбор и нормализация живут в components/shared/hotkey.ts — том же модуле, которым GrCommandPalette матчит своё сочетание открытия. Общий модуль, а не импорт из директории палитры: иначе на сборке возникло бы ребро GrKbd → GrCommandPalette, и granular doctor посчитал бы его незадекларированной зависимостью.

Скринридер

Символьные клавиши получают читаемое имя рядом с символом:

html
<kbd><span aria-hidden="true">⌘</span><span class="sr-only">Command</span></kbd>

Без этого диктор произносит ⌘ как «знак места интереса». Слова (Ctrl, Shift, Enter) читаются сами — имя к ним не добавляется, иначе вышло бы «Ctrl Control». Тексты имён — ключи gr.kbd.*.

Размеры

Полная шкала пакета: xs, sm, md (по умолчанию), lg — меняются высота, минимальная ширина, padding, кегль и зазор между клавишами. size читается из GrConfigProvider.

min-w держит одиночный символ квадратным: без него «K» была бы у́же, чем «Esc», и ряд хоткеев прыгал бы.