Scenarios: Component Integration
Component Library Integration
This scenario specifies how component libraries consume variables.
Failure if ignored: components bypass semantic aliases and hardcode values.
Component variable patterns
Pattern 1: Semantic variables
Components consume semantic variables, not base variables.
Good:
.button {
background-color: var(--color-surface-brand);
color: var(--color-text-primary);
padding: var(--spacing-component-button-padding);
}
Bad:
.button {
background-color: var(--color-gray-900);
color: var(--color-gray-0);
padding: var(--spacing-4);
}
Pattern 2: Component-specific variables
Components use component-scoped variables when needed.
Structure:
{
"component": {
"button": {
"color": {
"background": {
"default": {
"$type": "color",
"$value": "{color.surface.brand}"
},
"hover": {
"$type": "color",
"$value": "{color.surface.brand-hover}"
}
}
},
"spacing": {
"padding": {
"$type": "dimension",
"$value": "{spacing.component.button.padding}"
}
}
}
}
}
Pattern 3: Variable overrides
Components allow variable overrides for customization.
CSS:
.button {
background-color: var(
--component-button-color-background-default,
var(--color-surface-brand)
);
}
JavaScript:
const buttonStyle = {
backgroundColor: "var(--component-button-color-background-default)",
};
Component library integration
React integration
Use CSS variables in React components:
function Button({ children }) {
return <button className="button">{children}</button>;
}
.button {
background-color: var(--color-surface-brand);
color: var(--color-text-primary);
padding: var(--spacing-component-button-padding);
}
Vue integration
Use CSS variables in Vue components:
<template>
<button class="button">
<slot></slot>
</button>
</template>
<style scoped>
.button {
background-color: var(--color-surface-brand);
color: var(--color-text-primary);
padding: var(--spacing-component-button-padding);
}
</style>
TypeScript integration
Use generated TypeScript types:
import { color, spacing } from "./tokens";
const buttonStyle = {
backgroundColor: color.surface.brand,
color: color.text.primary,
padding: spacing.component.button.padding,
};
Override strategies
CSS custom properties
Use CSS custom properties for overrides:
.button {
background-color: var(--button-bg, var(--color-surface-brand));
color: var(--button-color, var(--color-text-primary));
}
Override:
.custom-button {
--button-bg: var(--color-surface-accent);
}
Component props
Use component props for overrides:
function Button({ bg, color, children }) {
const style = {
backgroundColor: bg || "var(--color-surface-brand)",
color: color || "var(--color-text-primary)",
};
return <button style={style}>{children}</button>;
}
Theme context
Use theme context for overrides:
const ThemeContext = createContext();
function Button({ children }) {
const theme = useContext(ThemeContext);
return (
<button
style={{
backgroundColor: theme.button.bg,
color: theme.button.color,
}}
>
{children}
</button>
);
}
Examples
Button component
Complete button component example:
Variables (tokens/component/button.json):
{
"component": {
"button": {
"color": {
"background": {
"default": {
"$type": "color",
"$value": "{color.surface.brand}"
},
"hover": {
"$type": "color",
"$value": "{color.surface.brand-hover}"
}
},
"text": {
"default": {
"$type": "color",
"$value": "{color.text.on-brand}"
}
}
},
"spacing": {
"padding": {
"horizontal": {
"$type": "dimension",
"$value": "{spacing.component.button.padding-x}"
},
"vertical": {
"$type": "dimension",
"$value": "{spacing.component.button.padding-y}"
}
}
}
}
}
}
CSS:
.button {
background-color: var(--component-button-color-background-default);
color: var(--component-button-color-text-default);
padding: var(--component-button-spacing-padding-vertical)
var(--component-button-spacing-padding-horizontal);
}
.button:hover {
background-color: var(--component-button-color-background-hover);
}
Input component
Input component example:
Variables (tokens/component/input.json):
{
"component": {
"input": {
"color": {
"border": {
"default": {
"$type": "color",
"$value": "{color.border.default}"
},
"focus": {
"$type": "color",
"$value": "{color.border.focus}"
}
}
},
"spacing": {
"padding": {
"$type": "dimension",
"$value": "{spacing.component.input.padding}"
}
}
}
}
}
CSS:
.input {
border-color: var(--component-input-color-border-default);
padding: var(--component-input-spacing-padding);
}
.input:focus {
border-color: var(--component-input-color-border-focus);
}
Implementation rules
- Use semantic variables in components
- Create component-specific variables when needed
- Allow variable overrides for customization
- Document component variable usage
- Test component variable consumption
Failure modes
If component integration is wrong:
- Hardcoded values in components
- Inconsistent styling
- Maintenance burden
- No customization options
Out of scope
- Component library architecture (focus on variables)
- Component API design (separate concern)
- Component testing (separate concern)