Bläddra i källkod

refactor(ui): add button shortcut component

Shoubhit Dash 1 vecka sedan
förälder
incheckning
f714300e9a

+ 36 - 0
packages/ui/src/components/button-shortcut.css

@@ -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;
+  }
+}

+ 86 - 0
packages/ui/src/components/button-shortcut.stories.tsx

@@ -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",
+  },
+}

+ 33 - 0
packages/ui/src/components/button-shortcut.tsx

@@ -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>
+  )
+}

+ 1 - 0
packages/ui/src/styles/index.css

@@ -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);