Commit Graph
14 Commits
Author SHA1 Message Date
brooklyn! f033b7dbfb feat(desktop): unified overlay design system, BrandMark & onboarding redesign (#40708)
* fix(desktop): unify dialog/overlay buttons on shared Button component

Replace raw <button> action/text controls across the modal layer (boot
failure, install, update, onboarding, clarify, model-visibility,
notifications, gateway menu) with the shared Button + its variants
(text / ghost / icon-xs). Drops the bespoke square-cornered styling so
every dialog matches the app's slightly-rounded button system, and
swaps clarify-tool's hardcoded "Skip" for the existing i18n string.

* feat(desktop): add dev-only dialog gallery for auditing overlays

A code-split, DEV-gated harness (toggle ⌘/Ctrl+Alt+Shift+D) that triggers
every dialog/overlay so their buttons can be eyeballed in one place:
store-driven overlays (boot failure, updates, notifications, sudo/secret)
plus in-place dialogs (confirm, profile create/rename, attach-url, model
picker/visibility, clarify, tool approval). Never ships to production.

* fix(desktop): use Ctrl+Shift+D for dialog gallery (mac-friendly)

The Cmd/Ctrl+Alt+Shift+D chord is impractical on macOS (Option mangles
the keypress). Ctrl+Shift+D is the same chord on every platform and uses
neither Cmd nor Option.

* fix(desktop): stop overriding button icon size to size-4

Action buttons hardcoded size-4 icons, overriding the Button component's
built-in size-3.5. That extra 2px is why boot-failure / onboarding / gateway
buttons looked chunkier than the settings "Apply" (size-3.5 spinner) despite
being the same component+size. Drop the overrides so icons inherit 3.5.

* feat(desktop): add BrandMark, use it in the updates overlay hero

New BrandMark renders the white logo.png on a hardcoded brand-blue tile
(#0000F2 light / #222 dark), replacing the generic Sparkles hero glyph in
the "update available" overlay. Trying it here first to iterate on the look.

NOTE: apps/desktop/public/logo.png is currently a 1x1 placeholder — the tile
renders now; the glyph appears once the real white logo art is dropped in.

* feat(desktop): add real logo.png asset, render it white in BrandMark

logo.png is blue line-art on transparent, so force it white via filter to
read on both the brand-blue (#0000F2) and near-black (#222) tiles. Bump the
glyph to 62% of the tile for the portrait aspect.

* fix(desktop): BrandMark renders logo as-is, no light bg/radius/padding

Drop the white filter, the hardcoded light-mode blue tile, the radius, and
the inner padding. Logo now fills the tile over a transparent surface in
light mode; dark keeps the #222 tile.

* fix(desktop): bump updates-overlay BrandMark to size-16

* feat(desktop): use downscaled karb.webp in BrandMark

Swap the BrandMark glyph to karb.webp, downscaled from 1129x1418/888KB to
254x320/81KB for the hero badge.

* feat(desktop): use nous-girl mark in BrandMark, invert in dark

Key the white background to transparent so only the black line-art remains
(384px/20KB webp). Light mode shows black art; dark mode flips it white via
dark:invert on the #222 tile. Drop the now-unused karb.webp and logo.png.

* fix(desktop): BrandMark uses nous-girl as-is (no transparent/invert)

The dark-mode invert read as a creepy negative. Use the opaque black-on-white
mark unchanged in both themes; drop the white-key, dark:invert, and #222 tile.

* fix(desktop): give BrandMark an explicit white bg tile

* fix(desktop): use nous-girl.jpg directly in BrandMark

* perf(desktop): downscale nous-girl.jpg to 256x256 (466KB -> 19KB)

* style(desktop): bump nous light --theme-secondary to 14% blue

* fix(desktop): outline button is transparent, not chrome-filled

The outline variant used bg-background (the chrome color), so on cards/overlays
with a different surface it rendered as an odd gray-blue fill (visible on the
boot overlay's Repair install / Use local gateway). Make it bg-transparent so
it inherits the surface like a real outline. Reverts the unrelated
--theme-secondary tweak.

* fix(desktop): clean outline button — thin border, no shadow/fill

Drop shadow-xs and the resting fills (light chrome bg, dark bg-input/30) so
outline is just a thin clean border with a subtle hover, in both themes.

* fix(desktop): stop forcing tertiary bg on outline buttons

A global [data-variant='outline'] rule set background: var(--ui-bg-tertiary),
which (attribute-selector specificity) overrode the cva bg-transparent — so
outline buttons always showed the pale tertiary fill on cards/overlays
regardless of the variant classes. Scope that fill to secondary only; outline
is now a true transparent border.

* style(desktop): unified overlay design system + restore #38631 flat-UI

Overlays/dialogs/toasts share a custom shadow-nous (downward-weighted) and
--stroke-nous hairline instead of hard borders: boot-failure, install,
notifications, model-picker, onboarding, prompt-overlays, updates, Dialog.

- button: outline is a 1px inset ring (no fill/shadow); chrome lives in Button
- BrandMark: 256px nous-girl mark replaces sparkle glyphs (updates/onboarding/about)
- onboarding: conditional header, lemniscate-bloom loaders, OTP device-code boxes,
  NOUS CONNECTED hero (ascii decode) + cuneiform easter egg, "Begin" matrix exit
- shared LogView + ErrorState; math/ascii loaders over "Loading..." text
- appearance-settings flattened to SegmentedControl/ListRow; keybind-panel on
  shadow-nous + text-variant reset
- restore flat-UI clobbered by #38631's stale-squash (4a1907bd1): command-center,
  profiles, skills, messaging, cron de-boxed; shared SearchField + PAGE_INSET_X;
  profiles back on OverlaySplitLayout; skills tabs+search one row, no row dividers

* refactor(desktop): clean pass — drop dead code, dedupe, fix stale docs

- log-view: drop unused `bare` prop + forwardRef (no caller uses ref)
- install-overlay: drop `stateOverride` (only the removed dev gallery used it)
- profiles: ProfilesViewProps down to { onClose } (drop vestigial section/titlebar)
- onboarding: hoist shared PROVIDER_ROW_CLASS (was duplicated 2x)
- brand-mark / error-state: tighten comments, fix stale AlertCircle reference
2026-06-06 16:32:47 -05:00
Brooklyn Nicholson 258984fcb9 feat(desktop): broaden hotkey coverage + fold in stray shortcuts
Add rebindable actions for the high-frequency gaps: focus composer, open
model picker, next/prev session, search sessions (⌘⇧F), show files/
terminal tab, and nav→artifacts. Reconcile the duplicate Shift+N new-
session listener into session.new's defaults, and surface the remaining
context-local shortcuts (⌘↵ steer, ⌘L terminal selection, ⌘W close
preview) as read-only rows so the panel is the honest source of truth.
2026-06-06 11:47:33 -05:00
Brooklyn Nicholson 5e2b83a8ad feat(desktop): rebindable keyboard shortcuts panel
Add a central keybind registry + nanostore so desktop hotkeys are
discoverable and user-rebindable. A titlebar ⌨ button (and ⌘/) opens a
collapsible map grouped by Composer (read-only) / Profiles / Session /
Navigation / View; click any chip to capture a new combo. Overrides
persist to localStorage as a delta against shipped defaults, so future
default changes aren't shadowed by a stored snapshot.

Migrates the previously scattered inline listeners (palette, command
center, new session, sidebar, theme) into the registry, and adds profile
switch/cycle/create + default-profile hotkeys.
2026-06-06 11:41:57 -05:00
Jim Liu 宝玉 1c2189839d Refactor desktop settings i18n keys to camelCase 2026-06-06 07:51:44 -07:00
Jim Liu 宝玉 c24abf5b32 Add missing Chinese desktop i18n translations 2026-06-06 07:51:44 -07:00
Jim Liu 宝玉 112a0732c6 Translate missing desktop i18n strings for ja and zh-hant 2026-06-06 07:51:44 -07:00
Jim Liu 宝玉andKiro 有点Yes fbd423b94d feat(desktop): localize desktop chrome
Co-authored-by: Kiro 有点Yes <246816394+sdyckjq-lab@users.noreply.github.com>
2026-06-06 07:51:44 -07:00
Jim Liu 宝玉 812dc6957e Add searchable language picker 2026-06-06 07:51:44 -07:00
Jim Liu 宝玉 b1b89f843e Refactor desktop i18n field copy into nested structures 2026-06-06 07:51:44 -07:00
Jim Liu 宝玉 f18a9dbefc feat: Add desktop language switching for Japanese and Traditional Chinese 2026-06-06 07:51:44 -07:00
Brooklyn Nicholson 40aef6af91 feat(desktop): steer the live run from the composer
The desktop app could only queue while busy — `/steer` was in the palette
but had no first-class affordance, so the "nudge the agent mid-turn without
interrupting" lane was effectively unreachable.

Add a steer action to the composer: while busy with a text-only draft, a
steering-wheel button (and Cmd/Ctrl+Enter) injects the text into the live
turn via the `session.steer` RPC — the gateway folds it into the next tool
result so the model reads it on its next iteration. Plain Enter still queues.

steerPrompt returns false when the gateway has no live tool window (or the
RPC errors), and the composer re-queues the words so nothing is lost — the
same safety net as a plain queue.
2026-06-05 20:50:30 -05:00
brooklyn! 0cbcc75935 fix(desktop): reliable composer message queue (#40221)
* fix(desktop): make composer message queue reliable

The queue felt 'dumb' because of three real bugs:

1. Drained-after-interrupt sends went silent. cancelRun sets
   interrupted:true and nothing reset it; submitPromptText's optimistic
   seed preserved it, and the message stream drops every delta while
   interrupted. So Send-now-while-busy and any interrupt+drain submitted
   the next turn into a muted session. Fix: a fresh submit is a new turn —
   seed interrupted:false.

2. Back-to-back queue drains stalled. The drain fires on the busy->false
   settle edge, but busyRef (synced from the busy store by a separate
   effect) can still read true on that same edge, so the drained send hit
   the busy guard, returned false, and the entry was never removed. Fix:
   fromQueue sends bypass the busyRef guard (the queue drain lock
   serializes them); the user path keeps the guard.

3. Double-enter-to-interrupt killed single non-queue turns. The hidden
   450ms timer meant a natural double-tap after sending stopped the agent.
   Fix: empty Enter while busy is a no-op; interrupting is explicit —
   Stop button or Esc.

Also: clean stop (no [interrupted] marker), Send-now works while busy
(promote + interrupt + auto-drain), settle on the interrupted completion
path. Adds regression tests and unblocks the prompt-actions suite by
completing its stale @/hermes mock.

* fix(desktop): float the queue panel as an overlay so the chat doesn't resize

The queue list rendered in-flow inside the composer root, so its height
fed --composer-measured-height (the composer rect drives the thread's
bottom padding + last-message clearance). Queuing a message grew that
rect and the whole chat visibly resized.

Anchor the panel out of flow above the composer (absolute bottom-full,
capped at 40vh with internal scroll). It no longer contributes to the
measured height, so the thread layout stays put and the list overlays the
(already faded) chat. Still collapsible via the panel's own
disclosure header.

* fix(desktop): queue panel collapsed by default + shared border with composer

- Default the queue disclosure to collapsed (compact 'N queued' pill)
  instead of expanded.
- Drop the gap and merge the panel into the composer: square bottom
  corners, no bottom border/radius, and overlap down by the Root's pt-2
  (-mb-2) so the panel's borderless bottom lands on the composer surface's
  top border — one continuous bordered shape.

* style(desktop): tighten queue panel padding

* style(desktop): trim queue-ux comments to house style

* style(desktop): drop 'Cursor' references from comments
2026-06-05 20:21:41 -05:00
Jim Liu 宝玉 1d9c3ebae0 feat(desktop): persist i18n language in config 2026-06-05 10:32:26 -07:00
Jim Liu 宝玉 4a1907bd10 feat(desktop): add i18n with Simplified Chinese (zh-Hans) support
Introduce a lightweight React context-based i18n layer for the desktop
app and translate the UI into Simplified Chinese.

- New apps/desktop/src/i18n module: typed Translations interface, en + zh
  locale tables, I18nProvider/useI18n, localStorage-persisted locale
  (defaults to English), and language endonym metadata for the picker.
- Wire I18nProvider at the app root in main.tsx.
- Refactor 24 desktop screens/components to read strings from the `t`
  object instead of hard-coded English.
- Add a unit test for the i18n context.
2026-06-05 10:32:26 -07:00