Skip to main content
The Paste CustomizationProvider allows you to customize the look and feel of Paste components to match your brand. You can override design token values, customize individual components, and create custom themes while maintaining the benefits of a design system.

CustomizationProvider

The CustomizationProvider is a powerful wrapper that enables deep customization of Paste components and design tokens.

Basic Usage

import { CustomizationProvider } from '@twilio-paste/core/customization';

function App() {
  return (
    <CustomizationProvider baseTheme="default">
      <YourApp />
    </CustomizationProvider>
  );
}
Use CustomizationProvider instead of Theme.Provider when you need to customize tokens or component styles.

Customizing Design Tokens

Override design token values to match your brand:
import { CustomizationProvider } from '@twilio-paste/core/customization';
import { Button } from '@twilio-paste/core/button';
import { Box } from '@twilio-paste/core/box';

function App() {
  const customTheme = {
    // Override background colors
    backgroundColors: {
      colorBackgroundPrimary: '#6E3FF3',
      colorBackgroundPrimaryWeak: '#F4EBFF',
    },
    // Override text colors
    textColors: {
      colorTextLink: '#6E3FF3',
    },
    // Override spacing
    space: {
      space60: '2rem', // Change from default 1.5rem
    },
    // Override border radius
    radii: {
      borderRadius30: '8px', // Change from default 4px
    },
  };

  return (
    <CustomizationProvider baseTheme="default" theme={customTheme}>
      <Box padding="space60">
        <Button variant="primary">Custom Themed Button</Button>
      </Box>
    </CustomizationProvider>
  );
}

Partial Token Overrides

You only need to override the tokens you want to change:
import { CustomizationProvider } from '@twilio-paste/core/customization';

function App() {
  const brandTheme = {
    textColors: {
      colorTextLink: '#FF6B35',
    },
    backgroundColors: {
      colorBackgroundPrimary: '#FF6B35',
      colorBackgroundPrimaryWeak: '#FFE5DB',
    },
  };

  return (
    <CustomizationProvider baseTheme="default" theme={brandTheme}>
      <YourApp />
    </CustomizationProvider>
  );
}
All other tokens will use the base theme values.

Customizing Components

Customize the appearance of individual Paste components using the elements prop:

Element-Based Customization

Each Paste component exposes “element” props that allow targeting specific parts:
import { CustomizationProvider } from '@twilio-paste/core/customization';
import { Button } from '@twilio-paste/core/button';
import { Card } from '@twilio-paste/core/card';

function App() {
  const customElements = {
    BUTTON: {
      backgroundColor: 'colorBackgroundBrandHighlight',
      borderRadius: 'borderRadius20',
      ':hover': {
        backgroundColor: 'colorBackgroundBrandHighlightWeakest',
      },
    },
    CARD: {
      borderWidth: 'borderWidth20',
      borderColor: 'colorBorderPrimary',
      borderRadius: 'borderRadius30',
    },
  };

  return (
    <CustomizationProvider baseTheme="default" elements={customElements}>
      <Card>
        <Button variant="primary">Custom Button in Custom Card</Button>
      </Card>
    </CustomizationProvider>
  );
}

Targeting Component Variants

Customize specific variants of components:
import { CustomizationProvider } from '@twilio-paste/core/customization';

function App() {
  const customElements = {
    BUTTON: {
      // Base button styles
      fontWeight: 'fontWeightBold',
      
      // Variant-specific styles
      variants: {
        primary: {
          backgroundColor: 'colorBackgroundBrand',
          color: 'colorTextInverse',
        },
        secondary: {
          borderColor: 'colorBorderPrimary',
        },
      },
    },
  };

  return (
    <CustomizationProvider baseTheme="default" elements={customElements}>
      <YourApp />
    </CustomizationProvider>
  );
}

Custom Element Names

Use the element prop to create custom variants of components:
import { CustomizationProvider } from '@twilio-paste/core/customization';
import { Button } from '@twilio-paste/core/button';

function App() {
  const customElements = {
    DANGER_BUTTON: {
      backgroundColor: 'colorBackgroundError',
      color: 'colorTextInverse',
      ':hover': {
        backgroundColor: 'colorBackgroundErrorStronger',
      },
    },
    SUCCESS_BUTTON: {
      backgroundColor: 'colorBackgroundSuccess',
      color: 'colorTextInverse',
    },
  };

  return (
    <CustomizationProvider baseTheme="default" elements={customElements}>
      <Button element="DANGER_BUTTON">Delete</Button>
      <Button element="SUCCESS_BUTTON">Confirm</Button>
    </CustomizationProvider>
  );
}

CustomizationProvider Props

baseTheme

The base theme to start from before applying customizations:
<CustomizationProvider baseTheme="default">
  <YourApp />
</CustomizationProvider>

// Or use dark theme as base
<CustomizationProvider baseTheme="dark">
  <YourApp />
</CustomizationProvider>
Available base themes:
  • "default": Default light theme
  • "dark": Dark theme

theme

Design token overrides:
const customTokens = {
  backgroundColors: {
    colorBackgroundPrimary: '#6E3FF3',
  },
  textColors: {
    colorTextLink: '#6E3FF3',
  },
};

<CustomizationProvider baseTheme="default" theme={customTokens}>
  <YourApp />
</CustomizationProvider>

elements

Component-specific style overrides:
const customElements = {
  BUTTON: {
    borderRadius: 'borderRadius30',
  },
  CARD: {
    boxShadow: 'shadow',
  },
};

