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
6 changes: 3 additions & 3 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Hoist's chrome borrows directly from:

The Hoist designs (in `design.pen`) lay out **five shells** (Three-pane · Sidebar-only · Tabs · Harness grid · CLI-first) and pick the Three-pane as the recommended shell. They document **three real surfaces** (Library · Harness Detail · Install Wizard) with the Library as the canonical harness-management view. The document also defines a **six-component grammar** (install status filled · install status outlined · action buttons · ⌘K command bar · harness table · terminal output) and a **four-card spec** (where each shell wins · one color one state · six tokens three status additions · posture rules).

What we **don't** borrow: Light themes (Hoist is dark-only for now), decorative gradients, sidebars that are themselves apps (cf. 1Password's sidebar-of-vaults is *the* model).
What we **don't** borrow: decorative gradients or sidebars that are themselves apps (cf. 1Password's sidebar-of-vaults is *the* model). Hoist follows the system appearance with graphite dark surfaces and warm drafting-paper light surfaces.

---

Expand All @@ -50,7 +50,7 @@ All values live in `src/renderer/styles/tokens.css`. Components consume them via
--surface-4 #43434f Selected row / focused surface
```

Dark-only. Depth comes from surface ladder, never from drop shadows. Every chrome element is hairline-bordered against the surface below. The `--surface-recessed` token is reserved for the icon-only nav rail and the terminal code block surfaces that should feel "behind" the active canvas.
Both appearances use the same depth ladder. Dark mode uses graphite surfaces; light mode maps the ladder to warm paper and off-white panels. Depth comes from the ladder, never from drop shadows. Every chrome element is hairline-bordered against the surface below. The `--surface-recessed` token is reserved for the icon-only nav rail and the terminal code block, surfaces that should feel "behind" the active canvas.

### Rail + sidebar widths

Expand Down Expand Up @@ -409,7 +409,7 @@ These are open questions, not commitments:

- **Auto-lock the vault** after idle (1Password's Quick Access `Cmd+Shift+Space` re-prompts for master password; we should mirror that for the renderer when keys are read).
- **Discovered `.env` import** (1Password Watchtower pattern) — scan the user's filesystem for plaintext secrets, offer to vault them.
- **Theme picker** (Linear onboarding step 2). Currently dark-only; "Hoist Dark" is the only theme. A "Hoist Light" with the same surface ladder is straightforward to add since we use CSS variables.
- **Theme picker** (Linear onboarding step 2). Hoist currently follows the system light or dark appearance. A manual system/light/dark override can use the same token ladder.
- **Multi-window support** — currently a single `BrowserWindow`. The IPC handler is already window-agnostic; the renderer would just need a per-window `App.tsx` state slice.
- **Detail rail actions** — wire the buttons to actual IPC (Probe now → `probe.run`, Edit → opens a form, Delete → `vault.delete`).
- **Settings panel** — surface-level settings (theme, auto-lock timeout, keytar backend toggle, GitHub repo for issue tracking) in a modal. Mirrors Claude Code's `/config` tabbed interface.
Expand Down
2 changes: 1 addition & 1 deletion src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async function applyLiquidGlass(handle: Buffer): Promise<void> {
if (process.platform !== 'darwin') return
try {
const { default: liquidGlass } = await import('electron-liquid-glass')
liquidGlass.addView(handle, { cornerRadius: 12, tintColor: '#12121459' })
liquidGlass.addView(handle, { cornerRadius: 12 })
} catch { /* glass unsupported on this macOS version — window stays transparent */ }
}

Expand Down
10 changes: 5 additions & 5 deletions src/renderer/styles/components.css
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,16 @@
vertical-align: middle;
flex: 0 0 auto;
}
.badge-ok { background: var(--status-ok); color: var(--text-on-accent); }
.badge-ok { background: var(--status-ok); color: var(--text-on-status); }
.badge-ok-faded { background: var(--status-ok-soft); color: var(--status-ok); }
.badge-info { background: var(--status-info); color: var(--text-on-accent); }
.badge-info { background: var(--status-info); color: var(--text-on-status); }
.badge-info-faded { background: var(--status-info-soft); color: var(--status-info); }
.badge-accent { background: var(--status-accent); color: var(--surface-canvas); }
.badge-accent { background: var(--status-accent); color: var(--text-on-status); }
.badge-accent-faded { background: var(--status-accent-soft); color: var(--status-accent); }
.badge-merged { background: var(--status-merged); color: var(--text-on-accent); }
.badge-merged { background: var(--status-merged); color: var(--text-on-status); }
.badge-merged-faded { background: var(--status-merged-soft); color: var(--status-merged); }
.badge-warn { background: var(--status-warn-soft); color: var(--status-warn); }
.badge-bad { background: var(--status-bad); color: var(--text-on-accent); }
.badge-bad { background: var(--status-bad); color: var(--text-on-status); }
.badge-bad-faded { background: var(--status-bad-soft); color: var(--status-bad); }

.divider { height: 1px; background: var(--border); border: 0; margin: 0; }
Expand Down
40 changes: 20 additions & 20 deletions src/renderer/styles/layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -620,15 +620,15 @@ body.is-col-resizing * {
}
.hoist-stat-card .badge-ok {
background: var(--status-ok-soft);
color: #3dd68c;
color: var(--status-ok);
}
.hoist-stat-card .badge-bad {
background: var(--status-bad-soft);
color: #ff7b72;
color: var(--status-bad);
}
.hoist-stat-card .badge-warn {
background: var(--status-warn-soft);
color: #f0a000;
color: var(--status-warn);
}
.hoist-stat-sub {
font-size: 12px;
Expand Down Expand Up @@ -684,7 +684,7 @@ body.is-col-resizing * {
.hoist-catalogue-tile:hover { background: var(--surface-3); border-color: var(--border-strong); }
.hoist-catalogue-tile.is-featured {
background: var(--accent-soft);
border-color: rgba(21, 123, 243, 0.4);
border-color: color-mix(in srgb, var(--accent) 40%, transparent);
}
.hoist-catalogue-tile-icon {
width: 40px; height: 40px;
Expand Down Expand Up @@ -1340,16 +1340,16 @@ body.is-col-resizing * {
}
.hoist-doctor-pill.is-error.is-hot {
background: var(--status-bad-soft);
border-color: rgba(207, 34, 46, 0.35);
color: #ff7b72;
border-color: color-mix(in srgb, var(--status-bad) 35%, transparent);
color: var(--status-bad);
}
.hoist-doctor-pill.is-error.is-hot .hoist-doctor-pill-n { color: #ff7b72; }
.hoist-doctor-pill.is-error.is-hot .hoist-doctor-pill-n { color: var(--status-bad); }
.hoist-doctor-pill.is-warn.is-hot {
background: var(--status-warn-soft);
border-color: rgba(240, 160, 0, 0.35);
color: #f0a000;
border-color: color-mix(in srgb, var(--status-warn) 35%, transparent);
color: var(--status-warn);
}
.hoist-doctor-pill.is-warn.is-hot .hoist-doctor-pill-n { color: #f0a000; }
.hoist-doctor-pill.is-warn.is-hot .hoist-doctor-pill-n { color: var(--status-warn); }
.hoist-doctor-pill.is-ok .hoist-doctor-pill-n { color: var(--status-ok); }

.hoist-doctor-list {
Expand All @@ -1364,9 +1364,9 @@ body.is-col-resizing * {
border-radius: var(--radius-card);
overflow: hidden;
}
.hoist-doctor-card.is-error { border-color: rgba(207, 34, 46, 0.35); }
.hoist-doctor-card.is-warn { border-color: rgba(240, 160, 0, 0.28); }
.hoist-doctor-card.is-ok { border-color: rgba(45, 164, 78, 0.28); }
.hoist-doctor-card.is-error { border-color: color-mix(in srgb, var(--status-bad) 35%, transparent); }
.hoist-doctor-card.is-warn { border-color: color-mix(in srgb, var(--status-warn) 28%, transparent); }
.hoist-doctor-card.is-ok { border-color: color-mix(in srgb, var(--status-ok) 28%, transparent); }

.hoist-doctor-card-head {
display: grid;
Expand Down Expand Up @@ -1644,7 +1644,7 @@ body.is-col-resizing * {
}
.hoist-form-error {
margin: 0;
color: #ff7b72;
color: var(--status-bad);
font-size: 12px;
}

Expand Down Expand Up @@ -1681,7 +1681,7 @@ body.is-col-resizing * {
min-width: 0;
}
.hoist-path-item.is-winner {
border-color: rgba(45, 164, 78, 0.45);
border-color: color-mix(in srgb, var(--status-ok) 45%, transparent);
background: var(--status-ok-soft);
}
.hoist-path-item.is-current:not(.is-winner) {
Expand Down Expand Up @@ -1867,8 +1867,8 @@ select.input {
}

.hoist-sev-ok { color: var(--status-ok); font-weight: 600; }
.hoist-sev-warn { color: #f0a000; font-weight: 600; }
.hoist-sev-bad { color: #ff7b72; font-weight: 600; }
.hoist-sev-warn { color: var(--status-warn); font-weight: 600; }
.hoist-sev-bad { color: var(--status-bad); font-weight: 600; }

/* ─── Harness configure panel ──────────────────────────────────── */

Expand Down Expand Up @@ -2011,8 +2011,8 @@ select.input {

/* macOS liquid glass — panes go translucent so the window vibrancy reads through */
html[data-platform='darwin'] .hoist,
html[data-platform='darwin'] .hoist-main { background: transparent; }
html[data-platform='darwin'] .hoist-topbar { background: rgba(18, 18, 20, 0.55); }
html[data-platform='darwin'] .hoist-main { background: var(--glass-canvas); }
html[data-platform='darwin'] .hoist-topbar { background: var(--glass-topbar); }
html[data-platform='darwin'] .hoist-sidebar,
html[data-platform='darwin'] .hoist-rail,
html[data-platform='darwin'] .hoist-rail.hoist-rail { background: rgba(26, 26, 29, 0.42); }
html[data-platform='darwin'] .hoist-rail.hoist-rail { background: var(--glass-panel); }
53 changes: 53 additions & 0 deletions src/renderer/styles/tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/

:root {
color-scheme: dark;

/* Surface ladder — neutral graphite, no blue cast */
--surface-canvas: #121214; /* page background */
--surface-recessed: #0c0c0e; /* deeper than canvas — rail backdrop, terminal canvas */
Expand All @@ -28,6 +30,12 @@
--text-muted: #b0aca4;
--text-subtle: #7d7a73;
--text-on-accent: #121214;
--text-on-status: #121214;

/* Translucent macOS pane fills */
--glass-canvas: rgba(18, 18, 20, 0.48);
--glass-topbar: rgba(18, 18, 20, 0.72);
--glass-panel: rgba(26, 26, 29, 0.68);

/* Safety signal — reserved for actions and focus */
--accent: #f06a3c;
Expand Down Expand Up @@ -74,6 +82,51 @@
--space-8: 40px;
}

@media (prefers-color-scheme: light) {
:root {
color-scheme: light;

/* Warm drafting paper, not a clinical white inversion */
--surface-canvas: #f3f0e8;
--surface-recessed: #e6e1d6;
--surface-1: #fbf9f3;
--surface-2: #eeebe3;
--surface-3: #e4dfd4;
--surface-4: #d8d1c5;

--border: #d7d0c4;
--border-strong: #b9b0a3;
--border-soft: rgba(18, 18, 20, 0.06);

--text: #1b1b1d;
--text-muted: #625e57;
--text-subtle: #716c64;
--text-on-accent: #121214;
--text-on-status: #fffdf6;

--accent: #e45f34;
--accent-soft: rgba(228, 95, 52, 0.13);
--accent-strong: #cf4f29;

--status-ok: #1f7a62;
--status-ok-soft: rgba(31, 122, 98, 0.12);
--status-info: #3268a8;
--status-info-soft: rgba(50, 104, 168, 0.12);
--status-accent: #a65a00;
--status-accent-soft: rgba(166, 90, 0, 0.12);
--status-merged: #6f4eb8;
--status-merged-soft: rgba(111, 78, 184, 0.12);
--status-warn: #986100;
--status-warn-soft: rgba(152, 97, 0, 0.12);
--status-bad: #b72e36;
--status-bad-soft: rgba(183, 46, 54, 0.12);

--glass-canvas: rgba(243, 240, 232, 0.76);
--glass-topbar: rgba(251, 249, 243, 0.84);
--glass-panel: rgba(251, 249, 243, 0.78);
}
}

/* Colorway exploration — accent swaps from the icon colorway matrix.
Picked via data-theme on <html> (dev theme picker); default stays Rigging Yard orange. */
[data-theme='signal'] { --accent: #ff7a1a; --accent-strong: #ff9440; --accent-soft: rgba(255, 122, 26, 0.14); --text-on-accent: #121214; }
Expand Down