Button and focus
components/ui.tsx: Button, IconButton, ToggleIconButton, Hint, StatusDot, Kbd, and the two focus rings
import {
Button,
focus,
formatTimeAgo,
Hint,
HintIconButton,
HintToggleIconButton,
IconButton,
Kbd,
srOnly,
StatusDot,
ToggleIconButton,
} from "../components/ui.tsx";File: packages/desktop/src/renderer/src/components/ui.tsx. "Small shared controls, styled on the
palette."
focus
Two StyleX styles, and the only two focus treatments the desktop uses. From the file's comment:
Keyboard focus must be visible to navigate at all:
ringfor standalone controls,ringInsetfor rows and menu items that sit flush inside a scroll container or popover, where an outset ring would clip.
t.focusRing— not:focus-visible— is what keeps these off the mouse. Chromium matches:focus-visibleon every text field focus, so a plain ring lands on any input the user clicked into; focus-modality.ts drops the color totransparentuntil focus arrives by keyboard.
| Style | Outline |
|---|---|
focus.ring | 2px solid t.focusRing, offset 1px, on :focus-visible |
focus.ringInset | 2px solid t.focusRing, offset −2px, on :focus-visible |
Rule: every focusable in the desktop must apply one of these. A control that draws its own outline is a defect. The mechanism that gates the color is in Foundations › Focus.
srOnly
A visually-hidden style (1px clipped box) for text that must be announced but not seen. Used for tool-call state ("Running", "Failed"), live regions, and labels on controls that read by shape.
Button
Wraps @nyte-ai/ui/button with render={<button type={type} {...rest} />}.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "primary" | "secondary" | "ghost" | "danger" | "secondary" | Fill treatment on t.fill*. |
icon | IconName | Leading 14px glyph from Icons. | |
type | button type | "button" | |
disabled | boolean | Forwarded to Base UI. | |
| …rest | <button> props minus className/style | Spread onto the rendered element. |
Note the default variant is secondary, the opposite of @nyte-ai/ui's Button. Primary is
opt-in because most desktop buttons sit in toolbars and footers.
<Button variant="primary" onClick={save}>Save</Button>
<Button icon="refresh" onClick={refresh}>Refresh GitHub</Button>
<Button variant="danger" disabled={pending}>{pending ? "Deleting…" : "Delete"}</Button>IconButton
A ghost square button for one glyph.
| Prop | Type | Default | Description |
|---|---|---|---|
icon | IconName | ReactElement | A named glyph, or a custom element such as PanelToggleIcon. | |
label | string | Required. Becomes aria-label and title. | |
size | number | 15 | Glyph size. |
compact | boolean | false | Smaller box for tab strips and panel headers. |
ToggleIconButton
Same as IconButton on @nyte-ai/ui/toggle, so it carries aria-pressed.
| Prop | Type | Description |
|---|---|---|
pressed | boolean | Controlled state. |
onPressedChange | (pressed: boolean) => void |
aria-pressed and onClick are removed from the accepted rest props; Base UI Toggle owns them.
Hint, HintIconButton, HintToggleIconButton
Hint is the desktop tooltip on @nyte-ai/ui/tooltip: positionMethod="fixed", sideOffset 6,
collisionPadding 8.
| Prop | Type | Default |
|---|---|---|
content | ReactNode | |
trigger | ReactElement | |
side | Tooltip.Positioner.Props["side"] | "bottom" |
align | Tooltip.Positioner.Props["align"] | "center" |
HintIconButton and HintToggleIconButton wrap the two buttons in a Hint whose content defaults
to the button's label, and drop the native title so the tooltip is the only hint. Props:
the button's props plus hint, hintSide, hintAlign.
Tooltip keyboard and focus behavior is Base UI's: opens on hover after the delay and on keyboard focus, closes on Escape, never traps focus.
StatusDot
A role="img" span with an aria-label for a session's mark.
mark | Label | Draws |
|---|---|---|
idle | Idle | dot |
working | Running | dot + Spinner |
waiting | Needs attention | dot |
retry | Retrying | dot + Spinner |
failed | Failed | dot |
The switch over SessionMark is exhaustive with a never guard; adding a mark is a type error
until the label and style exist.
Kbd
<Kbd keys={["⌘", "K"]} />
<Kbd keys={["⌘", "N"]} plain />Renders <kbd> with one <span> per key. plain removes the keycap box for use inside menu
meta columns. Kbd is display only; the shortcut it shows is bound elsewhere (see the
client action table).
formatTimeAgo(timestamp, now?)
"now", Nm, Nh, Nd, then a short date. Used for session rows and palette results.