Features
- Supports themes and theme overrides.
- Supports controlled or uncontrolled color modes.
- Supports scoping to embedded apps.
- Supports
useToast, with per-position defaults. - Supports
useShortcutsand keyboard focus rings. - Supports right-to-left layouts and a fallback breakpoint.
App Root
Wrap your app at its root, after importing your generated theme CSS; Quick Start covers the full setup. This preview uses scoped to stay local. className and attributes go on a display: contents wrapper, so they don't affect layout.
"use client";
import "@vortexlabs/vortex/themes/vortex/theme.css";
import { Button, Stack, Text, VortexProvider } from "@vortexlabs/vortex";
export const ProviderUsage = () => {
return (
<VortexProvider defaultTheme="vortex" defaultColorMode="light" scoped>
<Stack backgroundColor="surface-subtlest" padding={5} gap={3} borderRadius="md">
<Text>Content inside the provider uses the Vortex theme.</Text>
<Button>Get started</Button>
</Stack>
</VortexProvider>
);
};Themes
Set defaultTheme to a theme name, or to an array like ["sleek", "astra"] to add overrides. Load the CSS for each one.
<VortexProvider defaultTheme={["sleek", "astra"]}>
{children}
</VortexProvider>Set theme instead when your app stores the selection; useTheme can't change it.
Controlled Color Mode
Set colorMode when your app stores the setting. Update it in onColorModeChange, or useTheme can't change it.
"use client";
import "@vortexlabs/vortex/themes/vortex/theme.css";
import { Button, Stack, Text, VortexProvider, useTheme } from "@vortexlabs/vortex";
import { useState } from "react";
const ModeButton = () => {
const { colorMode, invertColorMode } = useTheme();
return (
<Button onClick={invertColorMode}>
Use {colorMode === "light" ? "dark" : "light"} mode
</Button>
);
};
export const ProviderControlled = () => {
const [mode, setMode] = useState<"light" | "dark">("light");
return (
<VortexProvider scoped colorMode={mode} onColorModeChange={setMode}>
<Stack backgroundColor="surface-subtlest" padding={5} gap={3} borderRadius="md">
<Text>Controlled mode: {mode}</Text>
<ModeButton />
</Stack>
</VortexProvider>
);
};Embedded Content
Set scoped to keep theme and color mode inside the provider, like when Vortex runs inside another app. Without defaultColorMode, a nested provider starts in its parent's color mode. For local theme tokens only, use ThemeScope.
"use client";
import "@vortexlabs/vortex/themes/vortex/theme.css";
import { Button, Stack, Text, VortexProvider } from "@vortexlabs/vortex";
export const ProviderScoped = () => {
return (
<Stack direction={{ xs: "column", sm: "row" }} gap={4}>
<VortexProvider scoped defaultColorMode="light">
<Stack backgroundColor="surface-subtlest" padding={5} gap={3}>
<Text>Light embedded app</Text>
<Button>Light action</Button>
</Stack>
</VortexProvider>
<VortexProvider scoped defaultColorMode="dark">
<Stack backgroundColor="surface-subtlest" padding={5} gap={3}>
<Text>Dark embedded app</Text>
<Button>Dark action</Button>
</Stack>
</VortexProvider>
</Stack>
);
};Toast Defaults
Any component inside the provider can call useToast. toastOptions sets each position's width and expanded state; Toast shows how.
Direction and Responsive Fallback
defaultRTL starts the whole page right-to-left, even with scoped; useRTL changes it later.
defaultBreakpoint is what JavaScript responsive utilities use before the viewport is measured, like during server rendering. CSS breakpoints don't change.
import { Text, VortexProvider } from "@vortexlabs/vortex";
<VortexProvider defaultRTL defaultBreakpoint="xs">
<Text>مرحبًا بك</Text>
</VortexProvider>Server Rendering
In your server HTML, set the theme and color-mode attributes on <html> to match the root provider, and load the CSS for every theme you'll select. The provider doesn't generate CSS or save preferences; the Next.js guide shows a full setup.