replace symbol grid in card window sidebar with a compact symbol picker
The card window sidebar's Style section embedded StyleEditorView symbols-only (showsBackground: false, showsSymbols: true), drawing the curated grid whole inside the sidebar's own scroll view — a permanently open 5-7 row grid ahead of every other section. Replace it with the reusable compact SymbolPicker (already used by BoardInfoPopover for the board's glyph): a single well at rest, the grid only inside its own popover. - CardStyleSection no longer instantiates StyleEditorView at all. A new "Symbol" row mirrors the existing "Background" row's inspector shape (caption leading, control trailing), wiring SymbolPicker's onSelect/ onSelectColor to icon/iconColor through StyleCommand.apply(...on: undo), the exact funnel the background combo already rides — so the card window's undo session semantics (13-native-undo.md) are unchanged. - The picker is fed CuratedSymbols.available rather than its own smaller general-purpose default, so a card's curated vocabulary doesn't shrink. - StyleEditorLayout.sidebar and showsBackground stay in StyleEditor.swift (still correct, still tested) rather than being cut as dead code — a separate, larger cleanup this card doesn't make (recorded on the card). - DESIGN/03-board-ui.md and DESIGN/05-card-window.md: updated the sentences describing the sidebar hosting the style editor's symbol grid to describe the compact picker instead. - Tests: CardSessionUndoTests gains a symbol/tint analogue of the existing background-combo session-routing test; CardSidebarTests gains a curated-set tripwire and an updated file-header note. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -11,11 +11,16 @@ import Testing
|
||||
/// - **Details** shows frontmatter the app deliberately does not understand, so nothing downstream
|
||||
/// can notice when a key goes missing, arrives out of order, or renders as a YAML indicator. The
|
||||
/// only check on it is a test that reads a file and says what the rows must be.
|
||||
/// - **Style** embeds a shared, selection-aware component in a window that has no selection. An
|
||||
/// anchor wired to the wrong target would look completely normal until it restyled something else.
|
||||
/// - **Style** pins its own target — this window's card, always, never the selection-aware target the
|
||||
/// Style… popover carries — and (2026-08-08) hands the compact `SymbolPicker` the kanban-relevant
|
||||
/// `CuratedSymbols` set rather than the picker's own smaller general-purpose default. A target wired
|
||||
/// to the wrong card, or a curated list quietly narrowed back to the picker's default, would look
|
||||
/// completely normal until it restyled the wrong card or hid a symbol the vocabulary used to offer.
|
||||
/// - **The sidebar's geometry** is a grid of fixed-size wells in a column sized from font metrics:
|
||||
/// at the wrong column count the last well in each row is simply unreachable, at no text size
|
||||
/// anyone tests by eye.
|
||||
/// anyone tests by eye. (The `StyleEditorLayout.sidebar` variant below now describes geometry no
|
||||
/// view in the app currently requests — the Style section's grid moved into `SymbolPicker`'s own
|
||||
/// popover on 2026-08-08 — but the pure function is still correct and still worth pinning.)
|
||||
|
||||
// MARK: - Details ▸ which keys
|
||||
|
||||
@@ -328,6 +333,21 @@ struct CardStyleAnchorTests {
|
||||
let upper = ItemID(rawValue: Ident.card1.uppercased())
|
||||
#expect(CardStyleSection.target(forCard: lower) == CardStyleSection.target(forCard: upper))
|
||||
}
|
||||
|
||||
/// **The sidebar's `SymbolPicker` is fed `CuratedSymbols.available`, not the picker's own
|
||||
/// smaller default** — the design ruling behind the 2026-08-08 grid-to-picker swap ("so a card's
|
||||
/// curated vocabulary doesn't shrink"). Not a test *of* the view (this file's own stance), but of
|
||||
/// the two catalogs the ruling is a claim about: if `CuratedSymbols` ever shrank to
|
||||
/// `SymbolPickerCatalog.defaultSet`'s size or below, the sidebar's explicit `symbols:` argument
|
||||
/// would have quietly become a no-op, and this is the tripwire for that.
|
||||
@Test("The card sidebar's curated symbol vocabulary is at least as wide as the picker's own default")
|
||||
func theCuratedSetPassedToTheSidebarPickerDoesNotShrinkIt() {
|
||||
#expect(CuratedSymbols.available.count > SymbolPickerCatalog.defaultSet.count)
|
||||
// And it is still the same *available* set every other curated surface reads — filtered
|
||||
// through `ItemSymbol.exists` (`CuratedSymbols.available`'s own doc comment), never the
|
||||
// unfiltered `all`, so the sidebar never offers a well this Mac cannot draw.
|
||||
#expect(CuratedSymbols.available.allSatisfy(ItemSymbol.exists))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Style ▸ the anchor's geometry
|
||||
|
||||
Reference in New Issue
Block a user