AniUI

Theming

Customize colors using CSS variables and Tailwind classes.

How It Works#

AniUI uses CSS custom properties (variables) defined in global.css. These map to Tailwind utility classes through your tailwind.config.js. Colors use HSL format without the hsl() wrapper so Tailwind can apply opacity modifiers.

Convention#

Each color has a background and foreground pair. Use the background color for surfaces and the foreground for text on that surface:

<View className="bg-primary">
  <Text className="text-primary-foreground">Button text</Text>
</View>
<View className="bg-card">
  <Text className="text-card-foreground">Card content</Text>
</View>

Available Tokens#

PropTypeDefault
--background
bg-background / text-foreground
Page background
--primary
bg-primary / text-primary-foreground
Buttons, links
--secondary
bg-secondary / text-secondary-foreground
Secondary actions
--muted
bg-muted / text-muted-foreground
Subtle backgrounds, helper text
--accent
bg-accent / text-accent-foreground
Highlights, hover states
--destructive
bg-destructive / text-destructive-foreground
Errors, delete actions
--card
bg-card / text-card-foreground
Card surfaces
--border
border-border
Borders, dividers
--input
bg-input
Input backgrounds

Theme Presets#

Switch presets with the CLI. Each preset changes the primary color while keeping the neutral palette consistent:

npx @aniui/cli theme
  • Default — Neutral dark/light
  • Blue — Primary: #3B82F6
  • Green — Primary: #22C55E
  • Orange — Primary: #F97316
  • Rose — Primary: #F43F5E

Custom Colors#

To create your own theme, edit the CSS variables in global.css. Values use HSL format (hue saturation% lightness%) without the hsl() wrapper:

global.css
:root {
  --primary: 262 83% 58%;          /* purple */
  --primary-foreground: 0 0% 100%; /* white text on purple */
}
.dark {
  --primary: 262 83% 68%;          /* lighter purple for dark mode */
  --primary-foreground: 0 0% 100%;
}

No other config changes needed — Tailwind picks up the new values automatically since tailwind.config.js references hsl(var(--primary)).

How Tokens Flow#

Understanding the full pipeline helps when debugging or extending themes:

  1. global.css defines raw HSL values: --primary: 240 5.9% 10%
  2. tailwind.config.js maps them to Tailwind colors: primary: "hsl(var(--primary))"
  3. Components use Tailwind classes: bg-primary text-primary-foreground
  4. NativeWind compiles these to native styles at build time via Metro

Unlike web CSS where variables resolve at runtime, NativeWind processes CSS variables through the Metro bundler at build time. This means changes to global.css require a rebuild to take effect.

Adding Custom Tokens#

Need more semantic colors like success or info? Add them in three steps:

1. Define the CSS variable in both light and dark modes:

global.css
:root {
  --success: 142 76% 36%;
  --success-foreground: 0 0% 100%;
  --info: 217 91% 60%;
  --info-foreground: 0 0% 100%;
}
.dark {
  --success: 142 76% 46%;
  --success-foreground: 0 0% 100%;
  --info: 217 91% 70%;
  --info-foreground: 0 0% 100%;
}

2. Map them in tailwind.config.js:

tailwind.config.js
// Inside theme.extend.colors:
success: {
  DEFAULT: "hsl(var(--success))",
  foreground: "hsl(var(--success-foreground))",
},
info: {
  DEFAULT: "hsl(var(--info))",
  foreground: "hsl(var(--info-foreground))",
},

3. Use in your components:

<View className="bg-success rounded-md p-4">
  <Text className="text-success-foreground">Payment successful!</Text>
</View>

Global Component Overrides#

Since AniUI components are source files you own, you have two approaches for global styling changes:

Edit the component source directly:

Change the cva base string to affect all instances. For example, making all buttons fully rounded:

components/ui/button.tsx
// Change the base styles in buttonVariants:
const buttonVariants = cva(
  "flex-row items-center justify-center rounded-full min-h-12 min-w-12",
  //                                     ^^^^^^^^^^^^
  //                                     was: rounded-md
  { ... }
);

Create a wrapper component:

For project-wide defaults without modifying the source:

import { Button, ButtonProps } from "@/components/ui/button";
import { cn } from "@/lib/utils";

export function AppButton({ className, ...props }: ButtonProps) {
  return <Button className={cn("rounded-full", className)} {...props} />;
}