Skip to content

shadcn/ui Integration Guide for Authentication UI

shadcn/ui Integration Guide for Authentication UI

Section titled “shadcn/ui Integration Guide for Authentication UI”

This document provides comprehensive guidance on using shadcn/ui components in the Bartendie authentication system, including examples, best practices, and customization patterns.

Bartendie uses shadcn/ui as the primary component library for building consistent, accessible, and modern user interfaces. The authentication system showcases the full integration of shadcn/ui components with TypeScript and Tailwind CSS v4.

File: frontend/components.json

{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/index.css",
"baseColor": "gray",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui"
},
"iconLibrary": "lucide"
}

Key Configuration:

  • Style: “new-york” - Modern, clean design system
  • TypeScript: Full TypeScript support enabled
  • CSS Variables: Enabled for theming flexibility
  • Icon Library: Lucide React for consistent iconography

Location: frontend/src/components/ui/button.tsx

Usage Examples:

// Primary action button
<Button type="submit" className="w-full" size="lg">
{loading ? 'Signing in...' : 'Sign in'}
</Button>
// Secondary button with icon
<Button variant="outline" size="sm">
<Eye className="h-4 w-4 mr-2" />
Show Password
</Button>
// Destructive action
<Button variant="destructive">
Delete Account
</Button>

Available Variants:

  • default - Primary blue button
  • destructive - Red button for dangerous actions
  • outline - Bordered button with transparent background
  • secondary - Gray button for secondary actions
  • ghost - Transparent button with hover effects
  • link - Text-only button with underline

Available Sizes:

  • default - Standard height (36px)
  • sm - Small height (32px)
  • lg - Large height (40px)
  • icon - Square button for icons only

Location: frontend/src/components/ui/input.tsx

Usage Examples:

// Basic input with validation
<Input
id="email"
type="email"
value={formData.email}
onChange={handleInputChange('email')}
placeholder="Enter your email"
className={error?.field === 'email' ? 'border-red-500' : ''}
/>
// Password input with toggle visibility
<div className="relative">
<Input
type={showPassword ? 'text' : 'password'}
className="pr-10"
/>
<button className="absolute inset-y-0 right-0 flex items-center pr-3">
{showPassword ? <EyeOff /> : <Eye />}
</button>
</div>

Features:

  • Built-in focus states with ring effects
  • Error state styling support
  • Consistent padding and typography
  • Full accessibility support

Location: frontend/src/components/ui/card.tsx

Usage Examples:

// Authentication form card
<Card className="shadow-lg">
<CardHeader className="space-y-1">
<CardTitle className="text-2xl font-semibold text-center">
Sign in
</CardTitle>
<CardDescription className="text-center">
Enter your email and password to access your account
</CardDescription>
</CardHeader>
<CardContent>
<form className="space-y-4">
{/* Form content */}
</form>
</CardContent>
</Card>

Component Structure:

  • Card - Container with border and shadow
  • CardHeader - Top section for titles and descriptions
  • CardTitle - Primary heading
  • CardDescription - Secondary text
  • CardContent - Main content area
  • CardFooter - Bottom section for actions

Location: frontend/src/components/ui/label.tsx

Usage Examples:

// Form field label
<Label htmlFor="email" className="flex items-center gap-2">
<Mail className="h-4 w-4" />
Email address
</Label>
// Required field indicator
<Label htmlFor="password" className="text-sm font-medium">
Password *
</Label>

Features:

  • Proper form association with htmlFor
  • Consistent typography and spacing
  • Icon integration support
  • Accessibility compliance

Location: frontend/src/components/ui/checkbox.tsx

Usage Examples:

// Remember me checkbox
<div className="flex items-center space-x-2">
<Checkbox
id="remember-me"
checked={formData.rememberMe}
onCheckedChange={(checked) =>
setFormData(prev => ({ ...prev, rememberMe: checked as boolean }))
}
/>
<Label htmlFor="remember-me" className="text-sm font-normal">
Remember me
</Label>
</div>
// Terms acceptance
<Checkbox
id="accept-terms"
required
checked={formData.acceptTerms}
onCheckedChange={(checked) =>
setFormData(prev => ({ ...prev, acceptTerms: checked as boolean }))
}
/>

Features:

  • Controlled component pattern
  • Custom styling with CSS variables
  • Smooth animations
  • Keyboard navigation support

File: frontend/src/components/auth/LoginPage.tsx

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
const LoginPage: React.FC = () => {
return (
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-gray-50 to-gray-100">
<Card className="shadow-lg max-w-md w-full">
<CardHeader>
<CardTitle>Welcome back</CardTitle>
<CardDescription>
Sign in to your account to continue
</CardDescription>
</CardHeader>
<CardContent>
<form className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email address</Label>
<Input
id="email"
type="email"
placeholder="Enter your email"
/>
</div>
<Button type="submit" className="w-full">
Sign in
</Button>
</form>
</CardContent>
</Card>
</div>
);
};

