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

@luminpdf/ds

v0.2.0

Published

Lumin design system registry — shadcn/ui + Tailwind. Use with: npx shadcn add @lumin/<component>

Readme

@luminpdf/ds

Lumin design system, built on shadcn/ui + Tailwind v4.

Distributed two ways:

  1. As a regular npm packageimport { Button } from "@luminpdf/ds/button".
  2. As a shadcn/ui registrynpx shadcn add @lumin/button copies the component source into your own codebase.

Most teams use (2) because it matches the shadcn workflow: you own the source, you can tweak it, and upgrades are explicit.

Maintaining or contributing to the registry itself? See MAINTAINERS.md.


Table of Contents


1. Prerequisites

| Requirement | Version | |------------|---------| | Node.js | >=22.15.0 | | React | >=18 (19 recommended) | | Tailwind CSS | ^4.0.0 | | shadcn CLI | >=2.4.0 (for namespace support) |


2. Install Peer Dependencies

@luminpdf/ds declares these as peer dependencies — install them once in your host app:

pnpm add \
  @luminpdf/icons \
  class-variance-authority \
  clsx \
  tailwind-merge \
  tailwindcss \
  tw-animate-css \
  shadcn

tw-animate-css is optional — only needed if you use components that rely on animate-in/animate-out utilities (dialog, dropdown, popover, etc.).

shadcn is required because @luminpdf/ds/app/theme.css @imports shadcn/tailwind.css — the upstream file that ships the shadcn @custom-variant data-* rules (data-open, data-closed, data-active, data-selected, …), accordion keyframes, and the no-scrollbar utility. We intentionally depend on upstream rather than hand-rolling these variants, so they stay in sync with shadcn releases.

2.1 Framework-specific Tailwind v4 plugin

Tailwind v4 needs a bundler plugin to work. Install the one that matches your host stack:

| Stack | Plugin | Install | |-------|--------|---------| | Next.js (App Router, Pages Router) | @tailwindcss/postcss | pnpm add -D @tailwindcss/postcss | | Vite (any framework) | @tailwindcss/vite | pnpm add -D @tailwindcss/vite | | Webpack | @tailwindcss/postcss | pnpm add -D @tailwindcss/postcss | | Rspack / Rsbuild | @tailwindcss/postcss | pnpm add -D @tailwindcss/postcss | | Create React App (CRA) | @tailwindcss/postcss + CRACO | See shadcn/ui CRA guide |

create-next-app --tailwind and most create-vite templates preinstall the correct plugin already — if you scaffolded with a starter that includes Tailwind v4, skip this step.

Next.js (PostCSS)

postcss.config.mjs:

export default {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

Vite

vite.config.ts:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [react(), tailwindcss()],
});

No postcss.config is needed for Vite.

2.2 Install @luminpdf/ds itself

pnpm add @luminpdf/ds

3. Wire Up Tailwind + Theme + Tokens

The DS ships its Tailwind theme, design tokens, and @source scan paths as a single CSS file: @luminpdf/ds/app/theme.css.

3.1 Import order (critical)

Your host app's global stylesheet must look like this:

/* app/globals.css (or equivalent) */

/* 1. Your Tailwind instance. Only ONE @import "tailwindcss" in the whole app. */
@import "tailwindcss";

/* 2. Optional animate-in/out utilities used by DS overlays. */
@import "tw-animate-css";

/* 3. Lumin DS theme + tokens + shadcn data-state variants. */
@import "@luminpdf/ds/app/theme.css";

/* 4. Your own app styles… */

Do NOT import @luminpdf/ds/app/globals.css. That file is for the DS's own dev site only — it re-imports tailwindcss and will break your cascade.

3.2 How it works

  • theme.css @imports tokens.css (Figma-generated CSS variables) and shadcn/tailwind.css (upstream custom variants + accordion keyframes + no-scrollbar utility). Your bundler resolves shadcn/tailwind.css via the shadcn npm package's exports["./tailwind.css"] map — make sure shadcn is installed (see §2).
  • It declares @theme inline { ... } so Tailwind v4 exposes the tokens as utilities (bg-primary, text-muted-foreground, rounded-lg, …).
  • It @sources the DS's own components/, hooks/, lib/ folders so Tailwind generates the utilities used inside the shipped components.

