Skip to content

Design spec · macOS

This page covers macOS platform differences only. Shared rules live in Shared core; Windows in Windows platform. Based on Apple’s Human Interface Guidelines (macOS).

ItemRule
Title bartitleBarStyle: Overlay + hiddenTitle; content extends into the title bar (unified toolbar)
Traffic lightsFixed space on the left (x: 10, y: 14); content must not cover it
Title bar heightToolbar row 40px (compact unified toolbar), separated from content by a hairline, not a CSS shadow
Drag regionThe whole title bar / toolbar uses data-tauri-drag-region, except buttons
Window controlsUse the system traffic lights (never self-drawn); do not add minimize / maximize / close on the toolbar’s right
Critical infoNo critical controls or important info at the bottom (the bottom edge is often off-screen)

NSVisualEffectView semantic materials mapped to Tauri windowEffects (tauri.conf.json > app.windows[].windowEffects):

RegionApple materialTauri effectsBlendingFallback
Sidebar (nav list)Sidebarsidebarbehind windowopaque bg-sidebar
Toolbar / title barHeader viewheaderViewbehind windowopaque bg-background
Drop-down / menuMenumenu (or in-overlay CSS glass)within windowopaque bg-popover
Overlay / popoverPopoverpopoverwithin windowopaque bg-popover
Dialog (sheet)Sheetsheetwithin windowopaque bg-card
  • state should be followsWindowActiveState: material lightens when the window loses focus.
  • Respect Reduce Transparency: switch to opaque layers when prefers-reduced-transparency: reduce.
  • Window background contract: material is enabled by Rust apply_window_effects() (macOS underWindowBackground); once active, set_window_background skips the opaque base coat — the white-flash guard moves to an opaque content layer (body is always opaque bg-background; only chrome is translucent). If material fails to enable, fall back to opaque silently.
  • Layout premise: the toolbar stays in flow; blur comes from sticky headers (ToolShell’s header and the settings tab bar are sticky top-0 + material). Do not revert to an absolutely positioned toolbar with main top padding — it stacks into a visible empty band.
  • Do not add custom backgrounds or tinting to the toolbar; no accent color on translucent layers; primary text on material uses text-foreground.
SemanticsThis project (three font sizes)Native macOS
Regular control heighth-8 (26/28/30px)Regular 22pt
Compact control heighth-7 (22.75/24.5/26.25px)Small 19pt / Mini 16pt
List row height36 (compact 32)table row 24pt (list row 32pt)
Panel padding16 (compact 12)content margin 20pt (compact 16pt)

Rule: forms and tool pages use regular (h-8); toolbar, in-row table actions and dense settings use compact (h-7); do not mix the three steps within one screen.

  • Switch vs checkbox: fine-grained booleans use a checkbox (title on the right); “emphasis” or a whole group’s switch uses a switch; switches inside grouped forms (SettingsSection) use the mini size (size="sm").
  • Switches only appear in list rows, where the row provides context; never spread a label and switch apart with justify-between.
  • Segmented control: 2–7 tightly related options needing a persistent selected state, and not a window-level view switch.
  • Pop-up button: ≥6 options or long labels; current value shown inside the control (left-aligned + chevron on the right).
  • Search field: magnifier + left alignment, search-as-you-type, clear button on the right (SearchField).
  • Panes switch via a toolbar-style horizontal tab bar (as in Safari / Xcode preferences): stuck below the toolbar, same material. Selected state uses solid bg-primary + text-primary-foreground, not a low-saturation tint (it washes out on glass). Do not use a left vertical nav (to avoid a third column beside the app sidebar).
  • Bar height: auto + equal py-1.5; do not use a fixed height with items-center.
  • Content is a single centered column (12-grid col-start-3 col-span-8); each group uses SettingsSection + SettingsRow.
  • Settings apply immediately; no apply / OK button.
  • Prefer sheets: confirmations / forms tied to the current window use an attached sheet; global, destructive, strongly interrupting cases use a centered Alert-style dialog.
  • Button order: Cancel on the left, default button on the far right; the default button triggers on Return, Esc triggers cancel. Labels use concrete verbs (Delete, Save), not a generic OK / Cancel.
  • Do not use Alerts for informational or commonly reversible actions; never at startup; operations completable inline do not go modal.
  • The global menu bar is provided by src-tauri/src/menu.rs: every toolbar command must have a menu item, and vice versa if a menu item affects the current view it should also appear in the toolbar or command palette.
  • Standard keys:
ActionKey
Settings⌘,
Command palette⌘K
Find⌘F
Close window⌘W
Close all / quit⇧⌘W / ⌘Q
Undo / redo⌘Z / ⇧⌘Z
Switch sidebar group⌘1..9
Reload (dev only)⌘R
Full screen⌃⌘F
Close overlayEsc
  • Every shortcut must be visible in the UI (tooltip or menu item on the right).
  • Context menus use the system right-click; order: common → separator → dangerous last.
  • The sidebar is a source list: group titles (text-xs, text-muted-foreground) + rows (16px icon + 13px text, height 28–32) with bg-sidebar-accent selection (translucent), no border or accent line; it auto-collapses when the window narrows.
  • No critical info / actions at the sidebar bottom.
  • Tables: row height 24–32, sticky header, divide-y, right-aligned numeric columns + tabular-nums, optional zebra.
HIG styleSize / line heightThis project
Large Title / Title 126/32 · 22/26page Hero (rare)
Title 2 / Title 317/22 · 15/20page title (text-base ↗ large)
Headline13/16 Boldpanel title (text-xs + 600)
Body13/16list body (text-sm)
Callout / Subheadline12/15 · 11/14secondary text (text-xs)
Footnote / Caption10/13badges, tiny notes (project floor 11)
  • Fonts: prefer system fonts (-apple-system / SF Pro Text / SF Mono); no third-party fonts.
  • Dark Mode: follow the system appearance (never override “system”); test under Increase Contrast and Reduce Transparency.
  • Accent: six user-selectable accents, only for interactive controls and selected states, never decoration, never on translucent layers.
  • Use the shared durations / easing (Shared core §2.7; macOS feels 200–300ms).
  • Window / material entrances animate blur radius together with scale (material “arrives”, not fades in).
  • Respect prefers-reduced-motion; never use a looping animation as the only state cue.