UI refactor: standard window, bottom command bar, theme flavors#46
Merged
Conversation
The 1.2.0 fix intercepted Return via .onKeyPress but returned `.ignored` for Shift+Return, expecting the field editor to insert the break. Instead the event fell through to the field editor's default Return handling, which selected all the text. Handle both keys explicitly: plain Return submits; Shift+Return inserts the line break directly into the focused field editor (the key window's first responder while editing) at the caret, routing through the normal text-change path so the draft updates and the input auto-grows. Fixes the regression from #27.
…and Cursor The bonsai-board skill previously only existed as a local Claude Code skill file living outside the repo. Bundle the canvas API doc for three agents and offer to install it on first launch (only for agents detected on the Mac), with a reinstall/install-more control in Settings > Connectors > Agent Skills. Claude Code and Cursor get a dedicated file; Codex's AGENTS.md is shared with the user's own notes, so it's merged into a marked section instead of overwritten.
An image card renders its own rounded border. The accent selection ring was drawn `selectionGap` px outside at a larger corner radius, so selecting an image showed two concentric rounded borders with a visible gap. For image cards the ring now hugs the image's own edge (tight gap, matching radius, slightly heavier stroke) as a single clean accent outline. Text, shapes, and lines are unchanged.
Resolve conflict in AppDelegate.swift: keep both the agent-skills first-launch prompt (this PR) and the SIGTERM handler (release-1.2.2) — independent additions.
feat(agent-skills): install canvas-API skill for Claude Code, Codex, and Cursor
Brings in the 1.2.1 changelog + Shift+Enter select-all follow-up fix from main, and rolls the release-1.2.2 Unreleased notes into a [1.2.2] section (agent skills, model pickers, autosave-flush-on-quit, image selection ring).
…ring hugs the image Dropped images were created at a fixed 220x140 landscape frame while the image drew with scaledToFill and no frame clamp, so non-landscape images overflowed the card — the selection ring hugged the frame while the image spilled past it. Size the card to the image's pixel aspect ratio on drop, clamp the image to the frame so it fills-and-crops instead of overflowing, and align the image ring corner radius (10->8) to the image's own border.
…bundle; don't clobber an unreadable AGENTS.md
.process("Resources") flattens the bundle tree, so the subdirectory: "AgentSkills" lookup always returned nil and every install failed. Try the no-subdirectory form first (as EngineLogo does), with the subdirectory as fallback. Also: mergeMarkedSection mapped any read failure to "" via try?, so an existing-but-unreadable AGENTS.md would be overwritten with only BonsAI's section — now only a genuinely-absent file is treated as empty; a real read error propagates.
…the image On Copy/Compile an image card now serializes to its absolute file path instead of contributing nothing (or only OCR text) — so the reference is pasteable and a board that's just an image no longer copies as empty. Describe passes the image path through the board-state JSON and grants `claude -p` the read-only Read tool (--allowedTools Read) so the model opens and views the actual image.
…against reversed markers The Settings > Runtime > Models 'Describe board' picker sets a claude --model alias, so it silently no-op'd when preferredEngine() resolved to Codex (Claude disabled/unavailable). It now disables with an explanatory note whenever Claude isn't the engine that will run Describe. Also harden AgentSkillsInstaller.mergeMarkedSection: if a file's end marker precedes its begin marker, append a fresh section instead of trapping on a reversed replaceSubrange range.
The floating-panel mode is removed entirely; BonsAI is now a single titled, resizable macOS window with all chrome floating over a solid edge-to-edge canvas. - Window: FloatingPanel is always a standard window; traffic lights are re-laid onto the control row's centerline; PanelController loses all dock/summon logic (Agent/Settings are in-canvas glass overlays). - Layout (tldraw-style): board pill top-left that grows on hover into the board manager (switch, inline rename, two-click delete, New board); agent toggle top-right; ONE bottom command bar with zoom, tools, grounding folder, and Settings. Rail, top toolbar, and the History overlay are gone. - Design system: WindowChrome tokens (sizes, paddings, radius, fonts) plus a chromePill() wrapper so no chrome view carries inline metrics; trackpad haptics via Haptics.swift. - Theming: System/Light/Dark applied as NSAppearance; solid canvas (black dark / paper white light); all light-mode ink derives from #575757 — no black instances; board elements are outline-only in light mode. - Removed features superseded by the Canvas API: Describe Board and Copy Board (with copy-time connector/shell resolution, SelfContainedRenderer, the describe model pref, and the ⇧⌘C shortcut). - Panels modernized: Agent chat with slim header, input-area model/grounding chips, circular send, suggestion chips; Settings with capsule chip tabs and a Theme picker.
Themes become data: `ThemeFlavor` (14 semantic slots + appearance class + accent) with four named flavors — Bonsai Dark, Bonsai Light, Catppuccin Mocha, and Catppuccin Latte. Every `Theme.Palette` token maps a role onto the active flavor; `Color.accentColor` is fully swept for `Theme.Palette.accent`. - Settings ▸ Appearance: a 2×2 gallery of preview cards, each painted from its own flavor's palette (mini canvas, pill, accent, ink lines). - Theme switch sets the window appearance and rebuilds the canvas; `CanvasAgent` is now a singleton so the chat survives the rebuild. - Canvas transparency slider returns (canvas background over behind-window blur; solid at the default 0). - Light-mode fixes: NodeLabel ink, brand chip colors normalized per-flavor (dynamic NSColor), grayscale marks use the flavor ink.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The full UI refactor: BonsAI becomes a single standard macOS window with floating chrome, gets a token-driven design system, and ships four named themes with a preview gallery.
Window architecture
PanelControllershrinks to ~130 lines.Layout (tldraw-style)
Design system
WindowChrometokens (control size, paddings, radius, fonts, insets) + achromePill()wrapper — no inline metrics in chrome views.ThemeFlavor): Bonsai Dark, Bonsai Light, Catppuccin Mocha, Catppuccin Latte. Every palette token maps a semantic role onto the active flavor;Color.accentColorfully swept forTheme.Palette.accent.Panels
Test plan
swift test— 40/40 green.