3.3 Dark mode

theme.css registers @custom-variant dark (&:is(.dark *)). Toggle dark mode by adding the dark class to any ancestor (typically <html> or <body>). Works with next-themes out of the box.


4. Use the Shadcn Registry (recommended)

This is the workflow if you want to own the source of each component.

4.1 Register the @lumin namespace

Edit your own components.json (in your host app):

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tailwind": {
    "css": "app/globals.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "aliases": {
    "components": "@luminpdf/ds/components",
    "utils": "@luminpdf/ds/lib/utils",
    "ui": "@luminpdf/ds/components/ui",
    "lib": "@luminpdf/ds/lib",
    "hooks": "@luminpdf/ds/hooks"
  },
  "iconLibrary": "phosphor",
  "registries": {
    "@lumin": "https://unpkg.com/@luminpdf/ds@latest/public/r/{name}.json"
  }
}

"rsc": true is required. When rsc is false (or omitted — the default for some starters), the shadcn CLI strips the "use client" directive from generated files, which breaks dialog, dropdown-menu, select, popover, and every other component that uses React context. See shadcn-ui/ui#8173. This applies to all React frameworks, not just Next.js App Router — the flag is a CLI setting, not a runtime one.

Caching note: @latest on unpkg can cache for up to 10 minutes. For reproducible CI builds, pin a specific version:

"@lumin": "https://unpkg.com/@luminpdf/[email protected]/public/r/{name}.json"

Alternative CDN: https://cdn.jsdelivr.net/npm/@luminpdf/[email protected]/public/r/{name}.json.

4.2 Install components

npx shadcn@latest add @lumin/button
npx shadcn@latest add @lumin/dialog
npx shadcn@latest add @lumin/file-picker

The shadcn CLI will:

  1. Download the registry item JSON.
  2. Copy components/ui/button.tsx (and friends) into your project, rewriting @luminpdf/ds/... imports to match your aliases.
  3. npm install any npm dependencies declared on the item (e.g. radix-ui, class-variance-authority).
  4. Recursively add any registryDependencies (e.g. adding button also pulls utils and spinner).

4.3 Available items

Core UI components

| Item | shadcn add command | Notes | |------|---------------------|-------| | utils | shadcn add @lumin/utils | cn() helper — required by every component | | accordion | shadcn add @lumin/accordion | | | alert | shadcn add @lumin/alert | | | alert-dialog | shadcn add @lumin/alert-dialog | | | aspect-ratio | shadcn add @lumin/aspect-ratio | Radix UI aspect ratio primitive | | avatar | shadcn add @lumin/avatar | | | badge | shadcn add @lumin/badge | | | breadcrumb | shadcn add @lumin/breadcrumb | | | button | shadcn add @lumin/button | 6 variants × 8 sizes, loading state | | button-group | shadcn add @lumin/button-group | | | calendar | shadcn add @lumin/calendar | Requires date-fns, react-day-picker | | card | shadcn add @lumin/card | | | carousel | shadcn add @lumin/carousel | Requires embla-carousel-react | | chart | shadcn add @lumin/chart | Recharts-based with theme support | | checkbox | shadcn add @lumin/checkbox | | | collapsible | shadcn add @lumin/collapsible | | | combobox | shadcn add @lumin/combobox | Requires @base-ui/react | | command | shadcn add @lumin/command | Requires cmdk | | context-menu | shadcn add @lumin/context-menu | | | date-picker | shadcn add @lumin/date-picker | | | dialog | shadcn add @lumin/dialog | | | direction | shadcn add @lumin/direction | RTL/LTR text direction provider | | drawer | shadcn add @lumin/drawer | Vaul-based drawer/sheet | | dropdown-menu | shadcn add @lumin/dropdown-menu | | | empty | shadcn add @lumin/empty | Empty state with header, title, description, media | | field | shadcn add @lumin/field | Form field wrapper with label, description, error | | file-picker | shadcn add @lumin/file-picker | Composite — pulls many deps | | form | shadcn add @lumin/form | React Hook Form integration | | hover-card | shadcn add @lumin/hover-card | | | input | shadcn add @lumin/input | | | input-group | shadcn add @lumin/input-group | | | input-otp | shadcn add @lumin/input-otp | | | item | shadcn add @lumin/item | Generic item with media, content, actions | | kbd | shadcn add @lumin/kbd | Keyboard key display | | label | shadcn add @lumin/label | | | menubar | shadcn add @lumin/menubar | | | native-select | shadcn add @lumin/native-select | Native HTML select wrapper | | navigation-menu | shadcn add @lumin/navigation-menu | | | pagination | shadcn add @lumin/pagination | | | popover | shadcn add @lumin/popover | | | progress | shadcn add @lumin/progress | | | radio-group | shadcn add @lumin/radio-group | | | resizable | shadcn add @lumin/resizable | | | scroll-area | shadcn add @lumin/scroll-area | | | select | shadcn add @lumin/select | | | separator | shadcn add @lumin/separator | | | sheet | shadcn add @lumin/sheet | Dialog-based side sheet | | sidebar | shadcn add @lumin/sidebar | Collapsible app sidebar with mobile support | | skeleton | shadcn add @lumin/skeleton | Loading placeholder with animated pulse | | slider | shadcn add @lumin/slider | | | sonner | shadcn add @lumin/sonner | Toast notifications | | spinner | shadcn add @lumin/spinner | | | switch | shadcn add @lumin/switch | | | table | shadcn add @lumin/table | | | tabs | shadcn add @lumin/tabs | | | textarea | shadcn add @lumin/textarea | | | toggle | shadcn add @lumin/toggle | | | toggle-group | shadcn add @lumin/toggle-group | | | tooltip | shadcn add @lumin/tooltip | |

