Skip to Content
Livery is in early development. Star us on GitHub!
StylingCSS-in-JS

CSS-in-JS

Integrate Livery with CSS-in-JS libraries like Styled Components, Emotion, and more.

CSS Variables Approach

The simplest approach works with any CSS-in-JS library:

import styled from 'styled-components'; const Button = styled.button` background-color: var(--colors-primary); color: var(--colors-textInverse); padding: var(--spacing-sm) var(--spacing-md); border-radius: var(--borderRadius-md); border: none; font-family: var(--typography-fontFamily-sans); cursor: pointer; &:hover { opacity: 0.9; } `;

React Hooks Approach

Use Livery hooks for dynamic values:

import { useThemeValue } from '@/lib/livery'; import styled from 'styled-components'; function ThemedButton({ children }) { const primary = useThemeValue('colors.primary'); const textInverse = useThemeValue('colors.textInverse'); return ( <StyledButton $primary={primary} $textColor={textInverse}> {children} </StyledButton> ); } const StyledButton = styled.button<{ $primary: string; $textColor: string }>` background-color: ${(props) => props.$primary}; color: ${(props) => props.$textColor}; padding: 0.5rem 1rem; border-radius: 0.375rem; border: none; `;

Styled Components

With CSS Variables

import styled from 'styled-components'; export const Card = styled.div` background: var(--colors-surface); border: 1px solid var(--colors-border); border-radius: var(--borderRadius-lg); padding: var(--spacing-lg); box-shadow: var(--shadows-md); `; export const Heading = styled.h2` color: var(--colors-text); font-family: var(--typography-fontFamily-sans); font-size: var(--typography-fontSize-xl); font-weight: var(--typography-fontWeight-semibold); margin: 0 0 var(--spacing-md); `; export const Text = styled.p` color: var(--colors-textMuted); font-family: var(--typography-fontFamily-sans); font-size: var(--typography-fontSize-base); line-height: 1.5; margin: 0; `;

Theme Provider Integration

Create a Styled Components theme from Livery:

import { ThemeProvider } from 'styled-components'; import { useTheme } from '@/lib/livery'; function StyledThemeProvider({ children }) { const { theme, isReady } = useTheme(); if (!isReady || !theme) { return <LoadingState />; } return <ThemeProvider theme={theme}>{children}</ThemeProvider>; } // Usage in styled component const Button = styled.button` background-color: ${(props) => props.theme.colors.primary}; color: ${(props) => props.theme.colors.textInverse}; `;

Emotion

With CSS Variables

import { css } from '@emotion/react'; import styled from '@emotion/styled'; export const buttonStyles = css` background-color: var(--colors-primary); color: var(--colors-textInverse); padding: var(--spacing-sm) var(--spacing-md); border-radius: var(--borderRadius-md); border: none; cursor: pointer; transition: opacity 0.2s; &:hover { opacity: 0.9; } `; export const Button = styled.button` ${buttonStyles} `;

With Theme Context

import { ThemeProvider } from '@emotion/react'; import { useTheme } from '@/lib/livery'; function EmotionThemeProvider({ children }) { const { theme } = useTheme(); return <ThemeProvider theme={theme ?? {}}>{children}</ThemeProvider>; }

Stitches

import { createStitches } from '@stitches/react'; export const { styled, css, theme } = createStitches({ theme: { colors: { primary: 'var(--colors-primary)', secondary: 'var(--colors-secondary)', background: 'var(--colors-background)', text: 'var(--colors-text)', }, space: { sm: 'var(--spacing-sm)', md: 'var(--spacing-md)', lg: 'var(--spacing-lg)', }, radii: { sm: 'var(--borderRadius-sm)', md: 'var(--borderRadius-md)', lg: 'var(--borderRadius-lg)', }, }, }); const Button = styled('button', { backgroundColor: '$primary', color: 'white', padding: '$sm $md', borderRadius: '$md', });

Vanilla Extract

button.css.ts
import { style } from '@vanilla-extract/css'; export const button = style({ backgroundColor: 'var(--colors-primary)', color: 'var(--colors-textInverse)', padding: 'var(--spacing-sm) var(--spacing-md)', borderRadius: 'var(--borderRadius-md)', border: 'none', cursor: 'pointer', ':hover': { opacity: 0.9, }, });

Panda CSS

panda.config.ts
import { defineConfig } from '@pandacss/dev'; export default defineConfig({ theme: { extend: { tokens: { colors: { primary: { value: 'var(--colors-primary)' }, secondary: { value: 'var(--colors-secondary)' }, background: { value: 'var(--colors-background)' }, text: { value: 'var(--colors-text)' }, }, }, }, }, });

Best Practices

1. Prefer CSS Variables

CSS variables update automatically when the theme changes:

// Good - updates with theme const Button = styled.button` background: var(--colors-primary); `; // Requires re-render to update const Button = styled.button<{ $bg: string }>` background: ${(p) => p.$bg}; `;

2. Create Utility Functions

// lib/theme-utils.ts export const cssVar = (path: string) => `var(--${path.replace(/\./g, '-')})`; // Usage const Button = styled.button` background: ${cssVar('colors.primary')}; padding: ${cssVar('spacing.md')}; `;

3. Handle Loading States

function ThemedComponent() { const { isReady } = useTheme(); if (!isReady) { return <Skeleton />; } return <StyledContent>...</StyledContent>; }
Last updated on