Typography

Kbd

A key or a key combination (⌘K, Ctrl+Shift+P) as <kbd> elements, with symbols for the modifiers.

#typography#keyboard#text#no-js

Demo

Preview
ControlShiftPCommandKOptionEnterShiftTabCtrlC
EscUp arrowDown arrowLeft arrowRight arrowSpaceF5
CommandSCommandSCommandS

Press CommandK to open the command palette, or ? for the shortcuts.

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/kbd.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/kbd.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/kbd.qwe
view KbdDemo() =    <div.demo-stack>        <div.demo-row>            <Kbd keys="Ctrl+Shift+P" id="kbd-demo-combo"/>            <Kbd keys={["Cmd", "K"]} id="kbd-demo-cmdk"/>            <Kbd keys="Alt+Enter"/>            <Kbd keys="Shift+Tab"/>            <Kbd keys="Ctrl+C" symbols={false} id="kbd-demo-plain"/>        </div>        <div.demo-row>            <Kbd id="kbd-demo-one">Esc</Kbd>            <Kbd keys="Up"/><Kbd keys="Down"/><Kbd keys="Left"/><Kbd keys="Right"/>            <Kbd keys="Space"/>            <Kbd keys="F5"/>        </div>        <div.demo-row>            <Kbd size="sm" keys="Cmd+S"/>            <Kbd keys="Cmd+S"/>            <Kbd size="lg" keys="Cmd+S"/>        </div>        <p.demo-note>Press <Kbd keys="Cmd+K"/> to open the command palette, or <Kbd>?</Kbd> for the shortcuts.</p>    </div>

Source

ui/kbd.qwe
// Kbd: a key, or keys pressed together (⌘K, Ctrl+Shift+P), as real <kbd> elements.////   <Kbd>Enter</Kbd>//   <Kbd keys="Ctrl+Shift+P"/>//   <Kbd keys={["Cmd", "K"]} size="sm"/>//// children: one key, as written. keys: several, joined with "+" in a string, or a// list (write the plus key itself in a list: ["Ctrl", "+"]); each is a <kbd> inside// one <kbd>, with a "+" between them that screen readers skip.// symbols (true): Cmd, Shift, Alt, Option, Ctrl, Enter, Backspace, Tab, Esc, Up,// Down, Left and Right are shown as their symbols (⌘ ⇧ ⌥ ⌃ ↵ ⌫ ⇥ ⎋ ↑ ↓ ← →), with// the name for screen readers. size: "sm", "md" (default) or "lg". id: the element's id.import ui/theme.qwe use ui_clslet kbd_css = css`.ui-kbd { display: inline-flex; align-items: center; gap: 3px; font: 12px/1 var(--ui-mono); color: var(--ui-fg); vertical-align: middle; }.ui-kbd-key { display: inline-flex; align-items: center; justify-content: center; min-width: 1.9em; height: 1.9em; padding: 0 .45em;  border: 1px solid var(--ui-border); border-bottom-width: 2px; border-radius: 5px; background: var(--ui-surface);  color: var(--ui-fg); font: 500 12px/1 var(--ui-mono); white-space: nowrap; }.ui-kbd-sym { font-family: var(--ui-font); font-size: 1.1em; }.ui-kbd-plus { color: var(--ui-muted); font-size: 11px; }.ui-kbd-sm .ui-kbd-key { min-width: 1.7em; height: 1.7em; font-size: 11px; }.ui-kbd-lg .ui-kbd-key { min-width: 2.2em; height: 2.2em; font-size: 14px; padding: 0 .6em; }`// The symbol and name for a key written by name, or null for a plain key.fn kbd_symbol(key: str) -> map? =    match lower(trim(key)) {        "cmd" | "command" | "meta" => { sym: "⌘", name: "Command" }        "shift" => { sym: "⇧", name: "Shift" }        "alt" | "option" => { sym: "⌥", name: "Option" }        "ctrl" | "control" => { sym: "⌃", name: "Control" }        "enter" | "return" => { sym: "↵", name: "Enter" }        "backspace" | "delete" => { sym: "⌫", name: "Backspace" }        "tab" => { sym: "⇥", name: "Tab" }        "esc" | "escape" => { sym: "⎋", name: "Escape" }        "up" | "arrowup" => { sym: "↑", name: "Up arrow" }        "down" | "arrowdown" => { sym: "↓", name: "Down arrow" }        "left" | "arrowleft" => { sym: "←", name: "Left arrow" }        "right" | "arrowright" => { sym: "→", name: "Right arrow" }        _ => null    }// The keys of "Ctrl+Shift+P" (or a list) as a list of names.fn kbd_keys(keys) -> list =    type_of(keys) == "list" ? keys : split(str(keys), "+") | map((k) => trim(k)) | filter((k) => k != "")view Kbd(keys = null, symbols: bool = true, size: str = "md", id: str? = null, class: str? = null, children) {    style global kbd_css    let one = (k: str) => {        let s = symbols ? kbd_symbol(k) : null        s != null            ? <kbd.ui-kbd-key><span.ui-sr>{s.name}</span><span.ui-kbd-sym aria-hidden="true">{s.sym}</span></kbd>            : <kbd.ui-kbd-key>{k}</kbd>    }    let cls = ui_cls(["ui-kbd", size != "md" && `ui-kbd-${size}`, class])    if keys == null {        <kbd class={cls} id={id}>{children}</kbd>    } else {        let names = kbd_keys(keys)        <kbd class={cls} id={id}>            {for [i, k] in enumerate(names) => [i > 0 && <span.ui-kbd-plus aria-hidden="true">+</span>, one(k)]}        </kbd>    }}
Thread
57Useful? Like it, or add to its thread below.

Thread 0 posts

On Kbd: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.