Repository navigation
ThemeToggle
The ThemeToggle component provides an animated toggle switch that allows users to switch between light and dark themes. It features a sliding circle animation with theme-appropriate icons.
This component does not accept any props. It manages its own state through the useTheme context hook.
import ThemeToggle from "@/components/Layout/ThemeToggle";
<ThemeToggle />;The component supports two theme modes:
-
Light Mode (g10): Displays a sun icon (
LightFilled) -
Dark Mode: Displays a moon icon (
AsleepFilled)
- Click: Toggle between themes
-
Keyboard: Press
EnterorSpaceto toggle - Accessibility: Proper ARIA labels for screen readers
The toggle features a smooth sliding animation:
- Circle slides left for light mode
- Circle slides right for dark mode
- Transition duration: 0.3s with ease-in-out timing
The component uses the useTheme hook to:
- Access the current theme state
- Toggle between theme modes
- Persist theme preferences
const { theme, toggleTheme } = useTheme();The component uses the current theme to determine the state class:
className={`theme-toggle ${theme !== 'g10' ? 'on' : 'off'}`}- When
theme === 'g10'(light mode): class is"theme-toggle off" - When
theme !== 'g10'(dark mode / 'g100'): class is"theme-toggle on"
- Background: White
- Circle position: Left (translateX(0))
- Circle background: Brand color (bcgov-background-brand)
- Icon: Sun/light filled icon with white color
- Icon path fill: currentColor (white)
- Background: Dark gray (colors.gray-100)
- Circle position: Right (translateX(24px))
- Circle background: White
- Icon: Moon/asleep filled icon with dark gray color
- Icon path fill: currentColor (dark gray)
.theme-toggle {
width: 3rem;
height: 1.5rem;
border-radius: 1rem;
display: flex;
align-items: center;
padding: 0.188rem;
cursor: pointer;
position: relative;
overflow: hidden;
}.icon {
width: 3.125rem;
height: 3.125rem;
padding: 1px;
}Icons are oversized relative to the circle container to ensure proper visual coverage and fill.
.circle {
width: 1.125rem;
height: 1.125rem;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
transition:
transform 0.3s,
background-color 0.3s;
background-color: var(--#{variables.$bcgov-prefix}-background-brand);
}&.off {
background-color: colors.$white;
.circle {
transform: translateX(0);
}
.icon {
color: colors.$white;
}
.icon path {
fill: currentColor;
}
}
&.on {
background-color: colors.$gray-100;
.circle {
transform: translateX(24px);
background-color: colors.$white;
}
.icon {
color: colors.$gray-100;
}
.icon path {
fill: currentColor;
}
}-
Light mode background:
colors.$white(Carbon design token) -
Dark mode background:
colors.$gray-100(Carbon design token) -
Circle brand color:
var(--bcgov-background-brand)(BC Government design token) - Icon size: 3.125rem × 3.125rem
- Light mode icon:
aria-label="light mode" - Dark mode icon:
aria-label="dark mode"
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
toggleTheme();
}
}}- Component has
tabIndex={0}for keyboard navigation - Role is set to
buttonfor proper semantics
- Header Actions: Typically placed in the global header bar
- User Preferences: Part of the user settings interface
- Accessibility: Helps users with visual preferences or requirements
- ThemeProvider: Must be wrapped in ThemeProvider to access theme state
-
LightFilled: Sun icon for light mode -
AsleepFilled: Moon icon for dark mode
import { ThemeProvider } from "@/context/theme/ThemeProvider";
import ThemeToggle from "@/components/Layout/ThemeToggle";
function App() {
return (
<ThemeProvider>
<Header>
<HeaderGlobalAction>
<ThemeToggle />
</HeaderGlobalAction>
</Header>
</ThemeProvider>
);
}- LayoutHeaderGlobalBar: Contains ThemeToggle as a global action
- LayoutHeader: Parent component that displays the header bar
- Single Instance: Use only one ThemeToggle per application
- Theme Provider: Always wrap in ThemeProvider context
- Persistent Placement: Keep in a consistent location (typically header)
- Accessibility: Ensure keyboard navigation and screen reader support
- Theme changes are persisted across sessions
- The component follows Carbon Design System patterns
- Icons are properly sized and colored based on current theme
- Smooth transitions enhance user experience
This wiki documents NR Waste Plus for users and developers. Verify security and deployment guidance against the current application configuration before applying it elsewhere.
- Report an issue or ask a question in the GitHub repository.
- Follow the Contributing Guidelines to propose an update.
- Read the Code of Conduct.
Collection indexes support human browsing and machine retrieval. Keep both current when adding or moving wiki pages.
NR Waste Plus Wiki | GitHub Repository