The Paste Theme Designer is an interactive tool for creating and previewing custom themes. Build your theme visually and export the configuration for use in your application.
Overview
The Theme Designer helps you:
- Visualize theme changes in real-time
- Customize design tokens with a visual interface
- Preview components with your custom theme
- Export theme configuration as code
- Test color contrast for accessibility
- Experiment without writing code
Accessing the Theme Designer
The Theme Designer is a separate web application maintained by the Paste team:
https://theme-designer.twil.io
The Theme Designer is currently an internal Twilio tool. Check with your team about access or use the CustomizationProvider API to create themes programmatically.
Using the Theme Designer
Starting Point
- Choose a base theme (Default or Dark)
- Select which token categories to customize:
- Colors (backgrounds, text, borders)
- Typography (fonts, sizes, weights)
- Spacing (padding, margins, gaps)
- Borders (radii, widths)
- Shadows
Customizing Tokens
Color Tokens
Use the color picker to modify:
- Background Colors: Primary, secondary, status colors
- Text Colors: Body text, links, status text
- Border Colors: Default borders, status borders
// Example output from Theme Designer
{
backgroundColors: {
colorBackgroundPrimary: '#0D9488',
colorBackgroundPrimaryStrong: '#0F766E',
},
textColors: {
colorTextLink: '#0D9488',
},
}
Typography Tokens
Adjust font properties:
- Font Families: Text and code fonts
- Font Sizes: Base sizes and display sizes
- Font Weights: Normal, medium, bold, etc.
- Line Heights: Corresponding to font sizes
{
fonts: {
fontFamilyText: '"Inter", sans-serif',
},
fontSizes: {
fontSize30: '1rem',
fontSize40: '1.125rem',
},
}
Spacing Tokens
Define your spacing scale:
{
space: {
space50: '1rem',
space60: '1.25rem',
space70: '1.5rem',
},
}
Live Preview
The Theme Designer shows real-time previews of:
- Buttons: All variants (primary, secondary, destructive)
- Inputs: Text fields, textareas, selects
- Typography: Headings, paragraphs, links
- Cards: With different states
- Alerts: All variants (info, warning, error, success)
- Forms: Complete form layouts
Accessibility Checking
The tool automatically checks:
- Color Contrast: WCAG AA and AAA compliance
- Text Readability: Minimum contrast ratios
- Focus States: Visibility of focus indicators
Warnings appear if your color choices don’t meet accessibility standards.
Exporting Your Theme
Copy Theme Object
Export as a JavaScript object:
// Click "Export Theme" to get:
const myCustomTheme = {
backgroundColors: {
colorBackgroundPrimary: '#0D9488',
colorBackgroundPrimaryStrong: '#0F766E',
colorBackgroundPrimaryStronger: '#115E59',
},
textColors: {
colorText: '#111827',
colorTextLink: '#0D9488',
},
radii: {
borderRadius20: '6px',
borderRadius30: '10px',
},
fonts: {
fontFamilyText: '"Inter", sans-serif',
},
};
Copy CustomizationProvider Code
Get ready-to-use React code:
import { CustomizationProvider } from '@twilio-paste/core/customization';
function App() {
return (
<CustomizationProvider
baseTheme="default"
theme={{
backgroundColors: {
colorBackgroundPrimary: '#0D9488',
},
textColors: {
colorTextLink: '#0D9488',
},
}}
>
<YourApplication />
</CustomizationProvider>
);
}
Download as JSON
Save your theme as a JSON file for version control:
{
"name": "My Custom Theme",
"baseTheme": "default",
"tokens": {
"backgroundColors": {
"colorBackgroundPrimary": "#0D9488"
},
"textColors": {
"colorTextLink": "#0D9488"
}
}
}
Alternative: Programmatic Theme Creation
If you don’t have access to the Theme Designer, create themes programmatically:
Manual Theme Definition
import { CustomizationProvider } from '@twilio-paste/core/customization';
const brandTheme = {
// Define all your token overrides
backgroundColors: {
colorBackgroundPrimary: '#0D9488',
colorBackgroundPrimaryStrong: '#0F766E',
colorBackgroundPrimaryStronger: '#115E59',
colorBackgroundPrimaryStrongest: '#134E4A',
colorBackgroundPrimaryWeakest: '#CCFBF1',
},
textColors: {
colorText: '#111827',
colorTextWeak: '#4B5563',
colorTextLink: '#0D9488',
},
borderColors: {
colorBorder: '#E5E7EB',
colorBorderPrimary: '#0D9488',
},
radii: {
borderRadius20: '6px',
borderRadius30: '10px',
},
fonts: {
fontFamilyText: '"Inter", -apple-system, sans-serif',
},
};
function App() {
return (
<CustomizationProvider baseTheme="default" theme={brandTheme}>
<YourApplication />
</CustomizationProvider>
);
}
Using generateThemeFromTokens
For comprehensive themes, use the theme generator:
import { generateThemeFromTokens } from '@twilio-paste/theme';
import { CustomizationProvider } from '@twilio-paste/core/customization';
// Import or define all required tokens
const customTokens = {
backgroundColors: { /* all background colors */ },
borderColors: { /* all border colors */ },
borderWidths: { /* all border widths */ },
radii: { /* all border radii */ },
fonts: { /* all fonts */ },
fontSizes: { /* all font sizes */ },
fontWeights: { /* all font weights */ },
lineHeights: { /* all line heights */ },
boxShadows: { /* all shadows */ },
sizings: { /* all sizes - required */ },
spacings: { /* all spacing values */ },
textColors: { /* all text colors */ },
zIndices: { /* all z-indices */ },
colors: {},
colorSchemes: {},
dataVisualization: {},
};
const fullTheme = generateThemeFromTokens(customTokens);
function App() {
return (
<CustomizationProvider theme={fullTheme}>
<YourApplication />
</CustomizationProvider>
);
}
Common Workflows
Brand Color Update
Update your brand’s primary color across all components:
- Open Theme Designer
- Select base theme (default or dark)
- Navigate to “Background Colors”
- Update
colorBackgroundPrimary and related shades
- Update
colorTextLink to match
- Update
colorBorderPrimary to match
- Preview across components
- Check accessibility warnings
- Export and integrate into your app
Typography Customization
Change the font family throughout your app:
- Open Theme Designer
- Navigate to “Typography”
- Update
fontFamilyText
- Optionally adjust font sizes for better proportions
- Preview with different text components
- Export font family override
Creating a Dark Theme Variant
Build a custom dark theme:
- Start with “dark” base theme
- Adjust background colors for your brand
- Ensure text colors have sufficient contrast
- Test with focus states
- Verify all status colors work in dark mode
- Export complete dark theme
Testing Your Theme
Visual Regression Testing
After applying a custom theme, test visually:
import { CustomizationProvider } from '@twilio-paste/core/customization';
import { render } from '@testing-library/react';
describe('Custom Theme', () => {
it('should render components with custom theme', () => {
const { container } = render(
<CustomizationProvider theme={myCustomTheme}>
<Button variant="primary">Test Button</Button>
</CustomizationProvider>
);
// Add snapshot or visual regression test
expect(container).toMatchSnapshot();
});
});
Accessibility Testing
Verify contrast ratios:
import { useThemeContrastCheck } from '@twilio-paste/theme';
function ThemeValidator() {
const issues = useThemeContrastCheck(myCustomTheme);
if (issues.length > 0) {
console.error('Accessibility issues:', issues);
}
return null;
}
// Include in your app during development
<>
<ThemeValidator />
<App />
</>
Component Testing
Test all component variants:
function ThemeShowcase() {
return (
<CustomizationProvider theme={myCustomTheme}>
<Stack orientation="vertical" spacing="space60">
{/* Buttons */}
<Stack orientation="horizontal" spacing="space40">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
</Stack>
{/* Inputs */}
<Input placeholder="Test input" />
<Select><option>Test select</option></Select>
<Textarea placeholder="Test textarea" />
{/* Alerts */}
<Alert variant="info">Info alert</Alert>
<Alert variant="warning">Warning alert</Alert>
<Alert variant="error">Error alert</Alert>
{/* Cards */}
<Card>Card content</Card>
</Stack>
</CustomizationProvider>
);
}
Best Practices
1. Start with Small Changes
// Good: Incremental changes
const theme = {
backgroundColors: {
colorBackgroundPrimary: '#0D9488',
},
};
// Avoid: Changing everything at once
const theme = {
/* 100+ token overrides */
};
2. Maintain Color Relationships
// Good: Cohesive color scale
{
colorBackgroundPrimary: '#0D9488',
colorBackgroundPrimaryStrong: '#0F766E', // Darker
colorBackgroundPrimaryStronger: '#115E59', // Even darker
colorBackgroundPrimaryWeakest: '#CCFBF1', // Much lighter
}
// Avoid: Unrelated colors
{
colorBackgroundPrimary: '#0D9488',
colorBackgroundPrimaryStrong: '#DC2626', // Different hue!
}
3. Check Accessibility
Always verify:
- Text on background: minimum 4.5:1 ratio
- Large text on background: minimum 3:1 ratio
- Focus indicators: clearly visible
- Status colors: distinguishable
4. Test in Context
Preview your theme with:
- Real application content
- All component states (hover, focus, disabled)
- Different viewport sizes
- Light and dark system preferences
5. Version Your Themes
// themes/v1.js
export const brandThemeV1 = { /* ... */ };
// themes/v2.js
export const brandThemeV2 = { /* ... */ };
// Use feature flags for gradual rollout
const theme = useFeatureFlag('theme-v2')
? brandThemeV2
: brandThemeV1;
Troubleshooting
Theme Not Applying
Ensure CustomizationProvider wraps your app:
// ✓ Correct
<CustomizationProvider theme={myTheme}>
<App />
</CustomizationProvider>
// ✗ Incorrect - components outside provider
<>
<Header />
<CustomizationProvider theme={myTheme}>
<Main />
</CustomizationProvider>
</>
Tokens Not Working
Check token names match exactly:
// ✓ Correct
{ colorBackgroundPrimary: '#0D9488' }
// ✗ Incorrect - wrong name
{ colorBackgroundPrimaryColor: '#0D9488' }
{ background-color-primary: '#0D9488' }
Accessibility Warnings
If you see contrast warnings:
- Use a contrast checker tool
- Darken text colors or lighten backgrounds
- Test with actual users
- Don’t sacrifice accessibility for aesthetics
Resources
Color Tools
Font Resources
Design Token References
Next Steps