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

@aspireiq-design/design-system

v0.1.0

Published

<div align="center"> <img src="https://img.shields.io/badge/version-1.0.0-E3F1BB?style=for-the-badge&labelColor=16282D" alt="version" /> <img src="https://img.shields.io/badge/storybook-10.2.9-FF4785?style=for-the-badge&logo=storybook&logoColor=white"

Readme

Aspire Design Story


What's Inside

60+ production-ready components, 80+ Storybook stories, and full design token coverage — everything a developer needs to build consistent Aspire product experiences.

225+ source files  ·  60+ components  ·  80+ stories  ·  5 feature domains

Quick Start

# Clone the repo
git clone https://github.com/aspireiq/aspire-design-story.git
cd aspire-design-story

# Install dependencies
npm install

# Start Storybook
npm run storybook
# → Opens at http://localhost:6006

# Start Next.js dev server
npm run dev
# → Opens at http://localhost:3000

Stack

| Technology | Version | Purpose | |-----------|---------|---------| | Next.js | 16.x | Framework | | React | 19.x | UI library | | TypeScript | 5.x | Type safety | | Tailwind CSS | v4 | Styling | | shadcn/ui | latest | Component primitives | | shadcn Studio | Pro | Enhanced components & blocks | | Storybook | 10.2.9 | Component documentation | | Lucide React | latest | Icons | | Recharts | latest | Data visualization |


Project Structure

aspire-design-story/
├── .storybook/
│   ├── main.js              # Storybook config, webpack aliases, addons
│   ├── preview.tsx          # Global decorators, dark mode, theme
│   └── manager.ts           # Aspire-branded sidebar theme
│
├── src/
│   ├── app/
│   │   ├── globals.css      # ← All design tokens live here (HSL CSS variables)
│   │   └── layout.tsx       # Root layout
│   │
│   ├── components/
│   │   ├── ui/              # shadcn/ui base primitives (43 components)
│   │   ├── layout/          # AppShell, AppSidebar, PageHeader, AspireLogo
│   │   ├── shared/          # Reusable Aspire components (DataTable, FilterBar, etc.)
│   │   │   └── wizard/      # Reusable multi-step creation wizard
│   │   ├── analytics/       # Analytics page + charts + MetricCard
│   │   ├── campaigns/       # Campaigns page + CampaignCard + CreateCampaignWizard
│   │   ├── contact-detail/  # 5-tab creator profile page
│   │   ├── contacts/        # CRM contacts table page
│   │   ├── inbox/           # Split-pane messaging
│   │   ├── offers/          # Offers page + CreateOfferWizard
│   │   └── settings/        # All settings sections (profile, billing, etc.)
│   │
│   ├── hooks/
│   │   ├── use-sortable.ts       # Reusable table sorting
│   │   ├── use-search-filter.ts  # Reusable search/filter
│   │   └── use-pagination.ts     # Reusable pagination
│   │
│   ├── lib/
│   │   ├── utils.ts              # cn() helper
│   │   ├── formatters.ts         # formatK(), formatRelativeTime()
│   │   └── constants/
│   │       └── platforms.ts      # Platform type + color maps
│   │
│   └── stories/                  # Storybook stories (mirrors component structure)
│       ├── 1. getting-started/
│       ├── 2. foundations/
│       ├── 3. primitives/
│       ├── 4. components/
│       ├── 5. layout/
│       ├── 6. pages/
│       └── 7. patterns/
│
├── CLAUDE.md                # AI agent instructions for this codebase
├── components.json          # shadcn/ui config + studio registries
└── package.json

Using Components

Import Pattern

// shadcn/ui primitives → from @/components/ui/
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'

// Aspire shared components → from @/components/shared/
import { DataTable } from '@/components/shared/DataTable'
import { FilterBar } from '@/components/shared/FilterBar'
import { EmptyState } from '@/components/shared/EmptyState'
import { StatusDot } from '@/components/shared/StatusDot'
import { MetricCard } from '@/components/analytics/MetricCard'

// Layout → from @/components/layout/
import { AppShell } from '@/components/layout/AppShell'
import { PageHeader } from '@/components/layout/PageHeader'

Common Patterns

Page with Table

import { AppShell } from '@/components/layout/AppShell'
import { PageHeader } from '@/components/layout/PageHeader'
import { FilterBar } from '@/components/shared/FilterBar'
import { TableActionBar } from '@/components/shared/TableActionBar'
import { DataTable } from '@/components/shared/DataTable'
import { Pagination } from '@/components/shared/Pagination'
import { Button } from '@/components/ui/button'

export function ContactsPage() {
  return (
    <AppShell>
      <PageHeader
        title="Contacts"
        action={<Button>New Creator</Button>}
      />
      <FilterBar filters={filters} onFilterChange={setFilters} />
      <TableActionBar actions={bulkActions} />
      <DataTable data={creators} columns={columns} />
      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        onPageChange={setCurrentPage}
      />
    </AppShell>
  )
}

