The lane plate's strays return to their anchors — the replica's wash leaves the height arithmetic it broke
The pathfinder surface stack landed in e1ffe71 entangled with staged-index
placement drift: the replica's wash block sat inside replicaHeight (a CGFloat
has no .background — HEAD did not build), the body plate rode outside the cut
dim, the lanePlate property and the DESIGN bullet sat away from their kin.
Pure relocation, no new lines: every block moves to the anchor it was written
for. Verified by an isolated build of this tree.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -33,8 +33,8 @@ Toolbars are **pure enhancement**: every function they host already has a menu i
|
||||
### Capabilities (settled)
|
||||
|
||||
- **`background`** on board / lane / card: palette name (kebab-case, hand-editable) or `#RRGGBB[AA]` hex. Board color paints the board window's content background (the surface behind and between lanes). Lane and card color are **edge accents, not fills** (settled in the pathfinder's treatment shootout — its settings matrix of C-series lane / K-series card variants landed on **C7 · full-column top edge** and **K1 · left edge stripe**): a lane's color paints a full-width band along its top edge, a card's a stripe along its left edge; the surfaces themselves keep the standard chrome, so colored title text never sits on a colored fill.
|
||||
- **`icon`**: SF Symbol per item with per-level defaults (board `rectangle.split.3x1`, lane `square.stack`, card `doc.text`).
|
||||
- **The standard chrome is the pathfinder's surface stack** (settled 2026-08-06): the window keeps the neutral system background; every lane wears a quiet quaternary-wash plate (the trash plate's own figure — translucent, so a board-chosen color shows through and the board-level ink rule keeps its premise; opaque under Reduce Transparency, the trash precedent); every card sits on an opaque `controlBackgroundColor` plate — white over the washed lane in light appearance, a step *darker* than the window in dark. One plate value for every face a card draws (resting, replicas, placeholder, arriving), so a card is the same object wherever it renders.
|
||||
- **`icon`**: SF Symbol per item with per-level defaults (board `rectangle.split.3x1`, lane `square.stack`, card `doc.text`).
|
||||
- **`iconColor`**: resolved — **schema yes, control no**. The field renders when hand-written (tint palette name or hex); the app offers no control for it (Controls below).
|
||||
- The pathfinder's palettes (12 icon tints, 12 backgrounds) carry over as the starting point. **The 12+12 split is a picker split, not a name split** (settled): color resolution searches foregrounds then backgrounds, so a hand-written `background: carnation` (an icon-tint name) resolves and paints — the split governs what the grids offer, never what a name means.
|
||||
|
||||
|
||||
@@ -166,15 +166,15 @@ struct LaneView: View, Equatable {
|
||||
.padding(BoardMetrics.lanePlatePadding(bodyPointSize: pointSize))
|
||||
}
|
||||
.background(selectionBackground)
|
||||
// Behind the selection wash, not composed into it: the plate is the lane's resting
|
||||
// surface, the wash above it is the selection's own layer, and stacked `.background`s
|
||||
// put the later one further back.
|
||||
.background(lanePlate)
|
||||
.overlay(selectionStroke)
|
||||
// The deferred cut's dim (04-interactions.md ▸ Clipboard) — on the whole lane, because a cut
|
||||
// lane is cut cards and all.
|
||||
.cutTreatment(of: lane.id, in: store)
|
||||
.onGeometryChange(for: CGFloat.self) { $0.size.height } action: { measuredHeight = $0 }
|
||||
// Behind the selection wash, not composed into it: the plate is the lane's resting
|
||||
// surface, the wash above it is the selection's own layer, and stacked `.background`s
|
||||
// put the later one further back.
|
||||
.background(lanePlate)
|
||||
// **This lane's drop target**, on the whole body. It accepts *every* session type and routes
|
||||
// internally — card sessions against this lane's masonry zones, lane sessions forwarded to
|
||||
// the strip's logic, external Finder file sessions against those same zones — because
|
||||
@@ -657,6 +657,10 @@ struct LaneView: View, Equatable {
|
||||
.padding(BoardMetrics.lanePlatePadding(bodyPointSize: pointSize))
|
||||
}
|
||||
.frame(width: replicaWidth, height: replicaHeight, alignment: .topLeading)
|
||||
// The lane's own wash over an opaque base — the replica floats over whatever the cursor is
|
||||
// above, so unlike the resting lane it cannot let the wash composite against the board; the
|
||||
// opaque `.background` behind it stands in for the window's neutral surface.
|
||||
.background(lanePlate)
|
||||
.background(RoundedRectangle(cornerRadius: cornerRadius).fill(.background))
|
||||
.clipShape(RoundedRectangle(cornerRadius: cornerRadius))
|
||||
.dragReplicaShadow()
|
||||
@@ -672,10 +676,6 @@ struct LaneView: View, Equatable {
|
||||
|
||||
private var replicaHeight: CGFloat {
|
||||
max(measuredHeight, BoardMetrics.laneReplicaMinimumHeight(bodyPointSize: pointSize))
|
||||
// The lane's own wash over an opaque base — the replica floats over whatever the cursor is
|
||||
// above, so unlike the resting lane it cannot let the wash composite against the board; the
|
||||
// opaque `.background` behind it stands in for the window's neutral surface.
|
||||
.background(lanePlate)
|
||||
}
|
||||
|
||||
/// Where the title bar sits inside the replica — its **centre**, measured down from the replica's
|
||||
@@ -978,6 +978,16 @@ struct LaneView: View, Equatable {
|
||||
store.selection.container == .board && store.selection.ids.contains(lane.id)
|
||||
}
|
||||
|
||||
/// The lane's resting plate — the standard chrome's middle step (03-board-ui.md § Styling ▸
|
||||
/// Capabilities: window, washed lane, opaque card), the same quaternary wash the trash column
|
||||
/// wears (`Accommodations.lanePlateWash`). Translucent deliberately: a board-chosen colour
|
||||
/// shows through, so the header ink computed against the board's background (`headerInk`)
|
||||
/// keeps its premise on a painted board.
|
||||
private var lanePlate: some View {
|
||||
RoundedRectangle(cornerRadius: cornerRadius)
|
||||
.fill(Accommodations.lanePlateWash(reduceTransparency: reduceTransparency).style)
|
||||
}
|
||||
|
||||
/// The selection treatment: a subtle whole-lane accent wash and stroke. Deliberately quiet —
|
||||
/// 03-board-ui.md gives lane *colour* to the top-edge accent band, so selection must not read as
|
||||
/// a fill that would compete with it once that lands.
|
||||
@@ -997,16 +1007,6 @@ struct LaneView: View, Equatable {
|
||||
.strokeBorder(plateStroke, lineWidth: plateStrokeWidth)
|
||||
}
|
||||
|
||||
/// The lane's resting plate — the standard chrome's middle step (03-board-ui.md § Styling ▸
|
||||
/// Capabilities: window, washed lane, opaque card), the same quaternary wash the trash column
|
||||
/// wears (`Accommodations.lanePlateWash`). Translucent deliberately: a board-chosen colour
|
||||
/// shows through, so the header ink computed against the board's background (`headerInk`)
|
||||
/// keeps its premise on a painted board.
|
||||
private var lanePlate: some View {
|
||||
RoundedRectangle(cornerRadius: cornerRadius)
|
||||
.fill(Accommodations.lanePlateWash(reduceTransparency: reduceTransparency).style)
|
||||
}
|
||||
|
||||
private var plateStroke: AnyShapeStyle {
|
||||
if isSelected {
|
||||
AnyShapeStyle(Color.accentColor)
|
||||
|
||||
Reference in New Issue
Block a user