refactor(ui): add button shortcut component
parent
30c4ccbfee
commit
f714300e9a
|
|
@ -0,0 +1,36 @@
|
|||
[data-component="button"][data-button-shortcut] {
|
||||
[data-slot="button-shortcut-label"] {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
[data-slot="button-shortcut-key"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
[data-slot="button-shortcut-key"] [data-component="keybind"] {
|
||||
box-shadow: none;
|
||||
background: var(--surface-raised-base);
|
||||
color: var(--text-weak);
|
||||
font-family: var(--font-family-sans);
|
||||
font-weight: var(--font-weight-regular);
|
||||
}
|
||||
|
||||
&[data-size="small"] [data-slot="button-shortcut-key"] [data-component="keybind"],
|
||||
&[data-size="normal"] [data-slot="button-shortcut-key"] [data-component="keybind"] {
|
||||
height: 18px;
|
||||
padding: 0 4px;
|
||||
border-radius: 3px;
|
||||
font-size: var(--font-size-small);
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
&[data-size="large"] [data-slot="button-shortcut-key"] [data-component="keybind"] {
|
||||
height: 20px;
|
||||
padding: 0 6px;
|
||||
border-radius: 4px;
|
||||
font-size: var(--font-size-small);
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
// @ts-nocheck
|
||||
import { ButtonShortcut } from "./button-shortcut"
|
||||
|
||||
const docs = `### Overview
|
||||
Button with a trailing shortcut keycap.
|
||||
|
||||
Use this when the action label and shortcut should be taught together at the control level.
|
||||
|
||||
### API
|
||||
- Inherits Button props.
|
||||
- \`shortcut\`: visible keycap text.
|
||||
- \`shortcutAria\`: semantic shortcut string for \`aria-keyshortcuts\`.
|
||||
- \`shortcutClass\`: optional class override for the keycap.
|
||||
|
||||
### Variants and states
|
||||
- Uses the same \`variant\` and \`size\` options as \`Button\`.
|
||||
- Supports disabled state.
|
||||
|
||||
### Accessibility
|
||||
- Keep the visible shortcut concise.
|
||||
- Use \`shortcutAria\` for the canonical key sequence when it differs from the visible label.
|
||||
|
||||
### Theming/tokens
|
||||
- Extends \`Button\` and composes \`Keybind\`.
|
||||
|
||||
`
|
||||
|
||||
export default {
|
||||
title: "UI/ButtonShortcut",
|
||||
id: "components-button-shortcut",
|
||||
component: ButtonShortcut,
|
||||
tags: ["autodocs"],
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: docs,
|
||||
},
|
||||
},
|
||||
},
|
||||
args: {
|
||||
children: "Cancel",
|
||||
shortcut: "Esc",
|
||||
shortcutAria: "Escape",
|
||||
variant: "ghost",
|
||||
size: "small",
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: "select",
|
||||
options: ["primary", "secondary", "ghost"],
|
||||
},
|
||||
size: {
|
||||
control: "select",
|
||||
options: ["small", "normal", "large"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const Basic = {}
|
||||
|
||||
export const Sizes = {
|
||||
render: () => (
|
||||
<div style={{ display: "flex", gap: "12px", "align-items": "center" }}>
|
||||
<ButtonShortcut size="small" variant="ghost" shortcut="Esc" shortcutAria="Escape">
|
||||
Cancel
|
||||
</ButtonShortcut>
|
||||
<ButtonShortcut size="normal" variant="secondary" shortcut="Tab" shortcutAria="Tab">
|
||||
Focus
|
||||
</ButtonShortcut>
|
||||
<ButtonShortcut size="large" variant="primary" shortcut="Enter" shortcutAria="Enter">
|
||||
Submit
|
||||
</ButtonShortcut>
|
||||
</div>
|
||||
),
|
||||
}
|
||||
|
||||
export const Shell = {
|
||||
args: {
|
||||
children: "Cancel",
|
||||
shortcut: "Esc",
|
||||
shortcutAria: "Escape",
|
||||
variant: "ghost",
|
||||
size: "small",
|
||||
class: "h-6 gap-2 rounded-[6px] border-none px-0 py-0 pl-3 pr-0.75 text-13-medium text-text-base shadow-none",
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import { type ComponentProps, Show, splitProps } from "solid-js"
|
||||
import { Button, type ButtonProps } from "./button"
|
||||
import { Keybind } from "./keybind"
|
||||
|
||||
export interface ButtonShortcutProps extends ButtonProps {
|
||||
shortcut?: string
|
||||
shortcutAria?: string
|
||||
shortcutClass?: string
|
||||
shortcutClassList?: ComponentProps<"span">["classList"]
|
||||
}
|
||||
|
||||
export function ButtonShortcut(props: ButtonShortcutProps) {
|
||||
const [split, rest] = splitProps(props, [
|
||||
"children",
|
||||
"shortcut",
|
||||
"shortcutAria",
|
||||
"shortcutClass",
|
||||
"shortcutClassList",
|
||||
])
|
||||
|
||||
return (
|
||||
<Button {...rest} aria-keyshortcuts={split.shortcutAria} data-button-shortcut={split.shortcut ? "true" : undefined}>
|
||||
<span data-slot="button-shortcut-label">{split.children}</span>
|
||||
<Show when={split.shortcut}>
|
||||
<span data-slot="button-shortcut-key">
|
||||
<Keybind class={split.shortcutClass} classList={split.shortcutClassList}>
|
||||
{split.shortcut}
|
||||
</Keybind>
|
||||
</span>
|
||||
</Show>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
@import "../components/avatar.css" layer(components);
|
||||
@import "../components/basic-tool.css" layer(components);
|
||||
@import "../components/button.css" layer(components);
|
||||
@import "../components/button-shortcut.css" layer(components);
|
||||
@import "../components/card.css" layer(components);
|
||||
@import "../components/tool-error-card.css" layer(components);
|
||||
@import "../components/checkbox.css" layer(components);
|
||||
|
|
|
|||
Loading…
Reference in New Issue