Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/ui/src/components/hint-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import { Component, JSX } from "solid-js"
interface HintRowProps {
children: JSX.Element
class?: string
ariaHidden?: boolean
}

const HintRow: Component<HintRowProps> = (props) => {
return <span class={`text-xs text-muted ${props.class || ""}`}>{props.children}</span>
return (
<span aria-hidden={props.ariaHidden} class={`text-xs text-muted ${props.class || ""}`}>
{props.children}
</span>
)
}

export default HintRow
19 changes: 12 additions & 7 deletions packages/ui/src/components/instance/shell/SessionSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Show, type Accessor, type Component } from "solid-js"
import type { SessionThread } from "../../../stores/session-state"
import type { Session } from "../../../types/session"
import type { KeyboardShortcut } from "../../../lib/keyboard-registry"
import { keyboardRegistry, type KeyboardShortcut } from "../../../lib/keyboard-registry"
import type { DrawerViewState } from "./types"

import { PlusSquare, Search } from "lucide-solid"
Expand All @@ -13,7 +13,6 @@ import InfoOutlinedIcon from "@suid/icons-material/InfoOutlined"

import SessionList from "../../session-list"
import KeyboardHint from "../../keyboard-hint"
import Kbd from "../../kbd"
import WorktreeSelector from "../../worktree-selector"
import AgentSelector from "../../agent-selector"
import ModelSelector from "../../model-selector"
Expand Down Expand Up @@ -166,11 +165,17 @@ const SessionSidebar: Component<SessionSidebarProps> = (props) => (

<ThinkingSelector instanceId={props.instanceId} currentModel={activeSession().model} />

<div class="session-sidebar-selector-hints" aria-hidden="true">
<Kbd shortcut="cmd+shift+a" />
<Kbd shortcut="cmd+shift+m" />
<Kbd shortcut="cmd+shift+t" />
</div>
<KeyboardHint
class="session-sidebar-selector-hints"
ariaHidden={true}
shortcuts={[
keyboardRegistry.get("open-agent-selector"),
keyboardRegistry.get("focus-model"),
keyboardRegistry.get("focus-variant"),
].filter((shortcut): shortcut is KeyboardShortcut => Boolean(shortcut))}
separator=" "
showDescription={false}
/>
</div>
</>
)}
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/components/kbd.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, JSX, For } from "solid-js"
import useMediaQuery from "@suid/material/useMediaQuery"
import { isMac } from "../lib/keyboard-utils"

interface KbdProps {
Expand Down Expand Up @@ -27,6 +28,9 @@ const SPECIAL_KEY_LABELS: Record<string, string> = {
}

const Kbd: Component<KbdProps> = (props) => {
const desktopQuery = useMediaQuery("(min-width: 1280px)")
if (!desktopQuery()) return null

const parts = () => {
if (props.children) return [{ text: props.children, isModifier: false }]
if (!props.shortcut) return []
Expand Down
16 changes: 12 additions & 4 deletions packages/ui/src/components/keyboard-hint.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { Component, For } from "solid-js"
import { formatShortcut, isMac } from "../lib/keyboard-utils"
import useMediaQuery from "@suid/material/useMediaQuery"
import type { KeyboardShortcut } from "../lib/keyboard-registry"
import Kbd from "./kbd"
import HintRow from "./hint-row"

const KeyboardHint: Component<{
shortcuts: KeyboardShortcut[]
separator?: string
separator?: string | null
showDescription?: boolean
class?: string
ariaHidden?: boolean
}> = (props) => {
// Centralize layout gating here so call sites don't need to.
// We only show keyboard hint UI on desktop layouts.
const desktopQuery = useMediaQuery("(min-width: 1280px)")

function buildShortcutString(shortcut: KeyboardShortcut): string {
const parts: string[] = []

Expand All @@ -26,12 +32,14 @@ const KeyboardHint: Component<{
return parts.join("+")
}

if (!desktopQuery()) return null

return (
<HintRow>
<HintRow class={props.class} ariaHidden={props.ariaHidden}>
<For each={props.shortcuts}>
{(shortcut, i) => (
<>
{i() > 0 && <span class="mx-1">{props.separator || "•"}</span>}
{i() > 0 && props.separator !== null && <span class="mx-1">{props.separator ?? "•"}</span>}
{props.showDescription !== false && <span class="mr-1">{shortcut.description}</span>}
<Kbd shortcut={buildShortcutString(shortcut)} />
</>
Expand Down