Styles Documentation
Overview
The styles directory (src/styles/) contains global CSS styles and theming configuration. The application primarily uses Tailwind CSS for styling, with additional global styles for specific requirements.
Directory Structure
src/styles/
└── globals.css # Global CSS styles and Tailwind directivesAdditional styling configuration:
├── tailwind.config.ts # Tailwind configuration (project root)
├── components.json # shadcn/ui configuration (project root)
└── postcss.config.cjs # PostCSS configuration (project root)Global Styles (globals.css)
The main CSS file that defines Tailwind directives, CSS variables, and global styles.
Structure
@tailwind base;
@tailwind components;
@tailwind utilities;
/* CSS Variables */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--radius: 0.5rem;
}
}
/* Global element styles */
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
}
}
/* Custom utilities */
@layer utilities {
.step {
counter-increment: step;
}
.step:before {
@apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background -ml-[50px] mt-[-4px];
content: counter(step);
}
}Tailwind Configuration (tailwind.config.ts)
Extended Tailwind configuration with custom theme values.
Key Extensions
import type { Config } from 'tailwindcss';
const config: Config = {
darkMode: ['class'],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
theme: {
container: {
center: true,
padding: '2rem',
screens: {
'2xl': '1400px',
},
},
extend: {
// Color system using CSS variables
colors: {
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))',
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))',
},
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
},
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
fontFamily: {
sans: ['var(--font-howden)', 'system-ui', 'sans-serif'],
},
keyframes: {
'accordion-down': {
from: { height: '0' },
to: { height: 'var(--radix-accordion-content-height)' },
},
'accordion-up': {
from: { height: 'var(--radix-accordion-content-height)' },
to: { height: '0' },
},
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out',
},
},
},
plugins: [
require('tailwindcss-animate'),
],
};
export default config;shadcn/ui Configuration (components.json)
Configuration for shadcn/ui component library:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/styles/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/utils/cn"
}
}Styling Architecture
1. Tailwind First
Use Tailwind utilities for all styling needs:
// Preferred
<div className="flex items-center justify-between p-4 bg-white rounded-lg shadow-sm">
// Avoid
<div style={{ display: 'flex', alignItems: 'center', padding: '1rem' }}>2. Component Variants
Use class-variance-authority for component variants:
import { cva, type VariantProps } from 'class-variance-authority';
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground',
outline: 'border border-input bg-background',
secondary: 'bg-secondary text-secondary-foreground',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
icon: 'h-10 w-10',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
);3. CSS Variables for Theming
HSL values in CSS variables enable easy theming:
:root {
--primary: 240 5.9% 10%; /* HSL values */
}
/* Usage in Tailwind */
.text-primary { color: hsl(var(--primary)); }Benefits:
- Easy dark mode switching
- Runtime theme customization
- Opacity support with
/syntax:bg-primary/50
Color System
Semantic Colors
| Token | Light Mode | Usage |
|---|---|---|
--background | White | Page background |
--foreground | Near black | Primary text |
--primary | Dark gray | Primary buttons, links |
--secondary | Light gray | Secondary buttons |
--muted | Very light gray | Subtle backgrounds |
--accent | Light gray | Highlights, hover states |
--destructive | Red | Errors, deletions |
--border | Light gray | Borders, dividers |
Color Usage Patterns
// Primary actions
<Button className="bg-primary text-primary-foreground hover:bg-primary/90">
Save
</Button>
// Secondary actions
<Button variant="secondary">Cancel</Button>
// Destructive actions
<Button variant="destructive">Delete</Button>
// Muted text
<p className="text-muted-foreground">Helper text</p>
// Card backgrounds
<Card className="bg-card text-card-foreground">Responsive Design
Breakpoints
| Breakpoint | Width | Usage |
|---|---|---|
sm | 640px | Small tablets |
md | 768px | Tablets |
lg | 1024px | Small laptops |
xl | 1280px | Desktops |
2xl | 1400px | Large screens |
Responsive Patterns
// Mobile-first approach
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
// Responsive padding
<div className="p-4 md:p-6 lg:p-8">
// Responsive typography
<h1 className="text-xl md:text-2xl lg:text-3xl">
// Hide/show elements
<MobileNav className="block lg:hidden" />
<DesktopNav className="hidden lg:block" />Custom Utilities
Container Queries
@layer utilities {
.container-query {
container-type: inline-size;
}
@container (min-width: 400px) {
.container-responsive {
flex-direction: row;
}
}
}Animation Utilities
@layer utilities {
.animate-fade-in {
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
}Dark Mode
The application supports dark mode through CSS variables:
:root {
/* Light mode (default) */
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
}
.dark {
/* Dark mode overrides */
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
}Implementation:
// Using next-themes
import { ThemeProvider } from 'next-themes';
<ThemeProvider attribute="class" defaultTheme="light">
<App />
</ThemeProvider>
// Toggle theme
import { useTheme } from 'next-themes';
const { theme, setTheme } = useTheme();
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle
</button>Best Practices
1. Use cn() Utility
Combine Tailwind classes with proper merging:
import { cn } from '@/utils/cn';
<div className={cn(
'base-classes',
conditional && 'conditional-classes',
className // Allow override
)}>2. Avoid Arbitrary Values
// Avoid
<div className="w-[123px] h-[45px]">
// Prefer (add to tailwind.config.ts if needed)
<div className="w-32 h-12">3. Group Related Classes
// Logical grouping
<div className="
/* Layout */
flex items-center justify-between gap-4
/* Spacing */
p-4 m-2
/* Visual */
bg-white rounded-lg shadow-sm border
/* Typography */
text-sm font-medium text-gray-900
">4. Use Component Primitives
// Instead of repeating classes
const Card = ({ children, className }) => (
<div className={cn('rounded-lg border bg-card p-4', className)}>
{children}
</div>
);
// Use consistently
<Card className="hover:shadow-md">5. Responsive Container
// Use container queries for component-level responsiveness
<div className="@container">
<div className="flex flex-col @md:flex-row">Styling Checklist
When adding new components:
- Use Tailwind utilities (not inline styles)
- Apply
cn()for class merging - Support dark mode (use semantic colors)
- Add responsive breakpoints
- Test keyboard focus states
- Verify reduced motion support
- Check color contrast ratios
Related Documentation
Last updated on