Some checks failed
CI / Lint, typecheck, test (pull_request) Successful in 4m41s
CI / Build container images (pull_request) Successful in 4m4s
CI / Auth e2e pack (pull_request) Successful in 11m40s
CI / Import/export fidelity gate (pull_request) Successful in 52s
CD / Deploy to Test (push) Blocked by required conditions
CD / Smoke tests against Test (push) Blocked by required conditions
CD / Promote to Int (push) Blocked by required conditions
CI / Auth e2e pack (push) Blocked by required conditions
CI / Import/export fidelity gate (push) Blocked by required conditions
CI / Build container images (push) Blocked by required conditions
CD / Build and push images (push) Has been cancelled
CI / Lint, typecheck, test (push) Has been cancelled
apply-theme.ts derives BOTH modes' accent tokens from the stored choice
(ui.theme.accent: preset id or {custom:'#hex'}) and writes them as
<style id="user-theme"> with :root:root + :root:root[data-theme='dark']
blocks — the doubled :root beats tokens.css regardless of document
order, since theme-init.js injects the ui.theme.css cache during <head>
parsing, before the bundle styles. The default preset means NO override
(hand-tuned tokens.css values stay). main.tsx re-derives from the
choice at startup, healing stale caches after app updates.
Settings: accent radiogroup inside the Appearance section (visible
names, color never the only cue) with per-mode preview swatches on
each mode's canonical background, plus a custom color input; i18n
de+en. The second fieldset made bare .settings-fieldset locators
ambiguous — theme specs now scope via input[name] (fence stays).
Tests: apply-theme unit pack, BASE_PALETTE<->tokens.css drift fence in
theme-contrast.test.ts, e2e theme-accent.spec (instant apply, pre-paint
persistence, default removes override, axe smoke with garish yellow in
both modes). ADR 0018 amendment documents the stage-B details.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QRtCnB3uLdQtFmvp9HXcRX
56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
import { StrictMode } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { BrowserRouter } from 'react-router-dom';
|
|
|
|
import { App } from './App';
|
|
import { AuthProvider } from './auth/auth-context';
|
|
import { ToastProvider } from './components/Toast';
|
|
import './i18n';
|
|
import { ApiError } from './lib/api';
|
|
import { initUserTheme } from './theme/apply-theme';
|
|
import { applyTheme, initSystemThemeListener, readStoredThemeMode } from './theme/theme';
|
|
import './styles/tokens.css';
|
|
import './styles/base.css';
|
|
|
|
// theme-init.js already themed the document pre-paint; re-applying here is
|
|
// a no-op safety net for contexts serving index.html without it, and the
|
|
// listener keeps 'system' users in sync with live OS scheme changes.
|
|
applyTheme(readStoredThemeMode());
|
|
initSystemThemeListener();
|
|
// Accent choice (#184): re-derive from the stored choice — heals a stale
|
|
// ui.theme.css cache after app updates; theme-init.js only bridges paint.
|
|
initUserTheme();
|
|
|
|
const queryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
// A 4xx won't turn into something else on retry (wrong permissions,
|
|
// page in trash, not found, …) — only retry on network/5xx errors.
|
|
retry: (failureCount, error) => {
|
|
if (error instanceof ApiError && error.status >= 400 && error.status < 500) return false;
|
|
return failureCount < 3;
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const container = document.getElementById('root');
|
|
if (!container) {
|
|
throw new Error('index.html is missing the #root element');
|
|
}
|
|
|
|
createRoot(container).render(
|
|
<StrictMode>
|
|
<QueryClientProvider client={queryClient}>
|
|
<AuthProvider>
|
|
<ToastProvider>
|
|
<BrowserRouter>
|
|
<App />
|
|
</BrowserRouter>
|
|
</ToastProvider>
|
|
</AuthProvider>
|
|
</QueryClientProvider>
|
|
</StrictMode>,
|
|
);
|