From 30c4ccbfee90e86039be9dd026ba2c26deedac43 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Tue, 7 Apr 2026 18:10:35 +0530 Subject: [PATCH 1/3] style(app): update shell mode tray --- packages/app/src/components/prompt-input.tsx | 78 ++++++++++++-------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index eedbc91cfd..3743b312ce 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -21,6 +21,7 @@ import { useComments } from "@/context/comments" import { Button } from "@opencode-ai/ui/button" import { DockShellForm, DockTray } from "@opencode-ai/ui/dock-surface" import { Icon } from "@opencode-ai/ui/icon" +import { Keybind } from "@opencode-ai/ui/keybind" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" import { IconButton } from "@opencode-ai/ui/icon-button" @@ -1450,42 +1451,41 @@ export const PromptInput: Component = (props) => {
-
+
- {language.t("prompt.mode.shell")} -
+ {language.t("prompt.mode.shell")}
-
-
- - { + local.agent.set(value) + restoreFocus() + }} + class="capitalize max-w-[160px] text-text-base" + valueClass="truncate text-13-regular text-text-base" + triggerStyle={control()} + triggerProps={{ "data-action": "prompt-agent" }} + variant="ghost" + /> + +
0} @@ -1581,7 +1581,23 @@ export const PromptInput: Component = (props) => { />
- +
+ +
+
From f714300e9a3ac59833fe421d3d66242c6d5f8429 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Tue, 7 Apr 2026 19:34:05 +0530 Subject: [PATCH 2/3] refactor(ui): add button shortcut component --- .../ui/src/components/button-shortcut.css | 36 ++++++++ .../components/button-shortcut.stories.tsx | 86 +++++++++++++++++++ .../ui/src/components/button-shortcut.tsx | 33 +++++++ packages/ui/src/styles/index.css | 1 + 4 files changed, 156 insertions(+) create mode 100644 packages/ui/src/components/button-shortcut.css create mode 100644 packages/ui/src/components/button-shortcut.stories.tsx create mode 100644 packages/ui/src/components/button-shortcut.tsx diff --git a/packages/ui/src/components/button-shortcut.css b/packages/ui/src/components/button-shortcut.css new file mode 100644 index 0000000000..fd76464a29 --- /dev/null +++ b/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; + } +} diff --git a/packages/ui/src/components/button-shortcut.stories.tsx b/packages/ui/src/components/button-shortcut.stories.tsx new file mode 100644 index 0000000000..ca395e2845 --- /dev/null +++ b/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: () => ( +
+ + Cancel + + + Focus + + + Submit + +
+ ), +} + +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", + }, +} diff --git a/packages/ui/src/components/button-shortcut.tsx b/packages/ui/src/components/button-shortcut.tsx new file mode 100644 index 0000000000..ddf1e2f3b6 --- /dev/null +++ b/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 ( + + ) +} diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css index 1b17f6c2b7..72932f7884 100644 --- a/packages/ui/src/styles/index.css +++ b/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); From 01d80f37ddb765da8e6fe5831b84a72ebf5eaad8 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Tue, 7 Apr 2026 19:34:13 +0530 Subject: [PATCH 3/3] refactor(app): use button shortcut in shell tray --- packages/app/src/components/prompt-input.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 3743b312ce..20ede957a2 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -19,9 +19,9 @@ import { useSDK } from "@/context/sdk" import { useSync } from "@/context/sync" import { useComments } from "@/context/comments" import { Button } from "@opencode-ai/ui/button" +import { ButtonShortcut } from "@opencode-ai/ui/button-shortcut" import { DockShellForm, DockTray } from "@opencode-ai/ui/dock-surface" import { Icon } from "@opencode-ai/ui/icon" -import { Keybind } from "@opencode-ai/ui/keybind" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" import { IconButton } from "@opencode-ai/ui/icon-button" @@ -1584,20 +1584,19 @@ export const PromptInput: Component = (props) => {
- + {language.t("common.cancel")} +