diff --git a/docs/superpowers/specs/2026-09-01-work-app-design.md b/docs/superpowers/specs/2026-09-01-work-app-design.md index ffda87c..db90472 100644 --- a/docs/superpowers/specs/2026-09-01-work-app-design.md +++ b/docs/superpowers/specs/2026-09-01-work-app-design.md @@ -302,6 +302,16 @@ The margin That margin is the only part of the window that is not a web page, an therefore the only place left to grab it by. Full screen has no use for it and gets the room back. +### Borders + +One weight everywhere, and the lightest that still separates: `slate-200` in light, +`slate-800` in dark. Nothing is drawn heavier than it needs to be to read as an edge. + +The stage rect is rounded to whole pixels, and to the same edges every time. A fractional +left edge leaves a sliver of the stage's own background between the nav's border and the +app beside it, and at a hairline weight that sliver reads as a second border line running +the full height of the window. + ## Dialogs An app's webview is a native view that paints above the shell, so a dialog cannot simply diff --git a/src/App.tsx b/src/App.tsx index cf89d80..61199b4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -56,7 +56,13 @@ export default function App() { const el = stageRef.current; if (!el) return; const r = el.getBoundingClientRect(); - void api.setStage(r.x, r.y, r.width, r.height, 0); + /* Rounded to whole pixels, and to the same edges each time. A fractional + left edge leaves a sliver of the stage's own background showing between + the nav's border and the app — which reads as a second, lighter border + line running down the whole window. */ + const x = Math.round(r.x); + const y = Math.round(r.y); + void api.setStage(x, y, Math.round(r.right) - x, Math.round(r.bottom) - y, 0); }, []); useLayoutEffect(() => { diff --git a/src/components/Nav.tsx b/src/components/Nav.tsx index 3547182..e3a59cf 100644 --- a/src/components/Nav.tsx +++ b/src/components/Nav.tsx @@ -38,7 +38,7 @@ export default function Nav({ const disabled = !activeId; const shell = - "flex shrink-0 flex-col overflow-hidden border-r border-slate-300 bg-white " + + "flex shrink-0 flex-col overflow-hidden border-r border-slate-200 bg-white " + "dark:border-slate-800 dark:bg-slate-900"; /* Back, forward, reload and settings. Nothing hides an element here — that diff --git a/src/components/ui.tsx b/src/components/ui.tsx index 31d49a0..50e57f9 100644 --- a/src/components/ui.tsx +++ b/src/components/ui.tsx @@ -25,8 +25,8 @@ export const SECTION = "border-b border-slate-200 px-4 py-4 dark:border-slate-80 /* No width: callers set it. A `w-full` baked in here loses the specificity coin-toss against a `w-[110px]` or a `flex-1` at the call site. */ export const INPUT = - `${CONTROL_H} min-w-0 rounded-lg border border-slate-300 bg-white px-3 text-[12px] outline-none ` + - "placeholder:text-slate-400 dark:border-slate-700 dark:bg-slate-800 dark:placeholder:text-slate-500"; + `${CONTROL_H} min-w-0 rounded-lg border border-slate-200 bg-white px-3 text-[12px] outline-none ` + + "placeholder:text-slate-400 dark:border-slate-800 dark:bg-slate-800 dark:placeholder:text-slate-500"; export const SUBPANEL = "rounded-lg bg-slate-50 p-3 dark:bg-slate-800/50"; const BTN_BASE = @@ -34,9 +34,9 @@ const BTN_BASE = "disabled:cursor-not-allowed cursor-pointer"; export const BTN = - `${BTN_BASE} border border-slate-300 px-2.5 font-medium ` + + `${BTN_BASE} border border-slate-200 px-2.5 font-medium ` + "hover:border-sky-500 hover:text-sky-600 disabled:opacity-40 " + - "dark:border-slate-700 dark:hover:border-sky-500 dark:hover:text-sky-400"; + "dark:border-slate-800 dark:hover:border-sky-500 dark:hover:text-sky-400"; export const BTN_PRIMARY = `${BTN_BASE} bg-sky-500 px-3 font-semibold text-white hover:bg-sky-400 disabled:opacity-40`; @@ -86,7 +86,7 @@ export function Segmented({ return (
{options.map((o) => { const active = o.value === value; @@ -173,8 +173,8 @@ export function Dialog({ wide ? "max-w-[min(1120px,92vw)] max-h-[90vh] overflow-y-auto" : "max-w-sm" - } rounded-2xl border border-slate-300 bg-white p-5 shadow-2xl - dark:border-slate-700 dark:bg-slate-900`} + } rounded-2xl border border-slate-200 bg-white p-5 shadow-2xl + dark:border-slate-800 dark:bg-slate-900`} >

{title}