Redesign in Prime Intellect's design language, both themes, three viewports
Eighteen agents: three design directions judged on whether a COO on a phone actually learns what an environment is, on craft, and on landing without a rewrite; one spec; a foundation of measured tokens; six build lanes; three browser verifiers; a final gate pass. The materials are Prime Intellect's, measured from their site: near-black grounds, one green, sharp radii, mono small-caps labels, Geist and Geist Mono self-hosted because production CSP is font-src 'self'. Two of their own greys fail contrast on their own ground (#737373 is 4.02:1, #6E6E6E is 3.73:1 on #0F0F0F), so --muted is lifted and the CSS comment carries the number — or someone will 'correct' it back. Every text-on-ground pair in both themes is tabulated in src/index.css with its measured ratio. The two rules that resolved every conflict: data is mono, sentences are sans; the language wins on materials, the lesson wins on legibility. Light mode is a finished paper theme, not an inversion. What did not change: the derived-tabs contract, the honesty markers, the isolation lint, every gate. 419 contract checks, entry chunk at 74% of budget, zero horizontal overflow on any route at 390/1024/1440 in either theme. Also flips Alert Triage to status 'live' — the pipeline built it but never promoted it, so it was badged SPEC on its own playable page and the home page counted one environment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019mt6sHQHEnEYrJZvoMCJSB
This commit is contained in:
@@ -31,11 +31,11 @@ function writeStored(high: boolean): void {
|
||||
/**
|
||||
* One value shared by every mounted toggle, not one `useState` each.
|
||||
*
|
||||
* The header renders this control twice — once in the desktop bar, once inside
|
||||
* the mobile sheet — and only one of them is ever visible. With local state the
|
||||
* hidden one keeps a stale `aria-pressed`, so a visitor who toggles on a phone
|
||||
* and then rotates into the desktop layout is told the setting is off while the
|
||||
* page is plainly showing it on.
|
||||
* This control renders in three places — the desktop bar, the mobile sheet and
|
||||
* the Play tab — and at most two are ever visible at once. With local state the
|
||||
* hidden one keeps a stale `aria-pressed`, so a visitor who toggles on the
|
||||
* board and then opens the menu is told the setting is off while the page is
|
||||
* plainly showing it on.
|
||||
*/
|
||||
let high = false;
|
||||
let initialised = false;
|
||||
@@ -69,14 +69,57 @@ function subscribe(listener: () => void): () => void {
|
||||
};
|
||||
}
|
||||
|
||||
export function ContrastToggle({ className }: { className?: string }) {
|
||||
function useContrast(): boolean {
|
||||
// The server snapshot is `false` so a prerendered page never claims a
|
||||
// preference it cannot know; the real value lands on the first subscribe.
|
||||
const isHigh = React.useSyncExternalStore(
|
||||
return React.useSyncExternalStore(
|
||||
subscribe,
|
||||
() => high,
|
||||
() => false,
|
||||
);
|
||||
}
|
||||
|
||||
export interface ContrastToggleProps {
|
||||
className?: string;
|
||||
/**
|
||||
* Print "High contrast" beside the icon. This is the form the Play tab and
|
||||
* the mobile sheet use: a colour-blind visitor looking at the board finds the
|
||||
* mode by its name, not by guessing what a half-filled circle means.
|
||||
*/
|
||||
labelled?: boolean;
|
||||
}
|
||||
|
||||
export function ContrastToggle({ className, labelled = false }: ContrastToggleProps) {
|
||||
const isHigh = useContrast();
|
||||
const ariaLabel = isHigh ? 'High contrast tiles on. Turn off.' : 'High contrast tiles off. Turn on.';
|
||||
|
||||
if (labelled) {
|
||||
return (
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="touch"
|
||||
// 44px below lg, 36px at lg — the same step as the icon form, so the
|
||||
// Play tab's row lines up with the ghost button beside it.
|
||||
className={cn(
|
||||
'justify-start lg:min-h-9',
|
||||
isHigh && 'border-accent-edge bg-accent-subtle text-accent-fg',
|
||||
className,
|
||||
)}
|
||||
aria-pressed={isHigh}
|
||||
aria-label={ariaLabel}
|
||||
onClick={() => setHigh(!isHigh)}
|
||||
>
|
||||
<Contrast aria-hidden="true" />
|
||||
<span className="text-ui">High contrast</span>
|
||||
{/* The state as a word as well as a fill, on the control that exists
|
||||
for people who cannot rely on the fill. */}
|
||||
<span className="font-mono text-label uppercase tracking-label text-muted">
|
||||
{isHigh ? 'on' : 'off'}
|
||||
</span>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
@@ -85,7 +128,7 @@ export function ContrastToggle({ className }: { className?: string }) {
|
||||
size="icon-touch"
|
||||
className={cn('lg:size-9', isHigh && 'bg-accent-subtle text-accent-fg', className)}
|
||||
aria-pressed={isHigh}
|
||||
aria-label={isHigh ? 'High contrast tiles on. Turn off.' : 'High contrast tiles off. Turn on.'}
|
||||
aria-label={ariaLabel}
|
||||
title="High contrast tiles"
|
||||
onClick={() => setHigh(!isHigh)}
|
||||
>
|
||||
@@ -93,3 +136,8 @@ export function ContrastToggle({ className }: { className?: string }) {
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
/** The Play tab's form of the toggle. Same store, same state, with its name on it. */
|
||||
export function LabelledContrastToggle({ className }: { className?: string }) {
|
||||
return <ContrastToggle labelled className={className} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user