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

@yaip/yads-ui

v0.2.3

Published

A React component library built on [shadcn/ui](https://ui.shadcn.com) with layout primitives, Tailwind CSS v4, and React Server Component support.

Readme

yads-ui

A React component library built on shadcn/ui with layout primitives, Tailwind CSS v4, and React Server Component support.

Installation

pnpm add @yaip/yads-ui @phosphor-icons/react

No separate shadcn package install is required.

Publish

pnpm changeset # create a changeset pnpm changeset version # bump version + changelog pnpm publish # build + publish to npm

Local Smoke App

Use the local consumer app in examples/vite-smoke to verify the packed library, not the source tree:

pnpm run smoke:dev
pnpm run smoke:build
pnpm run smoke:next:dev
pnpm run smoke:next:build

These commands:

  • build dist
  • create a local tarball with pnpm pack
  • sync that tarball to a stable local file path
  • install the example app against that local tarball
  • run either the Vite smoke app or the Next App Router smoke app against the packed package

Peer dependencies: react >= 19, react-dom >= 19, tailwindcss >= 4, @phosphor-icons/react >= 2.

Setup

Use Tailwind-native setup in your main CSS file (e.g. globals.css, app.css):

@import "tailwindcss";
@import "@yaip/yads-ui/theme.css";
@import "@yaip/yads-ui/fonts.css";

@source "../node_modules/@yaip/yads-ui/dist";
  • @import "@yaip/yads-ui/theme.css" — Loads the yads-specific Tailwind theme mappings, tokens, base styles, custom variants, and animation helpers.
  • @import "@yaip/yads-ui/fonts.css" — Loads the optional DM Sans, Montserrat, and Geist Mono font faces used by the default theme.
  • @source — Tells Tailwind v4 to scan the library's dist for utility classes used by components. This is required because Tailwind v4 ignores node_modules by default.

Important: The @source path is relative to the CSS file that contains it, not your project root.

If this path is wrong, components can render without some Tailwind utilities from the packaged library. A common symptom is Spinner rendering without animate-spin.

Examples:

  • src/styles/app.css -> @source "../node_modules/@yaip/yads-ui/dist";
  • src/routes/__root.css -> @source "../../node_modules/@yaip/yads-ui/dist";

fonts.css is optional. Omit it if you want to use your app's own font stack.

Theming

ThemeProvider manages runtime theme state for light, dark, and system. First-paint theme selection is still an app-shell concern, so if you want to avoid a flash on initial load you should apply the theme before your React app hydrates.

Use the provider in your client app:

import { ThemeProvider } from "@yaip/yads-ui";

export function Providers({ children }: { children: React.ReactNode }) {
  return <ThemeProvider defaultTheme="system">{children}</ThemeProvider>;
}

Theme API:

  • theme — the saved user preference: light, dark, or system
  • resolvedTheme — the active theme after resolving system
  • setTheme(theme) — updates the preference and persists it to local storage
  • forcedTheme — optionally lock the resolved theme to light or dark for previews, docs, or embedded demos

Preventing First-Paint Flash

The provider applies the theme after React starts. To prevent an initial flash, bootstrap the theme in your app shell:

  • SSR / document-controlled apps — inject getThemeScript() into <head> or render ThemeScript in a document-level head/layout slot
  • Vite / static index.html apps — place an equivalent inline script directly in index.html before your app entry script

Framework example:

import { getThemeScript, ThemeProvider } from "@yaip/yads-ui";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <head>
        <script
          dangerouslySetInnerHTML={{ __html: getThemeScript() }}
          suppressHydrationWarning
        />
      </head>
      <body>
        <ThemeProvider>{children}</ThemeProvider>
      </body>
    </html>
  );
}

Vite example:

<!doctype html>
<html lang="en">
  <head>
    <script>
      (() => {
        const storageKey = "theme";
        const defaultTheme = "system";
        const root = document.documentElement;
        const getSystemTheme = () =>
          window.matchMedia("(prefers-color-scheme: dark)").matches
            ? "dark"
            : "light";

        let theme = defaultTheme;

        try {
          const stored = window.localStorage.getItem(storageKey);
          if (stored === "light" || stored === "dark" || stored === "system") {
            theme = stored;
          }
        } catch {}

        const resolvedTheme = theme === "system" ? getSystemTheme() : theme;
        root.style.colorScheme = resolvedTheme;
        root.classList.remove("light", "dark");
        root.classList.add(resolvedTheme);
      })();
    </script>
  </head>
