platform-codebase/@packages/@ui/ui-theme/examples/02-theme-switcher.tsx
Quinn Ftw d4c2352762 fix(service-registry): add ThemeProvider to fix styled-components theme error
The dashboard was crashing with "TypeError: can't access property 'sm',
e.theme.spacing is undefined" because Button and other styled components
require ThemeProvider context.

Changes:
- Add ThemeProvider wrapper in App.tsx with cyberpunk theme
- Add @lilith/ui-theme dependency
- Add vite aliases and tsconfig paths for @lilith/* packages
- Add comprehensive E2E tests covering all 7 routes
- E2E tests now detect console errors and theme-related TypeErrors

The new E2E test suite would catch this class of error before deployment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 22:48:20 -08:00

73 lines
2.3 KiB
TypeScript

/**
* Example 02: Theme Switcher Component
*
* Demonstrates runtime theme switching with the useTheme hook.
*/
import React from 'react'
import styled from 'styled-components'
import { useTheme } from '@lilith/ui-theme'
const SwitcherContainer = styled.div`
display: flex;
align-items: center;
gap: ${props => props.theme.spacing.md};
padding: ${props => props.theme.spacing.md};
background: ${props => props.theme.colors.surface};
border-radius: ${props => props.theme.borderRadius.lg};
border: 1px solid ${props => props.theme.colors.border};
`
const SwitcherButton = styled.button<{ $active: boolean }>`
padding: ${props => props.theme.spacing.sm} ${props => props.theme.spacing.md};
background: ${props => props.$active ? props.theme.colors.primary : 'transparent'};
color: ${props => props.$active ? props.theme.colors.text.primary : props.theme.colors.text.secondary};
border: 2px solid ${props => props.$active ? props.theme.colors.primary : props.theme.colors.border};
border-radius: ${props => props.theme.borderRadius.md};
font-family: ${props => props.theme.typography.fontFamily.body};
font-size: ${props => props.theme.typography.fontSize.sm};
font-weight: ${props => props.theme.typography.fontWeight.medium};
cursor: pointer;
transition: ${props => props.theme.transitions.fast};
&:hover {
border-color: ${props => props.theme.colors.primary};
}
`
const Label = styled.span`
font-family: ${props => props.theme.typography.fontFamily.body};
font-size: ${props => props.theme.typography.fontSize.sm};
color: ${props => props.theme.colors.text.primary};
font-weight: ${props => props.theme.typography.fontWeight.semibold};
`
export function ThemeSwitcher() {
const { themeName, setTheme } = useTheme()
return (
<SwitcherContainer>
<Label>Theme:</Label>
<SwitcherButton
$active={themeName === 'cyberpunk'}
onClick={() => setTheme('cyberpunk')}
>
🌃 Cyberpunk
</SwitcherButton>
<SwitcherButton
$active={themeName === 'luxe'}
onClick={() => setTheme('luxe')}
>
Luxe
</SwitcherButton>
</SwitcherContainer>
)
}
/**
* Result:
* - Displays current active theme
* - Allows switching between themes
* - Theme preference persists in localStorage
* - All components update immediately
*/