chain table round 3: waypoints icons gone + the alignment staircase (owner refinements)
- chain rows lose the WaypointsIcon (owner: not needed — the chips + connectors already read as chains); folders keep their icons. - THE ALIGNMENT STAIRCASE: every level's checkbox sits directly under its parent's expander arrow. The expander now shares the checkbox's 14px width (h-5 w-3.5), making each nesting step exactly 18px — clusters pl-3 (12px) → chains pl-7.5 (30px, the cluster expander) → statements pl-12 (48px, the chain expander). Live-measured: 318=318, 336=336.
This commit is contained in:
+22
-14
@@ -25,10 +25,20 @@
|
|||||||
* the → a clearly separated connector between chips — a lonely chip
|
* the → a clearly separated connector between chips — a lonely chip
|
||||||
* reads as a standalone proposition (the "(no premises)" annotation is
|
* reads as a standalone proposition (the "(no premises)" annotation is
|
||||||
* dead in the visible UI; it survives only as the row's aria-label).
|
* dead in the visible UI; it survives only as the row's aria-label).
|
||||||
* Icons: clusters FolderIcon (open when expanded), chains WaypointsIcon,
|
* Icons: ONLY the cluster FolderIcon survives (owner ruling, evening
|
||||||
* propositions chip-only. Chevrons rotate with expansion. Statement rows
|
* round 3: the chain waypoints icons are not needed — the chips +
|
||||||
* show propositions PLAIN (owner ruling: the derivation is already
|
* connectors already read as chains); propositions chip-only. Chevrons
|
||||||
* encoded in the chain line — no conclusion marker down there).
|
* rotate with expansion. Statement rows show propositions PLAIN (owner
|
||||||
|
* ruling: the derivation is already encoded in the chain line — no
|
||||||
|
* conclusion marker down there).
|
||||||
|
*
|
||||||
|
* THE ALIGNMENT STAIRCASE (owner ruling, round 3): every level's
|
||||||
|
* checkbox sits DIRECTLY UNDER its parent's expander arrow — open a
|
||||||
|
* folder and the chain checkboxes line up with the arrow, same one
|
||||||
|
* level down. Geometry: the expander shares the checkbox's 14px width
|
||||||
|
* (h-5 w-3.5), so each nesting step is exactly checkbox(14) + gap(4) =
|
||||||
|
* 18px — clusters pl-3 (12px, checkbox at 12), chains pl-7.5 (30px =
|
||||||
|
* the cluster expander), statements pl-12 (48px = the chain expander).
|
||||||
*
|
*
|
||||||
* SORTING: all three columns sortable (owner ruling — "consistency is
|
* SORTING: all three columns sortable (owner ruling — "consistency is
|
||||||
* key"): Name (A→Z), Props (largest-first), Created (newest-first);
|
* key"): Name (A→Z), Props (largest-first), Created (newest-first);
|
||||||
@@ -58,7 +68,6 @@ import {
|
|||||||
FolderOpenIcon,
|
FolderOpenIcon,
|
||||||
ListTreeIcon,
|
ListTreeIcon,
|
||||||
SearchIcon,
|
SearchIcon,
|
||||||
WaypointsIcon,
|
|
||||||
XIcon,
|
XIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { chainsForSelection, formatChainLine, fuzzyScore } from "@/src/core";
|
import { chainsForSelection, formatChainLine, fuzzyScore } from "@/src/core";
|
||||||
@@ -255,9 +264,11 @@ export function ChainTableBody({
|
|||||||
</TopBar>
|
</TopBar>
|
||||||
|
|
||||||
{/* The list: NO per-row lines (owner ruling) — the ONLY horizontal
|
{/* The list: NO per-row lines (owner ruling) — the ONLY horizontal
|
||||||
separators sit between cluster groups; PROMINENT indentation
|
separators sit between cluster groups; the ALIGNMENT STAIRCASE
|
||||||
carries the hierarchy (clusters → chains pl-11 → statements
|
carries the hierarchy (owner round 3: each level's checkbox sits
|
||||||
pl-[4.75rem]). All three columns sort, small chevron on active. */}
|
under its parent's expander arrow — clusters pl-3, chains pl-7.5
|
||||||
|
under the folder arrow, statements pl-12 under the chain arrow).
|
||||||
|
All three columns sort, small chevron on active. */}
|
||||||
<div className="min-h-0 flex-1 overflow-y-auto">
|
<div className="min-h-0 flex-1 overflow-y-auto">
|
||||||
<div className="sticky top-0 z-10 flex items-center gap-1 px-3 py-1.5 text-[11px] uppercase tracking-widest text-muted-foreground/70 backdrop-blur">
|
<div className="sticky top-0 z-10 flex items-center gap-1 px-3 py-1.5 text-[11px] uppercase tracking-widest text-muted-foreground/70 backdrop-blur">
|
||||||
<button
|
<button
|
||||||
@@ -344,7 +355,7 @@ export function ChainTableBody({
|
|||||||
<div
|
<div
|
||||||
data-testid={`chain-row-${chain.id}`}
|
data-testid={`chain-row-${chain.id}`}
|
||||||
aria-label={formatChainLine(chain, Object.fromEntries([...byId.entries()].map(([id, n]) => [id, { name: n.name }])))}
|
aria-label={formatChainLine(chain, Object.fromEntries([...byId.entries()].map(([id, n]) => [id, { name: n.name }])))}
|
||||||
className="flex items-center gap-1 py-1 pl-11 pr-3"
|
className="flex items-center gap-1 py-1 pl-7.5 pr-3"
|
||||||
>
|
>
|
||||||
<RowCheckbox
|
<RowCheckbox
|
||||||
checked={selectedInChain === memberIds.length && memberIds.length > 0}
|
checked={selectedInChain === memberIds.length && memberIds.length > 0}
|
||||||
@@ -354,9 +365,6 @@ export function ChainTableBody({
|
|||||||
label={`Select chain ${nameOf(chain.conclusion)}`}
|
label={`Select chain ${nameOf(chain.conclusion)}`}
|
||||||
/>
|
/>
|
||||||
<Expander open={chainOpen} onClick={() => onToggleChain(chain.id)} testid={`chain-toggle-${chain.id}`} label={`Expand chain ${nameOf(chain.conclusion)}`} />
|
<Expander open={chainOpen} onClick={() => onToggleChain(chain.id)} testid={`chain-toggle-${chain.id}`} label={`Expand chain ${nameOf(chain.conclusion)}`} />
|
||||||
<span className="flex shrink-0 items-center justify-center text-muted-foreground">
|
|
||||||
<WaypointsIcon className="size-3.5" />
|
|
||||||
</span>
|
|
||||||
{/* The chain line: proposition names as faint-outlined
|
{/* The chain line: proposition names as faint-outlined
|
||||||
chips, → the connector BETWEEN them (owner ruling) — a
|
chips, → the connector BETWEEN them (owner ruling) — a
|
||||||
lonely chip reads as a standalone proposition. */}
|
lonely chip reads as a standalone proposition. */}
|
||||||
@@ -394,7 +402,7 @@ export function ChainTableBody({
|
|||||||
<div
|
<div
|
||||||
key={id}
|
key={id}
|
||||||
data-testid={`prop-row-${id}`}
|
data-testid={`prop-row-${id}`}
|
||||||
className="flex items-start gap-2 py-1 pl-[4.75rem] pr-3"
|
className="flex items-start gap-2 py-1 pl-12 pr-3"
|
||||||
>
|
>
|
||||||
<RowCheckbox
|
<RowCheckbox
|
||||||
checked={selection.has(id)}
|
checked={selection.has(id)}
|
||||||
@@ -464,7 +472,7 @@ function Expander({ open, onClick, testid, label }: { open: boolean; onClick: ()
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
aria-expanded={open}
|
aria-expanded={open}
|
||||||
className="flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground/70 transition-colors hover:bg-accent hover:text-foreground"
|
className="flex h-5 w-3.5 shrink-0 items-center justify-center rounded text-muted-foreground/70 transition-colors hover:bg-accent hover:text-foreground"
|
||||||
>
|
>
|
||||||
<ChevronRightIcon className={`size-3.5 transition-transform ${open ? "rotate-90" : ""}`} />
|
<ChevronRightIcon className={`size-3.5 transition-transform ${open ? "rotate-90" : ""}`} />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
import "./.next/types/routes.d.ts";
|
import "./.next/dev/types/routes.d.ts";
|
||||||
import "./.next/types/root-params.d.ts";
|
import "./.next/dev/types/root-params.d.ts";
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|||||||
@@ -139,9 +139,9 @@ describe("ChainTableBody — THE shared TopBar + the lines law (owner, round 2)"
|
|||||||
const sep = html.split("border-b border-border/60").length - 1;
|
const sep = html.split("border-b border-border/60").length - 1;
|
||||||
assert.ok(sep >= 2, "separators between groups");
|
assert.ok(sep >= 2, "separators between groups");
|
||||||
// chain rows themselves carry NO border — their entire class list is
|
// chain rows themselves carry NO border — their entire class list is
|
||||||
// the indent law (pl-11 under the cluster folder, owner round 2); the
|
// the staircase law (pl-7.5 = under the cluster's expander arrow);
|
||||||
// chip outlines' border-border/70 is an outline, not a row line
|
// the chip outlines' border-border/70 is an outline, not a row line
|
||||||
assert.ok(html.includes('class="flex items-center gap-1 py-1 pl-11 pr-3"'), "the chain row: indent, no border");
|
assert.ok(html.includes('class="flex items-center gap-1 py-1 pl-7.5 pr-3"'), "the chain row: staircase indent, no border");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -154,7 +154,9 @@ describe("ChainTableBody — chain rows (chips + connectors)", () => {
|
|||||||
assert.ok(html.includes("Premise one"), "chip text");
|
assert.ok(html.includes("Premise one"), "chip text");
|
||||||
assert.ok(html.includes('data-testid="chain-arrow-c1-1"'), "the connector");
|
assert.ok(html.includes('data-testid="chain-arrow-c1-1"'), "the connector");
|
||||||
assert.ok(html.includes("→"), "the arrow glyph");
|
assert.ok(html.includes("→"), "the arrow glyph");
|
||||||
assert.ok(html.includes("lucide-waypoints"), "the chain icon");
|
// owner ruling (round 3): the chain waypoints icons are GONE — the
|
||||||
|
// chips + connectors already read as chains; only folders keep icons
|
||||||
|
assert.ok(!html.includes("lucide-waypoints"), "no chain icon");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("a singleton renders ONE lonely chip, no connector; the annotation survives only for screen readers", () => {
|
it("a singleton renders ONE lonely chip, no connector; the annotation survives only for screen readers", () => {
|
||||||
@@ -184,9 +186,14 @@ describe("ChainTableBody — chain rows (chips + connectors)", () => {
|
|||||||
// owner ruling: the derivation is already encoded in the chain line —
|
// owner ruling: the derivation is already encoded in the chain line —
|
||||||
// no conclusion marker down here
|
// no conclusion marker down here
|
||||||
assert.ok(!html.includes("prop-conclusion"), "no conclusion marker anywhere");
|
assert.ok(!html.includes("prop-conclusion"), "no conclusion marker anywhere");
|
||||||
// statements indent DEEPEST (pl-[4.75rem]); chains pl-11 under clusters
|
// THE ALIGNMENT STAIRCASE (owner ruling, round 3): each level's
|
||||||
assert.ok(html.includes("pl-[4.75rem]"), "the deepest indent");
|
// checkbox sits under its parent's expander arrow. The expander
|
||||||
assert.ok(html.includes("pl-11"), "the chain indent");
|
// shares the checkbox's 14px width, so each step is 18px: clusters
|
||||||
|
// pl-3 (12) → chains pl-7.5 (30 = the cluster expander) →
|
||||||
|
// statements pl-12 (48 = the chain expander)
|
||||||
|
assert.ok(html.includes("pl-12"), "statements under the chain's expander");
|
||||||
|
assert.ok(html.includes("pl-7.5"), "chains under the cluster's expander");
|
||||||
|
assert.ok(html.includes("h-5 w-3.5"), "the expander shares the checkbox's 14px width");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user