shell-redesign V1 attempt-3 Phase 2 BOUNCE-FIX #2: drawer 38rem + 1px borders

Triple-gate verdicts on commit 87f8155:
  review-lead APPROVE | design-reviewer DONE | guard-3 PROCESS-BLOCKER
Founder walk surfaced 2 spec-level aesthetic refinements; orch dispatched
this bounce-fix #2.

Canon updates landed upstream:
  universal-shell.md L36 — drawer width 720px → 608px (38rem) iPad-portrait
  universal-shell.md L39–L48 — NEW Border weight doctrine LOAD-BEARING:
    1px outline-variant for ALL inter-region borders. NO 2px stone-900
    between rail/explore/center/drawer/top-bar. Tactical-dossier aesthetic
    is "sheets of vellum paper layered together" via tonal shifts + thin
    lines, NOT boxed UI.
  content-drawer.md L9 + L19 — width recalibrated 720px → 608px after
    founder walk (too-wide drawer dominated viewport).

ITEM 1 — VellumSheet "wide" preset 45rem → 38rem:
  packages/ui/src/components/ui/vellum-sheet.tsx
  - widthClass.wide: "lg:w-[45rem]" → "lg:w-[38rem]"
  packages/ui/test/vellum-sheet.test.tsx
  - assertion updated to lg:w-[38rem]

ITEM 2 — Inter-region borders 2px stone-900 → 1px outline-variant
(7 edits across 3 files; runtime-verified via getComputedStyle):

  AppShell.tsx Rail base classes (lines 263–270):
    "bg-background border-stone-900 flex shrink-0" + "border-r-2"/"border-b-2"
    → "bg-background border-outline-variant flex shrink-0" + "border-r"/"border-b"

  AppShell.tsx top-bar header (line ~401):
    "border-b-2 border-stone-900" → "border-b border-outline-variant"

  AppShell.tsx mobile rail tray (line ~461):
    "border-r-2 border-stone-900" → "border-r border-outline-variant"

  Explorer.tsx aside right edge (line ~574):
    "border-r border-stone-300/25" → "border-r border-outline-variant"

  VellumSheet edge classes:
    "border-r-2 border-stone-900" / "border-l-2 border-stone-900"
    → "border-r border-outline-variant" / "border-l border-outline-variant"

  VellumSheet test assertions updated to match (border-l/r + border-outline-variant
  instead of border-l-2/r-2).

PRESERVED per dispatch EXCEPTIONS clause:
  - Active rail-icon left-edge accent (2px tertiary red stamp) — kept.
  - Hard-shadow 2px stamp on cards (paper press effect) — kept.
  - Card-internal borders (border-stone-900 on VellumCard etc.) — kept.
  - Tree-branch internal guides (border-l border-stone-200 in Explorer
    tree-branch helpers) — kept; tree-internal grammar.
  - Explorer collapse button border + VellumSheet [×] close button border
    — kept; control affordances, not inter-region edges.

ITEM 3 — Permission preflight artifact authored inline in
substrate/.../shell-redesign-v1/attempt-3-driver-3-phase-2-bounce-fix-2-ack.md
§6, per velocity-permission-preflight skill schema. Required fields all
present (active_profile, cwd, launch_flags, target_write_paths,
writable_root_coverage, approval_layer_probe, required_posture,
missing_posture_route, seat_freshness). guard-3 process gate satisfied.

Verification:
  - tsc --noEmit: clean
  - pnpm test: 597/598 PASS (single failure pre-existing
    test/library-review.test.tsx > Send-to-seat modal — unrelated)
  - pnpm build: ✓ in 1.98s
  - agent-browser at 1440x900 /topology:
    * getComputedStyle(app-topbar).borderBottomWidth === "1px"
    * getComputedStyle(app-rail).borderRightWidth === "1px"
    * getComputedStyle(explorer).borderRightWidth === "1px"
    * SC-1 strict count: querySelectorAll("nav, aside").length === 2 (unchanged)
    * Visually: chrome reads as architectural drafting / paper-layered;
      heavy black borders gone; OPENRIG brand + active rail accent
      retained as tactical accents.

Out-of-scope per orch direction:
  - RigDetailPanel legacy retire (deferred to Phase 4 drawer-viewer wiring).
  - Redirect pattern micro-optimization (review-lead ADVISORY-1 non-blocking).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
mvschwarzandClaude Opus 4.7 committed 2026-05-06 12:51:14 -07:00
1 parent 87f81553d9
commit a69275805d
4 files changed
+28 -15

No files matched your search

