Every export of kitr/theme, kitr/theme/provider, kitr/theme/server, read from the published type definitions. The guide shows them in use.
kitr/theme
Re-exports class-variance-authority, clsx unchanged, plus the following.
dataAttrs
function dataAttrs(values: Record<string, string | number | boolean | null | undefined>): Record<`data-${string}`, string>;
Data-attribute variants for vanilla CSS: <div {...dataAttrs({ state, size })}> → data-state="open".
defineTokens
function defineTokens<const T extends TokenGroup>(tokens: T, options?: {
prefix?: string;
}): DefineTokensResult<T>;
pick
function pick<K extends string>(styles: CssModule<K>, ...parts: Array<K | Partial<Record<K, boolean | undefined>> | false | null | undefined>): string;
Pick classes from a module with optional conditions: pick(styles, 'card', { active }).
setToastImplementation
function setToastImplementation(fn: ToastFn | null): void;
Called by the ui provider once sonner is loaded.
themeFromCookie
function themeFromCookie(cookieHeader: string | null | undefined, storageKey?: string): ResolvedTheme | undefined;
Read the theme cookie on the server to pass as initialResolved.
ThemeProvider
function ThemeProvider({ children, defaultTheme, storageKey, attribute, initialResolved, colors }: ThemeProviderProps): import("react").JSX.Element;
Light/dark/system with no flash: pair with <ThemeScript /> in the document head.
Sets data-theme="light|dark" on , which the Tailwind preset and styles.css read.
ThemeScript
function ThemeScript({ storageKey, attribute }: {
storageKey?: string;
attribute?: string;
}): import("react").JSX.Element;
Inline script for the document head; applies the stored theme before first paint.
toastError
function toastError(error: unknown, fallbackMessage?: string): void;
Show a KitrError (or anything) as an error toast with its message.
useTheme
function useTheme(): ThemeContextValue;
vars
function vars(values: Record<`--${string}`, string | number>): Record<string, string>;
Build a style object from CSS variables: vars({ '--gap': '8px' }).
darkTokens
const darkTokens: DefineTokensResult<{
readonly color: {
readonly background: "oklch(16% 0.01 260)";
readonly foreground: "oklch(95% 0.005 260)";
readonly muted: "oklch(24% 0.01 260)";
readonly mutedForeground: "oklch(70% 0.02 260)";
readonly border: "oklch(30% 0.01 260)";
readonly primary: "oklch(70% 0.17 262)";
readonly primaryForeground: "oklch(16% 0.01 260)";
readonly destructive: "oklch(65% 0.2 27)";
readonly destructiveForeground: "oklch(16% 0 0)";
readonly ring: "oklch(70% 0.17 262)";
};
}>;
defaultTokens
const defaultTokens: DefineTokensResult<{
readonly color: {
readonly background: "oklch(99% 0 0)";
readonly foreground: "oklch(20% 0.01 260)";
readonly muted: "oklch(96% 0.005 260)";
readonly mutedForeground: "oklch(50% 0.02 260)";
readonly border: "oklch(90% 0.01 260)";
readonly primary: "oklch(55% 0.2 262)";
readonly primaryForeground: "oklch(99% 0 0)";
readonly destructive: "oklch(55% 0.22 27)";
readonly destructiveForeground: "oklch(99% 0 0)";
readonly ring: "oklch(55% 0.2 262)";
};
readonly radius: {
readonly sm: "0.25rem";
readonly md: "0.5rem";
readonly lg: "0.75rem";
};
readonly font: {
readonly sans: "ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif";
readonly mono: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
};
readonly shadow: {
readonly sm: "0 1px 2px oklch(0% 0 0 / 0.06)";
readonly md: "0 4px 12px oklch(0% 0 0 / 0.08)";
};
}>;
kitr's default tokens. Override any of them in config/theme.ts.
defineConfig
const defineConfig: <const C extends ThemeConfig>(config: C) => C;
toast
const toast: ToastFn;
DefineTokensResult
interface DefineTokensResult<T extends TokenGroup> {
tokens: T;
/** `--kitr-color-primary` style names, typed from the token tree. */
var: (path: TokenPath<T>) => `var(--${string})`;
name: (path: TokenPath<T>) => `--${string}`;
/** `:root { --kitr-...: ...; }` ready to drop into a stylesheet. */
css: (selector?: string) => string;
/** Flat `{ '--kitr-color-primary': '#...' }` for inline styles or runtime theming. */
flat: () => Record<string, string>;
}
ThemeConfig
interface ThemeConfig {
/** 'light' | 'dark' | 'system'. Default 'system'. */
default?: 'light' | 'dark' | 'system';
/** Storage key (localStorage and the cookie the server reads). Default 'kitr-theme'. */
storageKey?: string;
/** Attribute set on <html>. Default 'data-theme'. */
attribute?: string;
/** Token overrides merged over kitr's defaults; emitted as CSS variables. */
tokens?: {
light?: TokenGroup;
dark?: TokenGroup;
};
/** `<meta name="theme-color">` and native window chrome per resolved theme. */
colors?: {
light?: string;
dark?: string;
};
/** Where `kitr ui add` pulls components from. Any shadcn-compatible registry. */
registry?: string;
/** Where components are written. Default `app/components/ui`. */
componentsDir?: string;
toaster?: {
position?: 'top-right' | 'top-center' | 'bottom-right' | 'bottom-center';
richColors?: boolean;
};
}
ThemeProviderProps
interface ThemeProviderProps {
children: ReactNode;
defaultTheme?: Theme;
storageKey?: string;
attribute?: string;
/** Theme known on the server (e.g. from a cookie) to avoid a flash. */
initialResolved?: ResolvedTheme;
/** `<meta name="theme-color">` per resolved theme, which native shells and PWAs show as window chrome. */
colors?: {
light?: string;
dark?: string;
};
}
TokenGroup
interface TokenGroup {
[key: string]: TokenLeaf | TokenGroup;
}
CssModule
/** Type a CSS Modules import so `styles.foo` is checked. Generate the `.d.ts` with `kitr css:types`. */
type CssModule<K extends string> = {
readonly [P in K]: string;
};
Type a CSS Modules import so styles.foo is checked. Generate the .d.ts with kitr css:types.
ResolvedTheme
type ResolvedTheme = 'light' | 'dark';
Theme
type Theme = 'light' | 'dark' | 'system';
TokenLeaf
type TokenLeaf = string | number;
Design tokens as plain objects, emitted as CSS custom properties.
The same tokens feed @kitr/tailwind's @theme block and vanilla CSS alike,
so switching styling approach never means re-typing colours.
TokenPath
type TokenPath<T, Prefix extends string = ''> = {
[K in keyof T & string]: T[K] extends TokenLeaf ? `${Prefix}${K}` : TokenPath<T[K], `${Prefix}${K}.`>;
}[keyof T & string];
kitr/theme/provider
themeProvider
const themeProvider: import("@kitr/core").KitrProvider;
Wraps the app in ThemeProvider with config/theme.ts and mounts the toaster (sonner, if installed).
Listed in kitrrc.ts as () => import('@kitr/theme/provider'). Pair with <ThemeScript /> in the document head.
kitr/theme/server
themeFromCookie
function themeFromCookie(cookieHeader: string | null | undefined, storageKey?: string): ResolvedTheme | undefined;
Read the theme cookie on the server to pass as initialResolved.
ResolvedTheme
type ResolvedTheme = 'light' | 'dark';
Theme
type Theme = 'light' | 'dark' | 'system';