</html>

Note: Mounting ThemeScript inside createRoot(...) is too late to prevent first-paint flash in a plain SPA. In that case, use index.html instead.

Entry Point

yads-ui now uses a single primary entry point:

  • @yaip/yads-ui — import both server-safe and interactive components from the same package root

The published build stays split internally, so modern bundlers can still tree-shake down to the leaf modules you actually use.

Usage

import { Stack, Card, CardHeader, CardTitle, CardContent } from "@yaip/yads-ui"
import { Button, Dialog, DialogTrigger, DialogContent } from "@yaip/yads-ui"

function Example() {
  return (
    <Stack gap="4">
      <Card>
        <CardHeader>
          <CardTitle>Welcome</CardTitle>
        </CardHeader>
        <CardContent>
          <Dialog>
            <DialogTrigger render={<Button>Open</Button>} />
            <DialogContent>Hello!</DialogContent>
          </Dialog>
        </CardContent>
      </Card>
    </Stack>
  )
}

Components (@yaip/yads-ui)

Server-safe and interactive components are both imported from @yaip/yads-ui. Interactive components still publish as client leaf modules internally, so RSC consumers can keep the correct boundaries while using one import surface.

Alert

import { Alert, AlertTitle, AlertDescription } from "@yaip/yads-ui"

<Alert>
  <AlertTitle>Heads up!</AlertTitle>
  <AlertDescription>This is an alert.</AlertDescription>
</Alert>

AspectRatio

import { AspectRatio } from "@yaip/yads-ui"

<AspectRatio ratio={16 / 9}>
  <img src="..." alt="..." />
</AspectRatio>

Card

import { Card, CardHeader, CardTitle, CardContent } from "@yaip/yads-ui"

<Card>
  <CardHeader>
    <CardTitle>Title</CardTitle>
  </CardHeader>
  <CardContent>Content</CardContent>
</Card>

Empty

import { Empty, EmptyTitle, EmptyDescription } from "@yaip/yads-ui"

<Empty>
  <EmptyTitle>No results</EmptyTitle>
  <EmptyDescription>Try a different search.</EmptyDescription>
</Empty>

Group

import { Group } from "@yaip/yads-ui"

<Group gap="2">
  <span>Left</span>
  <span>Right</span>
</Group>

Kbd

import { Kbd } from "@yaip/yads-ui"

<Kbd>⌘K</Kbd>

Label

import { Label } from "@yaip/yads-ui"

<Label htmlFor="email">Email</Label>

NativeSelect

import { NativeSelect, NativeSelectOption } from "@yaip/yads-ui"

<NativeSelect>
  <NativeSelectOption value="a">Option A</NativeSelectOption>
  <NativeSelectOption value="b">Option B</NativeSelectOption>
</NativeSelect>

Pagination

import { Pagination, PaginationContent, PaginationItem, PaginationLink } from "@yaip/yads-ui"

<Pagination>
  <PaginationContent>
    <PaginationItem>
      <PaginationLink href="#">1</PaginationLink>
    </PaginationItem>
  </PaginationContent>
</Pagination>

Skeleton

import { Skeleton } from "@yaip/yads-ui"

<Skeleton className="h-4 w-[200px]" />

Spinner

import { Spinner } from "@yaip/yads-ui"

<Spinner />

Stack

import { Stack } from "@yaip/yads-ui"

<Stack gap="4">
  <div>First</div>
  <div>Second</div>
</Stack>

Table

import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@yaip/yads-ui"

<Table>
  <TableHeader>
    <TableRow>
      <TableHead>Name</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>Alice</TableCell>
    </TableRow>
  </TableBody>
</Table>

Textarea

import { Textarea } from "@yaip/yads-ui"

<Textarea placeholder="Type here..." />

Interactive Components (@yaip/yads-ui)

These components use client-side JavaScript, but they are still imported from @yaip/yads-ui. The published package keeps those modules split internally so RSC-aware consumers can preserve the client boundary correctly.

Accordion

import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from "@yaip/yads-ui"

