Live-review iteration on the browser SPA, driven by crit feedback. Sidebar / session tree - Compact single-line leaf rows; status shown as a faint "alive" row wash instead of per-row dots (exited rows dim + keep the "exited" badge). - Host is now the first level of nesting (host → label path → session); the inline @daemon is dropped from rows. - Flush, borderless search input spanning the sidebar; drag-to-resize grip on the sidebar edge (width persisted to localStorage); narrower default. - Per-row clone action (opens the spawn modal prefilled); right-pointing chevron when collapsed. Chrome / layout - Buttons swapped to a bracket terminal style ([ + Spawn ]); ghost/icon drop the brackets. Old filled styles removed. - Squared corners globally (radius tokens) and tighter, denser spacing. - Session tally + daemon chips moved into the centered app header. - Shorter control height; shared --bar-h aligns the search and attach bars. Attach / terminal - Useful attach title (name · command @ host) over a bare UUID. - Robust fit: compute columns from the viewport's scrollbar-excluded clientWidth (fixes mobile under-fit and desktop overflow); ResizeObserver + font-load refit; full-bleed terminal on mobile. Spawn / empty states - Spawn modal accepts a prefill (clone); real "+ Spawn" buttons in welcome and no-sessions empty states. Dev - New ?kit design-kit page (kit.ts/kit.css, DEV-only) showcasing components. - Richer ?mock fixture with deeper label nesting. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+268
@@ -0,0 +1,268 @@
|
||||
/* =========================================================================
|
||||
maestro web — design kit (DEV-only)
|
||||
Loaded only by kit.ts (?kit). Layout for the specimen page + proposed
|
||||
terminal-native button variants offered for critique. Nothing here ships:
|
||||
kit.ts is dynamically imported behind import.meta.env.DEV.
|
||||
========================================================================= */
|
||||
|
||||
.kit {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background: var(--bg);
|
||||
color: var(--ink);
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--border-strong) transparent;
|
||||
}
|
||||
|
||||
.kit-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: var(--z-sticky);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--sp-3);
|
||||
padding: var(--sp-3) var(--sp-5);
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: color-mix(in oklab, var(--surface) 82%, transparent);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.kit-brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--sp-2);
|
||||
}
|
||||
|
||||
.kit-brand h1 {
|
||||
margin: 0;
|
||||
font-size: var(--fs-15);
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.kit-header-actions {
|
||||
margin-left: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--sp-2);
|
||||
}
|
||||
|
||||
.kit-main {
|
||||
max-width: 1080px;
|
||||
margin: 0 auto;
|
||||
padding: var(--sp-6) var(--sp-5) var(--sp-8);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--sp-8);
|
||||
}
|
||||
|
||||
.kit-section-head {
|
||||
margin-bottom: var(--sp-4);
|
||||
}
|
||||
|
||||
.kit-section-title {
|
||||
margin: 0;
|
||||
font-size: var(--fs-13);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.kit-section-note {
|
||||
margin: 6px 0 0;
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--fs-13);
|
||||
color: var(--muted);
|
||||
max-width: 70ch;
|
||||
}
|
||||
|
||||
.kit-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
gap: var(--sp-4);
|
||||
}
|
||||
|
||||
/* A specimen cell: the component above, its name below. */
|
||||
.kit-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--sp-2);
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.kit-slot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 44px;
|
||||
padding: var(--sp-3);
|
||||
border: 1px dashed var(--border);
|
||||
border-radius: var(--r-2);
|
||||
background: color-mix(in oklab, var(--surface) 40%, var(--bg));
|
||||
}
|
||||
|
||||
.kit-slot .modal-body {
|
||||
padding: 0;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.kit-label {
|
||||
font-size: var(--fs-11);
|
||||
color: var(--faint);
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
/* color swatches */
|
||||
.kit-swatches {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
gap: var(--sp-3);
|
||||
}
|
||||
|
||||
.kit-swatch {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.kit-swatch-chip {
|
||||
height: 48px;
|
||||
border-radius: var(--r-2);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
/* session-row specimen sits in a sidebar-width container so wrapping/ellipsis
|
||||
behave like the real sidebar. */
|
||||
.kit-tree-host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.kit-tree {
|
||||
width: clamp(280px, 26vw, 360px);
|
||||
padding: var(--sp-2) 0;
|
||||
background: color-mix(in oklab, var(--surface) 26%, var(--bg));
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-2);
|
||||
}
|
||||
|
||||
.kit-empties {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: var(--sp-4);
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.kit-empties .empty {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-2);
|
||||
background: color-mix(in oklab, var(--surface) 30%, var(--bg));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Proposed terminal-native button variants (critique only)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
.kit-btn-bracket,
|
||||
.kit-btn-prompt,
|
||||
.kit-btn-block,
|
||||
.kit-btn-underline {
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--fs-13);
|
||||
height: var(--control-h);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
color: var(--ink);
|
||||
transition:
|
||||
color var(--dur-fast) var(--ease-out),
|
||||
border-color var(--dur-fast) var(--ease-out),
|
||||
background var(--dur-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
/* [ + Spawn ] — brackets are the chrome */
|
||||
.kit-btn-bracket {
|
||||
padding: 0 var(--sp-2);
|
||||
}
|
||||
.kit-btn-bracket::before {
|
||||
content: "[";
|
||||
color: var(--faint);
|
||||
}
|
||||
.kit-btn-bracket::after {
|
||||
content: "]";
|
||||
color: var(--faint);
|
||||
}
|
||||
.kit-btn-bracket:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
.kit-btn-bracket:hover::before,
|
||||
.kit-btn-bracket:hover::after {
|
||||
color: var(--accent);
|
||||
}
|
||||
.kit-btn-bracket.is-primary {
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
.kit-btn-bracket.is-primary::before,
|
||||
.kit-btn-bracket.is-primary::after {
|
||||
color: var(--accent);
|
||||
}
|
||||
.kit-btn-bracket.is-primary:hover {
|
||||
background: var(--accent-tint);
|
||||
}
|
||||
|
||||
/* › spawn — a shell prompt */
|
||||
.kit-btn-prompt {
|
||||
padding: 0 var(--sp-2);
|
||||
color: var(--muted);
|
||||
}
|
||||
.kit-btn-prompt::before {
|
||||
content: "›";
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
.kit-btn-prompt:hover {
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
/* SPAWN — boxed, uppercase, tight */
|
||||
.kit-btn-block {
|
||||
padding: 0 var(--sp-3);
|
||||
border-color: var(--border-strong);
|
||||
border-radius: var(--r-1);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
font-size: var(--fs-11);
|
||||
font-weight: 600;
|
||||
color: var(--muted);
|
||||
}
|
||||
.kit-btn-block:hover {
|
||||
color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
background: var(--accent-tint);
|
||||
}
|
||||
|
||||
/* spawn — underline only */
|
||||
.kit-btn-underline {
|
||||
padding: 0 2px;
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid var(--border-strong);
|
||||
color: var(--muted);
|
||||
}
|
||||
.kit-btn-underline:hover {
|
||||
color: var(--accent);
|
||||
border-bottom-color: var(--accent);
|
||||
}
|
||||
|
||||
.kit-btn-bracket:focus-visible,
|
||||
.kit-btn-prompt:focus-visible,
|
||||
.kit-btn-block:focus-visible,
|
||||
.kit-btn-underline:focus-visible {
|
||||
outline: 2px solid var(--accent-ring);
|
||||
outline-offset: 2px;
|
||||
border-radius: var(--r-1);
|
||||
}
|
||||
Reference in New Issue
Block a user