Page with Cards + View Toggle

import { ViewToggle } from '@/components/shared/ViewToggle'
import { CampaignCard } from '@/components/campaigns/CampaignCard'

export function CampaignsPage() {
  const [view, setView] = useState<'grid' | 'list'>('grid')

  return (
    <AppShell>
      <PageHeader title="Campaigns" action={<Button>Create Campaign</Button>} />
      <div className="flex justify-end">
        <ViewToggle value={view} onChange={setView} />
      </div>
      {view === 'grid' ? (
        <div className="grid grid-cols-3 gap-4">
          {campaigns.map(c => <CampaignCard key={c.id} campaign={c} />)}
        </div>
      ) : (
        <DataTable data={campaigns} columns={campaignColumns} />
      )}
    </AppShell>
  )
}

Multi-Step Creation Wizard

import { CreationWizard } from '@/components/shared/wizard/CreationWizard'
import type { WizardStep } from '@/components/shared/wizard/CreationWizard'

const steps: WizardStep[] = [
  { id: 'basics',   label: 'Campaign Basics',       component: CampaignBasicsStep   },
  { id: 'creators', label: 'Creator Requirements',  component: CreatorRequirementsStep },
  { id: 'terms',    label: 'Compensation & Terms',  component: CompensationStep     },
  { id: 'advanced', label: 'Advanced Settings',     component: AdvancedStep         },
  { id: 'review',   label: 'Review & Create',       component: ReviewStep           },
]

export function CreateCampaignPage() {
  return (
    <CreationWizard
      title="Create New Campaign"
      steps={steps}
      onComplete={(data) => createCampaign(data)}
      onCancel={() => router.back()}
    />
  )
}

Status Indicators

import { StatusDot } from '@/components/shared/StatusDot'

// Small colored dot with label — use this instead of Badge for row-level status
<StatusDot status="active" />      // green dot + "Active"
<StatusDot status="paused" />      // orange dot + "Paused"
<StatusDot status="error" />       // red dot + "Error"
<StatusDot status="draft" />       // gray dot + "Draft"
<StatusDot status="completed" />   // blue dot + "Completed"

Metric Cards

import { MetricCard } from '@/components/analytics/MetricCard'

<MetricCard
  label="Total Impressions"
  value="1.2M"
  trend={+12.5}          // positive = green ↑, negative = red ↓
  sparklineData={weeklyData}
/>

Tag Pills

import { TagPillGroup } from '@/components/shared/TagPillGroup'

// Campaign tags (colored)
<TagPillGroup
  tags={['Petfluencer Perks', 'Summer Launch']}
  variant="campaign"
/>

// Group tags (colored, different palette)
<TagPillGroup
  tags={['Brand Ambassadors', 'VIP']}
  variant="group"
/>

// Generic tags (gray)
<TagPillGroup
  tags={['Partnership', 'Sponsored', 'Giveaway']}
  variant="tag"
/>

Empty States

import { EmptyState } from '@/components/shared/EmptyState'
import { Tag } from 'lucide-react'

<EmptyState
  icon={Tag}
  title="No Offers Yet"
  description="Create your first offer to start tracking affiliate performance."
  action={{ label: 'Create Offer', onClick: handleCreate }}
  learnMoreHref="https://help.aspire.io/offers"
/>

Design Tokens

All tokens are in src/app/globals.css as HSL CSS custom properties.

Colors

/* Usage: hsl(var(--token-name)) */

--background          /* Page background: white / dark: near-black     */
--foreground          /* Primary text: warm stone dark                  */
--primary             /* Deep dark teal #16282D — buttons, active states */
--primary-foreground  /* White #ffffff — text on primary bg              */
--accent              /* Lime green #E3F1BB — highlights, tags, active nav */
--accent-foreground   /* Deep dark teal #16282D — text on accent bg      */
--secondary           /* Subtle backgrounds                             */
--muted               /* Muted text, disabled states                    */
--border              /* Card borders, dividers: light gray             */
--destructive         /* Error, delete: red #dc2626                     */
--info                /* Informational: teal #0d9488                    */
--success             /* Success: green #059669                         */
--warning             /* Warning: amber #eab308                         */

Typography

// Font families
font-sans   → Inter
font-mono   → Geist Mono

// Common text styles used across the system
text-xs     → 12px  (timestamps, helper text)
text-sm     → 14px  (body text, labels, table content)
text-base   → 16px  (card titles, nav labels)
text-lg     → 18px  (section headers)
text-xl     → 20px  (page sub-headings)
text-2xl    → 24px  (page titles)
text-3xl    → 30px  (hero headings)

Border Radius

rounded-sm   → 6px   (tags, small badges)
rounded-md   → 8px   (inputs, buttons)
rounded-lg   → 10px  (cards, dialogs, dropdowns)
rounded-xl   → 14px  (large panels, sheets)
rounded-full → 9999px (avatar circles, pill badges)

Dark Mode

Dark mode is applied via the .dark class on the root element. All tokens automatically switch — no additional configuration needed.

