use-theme-switcher
Props
| Prop name | Type | Default | Description |
|---|---|---|---|
lightTheme | ThemeName | Required | The name of the theme to be used on light mode. |
darkTheme | ThemeName | Required | The name of the theme to be used on dark mode. |
switchCondition | boolean | undefined | Custom condition to run for matching darkTheme preference. |
The useThemeSwitcher hook abstracts logic to switch between two themes and also detect the user
preferred color scheme to automatically pick the adequate theme name.
The hook returns an array with:
- `theme`
- Current theme name.
- `toggleTheme`
- A function to toggle between two themes.
- `setTheme`
- The function to directly set the theme.
Basic theme switching using toggleTheme
The most basic setup only takes two arguments: lightTheme and darkTheme.
Tip: You can emulate the browser color scheme preference on the DevTools "Rendering" tool.
import { Box, Button, Text, ThemeWrapper, themeFlix, themeKamil, useThemeSwitcher } from '@flixbus/honeycomb-react'; const [theme, toggleTheme] = useThemeSwitcher({ lightTheme: 'flix', darkTheme: 'kamil' }); const isKamil = theme === 'kamil'; <ThemeWrapper theme={theme} themes={[themeFlix, themeKamil]}> <Box> <Text> I prefer "{isKamil ? 'Kamil' : 'Flix'}" theme </Text> <Button onClick={() => toggleTheme()} appearance="primary"> {`Go back to ${isKamil ? 'Flix' : 'Kamil'}`} </Button> </Box> </ThemeWrapper>
Using the setTheme function
If you need to set a theme name directly, you can use the setTheme function. This will bypass the
hook's internal logic.
In the example bellow the buttons simply set one of the themes, while the hook only runs at the first render.
import { Box, Button, ButtonGroup, Text, ThemeWrapper, themeFlix, themeKamil, useThemeSwitcher } from '@flixbus/honeycomb-react'; import { Icon, IconFlix, IconFlixNo } from '@flixbus/honeycomb-icons-react'; const [theme, , setTheme] = useThemeSwitcher({ lightTheme: 'flix', darkTheme: 'kamil' }); <ThemeWrapper theme={theme} themes={[themeFlix, themeKamil]}> <Box> <Text> I'm using "{theme}" theme. </Text> <ButtonGroup> <Button appearance="primary" onClick={() => setTheme('flix')}> <Icon InlineIcon={IconFlix} /> Go Flix! </Button> <Button appearance="primary" onClick={() => setTheme('kamil')}> <Icon InlineIcon={IconFlixNo} /> Go Kamil! </Button> </ButtonGroup> </Box> </ThemeWrapper>
Setting a custom user preference condition with switchCondition option
By default the hook will detect if the user prefers dark color scheme by matching the media query: (prefers-color-scheme: dark).
You can override this behavior by passing a boolean resulting condition to the switchCondition option.
In the example bellow we write a custom condition to check the time and assess if it's morning or night, then choose dark theme if it's night. Set the time using the input to change the theme on the fly.
Another example of custom switchCondition is wether the user has a saved theme preference on their profile or cookies.
import { Box, FormRow, Input, ButtonGroup, Button, ThemeWrapper, themeFlix, themeKamil, useThemeSwitcher } from '@flixbus/honeycomb-react'; import { Icon, IconBulb, IconBulbOff } from '@flixbus/honeycomb-icons-react'; const [time, setTime] = React.useState(`${new Date().getHours().toString()}:00`); const hours = time.split(':')[0]; const isNight = hours >= 18 || hours < 6; const [theme] = useThemeSwitcher({ lightTheme: 'flix', darkTheme: 'kamil', switchCondition: isNight }); const info = (<> Now is {isNight ? 'night' : 'day'} <Icon InlineIcon={isNight ? IconBulb : IconBulbOff} /> </>); <ThemeWrapper theme={theme} themes={[themeFlix, themeKamil]}> <Box> <FormRow> <Input type="time" label="Set the time" info={info} id="timed-theme-switcher" value={time} step="3600" onChange={(event) => setTime(event.target.value)} /> </FormRow> <ButtonGroup> <Button appearance="primary"> Primary button </Button> </ButtonGroup> </Box> </ThemeWrapper>