Skip to contentSkip to navigationSkip to topbar
Paste assistant Assistant
Figma
Star

How to build custom UI with Paste Tokens and Primitives

You may encounter times where you are required to build an experience that isn't covered by out of the box Paste components. This guide aims to help you create custom experiences while still using the design system.


Why would I need to build Custom Components?

Why would I need to build Custom Components? page anchor

While Paste will aim to provide ample coverage of components for teams to compose UIs, there will be occasions where you may need to build a custom component. This may be because:

  • It's in Paste's future roadmap, but you need a component for your product right now. In such cases, while the creation of parallel workstreams is not ideal, it may be necessary to ensure that your product ships on time while we still build the right experience from a system perspective.
  • It's not in Paste's roadmap yet, or will never be: Paste will never aim to cover every experience that Twilio ships to customers, since doing so will make the Design System bloated and hard to maintain for our small (but mighty) team.
  • It's an unique product experience: while most UIs will eventually be expressed by Paste, there will still be extremely specific product experiences that don't make sense as generic components or design patterns.

In these cases, it's still critical to ensure that your component looks like a Paste component in order to build a seamless experience. With that in mind we have devised some ways to help you and your team ship products while still being able to use assets from the design system.

Obviously, the first (and ideal) option is to work with your design partner and identify all the existing Paste components that can be used to create your desired experience. We're invested in helping you through this process - come through with your questions to our weekly Design System Office Hours or post in #help-design-system.

The ideal way to evaluate Paste components that will work for your project is:

  1. Find all the Paste components that exactly match your UI needs.
  2. Work with your design partner to evaluate compositional methods to use Paste components to create a larger, more complex component. For example, a Filter that needs to be placed above a table may not exist in Paste, but could be expressed using Inputs, Buttons, and Selects. This will help you reduce your list of truly custom components.
  3. Consider if your UI can be refactored to reduce the need of custom components by expressing the same interface with Paste components. The cost of building (and importantly, maintaining) custom components as a product team is really large, and you may want to avoid technical and design debt in the future.

The list of components you're left with may not be expressed via Paste. At this point, we recommend using our Design Primitive Components.

Design Primitive Components

Design Primitive Components page anchor

Design Primitive Components are React components that expose style properties using Styled-System(link takes you to an external page). These style properties are typed React props that only expose design tokens as values. There are style properties for each of the categories that are included on the Theme Object from the Theme Package.

We use these components internally to create almost everything in Paste. When used, they provide more than enough combinations of design tokens to to create new, unique things while still looking like a part of the Design System. They also support the themes Paste offers out of the box, and allow for easy upgrades to design language updates in the future. Your custom components are important and will never be left behind.

Each Design Primitive is a Styled Component(link takes you to an external page) that creates styles which are encapsulated to the component. This way you can style your custom components with the confidence that your styles should never clash with another team's work.

Box Primitive

Box Primitive page anchor

The Box Primitive component is designed to be a block level primitive. Think of it as a div, except with super powers. By exposing the as prop, Box can become any valid HTML element (obviously the sensible choices would be box or block style things). It exposes important styling properties like background color, padding, margin, border styles, etc., to allow you to create custom block level containers. The values the styling properties take are the names of the design tokens exposed on the theme object.

(information)

RIP Hex Values!

To ensure design system resiliency, Box and Text do not accept HTML Color Codes, Font Sizes, or arbitrary pixel values. Any styling choices must be expressed using tokens, and tokens only.

You can compose any number of Boxes together to create new UI components. Here's an example of three boxes, two of which are nested.

Component preview theme
<Box
as="article"
backgroundColor="colorBackgroundBody"
padding="space60"
>
Parent box on the hill side
<Box
backgroundColor="colorBackgroundSuccessWeakest"
display="inline-block"
padding="space40"
>
nested box 1 made out of ticky tacky
</Box>
<Box
backgroundColor="colorBackgroundPrimaryWeak"
display="inline-block"
padding="space40"
>
Nested box 2 may look the same
</Box>
</Box>

The Text component is designed to be a general purpose text primitive. Similar to Box, it too exposes the as prop to allow transformation into any valid HTML element and comes with a number of text styling properties. These properties include font-size, text color, weight and line height, allowing you to create text styles that should match the design system.

Component preview theme
<Box padding="space20">
<Text as="p" marginBottom="space40">the</Text>
<Text as="h1" fontSize="fontSize70" fontWeight="fontWeightMedium" lineHeight="lineHeight70" marginBottom="space80">Plan</Text>
<Text as="ol" marginLeft="space60">
<Text as="li" fontSize="fontSize40">collect components</Text>
<Text as="li" fontSize="fontSize40">???</Text>
<Text as="li" fontSize="fontSize40">Profit</Text>
</Text>
<Text as="p" color="colorTextError" fontSize="fontSize30" fontWeight="fontWeightBold">Custom Error Message</Text>
</Box>

Creating Thoughtful Compositions

Creating Thoughtful Compositions page anchor

You can use combinations of Box and Text to create custom compositions utilizing design token values from Paste. By doing this, your custom components can look and feel like standard Paste components (which will hopefully be expressing the rest of your UI, leading to a seamless experience). Remember that in spite of our approach with Tokens, you can still create broken experiences if you don't pair with a design partner. Always talk to your designer (and reach out to us on #help-design-system or visit Design System Office Hours as well)!

These compositions will automatically respond to the theme that the provider has set. To see this in action, try the theme switcher in this site's header and see how the examples below respond to switching the theme.

Component preview theme
<Box padding="space20">
<Box
as="article"
backgroundColor="colorBackgroundBody"
borderBottomLeftRadius="borderRadius30"
borderBottomRightRadius="borderRadius30"
borderWidth="borderWidth0"
borderTopWidth="borderWidth20"
borderStyle="solid"
borderColor="colorBorderPrimary"
marginBottom="space60"
paddingLeft="space80"
paddingRight="space80"
paddingTop="space60"
paddingBottom="space60"
>
<Text as="h2" fontSize="fontSize60" fontWeight="fontWeightMedium" marginBottom="space40">
The Last Question
</Text>
<Text as="p">
The last question was asked for the first time, half in jest, on May 21, 2061, at a time when humanity first stepped into the light. The question came about as a result of a fivedollar bet over highballs, and it happened this way:
</Text>
</Box>
<Box
role="alert"
backgroundColor="colorBackgroundErrorWeakest"
borderRadius="borderRadius20"
borderWidth="borderWidth10"
borderStyle="solid"
borderColor="colorBorderError"
paddingLeft="space40"
paddingRight="space40"
paddingTop="space30"
paddingBottom="space30"
>
<Text fontWeight="fontWeightMedium" color="colorTextError">
LET THERE BE LIGHT!
</Text>
</Box>
</Box>

Other alternatives to Design Primitives

Other alternatives to Design Primitives page anchor

If you choose to not use the design primitive components directly (and, if so, we'd love to learn more about your use case), check out the options provided by Theme Package. This package showcases ways to harness design tokens in React in a few different ways.

If you aren't using React, hop on over to the Design Tokens Package. This package distributes the tokens and their values via NPM in a variety of different formats, for a bunch of different technologies. Also, if you're doing this, reach out at #help-design-system - we're really curious about what you're up to!

Remember, Paste is not a component library. It's a design system - and design systems come with carefully curated opinions defined by our product design team over the years. By using this guide, we believe that you can express even the most unique UI needs while maintaining a seamless Twilio experience. We can't wait to see what you build.