We use cookies to enhance your experience on the site
CodeWorlds

Theming in Styled-components - Galactic Design System

ThemeProvider in styled-components allows you to create a cohesive system of colors, sizes, and typography -- like a unified interface for the entire space fleet.

ThemeProvider

ThemeProvider
is a component that provides a theme to all components inside it:

1import { ThemeProvider } from 'styled-components';
2
3const spaceTheme = {
4  colors: {
5    primary: '#7c4dff',
6    secondary: '#64b5f6',
7    background: '#0a0a2e',
8    surface: '#1a1a4e',
9    text: '#e0e0e0',
10    success: '#00e676',
11    warning: '#ffa726',
12    danger: '#f44336',
13  },
14  spacing: {
15    xs: '4px',
16    sm: '8px',
17    md: '16px',
18    lg: '24px',
19    xl: '32px',
20  },
21  borderRadius: {
22    sm: '4px',
23    md: '8px',
24    lg: '12px',
25    round: '50%',
26  },
27  fontSize: {
28    sm: '12px',
29    md: '16px',
30    lg: '20px',
31    xl: '28px',
32  },
33};
34
35function App() {
36  return (
37    <ThemeProvider theme={spaceTheme}>
38      <Dashboard />
39    </ThemeProvider>
40  );
41}

Using the theme in components

Every styled-component has automatic access to the theme through

props.theme
:

1const Panel = styled.div`
2  background: ${props => props.theme.colors.surface};
3  border-radius: ${props => props.theme.borderRadius.lg};
4  padding: ${props => props.theme.spacing.lg};
5  color: ${props => props.theme.colors.text};
6`;
7
8const Heading = styled.h2`
9  color: ${({ theme }) => theme.colors.primary};
10  font-size: ${({ theme }) => theme.fontSize.xl};
11  margin-bottom: ${({ theme }) => theme.spacing.md};
12`;

Notice the destructuring --

({ theme })
is a shorthand for
(props) => props.theme
.

Switching themes (Dark/Light)

One of the most popular uses of ThemeProvider is switching between dark and light themes:

1const darkTheme = {
2  colors: {
3    background: '#0a0a2e',
4    surface: '#1a1a4e',
5    text: '#e0e0e0',
6    primary: '#7c4dff',
7  },
8};
9
10const lightTheme = {
11  colors: {
12    background: '#f5f5f5',
13    surface: '#ffffff',
14    text: '#212121',
15    primary: '#5c6bc0',
16  },
17};
18
19function App() {
20  const [isDark, setIsDark] = useState(true);
21  const theme = isDark ? darkTheme : lightTheme;
22
23  return (
24    <ThemeProvider theme={theme}>
25      <AppContainer>
26        <button onClick={() => setIsDark(!isDark)}>
27          Toggle Theme
28        </button>
29        <Dashboard />
30      </AppContainer>
31    </ThemeProvider>
32  );
33}

Global Styles

createGlobalStyle
allows you to define global CSS styles that also have access to the theme:

1import { createGlobalStyle } from 'styled-components';
2
3const GlobalStyles = createGlobalStyle`
4  * {
5    margin: 0;
6    padding: 0;
7    box-sizing: border-box;
8  }
9
10  body {
11    background: ${({ theme }) => theme.colors.background};
12    color: ${({ theme }) => theme.colors.text};
13    font-family: 'Segoe UI', sans-serif;
14  }
15`;
16
17function App() {
18  return (
19    <ThemeProvider theme={spaceTheme}>
20      <GlobalStyles />
21      <Dashboard />
22    </ThemeProvider>
23  );
24}

useTheme Hook

If you need access to the theme in component logic (not just in styles), use the

useTheme
hook:

1import { useTheme } from 'styled-components';
2
3function StatusChart({ data }) {
4  const theme = useTheme();
5
6  // Use theme colors in logic, e.g., for Canvas, SVG, or conditions
7  const chartColor = data.isHealthy
8    ? theme.colors.success
9    : theme.colors.danger;
10
11  return (
12    <div>
13      <svg width="100" height="100">
14        <circle cx="50" cy="50" r="40" fill={chartColor} />
15      </svg>
16      <p style={{ color: theme.colors.text }}>
17        Status: {data.isHealthy ? 'OK' : 'Alert'}
18      </p>
19    </div>
20  );
21}

useTheme
is useful when you need theme values outside of styled-components -- for example, for drawing on Canvas, configuring chart libraries, or conditional logic based on theme colors.

Nested themes

ThemeProvider can be nested so that different sections of the application have different themes:

1function App() {
2  return (
3    <ThemeProvider theme={darkTheme}>
4      <Header />
5      <ThemeProvider theme={lightTheme}>
6        <ContentArea />  {/* lightTheme applies here */}
7      </ThemeProvider>
8      <Footer />  {/* darkTheme is back here */}
9    </ThemeProvider>
10  );
11}

It's like different sections of a spaceship with different lighting modes -- the command bridge can be dark while the laboratory is bright.

Theming best practices

  1. Centralize colors and sizes -- never hardcode values in components, always reference the theme
  2. Use TypeScript -- define a type for the theme to get auto-completion
  3. Maintain consistency -- all themes should have the same keys (colors, spacing, fontSize)
  4. Test both themes -- make sure every component looks good in both dark and light modes
Go to CodeWorlds