({
themeFamily,
themeMode,
themeId,
setTheme,
onBack,
onNext
}: {
themeFamily: ThemeFamily
themeMode: ThemeMode
themeId: string
setTheme: (next: { id: string; family: ThemeFamily; mode: ThemeMode }) => void
onBack: () => void
onNext: () => void
})
| 532 | } |
| 533 | |
| 534 | function ThemeStep({ |
| 535 | themeFamily, |
| 536 | themeMode, |
| 537 | themeId, |
| 538 | setTheme, |
| 539 | onBack, |
| 540 | onNext |
| 541 | }: { |
| 542 | themeFamily: ThemeFamily |
| 543 | themeMode: ThemeMode |
| 544 | themeId: string |
| 545 | setTheme: (next: { id: string; family: ThemeFamily; mode: ThemeMode }) => void |
| 546 | onBack: () => void |
| 547 | onNext: () => void |
| 548 | }): JSX.Element { |
| 549 | const applyFamily = (family: ThemeFamily): void => { |
| 550 | const prefersDark = |
| 551 | themeMode === 'dark' || |
| 552 | (themeMode === 'auto' && |
| 553 | typeof window !== 'undefined' && |
| 554 | window.matchMedia('(prefers-color-scheme: dark)').matches) |
| 555 | const id = resolveAuto(family, prefersDark, themeId) |
| 556 | setTheme({ id, family, mode: themeMode }) |
| 557 | } |
| 558 | |
| 559 | const applyMode = (mode: ThemeMode): void => { |
| 560 | const prefersDark = |
| 561 | mode === 'dark' || |
| 562 | (mode === 'auto' && |
| 563 | typeof window !== 'undefined' && |
| 564 | window.matchMedia('(prefers-color-scheme: dark)').matches) |
| 565 | const id = resolveAuto(themeFamily, prefersDark, themeId) |
| 566 | setTheme({ id, family: themeFamily, mode }) |
| 567 | } |
| 568 | |
| 569 | // Some families ship multiple flavors of the same mode (Gruvbox hard/medium/ |
| 570 | // soft, GitHub default/dimmed/high-contrast, Catppuccin frappe/macchiato/ |
| 571 | // mocha, etc.). Expose them as a contrast picker beside the Mode selector. |
| 572 | const resolvedMode: 'light' | 'dark' = |
| 573 | themeMode === 'light' |
| 574 | ? 'light' |
| 575 | : themeMode === 'dark' |
| 576 | ? 'dark' |
| 577 | : prefersDarkSystem() |
| 578 | ? 'dark' |
| 579 | : 'light' |
| 580 | const variants = useMemo( |
| 581 | () => THEMES.filter((t) => t.family === themeFamily && t.mode === resolvedMode), |
| 582 | [themeFamily, resolvedMode] |
| 583 | ) |
| 584 | |
| 585 | return ( |
| 586 | <div> |
| 587 | <StepHeading |
| 588 | eyebrow="Step 2" |
| 589 | title="Pick your theme" |
| 590 | subtitle="Each family has light + dark variants. Auto follows your system." |
| 591 | /> |
nothing calls this directly
no test coverage detected