# Theming URL: /docs/native/guide/theming Customize the look and feel of Docyrus UI Native components with DocyThemeProvider, color schemes, and Tailwind CSS. ## Overview Docyrus UI Native uses **Tailwind CSS v4** via Uniwind for component styling. Static styles are expressed as `className` using Tailwind utility classes and semantic color tokens (`bg-card`, `text-foreground`, `border-border`). Dynamic values that can't be expressed as className (DocyrusIcon colors, platform shadows, runtime color lookups) are accessed via the `useDocyTheme()` hook. Two sources of truth, kept in sync by value: - **CSS tokens** (`styles/docyrus-native/index.css`, installed by the CLI) — what every `className` resolves against. Required; see [Design Tokens](#design-tokens). - **JS palette** (`useDocyTheme().colors`) — the same colors as raw strings, for props that need one. ## Setup Import the design tokens from your Uniwind CSS entry (see [Installation](/docs/native/guide/installation#2-create-global-css)): ```css title="src/styles/global.css" @import "tailwindcss"; @import "uniwind"; @import "./docyrus-native/index.css"; ``` Then wrap your app root with `DocyThemeProvider`: ```tsx title="app/_layout.tsx" import '../src/styles/global.css'; import { DocyThemeProvider } from '@/lib/docyrus/theme'; export default function RootLayout() { return ( ); } ``` ### Provider Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `colorScheme` | `ColorScheme` | — | Controlled color scheme | | `mode` | `ThemeMode` | — | Controlled theme mode | | `lang` | `ThemeLanguage` | — | Controlled language | | `defaultColorScheme` | `ColorScheme` | `'docyrus'` | Initial color scheme | | `defaultMode` | `ThemeMode` | `'system'` | Initial theme mode | | `defaultLang` | `ThemeLanguage` | `'en'` | Initial language | | `brand` | `Record` | — | Custom brand colors | | `fontFamily` | `ThemeFontFamily` | System fonts | Custom font family | | `messages` | `Record` | — | App-level message bag exposed through `useDocyTheme()`. Docyrus components no longer read it — translate component copy with ` ); } ``` ### className vs style Decision Guide | Use Case | Approach | Example | |----------|----------|---------| | Static layout/colors | `className` | `className="flex-1 p-4 bg-card rounded-lg"` | | Semantic colors | `className` | `className="text-foreground bg-primary/10"` | | Dark mode | `className` | `className="bg-muted dark:bg-background"` | | Pressable states | `className` | `className="active:opacity-70 active:scale-95"` | | Animated values | `style` | `style={{ opacity: fadeAnim }}` | | Platform shadows | `style` | `style={cardShadow(isDark, colors.border)}` | | DocyrusIcon color | `color` prop | `color={colors.primary}` | | Dynamic theme lookup | `style` | `style={{ backgroundColor: colors[key] }}` | ## useDocyTheme Hook Access theme values for **dynamic use cases only** — static styling should use Tailwind className: ```tsx import { useDocyTheme } from '@/lib/docyrus/theme'; import { DocyrusIcon } from '@/components/docyrus-native/docyrus-icon'; function MyComponent() { const { colors, isDark } = useDocyTheme(); return ( ); } ``` ### Theme Object ```tsx const theme = useDocyTheme(); theme.colors // ThemeColors — semantic + Tailwind palette theme.spacing // ThemeSpacing — numeric scale theme.borderRadius // ThemeBorderRadius theme.fieldHeight // ThemeFieldHeight theme.fontFamily // ThemeFontFamily theme.isDark // boolean — for conditional logic theme.colorScheme // 'docyrus' | 'slate' | 'gray' | 'zinc' | ... theme.mode // 'light' | 'dark' | 'system' theme.lang // 'en' | 'tr' theme.brand // Custom brand object theme.messages // i18n messages ``` ## Color Schemes Docyrus UI Native ships with **13 color schemes**, each providing light and dark variants: ### Base Schemes (Neutral) | Scheme | Description | |--------|-------------| | `slate` | Blue-gray neutral tones | | `gray` | Pure gray neutral tones | | `zinc` | Warm gray neutral tones | | `stone` | Warm beige neutral tones | | `neutral` | True neutral (no hue) | ### Accent Schemes | Scheme | Primary Color | Base | |--------|--------------|------| | `docyrus` | Slate + Blue accent | Slate | | `red` | Red 600 | Zinc | | `rose` | Rose 600 | Zinc | | `orange` | Orange 500 | Stone | | `green` | Green 600 | Zinc | | `blue` | Blue 500 | Slate | | `yellow` | Yellow 500 | Stone | | `violet` | Violet 500 | Gray | ```tsx ``` `colorScheme` switches the **JS palette** (`useDocyTheme().colors`). The `className` tokens come from CSS: `index.css` ships only the default `docyrus` scheme. The other 12 are opt-in Uniwind custom themes in `color-schemes.css` (installed next to `index.css`), named `-light` / `-dark`, with the same variable set: 1. Import it after `index.css`, **by relative path**: ```css title="src/styles/global.css" @import "tailwindcss"; @import "uniwind"; @import "./docyrus-native/index.css"; @import "./docyrus-native/color-schemes.css"; ``` 2. Register the theme names in Metro — Tailwind rejects an `@variant` it doesn't know, so every scheme in the file must be listed. Restart Metro with `--clear` afterwards: ```js title="metro.config.js" const schemes = ['slate', 'gray', 'zinc', 'stone', 'neutral', 'red', 'rose', 'orange', 'green', 'blue', 'yellow', 'violet']; module.exports = withUniwindConfig(config, { cssEntryFile: './src/styles/global.css', polyfills: { rem: 14 }, extraThemes: schemes.flatMap(scheme => [`${scheme}-light`, `${scheme}-dark`]) }); ``` 3. Switch at runtime, keeping the JS palette in step: ```tsx import { Uniwind } from 'uniwind'; const { setColorScheme, isDark } = useDocyTheme(); function applyScheme(scheme: ColorScheme) { setColorScheme(scheme); Uniwind.setTheme(scheme === 'docyrus' ? 'system' : `${scheme}-${isDark ? 'dark' : 'light'}`); } ``` A custom theme is not adaptive — switch between `-light` and `-dark` yourself when the appearance changes, and note that `dark:` utilities only apply under the built-in `dark` theme. Core colors in `color-schemes.css` mirror the JS palettes; the extended surface / field tokens reuse the default Docyrus values. ## Semantic Color Tokens Every color scheme provides these semantic tokens, available as both Tailwind classes and `colors.*` values (the full class-only list is in [Design Tokens](#design-tokens)): | Token | Tailwind Class | JS Access | Description | |-------|---------------|-----------|-------------| | `background` | `bg-background` | `colors.background` | App background | | `foreground` | `text-foreground` | `colors.foreground` | Primary text | | `card` | `bg-card` | `colors.card` | Card surfaces | | `primary` | `bg-primary` | `colors.primary` | Primary actions | | `secondary` | `bg-secondary` | `colors.secondary` | Secondary surfaces | | `muted` | `bg-muted` | `colors.muted` | Muted backgrounds | | `destructive` | `bg-destructive` | `colors.destructive` | Destructive actions | | `border` | `border-border` | `colors.border` | Borders | | `success` | `bg-success` | `colors.success` | Success states | | `warning` | `bg-warning` | `colors.warning` | Warning states | | `info` | `bg-info` | `colors.info` | Info states | **Use Tailwind classes for static colors** (`className="bg-card text-foreground"`). **Use `colors.*` only when a raw color string is needed** (DocyrusIcon, chart libraries, `cardShadow()`, runtime lookups). ### Tailwind Color Palette In addition to semantic tokens, `colors` includes the full Tailwind palette (50–950 shades): ```tsx const { colors } = useDocyTheme(); // Only needed for dynamic runtime lookups — prefer className for static colors colors.blue[500] // '#3b82f6' colors.red[600] // '#dc2626' colors.emerald[400] // '#34d399' ``` Available palettes: `red`, `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`. ## Dark Mode ### With Tailwind Classes Components support dark mode variants via Tailwind: ```tsx ``` ### System-Based (Default) ```tsx ); } ``` ### Checking Dark Mode Use `isDark` for logic that can't be expressed as className (platform shadows, conditional rendering): ```tsx const { isDark, colors } = useDocyTheme(); // Platform shadows need style prop — no Tailwind equivalent ); } ``` ## Brand Colors Add custom brand-specific colors available throughout the theme: ```tsx type MyBrand = { accentBlue: string; accentGold: string; headerBg: string; }; brand={{ accentBlue: '#1E90FF', accentGold: '#FFD700', headerBg: '#0A1128', }} > ``` Access brand colors in components: ```tsx const { brand } = useDocyTheme(); // Brand colors are dynamic — use style prop ``` ## Localization The provider stores the active language (`lang` / `defaultLang`) and an optional `messages` bag for your own app code: ```tsx ``` ```tsx const { lang, messages } = useDocyTheme(); ``` Docyrus native components do **not** read `lang` or `messages` for their built-in copy. Every component renders an English fallback and looks up `ui..` through [``](/docs/native/hooks/use-ui-translation) — the same keys as the web package, so one translation catalog covers both platforms. Explicit copy props (`label`, `cancelLabel`, `messages`, …) always win. ## Web vs Native Comparison | Feature | Web (CSS Variables) | Native (Tailwind + Theme) | |---------|--------------------|-----------------------| | Static styling | `className="bg-primary p-4"` | `className="bg-primary p-4"` | | Token access | `var(--primary)` in CSS | `className="bg-primary"` or `colors.primary` | | Dark mode | `.dark` class + CSS | `className="dark:bg-background"` or `isDark` | | Color scheme | CSS variable swap | `colorScheme` prop on provider | | Custom colors | CSS variable override | `brand` prop | | Fonts | CSS `font-family` | `fontFamily` prop | | Animated values | CSS transitions / motion | `style` prop with Animated/Reanimated | | 3rd-party colors | CSS variable reference | `colors.*` from `useDocyTheme()` |