UNPKG

alouette

Version:

A modern, customizable design system built on top of NativeWind v5 with configurable defaults

209 lines (147 loc) 5.47 kB
--- name: alouette-theming description: > Re-theme a subtree with accents (brand, danger, info, success, warning) and light/dark modes. Use the accent prop, AccentScope, or ScopedTheme; children always consume base tokens (bg-surface, text-accent, text-sharp, text-muted, border-muted). Read token values in JS with useThemeToken; read the current mode with useCurrentMode. Load when applying colors, accents, dark mode, or reading a theme color for a non-className prop. type: core library: alouette library_version: "20.1.0" sources: - "christophehurpeau/alouette:packages/alouette/src/ui/containers/AccentScope.tsx" - "christophehurpeau/alouette:packages/alouette/src/ui/containers/ScopedTheme.tsx" - "christophehurpeau/alouette:packages/alouette/src/core/AlouetteConfig.ts" - "christophehurpeau/alouette:packages/alouette/src/core/useThemeToken.ts" - "christophehurpeau/alouette:CLAUDE.md" --- # alouette — Theming with modes and accents alouette colors come from theme tokens, not the raw Tailwind palette. A theme is a light/dark mode optionally combined with an accent. Tokens cascade down the tree: components use **base tokens** (`bg-surface`, `text-accent`, `text-sharp`, `text-muted`, `border-muted`) and inherit the resolved value from the nearest scope. Setting an accent re-themes a whole subtree. `Accent` = `"brand" | "danger" | "info" | "success" | "warning"`. ## Setup Most alouette components — `Text`, `Surface`, `Box`, `Button`, `Message`, … — take an `accent` prop that re-themes their subtree. Prefer the prop: ```tsx import { Surface, Text } from "alouette"; <Surface accent="danger"> <Text className="text-accent">Something went wrong</Text> </Surface> <Text accent="brand" className="text-accent">Brand-accented text</Text>; ``` Use `AccentScope` only to re-theme a group of children at once, or children that don't accept an `accent` prop: ```tsx import { AccentScope } from "alouette"; <AccentScope accent="brand"> <Header /> <Body /> </AccentScope>; ``` ## Core Patterns ### Read a token value in JS for a non-className prop ```tsx import { useThemeToken } from "alouette"; const accentColor = useThemeToken("--color-accent"); const [surface, sharp] = useThemeToken(["--color-surface", "--color-sharp"]); ``` Use this only for props that cannot take a className (gradient stops, `placeholderTextColor`, native `Switch` colors, SVG tint). Everything else uses a className token. ### Force a mode on a subtree ```tsx import { AccentScope } from "alouette"; <AccentScope mode="dark" accent="brand"> {children} </AccentScope>; ``` ### Read the active mode / theme ```tsx import { useCurrentMode, useCurrentTheme } from "alouette"; const mode = useCurrentMode(); // "light" | "dark" const theme = useCurrentTheme(); // e.g. "dark_brand" ``` ## Common Mistakes ### HIGH Hardcoding raw Tailwind colors instead of tokens Wrong: ```tsx <View className="bg-blue-500"> <Text className="text-gray-600">Hi</Text> </View> ``` Correct: ```tsx <Surface accent="brand"> <Text className="text-accent">Hi</Text> </Surface> ``` Raw palette classes (`bg-blue-500`, `text-gray-600`) ignore the alouette theme, so they do not adapt to mode or accent and break dark mode. Source: CLAUDE.md (Theming and semantic roles); src/ui/containers/AccentScope.tsx ### MEDIUM Setting color manually instead of an accent Wrong: ```tsx <Box> <Text style={{ color: "#c00" }}>Error</Text> </Box> ``` Correct: ```tsx <Box accent="danger"> <Text className="text-accent">Error</Text> </Box> ``` Setting `accent` re-themes the subtree so children resolve base tokens against the accent + current mode; a hardcoded color duplicates theme logic and skips mode adaptation. Source: packages/alouette/src/ui/containers/Box.tsx, AccentScope.tsx ### MEDIUM Wrapping an accent-capable component in AccentScope Wrong: ```tsx <AccentScope accent="brand"> <Text className="text-accent">Title</Text> </AccentScope> ``` Correct: ```tsx <Text accent="brand" className="text-accent">Title</Text> ``` `Text`, `Surface`, `Box`, `Button`, `Message` and others accept `accent` directly. Reserve `AccentScope` for grouping several children or wrapping ones that don't take the prop. Source: packages/alouette/src/ui/primitives/Text.tsx, ui/containers/AccentScope.tsx ### MEDIUM Using nativewind useUnstableNativeVariable for token values Wrong: ```tsx import { useUnstableNativeVariable } from "nativewind"; const color = useUnstableNativeVariable("--color-accent"); ``` Correct: ```tsx import { useThemeToken } from "alouette"; const color = useThemeToken("--color-accent"); ``` `useThemeToken` reads alouette's generated theme map keyed by the active theme; it works on web and native and is stable, unlike nativewind's unstable hook. Source: packages/alouette/src/core/useThemeToken.ts ### MEDIUM Expecting var() chains to resolve on native Wrong: ```css --color-accent: var(--color-brand); ``` Correct: ```css --color-accent: #2563eb; ``` On native, NativeWind resolves CSS variables from a lookup table and cannot follow a `var()` that points at another `var()`. alouette sub-themes use concrete hex values per mode+accent for this reason. Source: CLAUDE.md (Native constraint: no CSS variable chains) ## References - [Token catalog](references/tokens.md) — color, spacing, radius and shadow token names. See also: alouette-typography/SKILL.md — color tokens are applied through Text.