Skip to main content

Scoped Theming

Use ThemeScope to change the theme for part of a page. Content outside the scope keeps its existing theme.

Create an override

A full theme includes Vortex's defaults. A themeOverride contains only the tokens you change and is applied alongside a base theme.

Add this entry next to themes in your theme config. It gives buttons round corners:

vortex.config.ts
themeOverride: {
  rounded: {
    componentTokens: {
      borderRadius: {
        button: { borderRadius: "full" },
      },
    },
  },
},
bun run build:theme

Import the generated override after your base theme:

src/main.tsx
import "./themes/acme/globals.css";
import "./themes/overrides/rounded/theme.css";

This radius override only needs theme.css. An override that changes semanticTokens.typography also generates typography.css and globals.css; import its globals.css instead to load both stylesheets.

Apply the override

Inside your VortexProvider, pass the base theme and override names together:

import { Button, ThemeScope } from "@vortexlabs/vortex";

export const Actions = () => (
  <>
    <Button>Default corners</Button>
    <ThemeScope name={["acme", "rounded"]}>
      <Button>Round corners</Button>
    </ThemeScope>
  </>
);

Include the base name so its token references resolve inside the scope; without it, override changes to global tokens don't reach the semantic tokens that use them. For declarations with equal specificity, CSS import order determines which value wins; the order of names in the array does not.

To apply the override everywhere, use defaultTheme={["acme", "rounded"]} on VortexProvider. To use another full theme in a scope, load its CSS and pass its name instead.

Scope the color mode

Omit name to keep the parent's theme. Set colorMode to a fixed mode or invert the parent's mode:

<ThemeScope colorMode="dark">
  <Button>Always dark</Button>
</ThemeScope>

<ThemeScope colorMode="inverted">
  <Button>Opposite color mode</Button>
</ThemeScope>

Without colorMode, the scope inherits its parent's mode. ThemeScope uses display: contents; add a layout component inside it when you need a background or spacing.

Isolate embedded content

Use VortexProvider scoped when an embedded app or preview needs to switch its theme and color mode independently. A ThemeScope changes local appearance, but its color-mode setters still target the provider. See the embedded provider example.