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

@kuroshio-lab/ui

v0.3.0

Published

Radix UI-based component library for Kuroshio Lab

Downloads

814

Readme

@kuroshio-lab/ui

Radix UI-based primitive components for the Kuroshio Lab design system. Unstyled Radix primitives wrapped with Tailwind CSS, ref forwarding, and consistent design tokens.

Installation

npm install @kuroshio-lab/ui

Peer dependencies

npm install react react-dom

Components

Button

Polymorphic button with twelve style variants and four sizes. Supports asChild for composition with custom elements (e.g. router links).

import { Button } from '@kuroshio-lab/ui/button';

<Button variant="default" size="default">Click me</Button>

// Compose with a router link
<Button asChild variant="ghost">
  <a href="/home">Home</a>
</Button>

Props

Extends React.ButtonHTMLAttributes<HTMLButtonElement>.

| Prop | Type | Default | | --------- | ------------------------------------- | ----------- | | variant | see below | "default" | | size | "default" \| "sm" \| "lg" \| "icon" | "default" | | asChild | boolean | false |

Variants

| Variant | Description | | ------------- | ---------------------------------------- | | default | Blue primary | | destructive | Red danger | | outline | Border, no fill | | secondary | Gray secondary | | ghost | No background, accent on hover | | link | Text with underline | | edit | Brand cyan-blue with gradient hover | | delete | Coral with cyan gradient hover | | addingObs | Ocean-depth multi-colour gradient | | actions | Dark primary | | signOut | Neutral semi-transparent | | glass | Frosted glass (white/10 bg) | | glassDanger | Frosted glass with coral danger on hover |

Exports: Button, buttonVariants


Badge

Inline label for status or category display.

import { Badge } from "@kuroshio-lab/ui/badge";

<Badge variant="secondary">Pending</Badge>;

Props

Extends React.HTMLAttributes<HTMLDivElement>.

| Prop | Type | Default | | --------- | -------------------------------------------------------- | ----------- | | variant | "default" \| "secondary" \| "destructive" \| "outline" | "default" |

Exports: Badge, badgeVariants


Card

Composable card layout with header, content, and footer sub-components.

import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
} from "@kuroshio-lab/ui/card";

<Card>
  <CardHeader>
    <CardTitle>Title</CardTitle>
    <CardDescription>Description</CardDescription>
  </CardHeader>
  <CardContent>Content goes here.</CardContent>
  <CardFooter>Footer</CardFooter>
</Card>;

All sub-components extend React.HTMLAttributes<HTMLDivElement> and support refs.

Exports: Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter


Dialog

Modal dialog built on @radix-ui/react-dialog. DialogContent includes a built-in close button (X icon, top-right).

import {
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
  DialogClose,
} from "@kuroshio-lab/ui/dialog";

<Dialog>
  <DialogTrigger asChild>
    <Button>Open</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Title</DialogTitle>
      <DialogDescription>Description</DialogDescription>
    </DialogHeader>
    <p>Body content</p>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="outline">Cancel</Button>
      </DialogClose>
    </DialogFooter>
  </DialogContent>
</Dialog>;

Exports: Dialog, DialogPortal, DialogOverlay, DialogTrigger, DialogClose, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription


Form

Type-safe form primitives built on react-hook-form with automatic ARIA wiring and error display.

import { useForm } from "react-hook-form";
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormDescription,
  FormMessage,
} from "@kuroshio-lab/ui/form";
import { Input } from "@kuroshio-lab/ui/input";

const form = useForm<{ email: string }>();

<Form {...form}>
  <form onSubmit={form.handleSubmit(onSubmit)}>
    <FormField
      control={form.control}
      name="email"
      render={({ field }) => (
        <FormItem>
          <FormLabel>Email</FormLabel>
          <FormControl>
            <Input placeholder="[email protected]" {...field} />
          </FormControl>
          <FormDescription>We'll never share your email.</FormDescription>
          <FormMessage />
        </FormItem>
      )}
    />
  </form>
</Form>;

FormControl automatically sets id, aria-describedby, and aria-invalid from the field context. FormMessage renders the field error or falls back to children.

