feat: add the light palette, and the module that resolves a theme
The dark tokens re-struck under `[data-theme="light"]`. Nothing sets that attribute yet, so the app still renders exactly as it did. Two things could not be tokens. Game hues are data — ours and the reader's — and every one was picked against a near-black ground, so `readableHue` darkens them along the same hue until they read on paper, and returns dark untouched by construction. And the attribute has to be on the root before React can mount, or a reader who chose light gets a dark flash on every load, so the shell reads the preference itself. That leaves the ground colour written in three files that cannot import each other, which is what the test pins together. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
adab688e0e
commit
448c70968d
@@ -20,8 +20,14 @@ import { readerInstant, type EventDraft } from "../state/useCustom.ts";
|
||||
* instead of us.
|
||||
*/
|
||||
|
||||
/** Enough hues to tell lanes apart, none of them colliding with a tracked game. */
|
||||
const HUES = [
|
||||
/**
|
||||
* Enough hues to tell lanes apart, none of them colliding with a tracked game.
|
||||
*
|
||||
* Stored raw, as picked. What a light-mode reader sees is a darkened reading of
|
||||
* these (`readableHue`), for the same reason the tracked games get one — the
|
||||
* palette was struck against the dark ground.
|
||||
*/
|
||||
export const CUSTOM_HUES = [
|
||||
"#C74B50",
|
||||
"#E08A3C",
|
||||
"#D9C34A",
|
||||
@@ -52,7 +58,7 @@ export function GameForm({
|
||||
onCancel: () => void;
|
||||
}) {
|
||||
const [name, setName] = useState(initial?.name ?? "");
|
||||
const [hue, setHue] = useState(initial?.hue ?? HUES[0]!);
|
||||
const [hue, setHue] = useState(initial?.hue ?? CUSTOM_HUES[0]!);
|
||||
const valid = name.trim().length > 0 && name.trim().length <= 40;
|
||||
|
||||
return (
|
||||
@@ -77,7 +83,7 @@ export function GameForm({
|
||||
|
||||
<p className={`${labelClass()} mt-3`}>Lane colour</p>
|
||||
<div className="mt-1.5 flex flex-wrap gap-1.5">
|
||||
{HUES.map((h) => (
|
||||
{CUSTOM_HUES.map((h) => (
|
||||
<button
|
||||
key={h}
|
||||
type="button"
|
||||
|
||||
@@ -100,7 +100,7 @@ export function EventDetail({
|
||||
type="button"
|
||||
aria-label="Close details"
|
||||
onClick={onClose}
|
||||
className="absolute inset-0 bg-ground/80 backdrop-blur-sm"
|
||||
className="absolute inset-0 bg-scrim backdrop-blur-sm"
|
||||
/>
|
||||
<div
|
||||
role="dialog"
|
||||
@@ -297,7 +297,7 @@ export function EventDetail({
|
||||
className={`flex-1 rounded-lg border px-4 py-2.5 text-sm font-medium transition-colors ${
|
||||
completed
|
||||
? "border-hairline text-muted hover:text-ink"
|
||||
: "border-transparent bg-ink text-ground hover:bg-white"
|
||||
: "border-transparent bg-ink text-ground hover:bg-ink-strong"
|
||||
}`}
|
||||
>
|
||||
{completed ? "Mark not done" : "Mark done"}
|
||||
|
||||
@@ -119,7 +119,7 @@ export function Welcome({
|
||||
type="button"
|
||||
disabled={chosen.length === 0}
|
||||
onClick={() => onConfirm(chosen, view)}
|
||||
className="rounded-xl bg-ink px-5 py-3 text-sm font-semibold text-ground transition-colors duration-150 hover:bg-white disabled:cursor-not-allowed disabled:bg-raised disabled:text-faint"
|
||||
className="rounded-xl bg-ink px-5 py-3 text-sm font-semibold text-ground transition-colors duration-150 hover:bg-ink-strong disabled:cursor-not-allowed disabled:bg-raised disabled:text-faint"
|
||||
>
|
||||
{chosen.length === 0
|
||||
? "Pick at least one game"
|
||||
|
||||
Reference in New Issue
Block a user