fix(theme): text on glass holds 4.5:1 — light --muted kept at 6:1 on the page, tonal fills opaque
Pixel-measured over every scheme x mode x backdrop: the item count fell to 3.8:1 (dark too: its 8% fill let the toolbar glass and the thumbnails under it through), Channels' tabs to 4.1:1 and the current Files row to 4.4:1. Light --muted moves 15% toward --fg in every scheme; the badges, the item count and the current rail row paint opaque bg-tint* fills mixed into the surface. The token contract now asks 6:1 of --muted on the bare page and checks those three sites use the tints.
This commit is contained in:
@@ -63,7 +63,7 @@ function Entry({
|
||||
onClick={() => setView(view)}
|
||||
className={clsx(
|
||||
"flex w-full min-h-8 items-center gap-2 rounded-lg px-2 text-sm",
|
||||
active ? "bg-accent/12 font-medium text-accent" : "text-fg",
|
||||
active ? "bg-tint-current font-medium text-accent" : "text-fg",
|
||||
)}
|
||||
>
|
||||
<Icon className={clsx("size-4 shrink-0", !active && "text-muted")} />
|
||||
|
||||
@@ -7,10 +7,12 @@ import type { ReactNode } from "react";
|
||||
// at 8%, so it reads on the dark schemes and on white alike; `onDark` is the always-dark player's. A
|
||||
// `tone` says which kind of label it is (a role, a state to notice): its own colour at 6%, the most
|
||||
// that keeps its text at 4.5:1 on light (theme.contract.test.ts measures all three in every scheme).
|
||||
// Each tint is mixed into the surface (`bg-tint*`), opaque: a translucent one lets the glass and what
|
||||
// scrolls under it through, and the text's contrast goes with them.
|
||||
const TONES = {
|
||||
neutral: "bg-fg/8 text-muted",
|
||||
accent: "bg-accent/6 text-accent",
|
||||
warn: "bg-warn/6 text-warn",
|
||||
neutral: "bg-tint text-muted",
|
||||
accent: "bg-tint-accent text-accent",
|
||||
warn: "bg-tint-warn text-warn",
|
||||
} as const;
|
||||
|
||||
export function Badge({
|
||||
|
||||
@@ -8,7 +8,8 @@ import { formatNumber } from "../../lib/format";
|
||||
const OVERFLOW_AT = 1_000_000;
|
||||
|
||||
// A compact, FIXED-WIDTH count pill for a toolbar: the filtered item count at the toolbar's 28, flat
|
||||
// and tonal like a `Badge` — no edge, because it does nothing (edged = pressable, flat = just
|
||||
// and tonal like a `Badge` (the same opaque `bg-tint`: the toolbar is glass over scrolling thumbnails)
|
||||
// — no edge, because it does nothing (edged = pressable, flat = just
|
||||
// says; it used to wear the filter dropdowns' glass pill and read as one more). The fixed width is the point — a
|
||||
// changing number must never shove the controls beside it, so the box is sized to the widest value
|
||||
// ("999,999 items") and the content is centred within it. A count of a million or more collapses to
|
||||
@@ -46,7 +47,7 @@ export default function ItemCount({
|
||||
failed ? t("common.countFailed") : count == null ? undefined : formatNumber(count, lang)
|
||||
}
|
||||
aria-busy={stale || undefined}
|
||||
className="inline-flex h-7 min-w-[9rem] shrink-0 items-center justify-center gap-1.5 rounded-full bg-fg/8 px-3 text-sm whitespace-nowrap text-muted"
|
||||
className="inline-flex h-7 min-w-[9rem] shrink-0 items-center justify-center gap-1.5 rounded-full bg-tint px-3 text-sm whitespace-nowrap text-muted"
|
||||
>
|
||||
<Layers className="h-3.5 w-3.5 shrink-0 text-muted" aria-hidden="true" />
|
||||
<span className={clsx("tabular-nums transition-opacity", stale && "opacity-60")}>
|
||||
|
||||
Reference in New Issue
Block a user