npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

shadcn-ui-react

v0.7.20

Published

A collection of components for building beautiful and accessible user interfaces with React and Tailwind CSS.

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-react

Peer 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

  • Accordion
  • Alert
  • AlertDialog
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • IconButton
  • Calendar
  • Card
  • Carousel
  • Checkbox
  • Collapsible
  • Command
  • ContextMenu
  • Dialog
  • Drawer
  • DropdownMenu
  • HoverCard
  • Input
  • InputOtp
  • Label
  • Menubar
  • Modal
  • NavigationMenu
  • Pagination
  • Popover
  • Progress
  • RadioGroup
  • Resizable
  • ScrollArea
  • Select
  • Separator
  • Sheet
  • Skeleton
  • Slider
  • Sonner
  • Switch
  • Table
  • Tabs
  • Textarea
  • Toast
  • Toaster
  • Toggle
  • ToggleGroup
  • Tooltip

🧠 Forms

  • Form
  • FormField
  • FormSelect
  • FormCheckbox
  • FormItem
  • FormControl
  • FormLabel
  • FormDescription
  • FormMessage
  • UiInput
  • UiSelect
  • UiCheckbox

🧩 Shared Components

  • AlertModal
  • Breadcrumbs
  • DataTable
  • DataTableSkeleton
  • Dropzone
  • FileUpload
  • Heading
  • PageHead
  • PaginationSection
  • SearchInput
  • SearchableSelect

🛠️ Utilities

  • cn
  • useToast
  • toast
  • Icons
  • useSidebar

✨ 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.