<Accordion type="single" collapsible>
  <AccordionItem value="item-1">
    <AccordionTrigger>Is it accessible?</AccordionTrigger>
    <AccordionContent>Yes.</AccordionContent>
  </AccordionItem>
</Accordion>

AlertDialog

import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogAction } from "@yaip/yads-ui"

<AlertDialog>
  <AlertDialogTrigger>Open</AlertDialogTrigger>
  <AlertDialogContent>
    <AlertDialogAction>Continue</AlertDialogAction>
  </AlertDialogContent>
</AlertDialog>

Avatar

import { Avatar, AvatarImage, AvatarFallback } from "@yaip/yads-ui"

<Avatar>
  <AvatarImage src="https://example.com/avatar.png" />
  <AvatarFallback>AB</AvatarFallback>
</Avatar>

Badge

import { Badge } from "@yaip/yads-ui"

<Badge variant="secondary">New</Badge>

Breadcrumb

import { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink } from "@yaip/yads-ui"

<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="/">Home</BreadcrumbLink>
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>

Button

import { Button } from "@yaip/yads-ui"

<Button variant="outline">Click me</Button>

ButtonGroup

import { ButtonGroup } from "@yaip/yads-ui"

<ButtonGroup>
  <Button>One</Button>
  <Button>Two</Button>
</ButtonGroup>

Calendar

import { Calendar } from "@yaip/yads-ui"

<Calendar mode="single" />

Carousel

import { Carousel, CarouselContent, CarouselItem } from "@yaip/yads-ui"

<Carousel>
  <CarouselContent>
    <CarouselItem>Slide 1</CarouselItem>
  </CarouselContent>
</Carousel>

Checkbox

import { Checkbox } from "@yaip/yads-ui"

<Checkbox id="terms" />

Collapsible

import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "@yaip/yads-ui"

<Collapsible>
  <CollapsibleTrigger>Toggle</CollapsibleTrigger>
  <CollapsibleContent>Content</CollapsibleContent>
</Collapsible>

Combobox

import { Combobox, ComboboxInput, ComboboxContent, ComboboxItem } from "@yaip/yads-ui"

<Combobox>
  <ComboboxInput placeholder="Search..." />
  <ComboboxContent>
    <ComboboxItem value="option">Option</ComboboxItem>
  </ComboboxContent>
</Combobox>

Command

import { Command, CommandInput, CommandList, CommandItem } from "@yaip/yads-ui"

<Command>
  <CommandInput placeholder="Search..." />
  <CommandList>
    <CommandItem>Item</CommandItem>
  </CommandList>
</Command>

ContextMenu

import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem } from "@yaip/yads-ui"

<ContextMenu>
  <ContextMenuTrigger>Right click</ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuItem>Action</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>

Dialog

import { Dialog, DialogTrigger, DialogContent, DialogTitle } from "@yaip/yads-ui"

<Dialog>
  <DialogTrigger>Open</DialogTrigger>
  <DialogContent>
    <DialogTitle>Title</DialogTitle>
  </DialogContent>
</Dialog>

Drawer

import { Drawer, DrawerTrigger, DrawerContent } from "@yaip/yads-ui"

<Drawer>
  <DrawerTrigger>Open</DrawerTrigger>
  <DrawerContent>Content</DrawerContent>
</Drawer>

DropdownMenu

import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@yaip/yads-ui"

<DropdownMenu>
  <DropdownMenuTrigger>Open</DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuItem>Action</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Field

import { Field, FieldLabel, FieldDescription } from "@yaip/yads-ui"

<Field>
  <FieldLabel>Email</FieldLabel>
  <FieldDescription>Enter your email address.</FieldDescription>
</Field>

HoverCard

import { HoverCard, HoverCardTrigger, HoverCardContent } from "@yaip/yads-ui"

<HoverCard>
  <HoverCardTrigger>Hover me</HoverCardTrigger>
  <HoverCardContent>Info</HoverCardContent>
</HoverCard>

Input

import { Input } from "@yaip/yads-ui"

<Input type="email" placeholder="Email" />

InputGroup

import { InputGroup, InputGroupInput, InputGroupText } from "@yaip/yads-ui"

