Card
Displays a card with header, content, and footer.
import { Button } from "@/components/ui/button"import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "@/components/ui/card"import { Input } from "@/components/ui/input"import { Label } from "@/components/ui/label"export default function CardDemo() { return ( <div className="w-full p-6 flex justify-center"> <Card className="w-full max-w-sm"> <CardHeader> <CardTitle>Login to your account</CardTitle> <CardDescription> Enter your email below to login to your account </CardDescription> <CardAction> <Button variant="link">Sign Up</Button> </CardAction> </CardHeader> <CardContent> <form> <div className="flex flex-col gap-6"> <div className="grid gap-2"> <Label htmlFor="email">Email</Label> <Input id="email" type="email" placeholder="[email protected]" required /> </div> <div className="grid gap-2"> <div className="flex items-center"> <Label htmlFor="password">Password</Label> <Button variant="link" size="sm" className="ml-auto p-0 h-auto text-xs"> Forgot your password? </Button> </div> <Input id="password" type="password" required /> </div> </div> </form> </CardContent> <CardFooter className="flex-col gap-2"> <Button type="submit" className="w-full"> Login </Button> <Button variant="outline" className="w-full"> Login with Google </Button> </CardFooter> </Card> </div> )}
import * as React from "react"import { Slot } from "@radix-ui/react-slot"import { cva, type VariantProps } from "class-variance-authority"import { cn } from "@/lib/utils"const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", lg: "h-10 rounded-md px-6 has-[>svg]:px-4", icon: "size-9", }, }, defaultVariants: { variant: "default", size: "default", }, })function Button({ className, variant, size, asChild = false, ...props}: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & { asChild?: boolean }) { const Comp = asChild ? Slot : "button" return ( <Comp data-slot="button" className={cn(buttonVariants({ variant, size, className }))} {...props} /> )}export { Button, buttonVariants }
Installation
npx shadcn@latest add card
Usage
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
export function CardDemo() {
return (
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
<CardAction>Card Action</CardAction>
</CardHeader>
<CardContent>
<p>Card Content</p>
</CardContent>
<CardFooter>
<p>Card Footer</p>
</CardFooter>
</Card>
)
}
Examples
Simple Card
Basic card structure with all components:
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "@/components/ui/card"export default function CardSimple() { return ( <div className="w-full p-6 flex justify-center"> <Card className="w-full max-w-sm"> <CardHeader> <CardTitle>Card Title</CardTitle> <CardDescription>Card Description</CardDescription> </CardHeader> <CardContent> <p>Card Content</p> </CardContent> <CardFooter> <p>Card Footer</p> </CardFooter> </Card> </div> )}
import * as React from "react"import { cn } from "@/lib/utils"function Card({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card" className={cn( "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className )} {...props} /> )}function CardHeader({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-header" className={cn( "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className )} {...props} /> )}function CardTitle({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-title" className={cn("leading-none font-semibold", className)} {...props} /> )}function CardDescription({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-description" className={cn("text-muted-foreground text-sm", className)} {...props} /> )}function CardAction({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-action" className={cn( "col-start-2 row-span-2 row-start-1 self-start justify-self-end", className )} {...props} /> )}function CardContent({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-content" className={cn("px-6", className)} {...props} /> )}function CardFooter({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-footer" className={cn("flex items-center px-6 [.border-t]:pt-6", className)} {...props} /> )}export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent,}
Card with Form
Card containing form elements for user input:
import { Button } from "@/components/ui/button"import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "@/components/ui/card"import { Input } from "@/components/ui/input"import { Label } from "@/components/ui/label"import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from "@/components/ui/select"export default function CardWithForm() { return ( <div className="w-full p-6 flex justify-center"> <Card className="w-full max-w-sm"> <CardHeader> <CardTitle>Create project</CardTitle> <CardDescription> Deploy your new project in one-click. </CardDescription> </CardHeader> <CardContent> <form> <div className="grid w-full items-center gap-4"> <div className="flex flex-col space-y-1.5"> <Label htmlFor="name">Name</Label> <Input id="name" placeholder="Name of your project" /> </div> <div className="flex flex-col space-y-1.5"> <Label htmlFor="framework">Framework</Label> <Select> <SelectTrigger id="framework"> <SelectValue placeholder="Select" /> </SelectTrigger> <SelectContent position="popper"> <SelectItem value="next">Next.js</SelectItem> <SelectItem value="sveltekit">SvelteKit</SelectItem> <SelectItem value="astro">Astro</SelectItem> <SelectItem value="nuxt">Nuxt.js</SelectItem> </SelectContent> </Select> </div> </div> </form> </CardContent> <CardFooter className="flex justify-between"> <Button variant="outline">Cancel</Button> <Button>Deploy</Button> </CardFooter> </Card> </div> )}
import * as React from "react"import { Slot } from "@radix-ui/react-slot"import { cva, type VariantProps } from "class-variance-authority"import { cn } from "@/lib/utils"const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", lg: "h-10 rounded-md px-6 has-[>svg]:px-4", icon: "size-9", }, }, defaultVariants: { variant: "default", size: "default", }, })function Button({ className, variant, size, asChild = false, ...props}: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & { asChild?: boolean }) { const Comp = asChild ? Slot : "button" return ( <Comp data-slot="button" className={cn(buttonVariants({ variant, size, className }))} {...props} /> )}export { Button, buttonVariants }
Card with Action
Card with action button in header:
import { Button } from "@/components/ui/button"import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle,} from "@/components/ui/card"import { BellIcon } from "lucide-react"export default function CardWithAction() { return ( <div className="w-full p-6 flex justify-center"> <Card className="w-full max-w-sm"> <CardHeader> <CardTitle>Notifications</CardTitle> <CardDescription> You have 3 unread messages. </CardDescription> <CardAction> <Button size="sm" variant="outline"> <BellIcon className="h-4 w-4" /> Mark as read </Button> </CardAction> </CardHeader> <CardContent> <div className="space-y-4"> <div className="flex items-center space-x-4 rounded-md border p-4"> <BellIcon className="h-4 w-4" /> <div className="flex-1 space-y-1"> <p className="text-sm font-medium leading-none"> Push Notifications </p> <p className="text-sm text-muted-foreground"> Send notifications to device. </p> </div> </div> </div> </CardContent> </Card> </div> )}
import * as React from "react"import { Slot } from "@radix-ui/react-slot"import { cva, type VariantProps } from "class-variance-authority"import { cn } from "@/lib/utils"const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", lg: "h-10 rounded-md px-6 has-[>svg]:px-4", icon: "size-9", }, }, defaultVariants: { variant: "default", size: "default", }, })function Button({ className, variant, size, asChild = false, ...props}: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & { asChild?: boolean }) { const Comp = asChild ? Slot : "button" return ( <Comp data-slot="button" className={cn(buttonVariants({ variant, size, className }))} {...props} /> )}export { Button, buttonVariants }
Stats Cards
Dashboard-style cards for displaying metrics:
import { Card, CardContent, CardDescription, CardHeader, CardTitle,} from "@/components/ui/card"import { TrendingUpIcon, UsersIcon, DollarSignIcon, ActivityIcon } from "lucide-react"export default function CardStats() { return ( <div className="w-full p-6 flex justify-center"> <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4 w-full max-w-6xl"> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Total Revenue</CardTitle> <DollarSignIcon className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent> <div className="text-2xl font-bold">$45,231.89</div> <p className="text-xs text-muted-foreground"> +20.1% from last month </p> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Subscriptions</CardTitle> <UsersIcon className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent> <div className="text-2xl font-bold">+2350</div> <p className="text-xs text-muted-foreground"> +180.1% from last month </p> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Sales</CardTitle> <TrendingUpIcon className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent> <div className="text-2xl font-bold">+12,234</div> <p className="text-xs text-muted-foreground"> +19% from last month </p> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Active Now</CardTitle> <ActivityIcon className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent> <div className="text-2xl font-bold">+573</div> <p className="text-xs text-muted-foreground"> +201 since last hour </p> </CardContent> </Card> </div> </div> )}
import * as React from "react"import { cn } from "@/lib/utils"function Card({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card" className={cn( "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className )} {...props} /> )}function CardHeader({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-header" className={cn( "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className )} {...props} /> )}function CardTitle({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-title" className={cn("leading-none font-semibold", className)} {...props} /> )}function CardDescription({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-description" className={cn("text-muted-foreground text-sm", className)} {...props} /> )}function CardAction({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-action" className={cn( "col-start-2 row-span-2 row-start-1 self-start justify-self-end", className )} {...props} /> )}function CardContent({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-content" className={cn("px-6", className)} {...props} /> )}function CardFooter({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card-footer" className={cn("flex items-center px-6 [.border-t]:pt-6", className)} {...props} /> )}export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent,}
Product Card
E-commerce product card with image and actions:
import { Button } from "@/components/ui/button"import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "@/components/ui/card"import { StarIcon } from "lucide-react"export default function CardProduct() { return ( <div className="w-full p-6 flex justify-center"> <Card className="w-48"> <CardContent className="p-3"> <div className="aspect-square rounded-md bg-gray-100 mb-2"> <div className="flex items-center justify-center h-full text-muted-foreground text-xs"> Product Image </div> </div> <CardTitle className="text-sm mb-1">Wireless Headphones</CardTitle> <CardDescription className="text-xs mb-2 line-clamp-2"> High-quality wireless headphones </CardDescription> <div className="flex items-center space-x-1 mb-2"> <div className="flex"> {[1, 2, 3, 4].map((star) => ( <StarIcon key={star} className="h-3 w-3 fill-yellow-400 text-yellow-400" /> ))} <StarIcon className="h-3 w-3 text-gray-300" /> </div> <span className="text-xs text-muted-foreground">(4.0)</span> </div> <div className="flex items-center justify-between"> <span className="text-sm font-bold">$199</span> <Button size="sm" className="text-xs px-2 py-1 h-7">Add</Button> </div> </CardContent> </Card> </div> )}
import * as React from "react"import { Slot } from "@radix-ui/react-slot"import { cva, type VariantProps } from "class-variance-authority"import { cn } from "@/lib/utils"const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", lg: "h-10 rounded-md px-6 has-[>svg]:px-4", icon: "size-9", }, }, defaultVariants: { variant: "default", size: "default", }, })function Button({ className, variant, size, asChild = false, ...props}: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & { asChild?: boolean }) { const Comp = asChild ? Slot : "button" return ( <Comp data-slot="button" className={cn(buttonVariants({ variant, size, className }))} {...props} /> )}export { Button, buttonVariants }
Profile Card
User profile card with avatar and information:
import { Button } from "@/components/ui/button"import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle,} from "@/components/ui/card"export default function CardProfile() { return ( <div className="w-full p-6 flex justify-center"> <Card className="w-full max-w-sm"> <CardHeader> <div className="flex items-center space-x-4"> <div className="w-12 h-12 rounded-full bg-gray-200 flex items-center justify-center"> <span className="text-lg font-semibold">JD</span> </div> <div> <CardTitle>John Doe</CardTitle> <CardDescription>Software Developer</CardDescription> </div> </div> </CardHeader> <CardContent> <div className="space-y-2"> <div className="flex justify-between"> <span className="text-sm text-muted-foreground">Location</span> <span className="text-sm">San Francisco, CA</span> </div> <div className="flex justify-between"> <span className="text-sm text-muted-foreground">Joined</span> <span className="text-sm">March 2021</span> </div> <div className="flex justify-between"> <span className="text-sm text-muted-foreground">Followers</span> <span className="text-sm">1.2k</span> </div> </div> </CardContent> <CardFooter className="flex gap-2"> <Button className="flex-1">Follow</Button> <Button variant="outline" className="flex-1">Message</Button> </CardFooter> </Card> </div> )}
import * as React from "react"import { Slot } from "@radix-ui/react-slot"import { cva, type VariantProps } from "class-variance-authority"import { cn } from "@/lib/utils"const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", lg: "h-10 rounded-md px-6 has-[>svg]:px-4", icon: "size-9", }, }, defaultVariants: { variant: "default", size: "default", }, })function Button({ className, variant, size, asChild = false, ...props}: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & { asChild?: boolean }) { const Comp = asChild ? Slot : "button" return ( <Comp data-slot="button" className={cn(buttonVariants({ variant, size, className }))} {...props} /> )}export { Button, buttonVariants }
API Reference
Card
The root container for the card component.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling. |
children | React.ReactNode | - | Card content (header, body, footer). |
CardHeader
Container for card title, description, and optional action.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling. |
children | React.ReactNode | - | Header content (title, description, action). |
CardTitle
Primary heading for the card.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling. |
children | React.ReactNode | - | Title content. |
CardDescription
Secondary text providing additional context.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling. |
children | React.ReactNode | - | Description content. |
CardAction
Optional action element positioned in the header.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling. |
children | React.ReactNode | - | Action content (buttons, links). |
CardContent
Main content area of the card.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling. |
children | React.ReactNode | - | Main card content. |
CardFooter
Footer section for actions or additional information.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling. |
children | React.ReactNode | - | Footer content (buttons, links, text). |
Card best practices
What makes cards feel polished and professional:
- Consistent spacing - Use the same padding and gaps across all your cards
- Clear hierarchy - Title, description, and actions should have obvious importance levels
- Logical action placement - Quick actions in headers, primary actions in footers
- Responsive grids - Cards should stack nicely on mobile, spread on desktop
- Appropriate shadows - Subtle elevation helps cards feel interactive
- Loading states - Show skeleton placeholders while content loads
- Touch-friendly targets - Make interactive cards easy to tap on mobile
- Semantic structure - Use proper heading levels for screen readers
Calendar
React calendar component with date selection, range picking, and keyboard navigation. Perfect for date pickers, booking systems, and form inputs.
Carousel
React carousel component with touch gestures, keyboard navigation, and smooth animations. Perfect for image galleries, product showcases, and content sliders.