AI Elements

Components for building conversational AI interfaces, built on Vercel AI SDK types.

| Item | shadcn add command | Notes | |------|---------------------|-------| | attachments | shadcn add @lumin/attachments | Grid / inline / list variants with media preview | | chain-of-thought | shadcn add @lumin/chain-of-thought | Multi-step thought process display | | confirmation | shadcn add @lumin/confirmation | Tool approval flow (request / accepted / rejected) | | conversation | shadcn add @lumin/conversation | Scrollable message container with auto-scroll | | inline-citation | shadcn add @lumin/inline-citation | Citation badges with hover card carousel | | message | shadcn add @lumin/message | User/assistant message with Streamdown markdown | | prompt-input | shadcn add @lumin/prompt-input | Full-featured prompt form with file attachments | | reasoning | shadcn add @lumin/reasoning | Collapsible thinking block with duration tracking | | shimmer | shadcn add @lumin/shimmer | Animated text shimmer effect | | sources | shadcn add @lumin/sources | Collapsible source list | | suggestion | shadcn add @lumin/suggestion | Horizontally scrollable suggestion chips |

agent, artifact, audio-player, canvas, checkpoint, code-block, commit, connection, context, controls, edge, environment-variables, file-tree, image, jsx-preview, mic-selector, model-selector, node, open-in-chat, package-info, panel, persona, plan, queue, sandbox, schema-display, snippet, speech-input, stack-trace, task, terminal, test-results, tool, toolbar, transcription, voice-selector, web-preview

Install any of them with npx shadcn@latest add @lumin/<name>.

Run npx shadcn@latest view @lumin/<name> to preview an item before adding it.

4.4 Using a component

// app/page.tsx
import { Button } from "@luminpdf/ds/components/ui/button";
import { FolderPlus } from "@luminpdf/icons/csr";

export default function Page() {
  return (
    <Button>
      <FolderPlus />
      New project
    </Button>
  );
}

5. Use as a Regular npm Package

If you'd rather import components directly instead of copying their source, every component is also exported from @luminpdf/ds:

import { Button } from "@luminpdf/ds/button";
import { Dialog, DialogContent, DialogTitle } from "@luminpdf/ds/dialog";
import { cn } from "@luminpdf/ds/lib/utils";

The full list of entry points lives in the "exports" field of this package's package.json.

Trade-offs vs the registry workflow:

| | Registry (shadcn add) | Direct import (@luminpdf/ds/...) | |--|------------------------|-----------------------------------| | Own the source | ✅ | ❌ | | Customize a single component | ✅ trivial | ❌ have to wrap or fork | | Upgrade story | Re-run shadcn add per component | Bump @luminpdf/ds version once | | Tree-shaking | N/A (source in your repo) | ✅ (per-subpath exports) |


6. Versioning & Upgrades

  • @luminpdf/ds follows semver.
  • Breaking visual/API changes bump major; additive changes bump minor; token-only / non-visible tweaks bump patch.
  • When upgrading via the registry, re-run npx shadcn@latest add @lumin/<name> for each affected component. The CLI will show a diff before overwriting.
  • For reproducible builds, pin the @lumin registry URL to a specific version in components.json (see §4.1).

7. Troubleshooting

"Cannot find module @luminpdf/ds/lib/utils" after shadcn add

The shadcn CLI rewrites imports based on the aliases.utils field in your components.json. If you don't have @luminpdf/ds/lib/utils, change the alias or move the generated lib/utils.ts to match.

Styles look wrong / Tailwind utilities missing

Most commonly caused by:

  1. Missing the @import "@luminpdf/ds/app/theme.css" line in your global CSS.
  2. Importing @luminpdf/ds/app/globals.css (wrong file — DS-dev only).
  3. Having two @import "tailwindcss" statements (second one corrupts the cascade).

@lumin/<name> not found

You haven't registered the namespace in components.json. See §4.1. Verify with:

npx shadcn@latest view @lumin/button

CDN caching makes CI flaky

Pin to a specific version instead of @latest (see §4.1), or switch to cdn.jsdelivr.net.

Peer-dependency install warnings

These are informational — your package manager is telling you which versions @luminpdf/ds expects. Make sure your installed versions of react, tailwindcss, etc. satisfy the ranges in package.json's peerDependencies.

Can't resolve 'shadcn/tailwind.css'

Build error pointing at node_modules/@luminpdf/ds/app/theme.css:

Error: Can't resolve 'shadcn/tailwind.css' in '…/@luminpdf/ds/app'

shadcn/tailwind.css is a real file shipped by the shadcn npm package (exposed via exports["./tailwind.css"]), but it's declared as a peer dependency so it isn't installed automatically. Install it in your host app:

pnpm add shadcn

If you already have shadcn installed and still see the error, your bundler may not honor the style export condition — ensure you're on Tailwind v4 with its framework plugin (@tailwindcss/postcss or @tailwindcss/vite, see §2.1). Tailwind v4 processes CSS @imports before passing to PostCSS, which resolves subpath exports correctly.

@tailwindcss/postcss missing / Tailwind utilities not generated

Tailwind v4 is a peer dep, but you also need its bundler plugin. See §2.1 for the matrix of which plugin to install per framework (Next → @tailwindcss/postcss, Vite → @tailwindcss/vite, etc.).

TypeError: (0 , j.createContext) is not a function (or similar) from a DS component

Symptom: a server-rendered page that uses Dialog, DropdownMenu, Select, Popover, or another Radix-based component blows up at module init, usually during next build page data collection.

Cause: your shadcn-installed file is missing its "use client" directive at line 1. The DS source and registry JSON both ship the directive, but shadcn CLI strips it when rsc: false (the default when the key is missing from components.json).

Fix: add "rsc": true to your components.json (see §4.1), delete the broken files in components/ui/, and re-run npx shadcn@latest add @lumin/<name> for each one. Verify the first line of each generated .tsx is "use client" before rebuilding.

Direct @luminpdf/ds/* import fails to compile in Next.js

Symptom: import { Card } from "@luminpdf/ds/card" (the "regular npm package" workflow from §5) fails with Unknown module type or similar from Turbopack / Webpack.

Cause: Next.js does not transpile .tsx files inside node_modules by default.

Fix: add @luminpdf/ds to transpilePackages in next.config.ts:

const nextConfig: NextConfig = {
  transpilePackages: ["@luminpdf/ds"],
};

Components installed via shadcn add live in your app tree and are compiled normally — this setting is only needed for the direct-import workflow.