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

@cosplay-ai/ui

v0.7.2

Published

Shared UI components, shell primitives, and theming contract for [Cosplay](https://github.com/aaronk9-web/cosplay) and `cosplay-cloud` portal.

Readme

@cosplay-ai/ui

Shared UI components, shell primitives, and theming contract for Cosplay and cosplay-cloud portal.

Install

npm install @cosplay-ai/ui

The package is published to the public npm registry (registry.npmjs.org). No .npmrc configuration is needed — npm install @cosplay-ai/ui works out of the box.

Peer dependency matrix

The package requires the following peer dependencies to be provided by the consuming application. Pin to at least the minimum version shown.

| Peer dependency | Required version | | --- | --- | | react | ^19 | | react-dom | ^19 | | next | ^15 | | tailwindcss | ^3.4 | | @radix-ui/react-collapsible | ^1.1 | | @radix-ui/react-dialog | ^1.1 | | @radix-ui/react-dropdown-menu | ^2.1 | | @radix-ui/react-label | ^2.1 | | @radix-ui/react-scroll-area | ^1.2 | | @radix-ui/react-select | ^2.2 | | @radix-ui/react-separator | ^1.1 | | @radix-ui/react-slot | ^1.2 | | @radix-ui/react-tabs | ^1.1 | | @radix-ui/react-tooltip | ^1.2 | | lucide-react | ^1.7 | | next-themes | ^0.4 | | sonner | ^2 | | react-markdown | ^10 | | remark-gfm | ^4 |

Install them alongside @cosplay-ai/ui:

npm install react react-dom next tailwindcss \
  @radix-ui/react-collapsible @radix-ui/react-dialog \
  @radix-ui/react-dropdown-menu @radix-ui/react-label \
  @radix-ui/react-scroll-area @radix-ui/react-select \
  @radix-ui/react-separator @radix-ui/react-slot \
  @radix-ui/react-tabs @radix-ui/react-tooltip \
  lucide-react next-themes sonner \
  react-markdown remark-gfm

Tailwind configuration (required)

You must add the @cosplay-ai/ui source glob to your Tailwind content array. Without it, Tailwind will tree-shake every utility class used inside the package and your application will ship with broken or unstyled UI.

// tailwind.config.js
module.exports = {
  presets: [require("@cosplay-ai/ui/tailwind-preset")],
  content: [
    "./app/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
    // Required: scan package output so Tailwind does not purge package classes
    "./node_modules/@cosplay-ai/ui/**/*.{js,mjs}",
  ],
  theme: {
    extend: {
      // Add portal-specific tokens here (brand colors, custom radius, etc.)
    },
  },
};

The preset (@cosplay-ai/ui/tailwind-preset) exports the full theme.extend block (HSL-variable-driven palette, sidebar tokens, status colors, animation, typography). Consumers that need to override brand tokens do so in their own theme.extend after the preset — Tailwind merges them in order.

Import entrypoints

| Import path | Contents | | --- | --- | | @cosplay-ai/ui | Server-safe barrel — formatters, types, theme CSS re-export. Safe to import from React Server Components. | | @cosplay-ai/ui/client | Client-component barrel — every component marked "use client". Import from client components and layouts. | | @cosplay-ai/ui/styles | Default theme CSS (theme.css) — exposes the :root and html.light CSS custom property blocks. | | @cosplay-ai/ui/primitives | Primitive theme CSS (theme-primitives.css) — layout and animation primitives. | | @cosplay-ai/ui/tailwind-preset | Tailwind preset — the theme.extend block. Required in tailwind.config.js. |

Usage example

1. Import global styles

In your application's root layout or global CSS file, import the package stylesheet before your own overrides:

/* app/globals.css */
@import "@cosplay-ai/ui/styles";   /* default theme tokens (:root + html.light) */
@import "@cosplay-ai/ui/primitives"; /* layout + animation primitives */

/* Override brand tokens for this application */
:root {
  --primary: 226 70% 55.5%;
  --radius: 0.5rem;
}

2. Wrap your layout with AppShell

// app/layout.tsx
import { ThemeProvider } from "@cosplay-ai/ui/client";
import { Toaster } from "sonner";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="dark">
          <Toaster />
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

3. Use components

// components/my-page.tsx
"use client";

import { Button } from "@cosplay-ai/ui/client";
import { StatusBadge, PriorityPicker } from "@cosplay-ai/ui/client";

export function MyPage() {
  return (
    <div className="p-6 space-y-4">
      <StatusBadge status="in_progress" />
      <PriorityPicker value="P1" onChange={() => {}} />
      <Button variant="default">Run workflow</Button>
    </div>
  );
}

4. AppShell with nav config

// app/(shell)/layout.tsx
"use client";

import {
  AppShell,
  AppSidebar,
  ProjectProvider,
} from "@cosplay-ai/ui/client";
import { Home, Settings } from "lucide-react";
import type { NavGroup } from "@cosplay-ai/ui/client";

const navGroups: NavGroup[] = [
  {
    label: "Main",
    items: [
      { href: "/", label: "Home", icon: <Home size={16} /> },
      { href: "/settings", label: "Settings", icon: <Settings size={16} /> },
    ],
  },
];

export default function ShellLayout({ children }: { children: React.ReactNode }) {
  return (
    <ProjectProvider currentSlug={null} currentProjectName={null}>
      <AppShell
        sidebar={
          <AppSidebar
            brand={{ logo: <span>My App</span>, label: "MY APP", href: "/" }}
            navGroups={navGroups}
          />
        }
      >
        {children}
      </AppShell>
    </ProjectProvider>
  );
}

Theming

The package ships a three-layer theming contract so consumers can brand the UI without forking component source.

Layer 1 — CSS custom properties

Override any token in @cosplay-ai/ui/styles in your own stylesheet (loaded after the package's import):

/* your app/globals.css — after @import "@cosplay-ai/ui/styles" */
:root {
  --primary: 262 83% 58%;           /* purple brand */
  --primary-foreground: 0 0% 100%;
  --radius: 0.75rem;
  --sidebar-background: 262 30% 14%;
}
html.light {
  --primary: 262 83% 44%;
}

Every Tailwind utility class (bg-primary, text-foreground, border-border, etc.) resolves through these tokens — you never touch compiled Tailwind output.

Layer 2 — Tailwind preset

The preset exposes the full theme.extend block from the cosplay dashboard. Extend it with your own tokens:

// tailwind.config.js
module.exports = {
  presets: [require("@cosplay-ai/ui/tailwind-preset")],
  content: [
    "./app/**/*.{ts,tsx}",
    "./components/**/*.{ts,tsx}",
    "./node_modules/@cosplay-ai/ui/**/*.{js,mjs}",  // <-- required
  ],
  theme: {
    extend: {
      colors: {
        brand: { 500: "hsl(var(--primary))" },
      },
    },
  },
};

Layer 3 — Slot props

When you need a different shape (not just a different color), use component slot props: brand, navGroups, footerItems, themeToggle, projectPicker. See the AppShell example above.

Client/server boundaries

Planned barrel split (ADR — task_1148)

The package exposes three export entrypoints with strict RSC compatibility rules:

| Entrypoint | Contents | "use client" rule | | --- | --- | --- | | @cosplay-ai/ui | Server-safe barrel — pure formatters (cn, formatDate, formatDuration, …), presentational type definitions, and CSS re-exports. Safe to import from React Server Components. | No directive — the barrel file and every constituent file must be free of hooks and browser APIs. | | @cosplay-ai/ui/client | Client-only barrel — every React component that uses hooks or browser APIs: all 26 shadcn/Radix primitives, page bodies, workflow composites, shell components, landing components, state providers, and client hooks. | Must have "use client" at line 1 of both the barrel file (src/client.ts) and every constituent .tsx/.ts file so tree-shakers preserve the directive when files are bundled individually. | | @cosplay-ai/ui/styles | CSS-only — theme.css (:root and html.light custom property blocks). | N/A — CSS files have no directive concept. | | @cosplay-ai/ui/primitives | CSS-only — theme-primitives.css (layout and animation primitives). | N/A |

Why each constituent file needs its own directive

The "use client" directive on the barrel (src/client.ts) is not sufficient on its own. When a bundler (Next.js App Router, Webpack, Turbopack) processes individual files from the package, it re-evaluates the directive at the file level. A file without "use client" that happens to be re-exported from a barrel carrying the directive may still be treated as server-safe in some bundler configurations, causing a runtime error if the file contains useState or other client-only APIs. The fix is belt-and-suspenders: add "use client" to every file in the @cosplay-ai/ui/client bucket.

Current audit status

An audit checklist at .cosplay/artifacts/cto/shared-ui-client-audit.md enumerates every file slated for extraction with its current directive status. As of the UI-12 audit (task_1148), 29 dashboard source files are missing the "use client" directive and must have it added before they are extracted into packages/ui/src/. These additions are safe to land in-place in the dashboard (no runtime behavior change — Next.js already treats them as client components via their import chain).

Import rules for consumers

Components that use React hooks or browser APIs are exported exclusively from @cosplay-ai/ui/client (the "use client" barrel). Do not import from @cosplay-ai/ui/client inside React Server Components — Next.js will error at build time.

If you need a type from the client barrel inside a server file, use a type-only import:

import type { NavGroup } from "@cosplay-ai/ui/client";

Server-safe utilities (formatters, pure types) are available from the default entrypoint and are safe to import anywhere:

import { cn, formatDate, formatDuration } from "@cosplay-ai/ui";

Versioning + Migration

Pin discipline

The dashboard and every other consumer must exact-pin @cosplay-ai/ui — no caret (^), no tilde (~). Every version bump is intentional: you review the release notes, update the pin, run tests, then merge.

// dashboard/package.json — correct
"@cosplay-ai/ui": "0.1.0"

// dashboard/package.json — incorrect (auto-upgrades silently)
"@cosplay-ai/ui": "^0.1.0"

This mirrors the pattern established by @cosplay-ai/protocol, the reference implementation for Cosplay's shared package discipline. Treat @cosplay-ai/protocol as the authoritative example of how a shared package in this monorepo is versioned, pinned, and released.

Semantic versioning during 0.x

@cosplay-ai/ui starts at 0.x while the public API stabilises:

  • Patch releases (0.1.0 → 0.1.1) — additive only: new exports, bug fixes, internal refactors, documentation updates. Consumers can apply these safely.
  • Minor releases (0.1.0 → 0.2.0) — may contain breaking changes (renamed exports, changed prop types, removed components). Update the consumer pin deliberately and review the migration notes.
  • 1.0.0 — cut once both the Cosplay dashboard and cosplay-cloud portal build clean from the same release for two consecutive weekly cycles. From 1.0.0 onward, standard SemVer applies: breaking changes are major-only.

Release cadence

  • Weekly patch releases during the 0.x convergence phase — predictable cadence so consumers can stay current without large accumulation of changes.
  • Per-PR minor releases for breaking changes during 0.x — each breaking change ships immediately so the diff is small and reviewable.
  • Post-1.0: monthly minors, patches as needed.

Migration guides (1.x → 2.x and beyond)

Each future major release ships a MIGRATION-vX.md file at the root of the package (e.g. packages/ui/MIGRATION-v2.md) following the Stripe API versioning playbook: a numbered checklist of every breaking change with before/after code snippets, so consumers can step through the rollover systematically.

No MIGRATION-v*.md file exists yet — there are no breaking changes pending. This is the stub for when the first major bump happens.

Worked example: bumping the pin (dependabot-equivalent flow)

  1. A new patch or minor release of @cosplay-ai/ui is published (e.g. 0.1.1).
  2. Open dashboard/package.json and update the pin:
    -  "@cosplay-ai/ui": "0.1.0",
    +  "@cosplay-ai/ui": "0.1.1",
  3. Run npm install at the repo root to update the lockfile.
  4. If it is a minor bump (e.g. 0.1.0 → 0.2.0), read the release notes and any MIGRATION-v*.md before proceeding.
  5. Run the dashboard test suite:
    npx tsc --noEmit --project dashboard/tsconfig.json
    npx vitest run
    npm run build --workspace=cosplay-dashboard
  6. Fix any type errors or import renames surfaced by the above.
  7. Commit the package.json + package-lock.json change in a single commit: chore: bump @cosplay-ai/ui to 0.1.1.
  8. Open a PR, review the diff, merge.

License

MIT — see LICENSE.