commit 826437414d77839f2466328f8c4d55f6f21a4f7e
parent 57207100d37d1bf528b9438adf40097942e8cbc5
Author: Michael Camilleri <[email protected]>
Date: Sun, 14 Jun 2026 06:07:03 +0900
Fix fill letters and Clue Bar colour in Dark Mode
In Dark Mode the entered letters disappeared from the grid. The entry
letter drew with the hierarchical primary/secondary label style, which
follows the system appearance and resolves to near-white in Dark Mode.
Puzzle cells are always white regardless of appearance, though, so the
ink rendered white-on-white and the fill vanished. The letter is now
always black — a lighter black for pencil — which is safe because
revealed and checkedWrong state is shown by the corner triangle, not by
recolouring the letter.
The Clue Bar had a related but milder problem. Its background is the
player's colour at the faint author-tint opacity, but unlike the
always-white grid cells the wash composites over the system background;
at 10% over a near-black Dark Mode background the player's hue read as
black rather than, say, blue. A dedicated clueBarFill raises the opacity
in Dark Mode so the colour stays perceptible, while the shared author
tint on grid cells — which only ever sits over white — is left at its
original opacity.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Diffstat:
3 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/Crossmate/Models/PlayerColor.swift b/Crossmate/Models/PlayerColor.swift
@@ -33,6 +33,15 @@ struct PlayerColor: Sendable, Identifiable, Hashable {
/// Fill for UI tied to faint author-attribution tinting.
var authorTintFill: Color { tint.opacity(Self.authorTintOpacity) }
+
+ /// Background wash for the clue bar. The clue bar composites over the
+ /// system background, so unlike the always-white grid cells the wash's
+ /// perceived colour depends on the appearance: at the 10% author-tint
+ /// opacity over a near-black Dark Mode background the hue reads as black.
+ /// Raise the opacity in Dark Mode so the player's colour stays visible.
+ func clueBarFill(dark: Bool) -> Color {
+ tint.opacity(dark ? 0.20 : Self.authorTintOpacity)
+ }
}
extension PlayerColor {
diff --git a/Crossmate/Views/CellView.swift b/Crossmate/Views/CellView.swift
@@ -65,17 +65,19 @@ struct CellView: View, Equatable {
.contentShape(Rectangle())
}
- /// Foreground style for the main entry letter. Pencil entries use the
- /// hierarchical `.secondary` style so they render lighter and respect
- /// dark mode; everything else — including revealed and checkedWrong
- /// cells — uses the primary label colour. Reveal/wrong state is shown
- /// purely via the corner triangle, not by recolouring the letter.
+ /// Foreground style for the main entry letter. The cell fill is always
+ /// white regardless of system appearance, so the letter ink is always
+ /// black — it must not follow Dark Mode or it would vanish against the
+ /// white cell. Pencil entries render as a lighter black; everything else
+ /// — including revealed and checkedWrong cells — uses solid black. Reveal/
+ /// wrong state is shown purely via the corner triangle, not by recolouring
+ /// the letter.
private var entryStyle: AnyShapeStyle {
switch mark {
case .pencil:
- return AnyShapeStyle(HierarchicalShapeStyle.secondary)
+ return AnyShapeStyle(Color.black.opacity(0.5))
case .none, .pen, .revealed:
- return AnyShapeStyle(HierarchicalShapeStyle.primary)
+ return AnyShapeStyle(Color.black)
}
}
diff --git a/Crossmate/Views/PuzzleView.swift b/Crossmate/Views/PuzzleView.swift
@@ -1504,10 +1504,13 @@ private struct ClueBar: View {
@Bindable var session: PlayerSession
let replayClueTarget: ReplayClueTarget?
@Environment(PlayerPreferences.self) private var preferences
+ @Environment(\.colorScheme) private var colorScheme
@State private var slideEdge: Edge = .trailing
@State private var isShowingClueList = false
- private var backgroundColor: Color { preferences.color.authorTintFill }
+ private var backgroundColor: Color {
+ preferences.color.clueBarFill(dark: colorScheme == .dark)
+ }
var body: some View {
let display = replayClueDisplay ?? liveClueDisplay