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

@leanspec/ui-components

v0.2.23

Published

Framework-agnostic, tree-shakeable UI components for LeanSpec

Readme

@leanspec/ui-components

Framework-agnostic, tree-shakeable UI components for LeanSpec.

Installation

npm install @leanspec/ui-components
# or
pnpm add @leanspec/ui-components

Usage

import { StatusBadge, PriorityBadge, SpecCard, EmptyState, SearchInput } from '@leanspec/ui-components';
import '@leanspec/ui-components/styles.css';

function MyComponent() {
  return (
    <div>
      <SearchInput placeholder="Search specs..." onSearch={(q) => console.log(q)} />
      <StatusBadge status="in-progress" />
      <PriorityBadge priority="high" />
      <SpecCard 
        spec={{ 
          specNumber: 185, 
          specName: 'ui-components', 
          title: 'UI Components',
          status: 'in-progress',
          priority: 'high',
          tags: ['ui', 'components'],
          updatedAt: new Date().toISOString(),
        }} 
      />
    </div>
  );
}

Components

Spec Components

  • StatusBadge - Display spec status with icon
  • PriorityBadge - Display spec priority with icon
  • SpecCard - Compact spec card for lists
  • SpecMetadata - Metadata display card with all spec details
  • TagBadge - Display a single tag
  • TagList - Display multiple tags with truncation

Project Components

  • ProjectAvatar - Avatar with initials and color from project name
  • ProjectCard - Project card with avatar, description, stats, and tags
  • ProjectSwitcher - Project switcher dropdown (framework-agnostic with callbacks)
  • ProjectDialog - Project creation/edit dialog (framework-agnostic with callbacks)

Stats Components

  • StatsCard - Single stat card with icon and trend indicator
  • StatsOverview - Grid of stats cards for project overview
  • ProgressBar - Horizontal progress bar with variants

Search & Filter Components

  • SearchInput - Search input with keyboard shortcut hint
  • FilterSelect - Dropdown filter component
  • SearchResults - Search results grid display

Graph Components

  • SpecDependencyGraph - Interactive dependency graph using ReactFlow (framework-agnostic with callbacks)

Navigation Components

  • ThemeToggle - Light/dark theme toggle button
  • BackToTop - Floating scroll-to-top button

UI Components (shadcn/ui)

  • Accordion - Collapsible content sections
  • Alert - Feedback messages with variants
  • Avatar - Avatar with image and fallback (with size variants)
  • Badge - Base badge component with variants
  • Button - Button with variants (default, destructive, outline, secondary, ghost, link)
  • ButtonGroup - Group of related buttons
  • Card - Card container with header, content, footer
  • Carousel - Slideable content carousel
  • Collapsible - Expandable/collapsible content
  • Command - Command palette component
  • Dialog - Modal dialog component
  • DropdownMenu - Dropdown menu with nested items
  • HoverCard - Content shown on hover
  • Input - Form input field
  • InputGroup - Input with prefix/suffix addons
  • Popover - Floating content container
  • Progress - Progress bar indicator
  • ScrollArea - Custom scrollable container
  • Select - Dropdown select component (with size variants)
  • Separator - Horizontal or vertical divider
  • Skeleton - Loading placeholder
  • Switch - Toggle switch
  • Tabs - Tabbed content navigation
  • Textarea - Multi-line text input
  • Tooltip - Contextual information on hover

AI Elements (Chat/Agent UI)

All 48 AI Elements components for building AI chat interfaces:

  • Agent, AgentTools, AgentTool - AI agent display
  • Artifact - Code/content artifacts
  • Attachments - File attachments
  • AudioPlayer - Audio playback
  • Canvas - Drawing canvas
  • ChainOfThought, Reasoning - AI reasoning display
  • CodeBlock - Syntax-highlighted code with copy
  • Confirmation - User confirmation dialogs
  • Conversation, ConversationContent - Chat container
  • Message, MessageContent, MessageResponse - Chat messages
  • Loader, Shimmer - Loading indicators
  • PromptInput, PromptInputTextarea - Chat input
  • Terminal - Terminal output display
  • Tool, ToolExecution - Tool call visualization
  • And many more...

Layout Components

  • EmptyState - Empty state placeholder with icon, title, description, action
  • SpecListSkeleton - Loading skeleton for spec list
  • SpecDetailSkeleton - Loading skeleton for spec detail
  • StatsCardSkeleton - Loading skeleton for stats card
  • KanbanBoardSkeleton - Loading skeleton for kanban board
  • ProjectCardSkeleton - Loading skeleton for project card
  • SidebarSkeleton - Loading skeleton for sidebar
  • ContentSkeleton - Generic content skeleton

Hooks

  • useLocalStorage - Persist state in localStorage
  • useDebounce - Debounce a value
  • useDebouncedCallback - Debounce a callback function
  • useTheme - Theme state management with localStorage persistence

Utilities

  • cn - Merge Tailwind CSS classes
  • formatDate - Format date in readable format
  • formatDateTime - Format date with time
  • formatRelativeTime - Format relative time (e.g., "2 days ago")
  • formatDuration - Format duration between dates
  • getColorFromString - Generate consistent color from string
  • getContrastColor - Get contrasting text color for background
  • getInitials - Get initials from name string
  • PROJECT_COLORS - Predefined color palette

Types

All spec-related TypeScript types are exported:

  • Spec, LightweightSpec, SidebarSpec
  • SpecStatus, SpecPriority
  • StatsResult, DependencyGraph, etc.

Advanced Usage Examples

Using SpecDependencyGraph

import { SpecDependencyGraph } from '@leanspec/ui-components';

function MyDependencyView({ relationships, specNumber, specTitle }) {
  return (
    <div style={{ height: '600px' }}>
      <SpecDependencyGraph
        relationships={relationships}
        specNumber={specNumber}
        specTitle={specTitle}
        onNodeClick={(specId) => {
          // Handle navigation to spec
          router.push(`/specs/${specId}`);
        }}
        labels={{
          title: 'Dependencies',
          subtitle: 'Click to navigate',
        }}
      />
    </div>
  );
}

Using ProjectSwitcher

import { ProjectSwitcher } from '@leanspec/ui-components';

function MyProjectSwitcher({ currentProject, projects }) {
  return (
    <ProjectSwitcher
      currentProject={currentProject}
      projects={projects}
      onProjectSelect={(projectId) => {
        // Handle project switching
        router.push(`/projects/${projectId}`);
      }}
      onAddProject={() => {
        // Open project creation dialog
        setShowDialog(true);
      }}
      onManageProjects={() => {
        // Navigate to project management
        router.push('/projects');
      }}
    />
  );
}

Using ProjectDialog

import { ProjectDialog } from '@leanspec/ui-components';

function MyProjectDialog({ open, onOpenChange }) {
  return (
    <ProjectDialog
      open={open}
      onOpenChange={onOpenChange}
      onSubmit={async (path) => {
        // Handle project creation
        await createProject(path);
        onOpenChange(false);
      }}
      onBrowseFolder={async () => {
        // Show native file picker (Tauri/Electron)
        const result = await window.__TAURI__.dialog.open({
          directory: true,
        });
        return result;
      }}
    />
  );
}

Using SearchResults

import { SearchResults } from '@leanspec/ui-components';

function MySearch({ query, results, isSearching }) {
  return (
    <SearchResults
      query={query}
      results={results}
      isSearching={isSearching}
      onSpecClick={(specId) => {
        router.push(`/specs/${specId}`);
      }}
    />
  );
}

Development

# Install dependencies
pnpm install

# Build the library
pnpm build

# Run tests
pnpm test

License

MIT