# @neondatabase/auth-ui > React UI components and theming for Neon Auth - pre-built sign-in, sign-up, and user management forms with customizable styling. ## Installation ```bash npm install @neondatabase/auth-ui @neondatabase/auth ``` ## CSS Import Decision | Your Setup | Import Path | Bundle Size | |------------|-------------|-------------| | No Tailwind | `@import '@neondatabase/auth-ui/css'` | ~47KB | | Tailwind v4 | `@import '@neondatabase/auth-ui/tailwind'` | ~2KB (tokens only) | **Rule:** Never import both. Causes duplicate styles. **Without Tailwind (pre-built CSS):** ```typescript // In layout.tsx or _app.tsx import "@neondatabase/auth-ui/css"; ``` **With Tailwind v4:** ```css /* globals.css */ @import 'tailwindcss'; @import '@neondatabase/auth-ui/tailwind'; /* Your overrides go here */ ``` ## Available Components ### Authentication Forms - `SignInForm` - Email/password + OAuth sign in - `SignUpForm` - New user registration - `AuthView` - Dynamic view based on route path - `SignedIn` / `SignedOut` / `AuthLoading` - Conditional rendering wrappers ### Account Management - `UserButton` - Avatar with dropdown menu (sign out, settings) - `UserAvatar` - Just the avatar image - `AccountView` - Account settings pages - `SettingsCard` - Individual settings sections ### Organization (if enabled on server) - `OrganizationView` - Org management pages - `OrganizationSwitcher` - Switch between organizations ## Provider Props ```typescript import { NeonAuthUIProvider } from "@neondatabase/auth-ui"; {children} ``` | Prop | Type | Default | Description | |------|------|---------|-------------| | `authClient` | `NeonAuthPublicApi` | Required | Your auth client from `createAuthClient()` | | `className` | `string` | - | Additional CSS classes for the wrapper div | | `defaultTheme` | `'light' \| 'dark' \| 'system'` | `'system'` | Initial theme for next-themes | | `redirectTo` | `string` | - | URL to redirect after successful auth | ## CSS Layer Architecture Auth-UI styles use `@layer neon-auth` for cascade priority control. This ensures **your CSS always wins**. ``` Priority (lowest to highest): 1. @layer neon-auth ← Auth-UI styles live here 2. @layer base ← Your base styles 3. @layer components ← Your component styles 4. @layer utilities ← Tailwind utilities 5. Unlayered CSS ← Your custom overrides (HIGHEST priority) ``` **What this means:** - Your `:root` variables always override auth-ui defaults - Your unlayered CSS always beats auth-ui styles - No need to use `!important` or specificity hacks **Example:** ```css /* This ALWAYS wins over auth-ui's default --primary */ :root { --primary: oklch(0.55 0.25 250); } ``` ## Theme Tokens Auth-UI CSS is designed to **never override your theme**. It uses a fallback pattern that respects your existing CSS variables. ### How It Works Auth-UI defines `--neon-*` prefixed variables on `:root` inside `@layer neon-auth`: ```css --neon-primary: var(--primary, oklch(0.205 0 0)); ``` This means: 1. If you define `--primary` in `:root`, auth-ui uses YOUR value 2. If you don't, auth-ui uses its default ### Customizing Colors Override in `:root` (light) and `.dark` (dark mode): ```css :root { /* Primary - buttons, links, focus rings */ --primary: oklch(0.205 0 0); --primary-foreground: oklch(0.985 0 0); /* Secondary - secondary buttons */ --secondary: oklch(0.97 0 0); --secondary-foreground: oklch(0.205 0 0); /* Background/Foreground - page colors */ --background: oklch(1 0 0); --foreground: oklch(0.145 0 0); /* Muted - placeholders, disabled states */ --muted: oklch(0.97 0 0); --muted-foreground: oklch(0.556 0 0); /* Accent - hover states */ --accent: oklch(0.97 0 0); --accent-foreground: oklch(0.205 0 0); /* Destructive - errors, delete actions */ --destructive: oklch(0.577 0.245 27.325); /* UI Elements */ --border: oklch(0.922 0 0); --input: oklch(0.922 0 0); --ring: oklch(0.708 0 0); --radius: 0.625rem; } .dark { --primary: oklch(0.922 0 0); --primary-foreground: oklch(0.205 0 0); --secondary: oklch(0.269 0 0); --secondary-foreground: oklch(0.985 0 0); --background: oklch(0.145 0 0); --foreground: oklch(0.985 0 0); --muted: oklch(0.269 0 0); --muted-foreground: oklch(0.708 0 0); --accent: oklch(0.269 0 0); --accent-foreground: oklch(0.985 0 0); --destructive: oklch(0.704 0.191 22.216); --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); --ring: oklch(0.556 0 0); } ``` ### Token Pairing Rules **CRITICAL:** Always override pairs together to maintain contrast. | Background Token | Foreground Token | Min Contrast | |-----------------|------------------|--------------| | `--primary` | `--primary-foreground` | 4.5:1 | | `--secondary` | `--secondary-foreground` | 4.5:1 | | `--background` | `--foreground` | 4.5:1 | | `--muted` | `--muted-foreground` | 4.5:1 | | `--accent` | `--accent-foreground` | 4.5:1 | | `--destructive` | `--destructive-foreground` | 4.5:1 | ### Additional Tokens ```css :root { /* Cards and Popovers */ --card: oklch(1 0 0); --card-foreground: oklch(0.145 0 0); --popover: oklch(1 0 0); --popover-foreground: oklch(0.145 0 0); /* Border Radius Scale */ --radius: 0.625rem; /* Base (10px) */ --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); /* Sidebar (if using sidebar components) */ --sidebar: oklch(0.985 0 0); --sidebar-foreground: oklch(0.145 0 0); --sidebar-primary: oklch(0.205 0 0); --sidebar-primary-foreground: oklch(0.985 0 0); --sidebar-accent: oklch(0.97 0 0); --sidebar-accent-foreground: oklch(0.205 0 0); --sidebar-border: oklch(0.922 0 0); --sidebar-ring: oklch(0.708 0 0); /* Charts (if using data visualization) */ --chart-1: oklch(0.646 0.222 41.116); --chart-2: oklch(0.6 0.118 184.704); --chart-3: oklch(0.398 0.07 227.392); --chart-4: oklch(0.828 0.189 84.429); --chart-5: oklch(0.769 0.188 70.08); } ``` ## OKLCH Color Format Neon Auth UI uses OKLCH for perceptually uniform colors. **Format:** `oklch(L C H)` or `oklch(L C H / alpha)` | Parameter | Range | Description | |-----------|-------|-------------| | L (Lightness) | 0-1 | 0 = black, 1 = white | | C (Chroma) | 0-0.4 | 0 = gray, higher = more vivid | | H (Hue) | 0-360 | Color wheel degrees | | alpha | 0-1 or 0%-100% | Opacity | **Examples:** ```css --primary: oklch(0.55 0.25 250); /* Vivid blue */ --primary: oklch(0.55 0.25 250 / 50%); /* 50% opacity */ --muted: oklch(0.5 0 0); /* Neutral gray (no chroma) */ ``` **Convert HEX/RGB to OKLCH:** https://oklch.com ## Dark Mode Implementation ### Option 1: next-themes (Recommended for Next.js) ```bash npm install next-themes ``` ```typescript // app/layout.tsx import { ThemeProvider } from "next-themes"; export default function Layout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ```typescript // components/theme-toggle.tsx "use client"; import { useTheme } from "next-themes"; export function ThemeToggle() { const { theme, setTheme } = useTheme(); return ( ); } ``` ### Option 2: Vanilla JavaScript ```typescript // Check system preference const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; // Apply dark mode document.documentElement.classList.toggle("dark", prefersDark); // Toggle manually function toggleDarkMode() { document.documentElement.classList.toggle("dark"); } ``` ### Option 3: CSS Only (System Preference) ```css @media (prefers-color-scheme: dark) { :root { /* Dark mode values applied automatically */ --background: oklch(0.145 0 0); --foreground: oklch(0.985 0 0); /* ... other dark tokens */ } } ``` ## Common Mistakes ### 1. Importing Both CSS Paths ```css /* WRONG - duplicate styles, ~94KB */ @import '@neondatabase/auth-ui/css'; @import '@neondatabase/auth-ui/tailwind'; /* CORRECT - pick one */ @import '@neondatabase/auth-ui/css'; ``` ### 2. Missing Foreground Pairs ```css /* WRONG - white text on light background */ :root { --primary: oklch(0.9 0.1 250); } /* CORRECT - ensure contrast */ :root { --primary: oklch(0.9 0.1 250); --primary-foreground: oklch(0.1 0 0); } ``` ### 3. Using HEX/RGB Instead of OKLCH ```css /* WRONG - may not work correctly */ :root { --primary: #3b82f6; } /* CORRECT - use OKLCH format */ :root { --primary: oklch(0.59 0.2 262); } ``` ### 4. Wrong CSS Import Order ```css /* WRONG - overrides load before Neon CSS */ @import './my-overrides.css'; @import '@neondatabase/auth-ui/css'; /* CORRECT - Neon CSS first, then overrides */ @import '@neondatabase/auth-ui/css'; @import './my-overrides.css'; /* OR inline after import */ @import '@neondatabase/auth-ui/css'; :root { --primary: oklch(0.55 0.25 250); } ``` ### 5. Forgetting Dark Mode Tokens ```css /* WRONG - light mode only */ :root { --primary: oklch(0.55 0.25 250); --primary-foreground: oklch(0.98 0 0); } /* CORRECT - both modes */ :root { --primary: oklch(0.55 0.25 250); --primary-foreground: oklch(0.98 0 0); } .dark { --primary: oklch(0.75 0.2 250); --primary-foreground: oklch(0.1 0 0); } ``` ## Form Customization ### Props ```typescript ``` ### Disabling Features ```typescript ``` ### Custom Fields ```typescript ``` ## Component-Specific Styling All UI components accept `classNames` props for targeted customization: ```typescript import { SignInForm } from "@neondatabase/auth-ui"; ``` **Available classNames interfaces:** - `AuthViewClassNames` - `AuthFormClassNames` - `UserAvatarClassNames` - `UserButtonClassNames` - `SettingsCardClassNames` ## Browser Support Auth-UI uses modern CSS features with excellent browser support: | Feature | Chrome | Firefox | Safari | Edge | Coverage | |---------|--------|---------|--------|------|----------| | CSS `@layer` | 99+ | 97+ | 15.4+ | 99+ | ~95% | | `display: contents` | 65+ | 59+ | 11.1+ | 79+ | ~97% | | OKLCH colors | 111+ | 113+ | 15.4+ | 111+ | ~95% | | CSS custom properties | 49+ | 31+ | 9.1+ | 16+ | ~98% | **Graceful degradation:** - Older browsers ignore `@layer` but styles still work correctly via `:root` variables - If OKLCH is unsupported, consider providing HSL fallbacks in your overrides **Known issues:** - Safari < 16 may have accessibility issues with `display: contents` (rare edge case) ## Links - [Full theme.css source](https://github.com/neondatabase/neon-js/blob/main/packages/auth-ui/src/theme.css) - [OKLCH Color Converter](https://oklch.com) - [shadcn/ui Theming Guide](https://ui.shadcn.com/docs/theming) - [better-auth-ui Documentation](https://better-auth-ui.com) - [next-themes](https://github.com/pacocoursey/next-themes)