shadcn-ui-react
v0.7.20
Published
A collection of components for building beautiful and accessible user interfaces with React and Tailwind CSS.
Maintainers
Readme
🧩 shadcn-ui-react
A production-ready React UI library that packages shadcn/ui components into a single reusable library, with Tailwind CSS styling, Radix UI primitives, form helpers, and ready-to-use demos.
📦 Installation
npm install shadcn-ui-react
# or
pnpm add shadcn-ui-react
# or
yarn add shadcn-ui-reactPeer dependencies
npm install react react-dom🚀 Getting started
1. Import the global styles
Import the package stylesheet once in your app entry file, layout, or root component.
import 'shadcn-ui-react/dist/style.css';2. Use components
import { Button } from 'shadcn-ui-react';
export default function App() {
return (
<div className="flex gap-3 p-6">
<Button>Save</Button>
<Button variant="outline">Cancel</Button>
</div>
);
}🧱 Available Components
📦 UI Primitives
AccordionAlertAlertDialogAvatarBadgeBreadcrumbButtonIconButtonCalendarCardCarouselCheckboxCollapsibleCommandContextMenuDialogDrawerDropdownMenuHoverCardInputInputOtpLabelMenubarModalNavigationMenuPaginationPopoverProgressRadioGroupResizableScrollAreaSelectSeparatorSheetSkeletonSliderSonnerSwitchTableTabsTextareaToastToasterToggleToggleGroupTooltip
🧠 Forms
FormFormFieldFormSelectFormCheckboxFormItemFormControlFormLabelFormDescriptionFormMessageUiInputUiSelectUiCheckbox
🧩 Shared Components
AlertModalBreadcrumbsDataTableDataTableSkeletonDropzoneFileUploadHeadingPageHeadPaginationSectionSearchInputSearchableSelect
🛠️ Utilities
cnuseToasttoastIconsuseSidebar
✨ Demos
1. Button
import { Button } from 'shadcn-ui-react';
export function ButtonDemo() {
return (
<div className="flex flex-wrap gap-3">
<Button>Default</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Delete</Button>
<Button variant="soft">Soft</Button>
<Button variant="gradient">Gradient</Button>
<Button loading>Loading</Button>
</div>
);
}2. IconButton
import { Pencil, Trash2 } from 'lucide-react';
import { IconButton } from 'shadcn-ui-react';
export function IconButtonDemo() {
return (
<div className="flex gap-2">
<IconButton aria-label="Edit item" variant="outline">
<Pencil />
</IconButton>
<IconButton aria-label="Delete item" variant="softDestructive">
<Trash2 />
</IconButton>
</div>
);
}3. UiInput
import * as React from 'react';
import { UiInput } from 'shadcn-ui-react';
export function UiInputDemo() {
const [name, setName] = React.useState('');
return (
<UiInput
htmlFormItemId="name"
label="Name"
requiredLabel
placeholder="Enter your name"
value={name}
onChange={(event) => setName(event.target.value)}
errorMessage={
name.length > 0 && name.trim().length < 2
? 'Minimum 2 characters'
: undefined
}
/>
);
}4. UiSelect
import * as React from 'react';
import { UiSelect } from 'shadcn-ui-react';
export function UiSelectDemo() {
const [language, setLanguage] = React.useState('');
return (
<UiSelect
htmlFormItemId="language"
label="Language"
placeholder="Select a language"
value={language}
onChange={setLanguage}
items={[
{ label: 'English', value: 'en' },
{ label: 'Spanish', value: 'es' },
{ label: 'Portuguese', value: 'pt' },
{ label: 'French', value: 'fr' },
{ label: 'Japanese', value: 'ja', disabled: true }
]}
errorMessage={!language ? 'Select a language.' : undefined}
/>
);
}5. UiCheckbox
import * as React from 'react';
import { UiCheckbox } from 'shadcn-ui-react';
export function UiCheckboxDemo() {
const [accepted, setAccepted] = React.useState(false);
return (
<UiCheckbox
htmlFormItemId="terms"
checked={accepted}
onCheckedChange={(value) => setAccepted(value === true)}
label="I accept the terms and conditions"
description="You can change this option later from your account settings."
requiredLabel
errorMessage={!accepted ? 'You must accept the terms.' : undefined}
/>
);
}6. React Hook Form + Zod
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import {
Button,
Form,
FormCheckbox,
FormField,
FormSelect
} from 'shadcn-ui-react';
const schema = z.object({
name: z.string().min(2, 'Minimum 2 characters'),
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Minimum 8 characters'),
role: z.enum(['owner', 'editor', 'viewer']),
accepted: z.boolean().refine(Boolean, 'You must accept the terms')
});
type FormValues = z.infer<typeof schema>;
export function FormDemo() {
const form = useForm<FormValues>({
resolver: zodResolver(schema),
defaultValues: {
name: '',
email: '',
password: '',
role: 'viewer',
accepted: false
}
});
const onSubmit = (values: FormValues) => {
console.log(values);
};
return (
<Form
methods={form}
onSubmit={onSubmit}
formProps={{ className: 'space-y-4' }}
>
<FormField
control={form.control}
name="name"
label="Name"
placeholder="Jane Doe"
requiredLabel
/>
<FormField
control={form.control}
name="email"
label="Email"
type="email"
placeholder="[email protected]"
requiredLabel
/>
<FormField
control={form.control}
name="password"
label="Password"
type="password"
placeholder="••••••••"
requiredLabel
/>
<FormSelect
control={form.control}
name="role"
label="Role"
placeholder="Select a role"
items={[
{ label: 'Owner', value: 'owner' },
{ label: 'Editor', value: 'editor' },
{ label: 'Viewer', value: 'viewer' }
]}
/>
<FormCheckbox
control={form.control}
name="accepted"
label="I accept the terms"
description="This field is required to continue."
/>
<Button type="submit" className="w-full">
Create account
</Button>
</Form>
);
}7. SearchableSelect standalone
import * as React from 'react';
import { SearchableSelect } from 'shadcn-ui-react';
export function SearchableSelectDemo() {
const [fruit, setFruit] = React.useState('');
return (
<SearchableSelect
value={fruit}
onValueChange={setFruit}
placeholder="Select a fruit"
searchPlaceholder="Search fruit..."
items={[
{ label: 'Apple', value: 'apple', keywords: 'fruit red green sweet' },
{ label: 'Banana', value: 'banana', keywords: 'fruit yellow tropical' },
{ label: 'Orange', value: 'orange', keywords: 'fruit citrus vitamin c' },
{
label: 'Strawberry',
value: 'strawberry',
keywords: 'fruit berry red sweet'
},
{
label: 'Pineapple',
value: 'pineapple',
keywords: 'fruit tropical sweet'
}
]}
/>
);
}8. Accordion
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger
} from 'shadcn-ui-react';
export function AccordionDemo() {
return (
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="item-1">
<AccordionTrigger>What is included?</AccordionTrigger>
<AccordionContent>
Accessible components, Tailwind CSS styling, and reusable form helpers.
</AccordionContent>
</AccordionItem>
</Accordion>
);
}9. Dialog
import {
Button,
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger
} from 'shadcn-ui-react';
export function DialogDemo() {
return (
<Dialog>
<DialogTrigger asChild>
<Button>Open dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Create note</DialogTitle>
</DialogHeader>
<p className="text-sm text-muted-foreground">
Use this area for a form, message, or confirmation content.
</p>
</DialogContent>
</Dialog>
);
}10. AlertModal
import * as React from 'react';
import { AlertModal, Button } from 'shadcn-ui-react';
export function AlertModalDemo() {
const [open, setOpen] = React.useState(false);
return (
<>
<Button variant="destructive" onClick={() => setOpen(true)}>
Delete item
</Button>
<AlertModal
isOpen={open}
onClose={() => setOpen(false)}
onConfirm={() => setOpen(false)}
loading={false}
/>
</>
);
}11. DataTable
import * as React from 'react';
import type { ColumnDef } from '@tanstack/react-table';
import { DataTable } from 'shadcn-ui-react';
type Project = {
id: number;
name: string;
owner: string;
status: 'Active' | 'Paused' | 'Completed';
};
const columns: ColumnDef<Project>[] = [
{ accessorKey: 'id', header: 'ID' },
{ accessorKey: 'name', header: 'Project' },
{ accessorKey: 'owner', header: 'Owner' },
{ accessorKey: 'status', header: 'Status' }
];
const data: Project[] = [
{ id: 1, name: 'Website Redesign', owner: 'Jane Cooper', status: 'Active' },
{ id: 2, name: 'Mobile App', owner: 'Wade Warren', status: 'Paused' },
{ id: 3, name: 'Design System', owner: 'Esther Howard', status: 'Completed' }
];
export function DataTableDemo() {
const [page, setPage] = React.useState(1);
const [perPage, setPerPage] = React.useState(5);
const pageCount = Math.ceil(data.length / perPage);
const visibleRows = data.slice((page - 1) * perPage, page * perPage);
return (
<DataTable
columns={columns}
data={visibleRows}
page={page}
perPage={perPage}
pageCount={pageCount}
totalRows={data.length}
onPageChange={setPage}
onPageSizeChange={(size) => {
setPerPage(size);
setPage(1);
}}
template="neo"
accent="primary"
stickyHeader
animate
heightClassName="h-[420px]"
/>
);
}12. SearchInput
import * as React from 'react';
import { SearchInput } from 'shadcn-ui-react';
export function SearchInputDemo() {
const [search, setSearch] = React.useState('');
return (
<SearchInput
value={search}
placeholder="Search documents..."
debounceTime={400}
onSearch={(value) => setSearch(value ?? '')}
/>
);
}13. FileUpload / Dropzone
import { Dropzone } from 'shadcn-ui-react';
export function DropzoneDemo() {
return (
<Dropzone
onDrop={(files) => {
console.log(files);
}}
/>
);
}14. Toast
import { Button, Toaster, useToast } from 'shadcn-ui-react';
export function ToastDemo() {
const { toast } = useToast();
return (
<>
<Button
onClick={() => {
toast({
title: 'Saved',
description: 'Your changes were saved successfully.'
});
}}
>
Show toast
</Button>
<Toaster />
</>
);
}15. Sonner
import { toast } from 'sonner';
import { Button, Sonner } from 'shadcn-ui-react';
export function SonnerDemo() {
return (
<>
<Button onClick={() => toast.success('Operation completed')}>
Notify
</Button>
<Sonner />
</>
);
}16. Card + Badge
import {
Badge,
Card,
CardContent,
CardHeader,
CardTitle
} from 'shadcn-ui-react';
export function CardDemo() {
return (
<Card className="max-w-md">
<CardHeader>
<CardTitle className="flex items-center justify-between gap-4">
Starter Kit
<Badge>New</Badge>
</CardTitle>
</CardHeader>
<CardContent className="text-sm text-muted-foreground">
A simple card example with a title, badge, and supporting description.
</CardContent>
</Card>
);
}17. Tabs
import { Tabs, TabsContent, TabsList, TabsTrigger } from 'shadcn-ui-react';
export function TabsDemo() {
return (
<Tabs defaultValue="overview">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="settings">Settings</TabsTrigger>
</TabsList>
<TabsContent value="overview">General information goes here.</TabsContent>
<TabsContent value="settings">Preferences and configuration go here.</TabsContent>
</Tabs>
);
}💅 Theming
This package uses Tailwind CSS variables. You can override the default theme from your app CSS.
:root {
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(64.12% 0.209 16.22);
--destructive-foreground: oklch(97.913% 0.00011 271.152);
--border: oklch(0.922 0 0);
--input: #fdfdfd;
--ring: 221.2 83.2% 53.3%;
--radius: 0.75rem;
}📝 License
MIT.
