Design Tokens and Color Mode
A guide to using Spor tokens and managing color mode in your application for consistent theming.
🎨 Using Design Tokens in Spor
Design tokens are reusable values that define the visual style of a product, such as colors, typography, spacing, border, and shadows. Instead of hard-coding these values throughout a design and codebase, tokens provide a shared source of truth.
Spor provides design tokens for colors, rounding, typography, spacing, outlines, breakpoints, animation and z-index. An overview of all design tokens can be found hereEkstern lenke.
Color tokens
Spor color tokens work in three layers. The foundation is a palette that is a fixed set of raw colors defined by name and shade, like green.100 (#CCEAE4). On top of that, each color gets a friendlier alias name that describes what it looks like, such as seaMist. The third layer is semantic tokens that are named slots that describe the purpose of a color rather than its appearance, for example surface.brand, outline.core, text.disabled etc.
Semantic token names describe their purpose and intended use. The first part defines the type of element: bg (background), surface, outline, text, or icon. The second describes the context, such as subtle, disabled, brand, info, or critical, while an optional third part defines the state, such as hover or active. An example of a token name is surface.info.hover. This structure sets the stage for related tokens, such as surface.disabled, text.disabled, outline.disabled, and icon.disabled, to work together as a consistent set.
Additionally, all color tokens hold on both a lightmode value, and a darkmode value. Therefore, when using tokens like surface.brand or text.brand, the colors will automatically switch based on the active theme.
Try it yourself: Background and Text Tokens
Try changing the backgroundColor of the Box-component and the color of the Text-component to be different color tokens. For example, change the backgroundColor to surface.success, and the color to be text.success.
<Box backgroundColor="surface.brand" padding={4} borderRadius="sm"> <Text color="text.brand"> Some text </Text> </Box>
🌗 Changing Color Mode
To manage color mode in your app, Spor exports Chakra UI’s useColorMode and useColorModeValue hooks.
useColorMode
Use useColorMode to retrieve the current color mode and toggle between modes.
() => { const { colorMode, toggleColorMode } = useColorMode() return ( <Box> <Button onClick={toggleColorMode}> Change to {colorMode === 'light' ? 'dark' : 'light'} </Button> </Box> ) }
useColorModeValue
useColorModeValue returns different values based on the active color mode. However, you should primarily use design tokens instead of useColorModeValue.
Use useColorModeValue only if there is no available design token for the color you need.
import { useColorModeValue } from "@vygruppen/spor-react";const colorValues = useColorModeValue(lightValue, darkValue);
Example: When to Use useColorModeValue
If there’s no specific token for a color (e.g., a custom alias), you can use useColorModeValue:
() => { const { toggleColorMode } = useColorMode() const bg = useColorModeValue('darkTeal', 'mint') const color = useColorModeValue('white', 'darkTeal') return ( <> <Box marginBottom={4} padding={3} borderRadius="md" bg={bg} color={color}> This Box and text will change style based on the color mode. </Box> <Box> <Button onClick={toggleColorMode}> Toggle Color Mode </Button> </Box> </> ) }
🚫 Forcing a Specific Color Mode
In some cases, you may want a component to always stay in light or dark mode, regardless of the app’s color mode. Use className light or dark to accomplish this.
<Stack gap={3}> <Box className="light"> <Button variant="primary">This is always light mode</Button> </Box> <Box className="dark"> <Button variant="primary">This is always dark mode</Button> </Box> </Stack>
Use this approach sparingly—only when you need a component to be color mode-independent.
By following these guidelines, you can efficiently manage color modes while ensuring accessibility, performance, and future compatibility! 🚀