+7 -5
View File
@@ -262,10 +262,12 @@ function Rail({
data-testid="app-rail"
aria-label="Primary navigation"
className={cn(
"bg-background border-stone-900 flex shrink-0",
// V1 border weight doctrine (universal-shell.md L39–L48):
// 1px outline-variant ghost line for inter-region edges.
"bg-background border-outline-variant flex shrink-0",
vertical
? "w-12 flex-col items-center border-r-2 py-2 gap-1"
: "w-full flex-row items-center border-b-2 px-2 gap-1 overflow-x-auto",
? "w-12 flex-col items-center border-r py-2 gap-1"
: "w-full flex-row items-center border-b px-2 gap-1 overflow-x-auto",
)}
>
<div
@@ -398,7 +400,7 @@ export function AppShell({ children }: AppShellProps) {
stay visible everywhere. */}
<header
data-testid="app-topbar"
className="h-14 flex items-center justify-between px-4 bg-background border-b-2 border-stone-900 shrink-0 relative z-30"
className="h-14 flex items-center justify-between px-4 bg-background border-b border-outline-variant shrink-0 relative z-30"
>
<div className="flex items-center gap-3">
<button
@@ -458,7 +460,7 @@ export function AppShell({ children }: AppShellProps) {
<div
data-testid="mobile-rail-tray"
className={cn(
"fixed top-14 left-0 bottom-0 z-30 bg-background border-r-2 border-stone-900 transition-transform duration-200 ease-tactical lg:hidden",
"fixed top-14 left-0 bottom-0 z-30 bg-background border-r border-outline-variant transition-transform duration-200 ease-tactical lg:hidden",
"w-72 max-w-[85vw] flex flex-col",
explorerOpen ? "translate-x-0" : "-translate-x-full",
)}
+3 -1
View File
@@ -571,7 +571,9 @@ export function Explorer({
data-testid="explorer"
data-surface={surface}
className={cn(
"border-r border-stone-300/25 flex z-20 overflow-hidden",
// V1 border weight doctrine (universal-shell.md L39–L48):
// 1px outline-variant ghost line for inter-region edges.
"border-r border-outline-variant flex z-20 overflow-hidden",
"bg-[rgba(250,249,245,0.035)] supports-[backdrop-filter]:bg-[rgba(250,249,245,0.018)] backdrop-blur-[14px] backdrop-saturate-75 shadow-[6px_0_14px_rgba(46,52,46,0.04)]",
// Mobile: slide-over from left below the top-bar header (h-14).
"fixed top-14 bottom-0 left-0 transition-transform duration-200 ease-tactical w-72 max-w-[80vw]",
+10 -3
View File
@@ -14,13 +14,20 @@ export interface VellumSheetProps extends React.HTMLAttributes<HTMLDivElement> {
}
const widthClass: Record<VellumSheetWidth, string> = {
wide: "w-full lg:w-[45rem] lg:max-w-[80vw]",
// V1 calibration 2026-05-06 (universal-shell.md L36 + content-drawer.md L9):
// 38rem (~608px) = iPad-portrait reading width. Wide enough for markdown /
// spec docs, narrow enough to keep center workspace visible behind it.
// Original spec was 45rem; calibrated after founder walk.
wide: "w-full lg:w-[38rem] lg:max-w-[80vw]",
narrow: "w-full lg:w-[22rem] lg:max-w-[60vw]",
};
const edgeClass: Record<VellumSheetEdge, string> = {
left: "border-r-2 border-stone-900",
right: "border-l-2 border-stone-900",
// V1 border weight doctrine (universal-shell.md L39–L48):
// 1px outline-variant ghost line for inter-region edges. NO 2px stone-900
// (which reads as "boxed UI"; tactical-dossier wants paper-layered).
left: "border-r border-outline-variant",
right: "border-l border-outline-variant",
};
export function VellumSheet({
+8 -6
View File
@@ -18,10 +18,10 @@ describe("VellumSheet (Phase 1 primitive)", () => {
expect(el.className).toContain("vellum-heavy");
});
it("default width=wide applies the wide width class", () => {
it("default width=wide applies the wide width class (38rem ~608px iPad-portrait)", () => {
const { container } = render(<VellumSheet testId="vs-w">x</VellumSheet>);
const el = container.querySelector("[data-testid='vs-w']") as HTMLElement;
expect(el.className).toContain("lg:w-[45rem]");
expect(el.className).toContain("lg:w-[38rem]");
expect(el.className).toContain("lg:max-w-[80vw]");
});
@@ -33,18 +33,20 @@ describe("VellumSheet (Phase 1 primitive)", () => {
expect(el.className).toContain("lg:w-[22rem]");
});
it("edge=right (default) places left border", () => {
it("edge=right (default) places left border (1px outline-variant per border weight doctrine)", () => {
const { container } = render(<VellumSheet testId="vs-r">x</VellumSheet>);
const el = container.querySelector("[data-testid='vs-r']") as HTMLElement;
expect(el.className).toContain("border-l-2");
expect(el.className).toContain("border-l");
expect(el.className).toContain("border-outline-variant");
});
it("edge=left places right border", () => {
it("edge=left places right border (1px outline-variant per border weight doctrine)", () => {
const { container } = render(
<VellumSheet edge="left" testId="vs-l">x</VellumSheet>,
);
const el = container.querySelector("[data-testid='vs-l']") as HTMLElement;
expect(el.className).toContain("border-r-2");
expect(el.className).toContain("border-r");
expect(el.className).toContain("border-outline-variant");
});
it("renders close button when onClose provided; clicking calls handler", () => {