File: frontend/src/components/auth/AccountSettingsPage.tsx

// Profile settings section
<Card className="shadow-lg">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<User className="h-5 w-5" />
Profile Information
</CardTitle>
<CardDescription>
Update your account profile information
</CardDescription>
</CardHeader>
<CardContent>
<form className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email" className="flex items-center gap-2">
<Mail className="h-4 w-4" />
Email address
</Label>
<Input
id="email"
type="email"
value={profileData.email}
onChange={handleInputChange('email')}
/>
</div>
<Button type="submit" className="w-full">
<Save className="h-4 w-4 mr-2" />
Update Profile
</Button>
</form>
</CardContent>
</Card>

shadcn/ui components use CSS custom properties for theming:

:root {
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
}
// Custom button with additional styling
<Button
className={cn(
"bg-gradient-to-r from-indigo-500 to-purple-600",
"hover:from-indigo-600 hover:to-purple-700",
"transition-all duration-200"
)}
>
Custom Gradient Button
</Button>
// Input with custom validation styling
<Input
className={cn(
"transition-colors",
error ? "border-red-500 focus:border-red-500" : "",
success ? "border-green-500 focus:border-green-500" : ""
)}
/>
import {
Eye,
EyeOff,
Mail,
Lock,
User,
AlertCircle,
CheckCircle
} from 'lucide-react';
// Icon in button
<Button>
<Lock className="h-4 w-4 mr-2" />
Change Password
</Button>
// Icon in label
<Label className="flex items-center gap-2">
<Mail className="h-4 w-4" />
Email address
</Label>
// Status icons
{error && (
<div className="flex items-center gap-2 text-red-600">
<AlertCircle className="h-4 w-4" />
<span>{error.message}</span>
</div>
)}
// Use consistent spacing classes
<form className="space-y-4">
<div className="space-y-2">
<Label>Field Label</Label>
<Input />
</div>
</form>
// Always associate labels with inputs
<Label htmlFor="email">Email</Label>
<Input id="email" name="email" />
// Use semantic form elements
<form onSubmit={handleSubmit}>
<fieldset className="space-y-4">
<legend className="sr-only">Login Form</legend>
{/* Form fields */}
</fieldset>
</form>
// Consistent error display pattern
{error?.field === 'email' && (
<p className="text-sm text-red-600">{error.message}</p>
)}
// Global error messages
{error && !error.field && (
<div className="flex items-center gap-2 p-3 text-sm text-red-600 bg-red-50 border border-red-200 rounded-md">
<AlertCircle className="h-4 w-4 flex-shrink-0" />
<span>{error.message}</span>
</div>
)}
// Button loading states
<Button disabled={isLoading}>
{isLoading ? 'Processing...' : 'Submit'}
</Button>
// Input disabled states
<Input
disabled={isLoading}
placeholder="Enter email"
/>
  • Keyboard Navigation: All components support tab navigation
  • Screen Reader Support: Proper ARIA attributes and labels
  • Focus Management: Visible focus indicators
  • Color Contrast: WCAG compliant color combinations
// Enhanced form accessibility
<form role="form" aria-labelledby="login-title">
<h2 id="login-title" className="sr-only">Login Form</h2>
<div role="group" aria-labelledby="credentials-group">
<h3 id="credentials-group" className="sr-only">Credentials</h3>
<Label htmlFor="email">
Email address
<span className="sr-only">(required)</span>
</Label>
<Input
id="email"
required
aria-describedby="email-error"
aria-invalid={!!emailError}
/>
{emailError && (
<p id="email-error" role="alert" className="text-red-600">
{emailError}
</p>
)}
</div>
</form>

shadcn/ui components are designed for optimal tree shaking:

// Import only what you need
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
// Avoid importing entire library
// import * from '@/components/ui'; // ❌ Don't do this

Current authentication UI bundle impact:

  • Button component: ~2KB
  • Input component: ~1.5KB
  • Card components: ~1KB
  • Total shadcn/ui overhead: ~8KB (gzipped)
  1. Toast Notifications - For success/error feedback
  2. Dialog/Modal - For confirmation dialogs
  3. Dropdown Menu - For user account menu
  4. Form Components - Enhanced form validation
  5. Loading Spinner - Better loading states
  1. Multiple Theme Support - Light/dark/custom themes
  2. Brand Customization - Company-specific styling
  3. Component Variants - Additional style variations

This guide provides the foundation for consistent shadcn/ui usage across the Bartendie application, ensuring maintainable and accessible user interfaces.