The board's symbol takes a tint — a 4×2 colour row under the picker's glyphs, and the glyph itself moves into the titlebar
iconColor stops being hand-written-only (user-ruled, superseding 03's "schema yes, control no"): it rides StyleCommand.apply → applyStyle as the third styled dimension — per-dimension no-op skip, one bracket, one history step, ExpectedField.iconColor for staleness. The SymbolPicker grows an opt-in colour row (leading None plus seven Palette.foregrounds hues, None removes the key); the board popover is its one caller. The window-title widget now draws the board's resolved glyph in that tint beside the name. Doc realignment filed on the Redesign board (Minor). Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -1698,8 +1698,8 @@ public final class BoardStore: HealHost {
|
||||
|
||||
// MARK: - Styling
|
||||
|
||||
/// One item a style gesture is about to act on: where its `index.md` is, and what the two styled
|
||||
/// keys currently say there.
|
||||
/// One item a style gesture is about to act on: where its `index.md` is, and what the three
|
||||
/// styled keys currently say there.
|
||||
///
|
||||
/// The editor reads these for its per-dimension current-value display (`StyleFieldState.resolve`)
|
||||
/// and `applyStyle` reads the *same* values to decide what is a no-op, so the display and the
|
||||
@@ -1710,6 +1710,7 @@ public final class BoardStore: HealHost {
|
||||
public let folder: URL
|
||||
public let background: FieldValue<String>
|
||||
public let icon: FieldValue<String>
|
||||
public let iconColor: FieldValue<String>
|
||||
}
|
||||
|
||||
/// The live items `target` names, in display order — lanes left to right, each lane's cards top
|
||||
@@ -1727,7 +1728,8 @@ public final class BoardStore: HealHost {
|
||||
id: nil,
|
||||
folder: rootURL,
|
||||
background: snapshot.background,
|
||||
icon: snapshot.icon
|
||||
icon: snapshot.icon,
|
||||
iconColor: snapshot.iconColor
|
||||
)]
|
||||
|
||||
case let .items(ids):
|
||||
@@ -1739,7 +1741,8 @@ public final class BoardStore: HealHost {
|
||||
id: lane.id,
|
||||
folder: laneFolder,
|
||||
background: lane.background,
|
||||
icon: lane.icon
|
||||
icon: lane.icon,
|
||||
iconColor: lane.iconColor
|
||||
))
|
||||
}
|
||||
for card in lane.cards where ids.contains(card.id) {
|
||||
@@ -1747,7 +1750,8 @@ public final class BoardStore: HealHost {
|
||||
id: card.id,
|
||||
folder: laneFolder.appendingPathComponent(card.id.rawValue),
|
||||
background: card.background,
|
||||
icon: card.icon
|
||||
icon: card.icon,
|
||||
iconColor: card.iconColor
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -1790,9 +1794,10 @@ public final class BoardStore: HealHost {
|
||||
/// no-ops is dropped entirely; and a gesture that changes nothing anywhere never opens the
|
||||
/// bracket at all.
|
||||
///
|
||||
/// **`iconColor` is not a parameter, and that is the design**: it is "resolved — schema yes,
|
||||
/// control no" (§ Capabilities). The field renders when hand-written and the app offers no
|
||||
/// control for it, so there is nothing here to pass.
|
||||
/// **`iconColor` joined as the third dimension with the board popover's colour row**
|
||||
/// (2026-08-07). It had been "resolved — schema yes, control no" (§ Capabilities); the symbol
|
||||
/// picker's colour grid is the control that ended that, and it rides this funnel exactly as the
|
||||
/// other two dimensions do — per-dimension no-op skipping, one bracket, one history step.
|
||||
///
|
||||
/// Failure is `performWrite`'s: the banner is posted before the rethrow, which is swallowed here
|
||||
/// like every other gesture with no second thing to do. A batch that fails partway leaves the
|
||||
@@ -1816,6 +1821,7 @@ public final class BoardStore: HealHost {
|
||||
to target: StyleTarget,
|
||||
background: StyleChange = .keep,
|
||||
icon: StyleChange = .keep,
|
||||
iconColor: StyleChange = .keep,
|
||||
on window: CardWindowUndo? = nil
|
||||
) {
|
||||
// A session gesture anchors to the card, everything else to the folder it resolved (above).
|
||||
@@ -1829,13 +1835,16 @@ public final class BoardStore: HealHost {
|
||||
anchor: HistoryAnchor,
|
||||
background: StyleChange,
|
||||
icon: StyleChange,
|
||||
iconColor: StyleChange,
|
||||
priorBackground: FieldValue<String>,
|
||||
priorIcon: FieldValue<String>
|
||||
priorIcon: FieldValue<String>,
|
||||
priorIconColor: FieldValue<String>
|
||||
)] = styleSubjects(of: target)
|
||||
.compactMap { subject in
|
||||
let background = Self.effective(background, against: subject.background)
|
||||
let icon = Self.effective(icon, against: subject.icon)
|
||||
guard background != .keep || icon != .keep else { return nil }
|
||||
let iconColor = Self.effective(iconColor, against: subject.iconColor)
|
||||
guard background != .keep || icon != .keep || iconColor != .keep else { return nil }
|
||||
let anchor: HistoryAnchor = if anchorsByIdentity, let id = subject.id {
|
||||
.card(id)
|
||||
} else {
|
||||
@@ -1847,8 +1856,10 @@ public final class BoardStore: HealHost {
|
||||
anchor: anchor,
|
||||
background: background,
|
||||
icon: icon,
|
||||
iconColor: iconColor,
|
||||
priorBackground: subject.background,
|
||||
priorIcon: subject.icon
|
||||
priorIcon: subject.icon,
|
||||
priorIconColor: subject.iconColor
|
||||
)
|
||||
}
|
||||
guard !edits.isEmpty else { return }
|
||||
@@ -1866,6 +1877,7 @@ public final class BoardStore: HealHost {
|
||||
) { document in
|
||||
Self.apply(edit.background, to: FrontmatterKeys.background, in: &document)
|
||||
Self.apply(edit.icon, to: FrontmatterKeys.icon, in: &document)
|
||||
Self.apply(edit.iconColor, to: FrontmatterKeys.iconColor, in: &document)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1891,14 +1903,20 @@ public final class BoardStore: HealHost {
|
||||
subject: subject,
|
||||
on: window,
|
||||
undoExpects: edits.map {
|
||||
.present($0.anchor, fields: Self.styledFields(background: $0.background, icon: $0.icon))
|
||||
.present($0.anchor, fields: Self.styledFields(
|
||||
background: $0.background,
|
||||
icon: $0.icon,
|
||||
iconColor: $0.iconColor
|
||||
))
|
||||
},
|
||||
redoExpects: edits.map {
|
||||
.present($0.anchor, fields: Self.restoredStyleFields(
|
||||
background: $0.background,
|
||||
priorBackground: $0.priorBackground,
|
||||
icon: $0.icon,
|
||||
priorIcon: $0.priorIcon
|
||||
priorIcon: $0.priorIcon,
|
||||
iconColor: $0.iconColor,
|
||||
priorIconColor: $0.priorIconColor
|
||||
))
|
||||
}
|
||||
) { store in
|
||||
@@ -1910,6 +1928,7 @@ public final class BoardStore: HealHost {
|
||||
) { document in
|
||||
Self.restore(edit.priorBackground, to: FrontmatterKeys.background, in: &document)
|
||||
Self.restore(edit.priorIcon, to: FrontmatterKeys.icon, in: &document)
|
||||
Self.restore(edit.priorIconColor, to: FrontmatterKeys.iconColor, in: &document)
|
||||
}
|
||||
}
|
||||
} redo: { store in
|
||||
@@ -1921,6 +1940,7 @@ public final class BoardStore: HealHost {
|
||||
) { document in
|
||||
Self.apply(edit.background, to: FrontmatterKeys.background, in: &document)
|
||||
Self.apply(edit.icon, to: FrontmatterKeys.icon, in: &document)
|
||||
Self.apply(edit.iconColor, to: FrontmatterKeys.iconColor, in: &document)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user