Exports: Form, FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage, useFormField


Input

Styled native <input> element.

import { Input } from "@kuroshio-lab/ui/input";

<Input type="email" placeholder="[email protected]" />;

Extends React.ComponentProps<"input">. Supports refs.

Exports: Input


Label

Accessible label built on @radix-ui/react-label. Automatically pairs with disabled peer elements.

import { Label } from "@kuroshio-lab/ui/label";

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

Extends React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>. Supports refs.

Exports: Label


Select

Dropdown select built on @radix-ui/react-select. SelectTrigger includes a built-in chevron icon. SelectContent wraps in a portal with scroll buttons.

import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectGroup,
  SelectLabel,
  SelectItem,
  SelectSeparator,
} from "@kuroshio-lab/ui/select";

<Select onValueChange={(val) => console.log(val)}>
  <SelectTrigger>
    <SelectValue placeholder="Pick one…" />
  </SelectTrigger>
  <SelectContent>
    <SelectGroup>
      <SelectLabel>Fruits</SelectLabel>
      <SelectItem value="apple">Apple</SelectItem>
      <SelectItem value="banana">Banana</SelectItem>
    </SelectGroup>
    <SelectSeparator />
    <SelectItem value="other">Other</SelectItem>
  </SelectContent>
</Select>;

Exports: Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton


ScrollArea

Scrollable container with a custom scrollbar, built on @radix-ui/react-scroll-area.

import { ScrollArea, ScrollBar } from "@kuroshio-lab/ui/scroll-area";

<ScrollArea className="h-64 w-full">
  <div>{/* long content */}</div>
  <ScrollBar orientation="vertical" />
</ScrollArea>;

ScrollArea renders a vertical ScrollBar by default. Add a second ScrollBar with orientation="horizontal" for two-axis scrolling.

Exports: ScrollArea, ScrollBar


Separator

Horizontal or vertical divider, built on @radix-ui/react-separator. Decorative by default.

import { Separator } from '@kuroshio-lab/ui/separator';

<Separator />
<Separator orientation="vertical" />

Extends React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>. Supports refs.

| Prop | Type | Default | | ------------- | ---------------------------- | -------------- | | orientation | "horizontal" \| "vertical" | "horizontal" | | decorative | boolean | true |

Exports: Separator


Textarea

Styled native <textarea> element.

import { Textarea } from "@kuroshio-lab/ui/textarea";

<Textarea placeholder="Write something…" rows={4} />;

Extends React.ComponentProps<"textarea">. Supports refs.

Exports: Textarea


Import paths

Each component has a granular export path, avoiding full-package imports:

import { Button }     from '@kuroshio-lab/ui/button';
import { Badge }      from '@kuroshio-lab/ui/badge';
import { Card, … }   from '@kuroshio-lab/ui/card';
import { Dialog, … } from '@kuroshio-lab/ui/dialog';
import { Form, … }   from '@kuroshio-lab/ui/form';
import { Input }      from '@kuroshio-lab/ui/input';
import { Label }      from '@kuroshio-lab/ui/label';
import { Select, … } from '@kuroshio-lab/ui/select';
import { ScrollArea } from '@kuroshio-lab/ui/scroll-area';
import { Separator }  from '@kuroshio-lab/ui/separator';
import { Textarea }   from '@kuroshio-lab/ui/textarea';

Or import everything from the main entry:

import { Button, Input, … } from '@kuroshio-lab/ui';

Design patterns

  • Ref forwarding — all components except Badge support ref.
  • asChildButton and DialogTrigger support asChild via Radix Slot for polymorphic composition.
  • cn() utility — all components use cn() from @kuroshio-lab/styles for safe Tailwind class merging; pass a className prop to override or extend any component's styles.
  • Accessibility — ARIA roles and attributes are handled by Radix primitives; Form wires aria-invalid and aria-describedby automatically.

Development

# From repo root
npm run dev              # Watch all packages
cd packages/ui
npm run build            # Build this package only

See the root DEVELOPMENT.md for full monorepo setup instructions.