<InputGroup>
  <InputGroupText>@</InputGroupText>
  <InputGroupInput placeholder="username" />
</InputGroup>

InputOTP

import { InputOTP, InputOTPGroup, InputOTPSlot } from "@yaip/yads-ui"

<InputOTP maxLength={6}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
  </InputOTPGroup>
</InputOTP>

Item

import { Item, ItemTitle, ItemDescription } from "@yaip/yads-ui"

<Item>
  <ItemTitle>Title</ItemTitle>
  <ItemDescription>Description</ItemDescription>
</Item>

Menubar

import { Menubar, MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem } from "@yaip/yads-ui"

<Menubar>
  <MenubarMenu>
    <MenubarTrigger>File</MenubarTrigger>
    <MenubarContent>
      <MenubarItem>New</MenubarItem>
    </MenubarContent>
  </MenubarMenu>
</Menubar>

NavigationMenu

import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuLink } from "@yaip/yads-ui"

<NavigationMenu>
  <NavigationMenuList>
    <NavigationMenuItem>
      <NavigationMenuLink href="/">Home</NavigationMenuLink>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>

Popover

import { Popover, PopoverTrigger, PopoverContent } from "@yaip/yads-ui"

<Popover>
  <PopoverTrigger>Open</PopoverTrigger>
  <PopoverContent>Content</PopoverContent>
</Popover>

Progress

import { Progress } from "@yaip/yads-ui"

<Progress value={50} />

RadioGroup

import { RadioGroup, RadioGroupItem } from "@yaip/yads-ui"

<RadioGroup defaultValue="a">
  <RadioGroupItem value="a" />
  <RadioGroupItem value="b" />
</RadioGroup>

Resizable

import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from "@yaip/yads-ui"

<ResizablePanelGroup direction="horizontal">
  <ResizablePanel>Left</ResizablePanel>
  <ResizableHandle />
  <ResizablePanel>Right</ResizablePanel>
</ResizablePanelGroup>

ScrollArea

import { ScrollArea } from "@yaip/yads-ui"

<ScrollArea className="h-[200px]">
  <div>Scrollable content</div>
</ScrollArea>

Select

import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@yaip/yads-ui"

<Select>
  <SelectTrigger>
    <SelectValue placeholder="Pick one" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="a">Option A</SelectItem>
  </SelectContent>
</Select>

Separator

import { Separator } from "@yaip/yads-ui"

<Separator />

Sheet

import { Sheet, SheetTrigger, SheetContent } from "@yaip/yads-ui"

<Sheet>
  <SheetTrigger>Open</SheetTrigger>
  <SheetContent>Content</SheetContent>
</Sheet>

Sidebar

import { SidebarProvider, Sidebar, SidebarContent } from "@yaip/yads-ui"

<SidebarProvider>
  <Sidebar>
    <SidebarContent>Nav items</SidebarContent>
  </Sidebar>
</SidebarProvider>

Slider

import { Slider } from "@yaip/yads-ui"

<Slider defaultValue={[50]} max={100} step={1} />

Switch

import { Switch } from "@yaip/yads-ui"

<Switch />

Tabs

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@yaip/yads-ui"

<Tabs defaultValue="tab1">
  <TabsList>
    <TabsTrigger value="tab1">Tab 1</TabsTrigger>
  </TabsList>
  <TabsContent value="tab1">Content</TabsContent>
</Tabs>

Toaster (Sonner)

import { Toaster } from "@yaip/yads-ui"

<Toaster />

Toggle

import { Toggle } from "@yaip/yads-ui"

<Toggle>Bold</Toggle>

ToggleGroup

import { ToggleGroup, ToggleGroupItem } from "@yaip/yads-ui"

<ToggleGroup type="single">
  <ToggleGroupItem value="a">A</ToggleGroupItem>
  <ToggleGroupItem value="b">B</ToggleGroupItem>
</ToggleGroup>

Tooltip

import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from "@yaip/yads-ui"

<TooltipProvider>
  <Tooltip>
    <TooltipTrigger>Hover</TooltipTrigger>
    <TooltipContent>Tooltip text</TooltipContent>
  </Tooltip>
</TooltipProvider>

Utilities

import { cn } from "@yaip/yads-ui"

<div className={cn("base-class", conditional && "extra-class")} />

License

MIT