<CustomizationProvider baseTheme="default" elements={customElements}>
  <YourApp />
</CustomizationProvider>

customBreakpoints

Custom responsive breakpoints:
<CustomizationProvider 
  baseTheme="default" 
  customBreakpoints={['640px', '768px', '1024px', '1280px']}
>
  <YourApp />
</CustomizationProvider>

disableAnimations

Disable all animations:
<CustomizationProvider baseTheme="default" disableAnimations>
  <YourApp />
</CustomizationProvider>

Real-World Example: Brand Customization

Here’s a complete example of customizing Paste for a brand:
import React from 'react';
import { CustomizationProvider } from '@twilio-paste/core/customization';
import { Box } from '@twilio-paste/core/box';
import { Button } from '@twilio-paste/core/button';
import { Card } from '@twilio-paste/core/card';
import { Heading } from '@twilio-paste/core/heading';
import { Text } from '@twilio-paste/core/text';

function App() {
  // Brand colors and customization
  const brandTheme = {
    backgroundColors: {
      colorBackgroundPrimary: '#FF6B35',
      colorBackgroundPrimaryWeak: '#FFE5DB',
      colorBackgroundPrimaryWeaker: '#FFF3EE',
    },
    textColors: {
      colorTextLink: '#FF6B35',
      colorTextLinkStronger: '#E55A2B',
    },
    borderColors: {
      colorBorderPrimary: '#FF6B35',
    },
  };

  const brandElements = {
    BUTTON: {
      borderRadius: 'borderRadius30',
      fontWeight: 'fontWeightBold',
      paddingLeft: 'space70',
      paddingRight: 'space70',
    },
    CARD: {
      borderRadius: 'borderRadius30',
      boxShadow: 'shadowCard',
    },
    HEADING: {
      fontWeight: 'fontWeightBold',
    },
  };

  return (
    <CustomizationProvider 
      baseTheme="default" 
      theme={brandTheme}
      elements={brandElements}
    >
      <Box 
        padding="space100" 
        backgroundColor="colorBackgroundPrimaryWeaker"
      >
        <Card padding="space80">
          <Heading as="h1" variant="heading10" marginBottom="space40">
            Welcome to Our App
          </Heading>
          <Text marginBottom="space60">
            This interface uses our custom brand theme built on Paste.
          </Text>
          <Box display="flex" columnGap="space40">
            <Button variant="primary">Get Started</Button>
            <Button variant="secondary">Learn More</Button>
          </Box>
        </Card>
      </Box>
    </CustomizationProvider>
  );
}

export default App;

Combining with Theme Provider

Don’t use CustomizationProvider and Theme.Provider together. CustomizationProvider replaces Theme.Provider with additional customization capabilities.
Incorrect:
// ❌ Don't do this
<Theme.Provider theme="default">
  <CustomizationProvider>
    <App />
  </CustomizationProvider>
</Theme.Provider>
Correct:
// ✅ Use only CustomizationProvider
<CustomizationProvider baseTheme="default">
  <App />
</CustomizationProvider>

Accessing Custom Theme Values

Use the same hooks to access customized theme values:
import { useTheme } from '@twilio-paste/core/theme';

function CustomComponent() {
  const theme = useTheme();
  
  return (
    <div style={{
      backgroundColor: theme.backgroundColors.colorBackgroundPrimary,
      padding: theme.space.space60,
    }}>
      Using custom theme values
    </div>
  );
}

Best Practices

Do’s

  • Start with a base theme: Always specify a baseTheme
  • Override selectively: Only customize what you need
  • Use design tokens: Reference tokens in customizations, not hardcoded values
  • Test accessibility: Verify color contrast after customization
  • Document customizations: Keep track of your brand customizations

Don’ts

  • Don’t override everything: Maintain consistency with Paste patterns
  • Don’t break accessibility: Ensure sufficient color contrast
  • Don’t use arbitrary values: Stick to the token scale when possible
  • Don’t forget responsive design: Test customizations at all breakpoints

Migration from Theme.Provider

If you’re currently using Theme.Provider:
// Before
import { Theme } from '@twilio-paste/core/theme';

<Theme.Provider theme="default">
  <App />
</Theme.Provider>

// After
import { CustomizationProvider } from '@twilio-paste/core/customization';

<CustomizationProvider baseTheme="default">
  <App />
</CustomizationProvider>
For simple theme switching without customization, Theme.Provider is sufficient. Use CustomizationProvider when you need to override tokens or component styles.

Advanced: Deep Customization

For complex customizations, you can use the utilities provided:
import { CustomizationProvider } from '@twilio-paste/core/customization';
import deepmerge from 'deepmerge';

function App() {
  const baseCustomizations = {
    backgroundColors: {
      colorBackgroundPrimary: '#6E3FF3',
    },
  };

  const additionalCustomizations = {
    textColors: {
      colorTextLink: '#6E3FF3',
    },
  };

  const mergedTheme = deepmerge(baseCustomizations, additionalCustomizations);

  return (
    <CustomizationProvider baseTheme="default" theme={mergedTheme}>
      <YourApp />
    </CustomizationProvider>
  );
}
The CustomizationProvider uses deepmerge internally to merge your customizations with the base theme.

Next Steps

  • Design Tokens: Learn about all available tokens to customize
  • Theming: Understand the base themes you can start from
  • Accessibility: Ensure your customizations maintain accessibility

Build docs developers (and LLMs) love