// In your story or component:
<div className="dark">
  <YourComponent />
</div>

Icons

All icons use Lucide React. Convention: 20px size, 1.5px stroke.

import { Users, Megaphone, BarChart3, Tag, Image, Settings } from 'lucide-react'

// Standard usage
<Users className="h-5 w-5" />          // 20px
<Megaphone className="h-4 w-4" />      // 16px (inline / table)
<Settings className="h-6 w-6" />       // 24px (nav icons)

// With color
<Users className="h-5 w-5 text-muted-foreground" />

Utility Functions

import { cn } from '@/lib/utils'
import { formatK, formatRelativeTime } from '@/lib/formatters'
import { PLATFORM_COLORS, Platform } from '@/lib/constants/platforms'

// Merge classNames (handles conditional classes)
cn('text-sm font-medium', isActive && 'text-primary')

// Format large numbers
formatK(1234567)   // → "1.2M"
formatK(45300)     // → "45.3K"
formatK(890)       // → "890"

// Relative timestamps
formatRelativeTime(new Date())             // → "just now"
formatRelativeTime(new Date(Date.now() - 3600000))  // → "1 hrs ago"

// Platform colors
PLATFORM_COLORS['instagram']  // → "#E1306C"
PLATFORM_COLORS['tiktok']     // → "#000000"
PLATFORM_COLORS['youtube']    // → "#FF0000"

Custom Hooks

import { useSortable } from '@/hooks/use-sortable'
import { useSearchFilter } from '@/hooks/use-search-filter'
import { usePagination } from '@/hooks/use-pagination'

// Sorting
const { sorted, sortKey, sortDirection, toggleSort } = useSortable(data)

// Search + filter
const { filtered } = useSearchFilter(creators, ['name', 'handle', 'email'])

// Pagination
const { paginated, currentPage, totalPages, setPage } = usePagination(data, 50)

Storybook Structure

1. Getting Started    → Welcome, How to Use, Component Index
2. Foundations        → Design Tokens, Typography, Colors, Icons, Brand
3. Primitives         → Button, Input, Badge, Avatar, Switch... (17 components)
4. Components         → DataTable, FilterBar, Charts, EmptyState... (30+ components)
   ├── Data Display
   ├── Forms
   ├── Feedback
   ├── Navigation
   ├── Tables
   ├── Charts
   └── Utilities
5. Layout             → AppShell, AppSidebar, PageHeader, AspireLogo
6. Pages              → Full page compositions with realistic data
   ├── Contacts & Contact Detail
   ├── Campaigns
   ├── Offers
   ├── Analytics
   ├── Inbox
   └── Settings (8 sections)
7. Patterns           → Form Patterns, Table Patterns, Empty States

Each story has:

  • Docs tab — full JSDoc, props table, code snippets, usage guidelines
  • Story tab — interactive component with controls panel
  • Source tab — copy-paste ready component code

For AI Agents

See CLAUDE.md in the project root for complete AI agent instructions, including component APIs, import paths, common patterns, and design token references.

Quick reference for agents:

Base primitives:    @/components/ui/*
Aspire components:  @/components/shared/*
Layout:             @/components/layout/*
Feature pages:      @/components/[feature]/*
Utilities:          @/lib/utils, @/lib/formatters, @/lib/constants/*
Hooks:              @/hooks/*
Tokens:             src/app/globals.css (CSS custom properties)

Development Scripts

npm run dev          # Next.js dev server (port 3000)
npm run storybook    # Storybook (port 6006)
npm run build        # Production build
npm run build-storybook  # Build Storybook for deployment
npm run lint         # ESLint
npm run type-check   # TypeScript check (tsc --noEmit)

Adding a New Component

  1. Create the component in the appropriate directory:

    # For a new shared component
    touch src/components/shared/MyComponent.tsx
    
    # For a new feature component
    touch src/components/campaigns/MyComponent.tsx
  2. Add it to the barrel export (if one exists):

    // src/components/shared/index.ts
    export { MyComponent } from './MyComponent'
  3. Create the story:

    touch src/stories/4.\ components/MyCategory/MyComponent.stories.tsx
  4. Follow the story template in src/stories/3. primitives/Button.stories.tsx


Adding New shadcn/ui Components

# Add a single component
npx shadcn@latest add [component-name]

# From shadcn Studio Pro registry (requires .env with credentials)
npx shadcn@latest add @ss-components/[component-name]
npx shadcn@latest add @ss-blocks/[block-name]

Browser Support

| Browser | Support | |---------|---------| | Chrome | Last 2 versions | | Firefox | Last 2 versions | | Safari | Last 2 versions | | Edge | Last 2 versions |


Contributing

  1. Follow existing component patterns (see Button as reference)
  2. Write TypeScript — no any types
  3. Add a story for every new component
  4. Support dark mode with Tailwind dark: modifier
  5. Use Aspire CSS tokens, not raw hex values
  6. Test in both light and dark mode before submitting