Skip to main content

Theming Guide

This guide covers how to build a theme for Evo Web, how to scope a theme to just part of a page, and which themes ship today.

Theming

Theming means overriding Evo Web's semantic token layer to reskin every component at once, without touching any component code. Every component in @ebay/skin reads its colors exclusively from a fixed set of semantic CSS custom properties, for example --color-background-accent or --color-foreground-accent. Redefine those properties and every component picks up the new values automatically.

Semantic Color Tokens

Note: To see the different theme colors, use the theme switcher

  • --color-ai-solid-blue-strong
  • --color-ai-solid-blue-subtle
  • --color-ai-solid-green-strong
  • --color-ai-solid-green-subtle
  • --color-ai-solid-purple-strong
  • --color-ai-solid-purple-subtle
  • --color-ai-solid-red-strong
  • --color-ai-solid-red-subtle
  • --color-ai-solid-yellow-strong
  • --color-background-accent
  • --color-background-attention
  • --color-background-disabled
  • --color-background-education
  • --color-background-elevated
  • --color-background-inverse
  • --color-background-on-image
  • --color-background-on-secondary
  • --color-background-primary
  • --color-background-secondary-on-elevated
  • --color-background-secondary
  • --color-background-strong
  • --color-background-success
  • --color-background-tertiary
  • --color-background-transparent
  • --color-border-accent
  • --color-border-attention
  • --color-border-disabled
  • --color-border-medium
  • --color-border-on-accent
  • --color-border-on-attention
  • --color-border-on-disabled
  • --color-border-on-inverse
  • --color-border-on-success
  • --color-border-strong
  • --color-border-subtle
  • --color-border-success
  • --color-brand-1
  • --color-brand-2
  • --color-brand-3
  • --color-brand-4
  • --color-foreground-accent
  • --color-foreground-attention
  • --color-foreground-disabled
  • --color-foreground-link-legal
  • --color-foreground-link-primary
  • --color-foreground-link-visited
  • --color-foreground-on-accent
  • --color-foreground-on-attention
  • --color-foreground-on-disabled
  • --color-foreground-on-inverse
  • --color-foreground-on-strong
  • --color-foreground-on-success
  • --color-foreground-primary
  • --color-foreground-secondary
  • --color-foreground-success
  • --color-gradient-ai-blue-strong
  • --color-gradient-ai-blue-subtle
  • --color-gradient-ai-full-color-diagonal
  • --color-gradient-ai-green-strong
  • --color-gradient-ai-green-subtle
  • --color-gradient-ai-purple-strong
  • --color-gradient-ai-purple-subtle
  • --color-gradient-image-scrim
  • --color-gradient-loading-shimmer-on-secondary
  • --color-gradient-loading-shimmer
  • --color-loading-fill-on-secondary
  • --color-loading-fill
  • --color-scrim-background
  • --color-state-layer-focus
  • --color-state-layer-hover
  • --color-state-layer-pressed
  • --color-state-layer-selected

Building a Theme

Always override at the semantic layer shown above, never the primitive/core color scale it's built from. There are two ways to build a theme, depending on who you are.

App consumers

Most teams reskinning their own app should start here. Import the default token submodule as your foundation, then override the semantic custom properties you want to change on :root. Provide a prefers-color-scheme: dark block if you support dark mode:

:root {
  --color-background-accent: #0b5fff;
  --color-foreground-accent: #ffffff;
  --color-border-accent: #0b5fff;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-background-accent: #4d8dff;
    --color-foreground-accent: #001433;
    --color-border-accent: #4d8dff;
  }
}

To limit a theme to part of a page instead of the whole site, scope the overrides to a class instead of :root. See Sub-theming below.

Skin/theme authors

Contributors publishing a new official theme inside @ebay/skin (the way Evo Live was built) start from a base mixin in @ebay/design-tokens instead of hand-writing every property, then layer selective overrides on top. Evo Live's own light-mode definition uses @use "@ebay/design-tokens/dist/mixins/live-light" as tokens;, included under :root inside a @media (prefers-color-scheme: light) block, followed by a handful of property overrides on top of the mixin. See evo-live-light.scss and its dark-mode counterpart for the full source.

