Features
- Supports fixed light and dark color modes.
- Supports inverting the parent's color mode.
- Supports nested scopes.
- Supports themes and theme overrides.
Color Modes
Place ThemeScope inside VortexProvider. Set colorMode to light or dark to keep that mode when the page changes; without it, the scope follows its parent.
ThemeScope adds no layout box, so put a Stack inside for background and spacing.
"use client";
import { Button, Stack, Text, ThemeScope } from "@vortexlabs/vortex";
export const ThemeScopeModes = () => {
return (
<Stack direction={{ xs: "column", sm: "row" }} gap={4}>
<ThemeScope colorMode="light">
<Stack backgroundColor="surface-subtlest" padding={5} gap={3} borderRadius="md">
<Text>Always light</Text>
<Button>Light action</Button>
</Stack>
</ThemeScope>
<ThemeScope colorMode="dark">
<Stack backgroundColor="surface-subtlest" padding={5} gap={3} borderRadius="md">
<Text>Always dark</Text>
<Button>Dark action</Button>
</Stack>
</ThemeScope>
</Stack>
);
};Inverted Color Mode
Set colorMode="inverted" to use the opposite of the parent's mode, like a dark footer on a light page.
"use client";
import { Button, Stack, Text, ThemeScope } from "@vortexlabs/vortex";
export const ThemeScopeInverted = () => {
return (
<ThemeScope colorMode="inverted">
<Stack backgroundColor="surface-subtlest" padding={5} gap={3} borderRadius="md">
<Text>This panel uses the opposite color mode.</Text>
<Button>Scoped action</Button>
</Stack>
</ThemeScope>
);
};Nested Scopes
Each scope inherits from its nearest parent scope, so inverting inside a dark scope gives a light region.
"use client";
import { Button, Stack, Text, ThemeScope } from "@vortexlabs/vortex";
export const ThemeScopeNested = () => {
return (
<ThemeScope colorMode="dark">
<Stack backgroundColor="surface-subtlest" padding={5} gap={4} borderRadius="md">
<Text>Dark outer panel</Text>
<ThemeScope colorMode="inverted">
<Stack
backgroundColor="surface-subtlest"
padding={4}
gap={3}
borderRadius="sm"
>
<Text>Light inner panel</Text>
<Button>Inner action</Button>
</Stack>
</ThemeScope>
</Stack>
</ThemeScope>
);
};Themes
Set name to a theme you've generated and imported, or an array like ["sleek", "astra"] to add an override. Without name or defaultName, the scope keeps its parent's theme.
import "./themes/sleek/globals.css";
import { Button, ThemeScope } from "@vortexlabs/vortex";
<ThemeScope name="sleek">
<Button>Sleek action</Button>
</ThemeScope>Use defaultName when the scope needs its own theme switcher, like a preview area. Calling setTheme from useTheme inside the scope changes only that scope; it can't change a controlled name.
import { Button, ThemeScope, useTheme } from "@vortexlabs/vortex";
const ThemeSwitch = () => {
const { theme, setTheme } = useTheme();
const astra = Array.isArray(theme);
return (
<Button onClick={() => setTheme(astra ? "sleek" : ["sleek", "astra"])}>
{astra ? "Remove Astra" : "Apply Astra"}
</Button>
);
};
export const Preview = () => {
return (
<ThemeScope defaultName="sleek">
<ThemeSwitch />
</ThemeScope>
);
};