Remove the lane header's "+" new-card control

The lane header no longer draws a new-card button. Every other
creation path is untouched: File > New Card (Cmd-N), Return on a
selected lane, and double-click on lane empty space.

- LaneView: drop the button and its overlay slot, leaving the
  collapse chevron as the header's one piece of trailing chrome.
- NewCardTarget: drop the button's click-names-target carve-out over
  the Cmd-N target rule (Return on a selected lane is now the only
  direct-target path left).
- AccessibilityPhrases: drop the button's spoken label.
- BoardMetrics: drop its width reserve; laneHeaderTrailingReserve now
  reduces to the collapse chevron's own reserve.
- DESIGN/03, 04, 10, 11: update the lane title-bar inventory, the
  Cmd-N override clause and search-clearing mechanism list, the
  accessibility tree-shape sentence, and the pointer-grammar row that
  described the button.
- Tests: drop the two pinned accessibility-label tests and the
  newCardButtonReserve assertions; retarget the truncation-headroom
  test at the now-solo laneHeaderTrailingReserve; fix stale doc-quote
  comments and the manual accessibility-verification checklist.

Full KanbanTests suite: 2807 tests, 482 suites, all passing.

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
2026-08-08 23:28:05 -04:00
parent b09c4bd5c0
commit eb950ee881
16 changed files with 76 additions and 126 deletions
+14 -13
View File
@@ -39,12 +39,12 @@ struct BoardMetricsSettledFiguresTests {
#expect(BoardMetrics.laneStackSpacing(bodyPointSize: size) == 8)
#expect(BoardMetrics.laneHeaderSpacing(bodyPointSize: size) == 6)
#expect(BoardMetrics.laneAccentBandHeight(bodyPointSize: size) == 5)
#expect(BoardMetrics.newCardButtonReserve(bodyPointSize: size) == 22)
// The fold's two figures (03-board-ui.md § Lane Collapsed lanes): the strip is the ruling's
// ~44pt, and the chevron's reserve is 18 together the header's 40pt trailing budget.
// The fold's own figure (03-board-ui.md § Lane Collapsed lanes): the strip is the ruling's
// ~44pt, and the chevron's reserve is 18 which is also the header's whole trailing budget
// now that the new-card button that once shared it is gone (m-remove-header-add).
#expect(BoardMetrics.collapsedLaneWidth(bodyPointSize: size) == 44)
#expect(BoardMetrics.laneCollapseButtonReserve(bodyPointSize: size) == 18)
#expect(BoardMetrics.laneHeaderTrailingReserve(bodyPointSize: size) == 40)
#expect(BoardMetrics.laneHeaderTrailingReserve(bodyPointSize: size) == 18)
#expect(BoardMetrics.cardCornerRadius(bodyPointSize: size) == 8)
#expect(BoardMetrics.cardStripeWidth(bodyPointSize: size) == 4)
#expect(BoardMetrics.cardContentPadding(bodyPointSize: size) == 10)
@@ -95,7 +95,6 @@ struct BoardMetricsScalingTests {
("laneHeaderSpacing", { BoardMetrics.laneHeaderSpacing(bodyPointSize: $0) }),
("laneHeaderInset", { BoardMetrics.laneHeaderInset(bodyPointSize: $0) }),
("laneAccentBandHeight", { BoardMetrics.laneAccentBandHeight(bodyPointSize: $0) }),
("newCardButtonReserve", { BoardMetrics.newCardButtonReserve(bodyPointSize: $0) }),
("collapsedLaneWidth", { BoardMetrics.collapsedLaneWidth(bodyPointSize: $0) }),
("laneCollapseButtonReserve", { BoardMetrics.laneCollapseButtonReserve(bodyPointSize: $0) }),
("laneHeaderTrailingReserve", { BoardMetrics.laneHeaderTrailingReserve(bodyPointSize: $0) }),
@@ -122,19 +121,21 @@ struct BoardMetricsScalingTests {
}
}
/// **The new-card button's reserve stays ahead of the header's own furniture.**
/// **The header's trailing reserve stays ahead of the header's own furniture.**
///
/// 03-board-ui.md's graceful-truncation rule says a long lane title truncates rather than
/// colliding with the button, and the reserve is what makes that true. It has to stay wider than
/// a glyph-and-margin at every size, which is the fixed-22pt failure this conversion exists to
/// remove: at 24pt the glyph alone approaches the old reserve.
@Test("The header's button reserve stays wider than the glyph it reserves for")
func theButtonReserveOutgrowsItsGlyph() {
/// colliding with the collapse chevron, and the reserve is what makes that true. It has to stay
/// wider than a glyph-and-margin at every size, which is the fixed-point-size failure this
/// conversion exists to remove: at 24pt the glyph alone approaches a stale fixed reserve. (Once
/// the sum of two glyphs' room the new-card button and the chevron this is now the chevron's
/// alone, the button having been removed.)
@Test("The header's trailing reserve stays wider than the glyph it reserves for")
func theTrailingReserveOutgrowsItsGlyph() {
for size in Self.sizes {
#expect(BoardMetrics.newCardButtonReserve(bodyPointSize: size) > size,
#expect(BoardMetrics.laneHeaderTrailingReserve(bodyPointSize: size) > size,
"the reserve is narrower than one em at \(size)pt")
#expect(
BoardMetrics.newCardButtonReserve(bodyPointSize: size)
BoardMetrics.laneHeaderTrailingReserve(bodyPointSize: size)
> BoardMetrics.laneHeaderSpacing(bodyPointSize: size),
"the reserve is narrower than the header's own spacing at \(size)pt"
)