Engineering6 min read

Multi-brand theming: one component library, many brands

Layer tokens for brand and mode, ship them as CSS custom properties, model them in Figma, govern overrides, and test every combination.

Figma's purpose-built answer to multi-brand design systems, extended collections, is available only on the Enterprise plan as of October 2026. Everyone else builds brand theming from ordinary collections and modes, which works well if the token layers are right and turns into a mode-limit puzzle if they aren't.

Multi-brand theming is a token architecture in which every brand shares the same components and the same semantic token names, and only the values behind those names change per brand and per mode. Components never know which brand they render; the theme layer decides.

Key takeaways

  • Brand and mode are separate axes, so model them as two layers rather than one flat list of themes.
  • Brands override semantic token values, never token names or component structure.
  • In CSS, a data-brand and a data-theme attribute on the root element select which custom property values apply, with no change to component code.
  • In Figma, a Brand collection and a Theme collection cover brand and mode on any paid plan; extended collections on Enterprise add inheritance from a parent.
  • Every brand and mode combination needs its own visual test and its own contrast check, because a palette that passes in one brand can fail in another.

How does token layering work for brand and mode?

Three brands with light and dark modes means six sets of values. The trick is keeping the number of names flat while the number of values multiplies.

LayerVaries byExampleOwned by
Brand primitivesBrandblue.600, teal.600, font familiesEach brand
Brand semanticsBrandcolor.brand.primary, font.family.displayEach brand, within rules
Theme semanticsBrand and modecolor.background.action, color.text.primarySystem team
Component tokensNeither (aliases only)button.primary.backgroundSystem team

Brand primitives hold each brand's raw palette. Brand semantics give that palette shared names. Theme semantics alias brand semantics differently in light and dark. Components alias theme semantics and never touch the layers below.

The DTCG Resolver Module, part of the stable 2025.10 specification, formalizes the same idea: a resolver file defines modifiers such as theme with contexts like light and dark, and a brand is simply a second modifier. The spec recommends keeping modifiers orthogonal, so each one changes a different set of tokens and the order of resolution never decides the result by accident.

How do CSS custom properties handle multiple brands?

The build emits one block of custom properties per combination. Defaults sit on :root, a brand's overrides sit under [data-brand="b"], and that brand's dark values sit under [data-brand="b"][data-theme="dark"]. Components reference var(--color-background-action) and nothing else, so switching brand is one attribute on the root element.

Two practical choices:

  • One file or one per brand. A white-label product that serves one brand per deployment should ship only that brand's CSS. An app that switches brands at runtime needs them all.
  • light-dark() for mode. The CSS light-dark() function, Baseline since May 2024 according to MDN, returns its first value in light and its second in dark when color-scheme is light dark. Inside each brand block, one declaration per token can then carry both modes.

Components never know which brand they render; the theme layer decides.

How do Figma modes and collections handle multiple brands?

ApproachPlanHow it worksTrade-off
Brand collection plus Theme collectionProfessional and upBrand modes hold brand values; Theme aliases into BrandDesigners set two modes on a frame
One collection, a mode per brand and themeProfessional and upModes like A Light and A Dark10 modes on Professional is only five brands with light and dark
Extended collectionsEnterpriseOne parent collection, one extension per brandExtensions can't add variables or modes

The two-collection approach is the default choice. As of October 2026, Figma allows up to 10 modes per collection on Professional and 20 on Organization, so a Brand collection fits 10 or 20 brands while the Theme collection keeps its light and dark modes. Objects set to Auto inherit modes from their parent, so setting both modes on the top frame of a screen is enough.

Extended collections add inheritance: each brand extension picks up every parent change it hasn't overridden. Figma's docs list caveats worth planning for. A color's value and opacity count as one override, so changing only opacity freezes the color too, and after migrating, accepting the library update removes previously set modes from designs.

Governing brand overrides

Brand teams will ask to change everything. Decide in advance what each brand may touch, and match it to who reviews the change.

The override ladder

  1. Brand-owned, no review: brand primitives, meaning the palette and font files.
  2. Brand-owned, checked automatically: semantic color values for text, surfaces, actions, and borders, gated by a contrast check in the build.
  3. Reviewed by the system team: radius, shadow, and the type scale, because they change how components feel and fit.
  4. Locked: token names, the spacing scale, component structure, focus indicators, and interaction states.

One rule sits above the ladder: a brand that needs a new token requests it in the shared set, where every brand gets it with a default value. Brand-only tokens are how a shared library splits into forks. Figma's extended collections enforce the same rule, since you can't add variables or modes in an extension.

How do you test every brand?

Test the combinations, not just the default. Storybook's themes addon, @storybook/addon-themes, includes a withThemeByDataAttribute decorator that sets a data attribute on a parent element; for two axes, a small custom decorator can set data-brand and data-theme from two toolbar globals.

For visual regression, Chromatic's story modes let you save combinations of globals as named modes and apply them with the chromatic.modes parameter. Each mode gets its own snapshot and baseline, and Chromatic's docs note that two stories with two modes produce four tests, so budget for brands times modes times stories.

Then check contrast at the token level, before any component renders. WCAG 2.1 success criterion 1.4.3 requires 4.5:1 for normal text and 3:1 for large text. List every text and background token pair, resolve both tokens for each brand and mode, and fail the build when a pair drops below the ratio. That catches the new brand's pale accent before it reaches a single screen.

Where Pegasus fits

Pegasus doesn't ship built-in multi-brand modes. It ships light and dark modes and one token source that themes both the Figma variables and the React code's theme object, using the same token names on both surfaces. That single source is what makes adding a brand a matter of token values: a new set of values for the same 470 tokens (color, type, spacing, radius, and shadow), applied the same way in Figma and in code.

The license fits white-label work. It is perpetual and covers unlimited commercial projects, including client work, so an agency can theme one system for several clients.

Pegasus is built to WCAG 2.1 AA, with keyboard paths, focus states, and contrast documented per component, which gives each new brand a baseline to check its values against.

FAQ

What is the difference between multi-brand theming and dark mode?

Dark mode changes values along one axis, light versus dark, for a single brand. Multi-brand theming adds a second axis: which brand's palette, type, and shape the product uses. The two combine, so three brands with light and dark modes need six resolved sets of values. Keeping them as separate layers stops the combinations from turning into duplicated token names.

Do I need Figma Enterprise for a multi-brand design system?

No. As of October 2026, Professional and Organization plans support up to 10 and 20 modes per collection, which is enough for a Brand collection plus a separate Theme collection with light and dark modes. Enterprise adds extended collections, where each brand inherits from a parent and overrides only what differs, which helps most when you manage many brands.

Should each brand get its own component library?

Usually not. Separate component libraries drift, because every fix has to be made once per brand. Keep one component library, and put brand differences in token values. Fork a component only when a brand needs genuinely different structure or behavior, and treat that as a new component with its own name rather than a brand override.

Sources

One system. In Figma and in code.

Pegasus ships 1,540 components, 470 tokens, matching React code, Storybook, and a local MCP server. $149, one-time.

Get the full system