Frontile

Kbd

Renders keyboard keys and shortcuts.

Kbd knows the common keys by name, so "mod+k" becomes ⌘K on Apple platforms and Ctrl+K everywhere else — one string, correct on every machine.

Import

import { Kbd } from 'frontile';

Usage

Pass a shortcut to @keys as +-separated keys.

Ctrl K Ctrl Shift P Enter Esc Arrow up
import { Kbd } from 'frontile';

<template>
  <div class='flex items-center gap-4 not-prose p-2'>
    <Kbd @keys='mod+k' />
    <Kbd @keys='mod+shift+p' />
    <Kbd @keys='enter' />
    <Kbd @keys='esc' />
    <Kbd @keys='up' />
  </div>
</template>

Anything that is not a known key renders as given, and a single letter is capitalised. Pass a block for arbitrary content.

F5 Ctrl / Fn
import { Kbd } from 'frontile';

<template>
  <div class='flex items-center gap-4 not-prose p-2'>
    <Kbd @keys='F5' />
    <Kbd @keys='mod+/' />
    <Kbd>Fn</Kbd>
  </div>
</template>

Keys

Named keys are case-insensitive.

Group Names
Modifiers mod, meta / cmd / command, ctrl / control, alt / option, shift, win, fn
Special enter / return, esc / escape, tab, space, backspace, del / delete, capslock, plus
Navigation up, down, left, right, pageup, pagedown, home, end

Use plus when you need a literal +, since + is the separator.

Only three keys differ by platform:

Name Apple Elsewhere
mod Ctrl
ctrl Ctrl
alt Alt

Prefer mod for application shortcuts — it names the role, so it follows the platform. Use meta only when you mean the Command key specifically.

Display

@display='merged' puts every glyph in a single cap, and @separator places a character between caps.

Ctrl K CtrlK Ctrl B
import { Kbd } from 'frontile';

<template>
  <div class='flex items-center gap-4 not-prose p-2'>
    <Kbd @keys='mod+k' />
    <Kbd @keys='mod+k' @display='merged' />
    <Kbd @keys='ctrl+b' @separator='+' />
  </div>
</template>

Sizes

Ctrl K Ctrl K Ctrl K
import { Kbd } from 'frontile';

<template>
  <div class='flex items-center gap-4 not-prose p-2'>
    <Kbd @keys='mod+k' @size='sm' />
    <Kbd @keys='mod+k' @size='md' />
    <Kbd @keys='mod+k' @size='lg' />
  </div>
</template>

Variant and color

Ctrl K Ctrl K Ctrl K Ctrl K Ctrl K Ctrl K
Ctrl K Ctrl K Ctrl K Ctrl K Ctrl K Ctrl K
Ctrl K Ctrl K Ctrl K Ctrl K Ctrl K Ctrl K
import { Kbd } from 'frontile';

const variants = ['solid', 'outline', 'subtle'];
const intents = [
  'default',
  'primary',
  'secondary',
  'success',
  'warning',
  'danger'
];

<template>
  <div class='flex flex-col gap-3 not-prose p-2'>
    {{#each variants as |variant|}}
      <div class='flex items-center gap-3'>
        {{#each intents as |intent|}}
          <Kbd @keys='mod+k' @variant={{variant}} @color={{intent}} />
        {{/each}}
      </div>
    {{/each}}
  </div>
</template>

Two variants take their colour from their surroundings rather than from @color. inherit keeps a hairline box drawn in the current colour, which is what lets a keycap sit on a filled, active row without the row's theme having to repaint it. plain drops the box entirely, for a quiet trailing shortcut.

Open command palette Ctrl K
Open command palette Ctrl K
import { Kbd } from 'frontile';

<template>
  <div class='flex flex-col gap-2 not-prose p-2'>
    <div
      class='flex items-center justify-between gap-3 rounded-lg bg-primary-soft text-on-primary-soft px-3 py-2'
    >
      <span>Open command palette</span>
      <Kbd @keys='mod+k' @variant='inherit' @size='sm' />
    </div>
    <div class='flex items-center justify-between gap-3 rounded-lg px-3 py-2'>
      <span>Open command palette</span>
      <Kbd @keys='mod+k' @variant='plain' @size='sm' />
    </div>
  </div>
</template>

Listbox, Dropdown and Command render their items' @shortcut through Kbd. Their keycaps default to inherit, so a shortcut stays legible on an active or filled row; pass @shortcutVariant on the Listbox or Dropdown to change every item at once.

Platform

By default the platform is detected from the browser. Set it explicitly when detection cannot work or would be wrong — during server rendering, where every visitor looks non-Apple, or in tests, which would otherwise depend on the machine running them.

import { setKbdPlatform } from 'frontile';

setKbdPlatform('apple'); // or 'other', or 'auto' to detect

@platform overrides it for a single keycap.

Accessibility

Rendered as nested <kbd> elements, which is how HTML expresses a key combination.

Symbol glyphs are hidden from assistive technology and their names announced instead, since "⌘" read aloud is meaningless. Glyphs that already read correctly — Esc, Ctrl, a letter — are left alone, because labelling them would announce the name twice. Named keys also carry a title, which helps sighted users who do not recognise a glyph.

API

Kbd

Element: HTMLElement

Renders keyboard keys and shortcuts.

A wrapper <kbd> holds one child <kbd> per key, which is the HTML specification's own idiom for a key combination.

Arguments

Name Type Default Description
class string - Custom class name, it will override the default ones using Tailwind Merge library.
classes SlotsToClasses<'base' | 'separator' | 'key'> - Custom CSS classes for styling the individual slots: base for the wrapper, key for each cap, separator for the character between caps.
color enum 'neutral'
display enum 'split' split gives each key its own cap; merged puts every glyph in one.
keys string -

The shortcut to render, as +-separated keys: "mod+shift+p".

Named keys resolve to glyphs (mod, shift, enter, esc, up, …); anything else renders verbatim, with a single letter capitalised. Use plus for a literal +. A string with no + is one key, rendered as given.

Ignored when a block is passed.

platform enum - Overrides the platform for this keycap only. Prefer setKbdPlatform to set it once for the whole app.
separator string - Rendered between caps, e.g. "+". Only applies when @display is split.
size enum 'md'
variant enum 'solid' inherit follows the colour it sits on, for keycaps on a filled row. plain drops the box entirely, for quiet trailing shortcuts.

Blocks

Name Type Default Description
default * Array - Replaces @keys with arbitrary content, rendered as a single cap.
Released under MIT License - Created by Josemar Luedke