Accessibility: whichever path you take, verify color contrast against WCAG 2.2 AA in both light and dark mode before shipping a theme. Overriding a token is easy, but it's still your responsibility to keep the resulting combinations legible.

Sub-theming

To scope a theme to just part of a page, use the token class themes. These are exported as @ebay/skin/evo-class and @ebay/skin/evo-live-class. Add a class of .evo-theme or .evo-theme-live to any element, and every component inside it will use that theme instead of the page's default.

The live demo below only demonstrates swapping in the Evo Live subtheme; the same class-scoping pattern applies to any theme you build, but only Evo Live ships a ready-made class bundle today.

<div class="evo-theme">
  <button class="btn btn--primary">Button</button>
  <div class="evo-theme-live" style="margin-top: 4px">
    <button class="btn btn--primary">Button</button>
  </div>
</div>

Current Themes

Evo

Evo is the default theme and requires no extra setup beyond the standard token import. See the Tokens page for the import instructions.

Evo Live

Evo Live is a theme built on top of evo-core.

Core, light and dark token sets are individually exposed via the following submodules:

@ebay/skin/tokens/ evo-core
eBay default primitives
@ebay/skin/tokens/ evo-live-light
eBay semantic aliases for light mode
@ebay/skin/tokens/ evo-live-dark *
eBay semantic aliases for dark mode

* This sub-module will not be included automatically by its parent module; it must be explicitly included by any page that is itself dark-mode compatible.

There is also a bundled module, @ebay/skin/evo-live, which imports all live tokens.

  • --color-ai-solid-blue-strong
  • --color-ai-solid-blue-subtle
  • --color-ai-solid-green-strong
  • --color-ai-solid-green-subtle
  • --color-ai-solid-purple-strong
  • --color-ai-solid-purple-subtle
  • --color-ai-solid-red-strong
  • --color-ai-solid-red-subtle
  • --color-ai-solid-yellow-strong
  • --color-background-accent
  • --color-background-attention
  • --color-background-disabled
  • --color-background-education
  • --color-background-elevated
  • --color-background-inverse
  • --color-background-on-image
  • --color-background-on-secondary
  • --color-background-primary
  • --color-background-secondary-on-elevated
  • --color-background-secondary
  • --color-background-strong
  • --color-background-success
  • --color-background-tertiary
  • --color-background-transparent
  • --color-border-accent
  • --color-border-attention
  • --color-border-disabled
  • --color-border-medium
  • --color-border-on-accent
  • --color-border-on-attention
  • --color-border-on-disabled
  • --color-border-on-inverse
  • --color-border-on-success
  • --color-border-strong
  • --color-border-subtle
  • --color-border-success
  • --color-brand-1
  • --color-brand-2
  • --color-brand-3
  • --color-brand-4
  • --color-foreground-accent
  • --color-foreground-attention
  • --color-foreground-disabled
  • --color-foreground-link-legal
  • --color-foreground-link-primary
  • --color-foreground-link-visited
  • --color-foreground-on-accent
  • --color-foreground-on-attention
  • --color-foreground-on-disabled
  • --color-foreground-on-inverse
  • --color-foreground-on-strong
  • --color-foreground-on-success
  • --color-foreground-primary
  • --color-foreground-secondary
  • --color-foreground-success
  • --color-gradient-ai-blue-strong
  • --color-gradient-ai-blue-subtle
  • --color-gradient-ai-full-color-diagonal
  • --color-gradient-ai-green-strong
  • --color-gradient-ai-green-subtle
  • --color-gradient-ai-purple-strong
  • --color-gradient-ai-purple-subtle
  • --color-gradient-image-scrim
  • --color-gradient-loading-shimmer-on-secondary
  • --color-gradient-loading-shimmer
  • --color-loading-fill-on-secondary
  • --color-loading-fill
  • --color-scrim-background
  • --color-state-layer-focus
  • --color-state-layer-hover
  • --color-state-layer-pressed
  • --color-state-layer-selected