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

@codeatlasdev/ui

v0.1.0

Published

Glass-first Svelte 5 design system. OKLCH tokens, Liquid Glass materials, Bits UI primitives.

Readme

Install

npm install @codeatlasdev/ui
# or
bun add @codeatlasdev/ui

@codeatlasdev/ui

Glass-first Svelte 5 design system. Svelte 5 runes, Bits UI primitives, OKLCH tokens, zero Tailwind.


Setup

// app.css (or root layout)
import '@codeatlasdev/ui/styles/global.css';
import '@codeatlasdev/ui/styles/materials.css';
<!-- root +layout.svelte -->
<script>
  import { colorScheme } from '@codeatlasdev/ui';
  import { onMount } from 'svelte';
  onMount(() => colorScheme.init());
</script>

Page layouts — which one to use

| Layout | Use when | |---|---| | AppList | List/CRUD page — table with internal scroll, fixed pagination footer | | AppForm | Create/edit form — fixed header, scrollable body, sticky action footer | | AppSettings | Settings page — fixed left nav + scrollable content (GitHub/Vercel style) | | PageShell | Dashboard, reports, free content — normal scroll |

AppList

Data-driven mode (recommended):

<!-- Data-driven mode (recommended) -->
<AppList title="Users" data={ALL} searchKeys={['name', 'email']} perPage={8}>
  {#snippet filters(list)}
    <FilterGroup options={roleOpts} value={list.filters['role']}
                 onchange={v => list.setFilter('role', v)} />
  {/snippet}
  {#snippet children(list)}
    <SimpleTable>
      <thead><tr><th>Name</th><th>Role</th><th>Status</th><th></th></tr></thead>
      <tbody>
        {#each list.rows as u (u.id)}
          <tr>
            <td class="primary"><UserCell name={u.name} email={u.email} /></td>
            <td>{u.role}</td>
            <td><StatusChip status={u.status === 'active' ? 'success' : 'neutral'} /></td>
            <td><Row gap={4} class="ca-row-actions">
              <Button variant="ghost" size="sm"><Edit2 size={13} /></Button>
              <Button variant="ghost" size="sm"><Trash2 size={13} /></Button>
            </Row></td>
          </tr>
        {/each}
      </tbody>
    </SimpleTable>
  {/snippet}
</AppList>

Manual mode (for server-side data):

<AppList title="Users" description="24 of 240">
  {#snippet actions()}
    <Button variant="filled" href="/users/new">+ New user</Button>
  {/snippet}

  {#snippet toolbar()}
    <TextField placeholder="Search…" bind:value={search} class="search-field">
      {#snippet leading()}<Search size={14} />{/snippet}
    </TextField>
    <Select bind:value={roleF} options={roleOpts} />
  {/snippet}

  <SimpleTable>
    <thead><tr><th>Name</th><th>Role</th><th>Status</th><th></th></tr></thead>
    <tbody>
      {#each rows as u (u.id)}
        <tr>
          <td class="primary"><UserCell name={u.name} email={u.email} /></td>
          <td>{u.role}</td>
          <td><StatusChip status={u.status === 'active' ? 'success' : 'neutral'} /></td>
          <td><Row gap={4} class="ca-row-actions">
            <Button variant="ghost" size="sm"><Edit2 size={13} /></Button>
            <Button variant="ghost" size="sm"><Trash2 size={13} /></Button>
          </Row></td>
        </tr>
      {/each}
    </tbody>
  </SimpleTable>

  {#snippet footer()}
    <span class="ca-page-info">1–8 of 24</span>
    <Pagination count={24} perPage={8} bind:page />
  {/snippet}
</AppList>

AppForm

<AppForm title="New User" description="Fill in the details." backHref="/users">

  <!-- layout="grid" is default — auto 2-column for text fields -->
  <FormSection title="Account details">
    <TextField label="Full name" bind:value={name} />
    <TextField label="Email" type="email" bind:value={email} />
    <Select label="Role" bind:value={role} options={roleOpts} />
  </FormSection>

  <!-- layout="list" for Switch/SettingItem rows -->
  <FormSection title="Notifications" layout="list">
    <Switch label="Send welcome email" bind:checked={notify} />
  </FormSection>

  {#snippet footer()}
    <Button variant="ghost" href="/users">Cancel</Button>
    <Button variant="filled" onclick={save} disabled={saving || !name || !email}>
      {saving ? 'Saving…' : 'Create user'}
    </Button>
  {/snippet}
</AppForm>

AppSettings

<!-- No external state needed — AppSettings manages tab internally -->
<AppSettings title="Settings" tabs={TABS}>
  {#snippet actions()}
    <Button variant="filled" size="sm" onclick={save}>Save changes</Button>
  {/snippet}

  {#snippet children(tab)}
    {#if tab === 'general'}
      <FormSection title="Workspace">
        <TextField label="Name" bind:value={workspaceName} />
        <Select label="Timezone" bind:value={timezone} options={tzOpts} />
      </FormSection>
    {/if}

    {#if tab === 'security'}
      <FormSection title="Authentication" layout="list">
        <SettingItem label="Two-factor authentication" description="Require 2FA for all members.">
          <Switch bind:checked={mfa} />
        </SettingItem>
        <Divider />
        <SettingItem label="Single sign-on" description="SAML or OIDC provider.">
          <Switch bind:checked={sso} />
        </SettingItem>
      </FormSection>
    {/if}
  {/snippet}
</AppSettings>

PageShell

<PageShell title="Dashboard" description="Sep 22, 2026" maxWidth="1200px" gap={24}>
  {#snippet actions()}
    <Button variant="ghost" size="sm">Export</Button>
  {/snippet}

  <Grid cols="repeat(auto-fill, minmax(200px, 1fr))" gap={16}>
    <KpiCard title="Revenue" value="$112k" trend={18.4} icon={DollarSign} />
    <KpiCard title="Users"   value="24.8k" trend={12.1} icon={Users}      />
  </Grid>

  <GlassCard title="Revenue vs Expenses">
    <LineChart series={[...]} categories={months} area height="260px" />
  </GlassCard>
</PageShell>

FormSection layouts

| layout | Use for | Behaviour | |---|---|---| | "grid" (default) | TextField, Select, NumberField | Auto 2-col, minmax(260px, 1fr) | | "list" | Switch, SettingItem, Divider | Single col, flush (no gap) | | "stack" | Composite blocks (Avatar + fields) | Single col, gap: 16px |

Never wrap fields in <Stack gap={N}> inside FormSection — the layout prop handles it.


Layout primitives

<!-- Grid: cols as number (equal) or CSS string -->
<Grid cols={3} gap={16}>…</Grid>
<Grid cols="2fr 1fr" gap={20}>…</Grid>
<Grid cols="repeat(auto-fill, minmax(200px, 1fr))" gap={16}>…</Grid>

<!-- Row: horizontal flex -->
<Row gap={8} align="center" justify="space-between">…</Row>

<!-- Stack: vertical flex -->
<Stack gap={16}>…</Stack>

Utility classes (from global.css)

| Class | Use | |---|---| | ca-search-field | Search input in toolbar — flex:1, min 180px, max 320px | | ca-toolbar-spacer | flex:1 push-right in toolbar | | ca-toolbar-sep | 1px vertical separator between toolbar groups | | ca-clear-btn | "Clear filters" button in toolbar | | ca-page-info | Pagination label "1–8 of 240" | | ca-row-actions | Table row actions — hidden by default, visible on row hover | | ca-col-check | Checkbox column — fixed width + compact padding | | ca-col-actions | Actions column — 80px fixed width | | ca-row-check | Row checkbox — brand accent color | | ca-row--selected | Selected row — brand tinted background | | ca-avatar-row | Avatar + metadata flex row (profile pages) | | ca-trend-up | Positive trend — success color | | ca-trend-down | Negative trend — error color | | ca-rail-btn | Icon button in AppShell rail bottom slot | | ca-rail-avatar | Avatar link in AppShell rail bottom slot | | ca-btn-danger | Outlined button in error color | | ca-btn-danger-ghost | Ghost/text button in error color | | ca-bar-fill | Progress bar width via --bar-w CSS var | | ca-bar-fill--warn | Warning variant of progress bar | | ca-pricing-cta | Full-width CTA at bottom of pricing card | | CodeSnippet | Syntax-highlighted code block with copy button |


Slider

<!-- Single value (most common) -->
<Slider bind:value={volume} min={0} max={100} />

<!-- Range (two thumbs) -->
<Slider bind:values={range} min={0} max={100} />

Spacing tokens

All page layouts share the same spacing vars. Override in your app root to change globally.

--ca-page-px:    24px;  /* horizontal padding of all page layouts */
--ca-page-pt:    20px;  /* top padding */
--ca-page-gap:   20px;  /* gap between sections */
--ca-card-padding: 20px; /* default GlassCard padding */

/* Scale (base 4px) */
--ca-space-1: 4px   --ca-space-4: 16px  --ca-space-8:  32px
--ca-space-2: 8px   --ca-space-5: 20px  --ca-space-10: 40px
--ca-space-3: 12px  --ca-space-6: 24px  --ca-space-12: 48px

AppShell

<AppShellLayout
  modules={MODULES}
  pathname={$page.url.pathname}
  persistPanel={false}
  onNavigate={path => goto(path)}
>
  {#snippet railBottom()}
    <!-- Avatar, notifications, search — pinned to bottom of the rail -->
    <button class="rail-btn" onclick={() => (cmdOpen = true)}>
      <Search size={16} />
    </button>
    <NotificationBell {notifications} onRead={handleRead} />
    <a href="/profile" class="rail-avatar">
      <Avatar alt={user.name} size="sm" />
    </a>
  {/snippet}

  <!-- No {#snippet header()} — each page owns its own header via AppList/AppForm/etc -->
  {@render children?.()}
</AppShellLayout>

NavModule shape:

const MODULES: NavModule[] = [
  {
    id: 'main', label: 'Main', icon: LayoutDashboard, basePath: '/app',
    items: [
      { id: 'dashboard', label: 'Dashboard', icon: LayoutDashboard, path: '/app/dashboard' },
      { id: 'users',     label: 'Users',     icon: Users,           path: '/app/users'     },
    ],
  },
];

Theming

<!-- data-preset on <html> -->
<html data-preset="ocean">
<!-- amber | ocean | crimson | cyan | violet | emerald | rose | slate -->

<!-- dark mode -->
<html class="dark">
colorScheme.toggle()          // light ↔ dark
colorScheme.setPreset('ocean') // switch preset
colorScheme.isDark             // reactive boolean

Surface styles

Four visual modes controlled by a single attribute. Applied automatically via colorScheme.setStyle().

colorScheme.setStyle('glass')    // default — Liquid Glass, blur + mesh background
colorScheme.setStyle('frosted')  // reduced blur, subtle gradient
colorScheme.setStyle('solid')    // no blur, opaque surfaces, pastel-friendly
colorScheme.setStyle('flat')     // no elevation, border-based separation only
<!-- Or set directly on <html> -->
<html data-preset="amber" data-style="solid">

Override individual surfaces (CSS):

/* All overlays solid */
:root {
  --ca-overlay-bg:   var(--ca-surface-overlay);
  --ca-overlay-blur: none;
}

/* Just Popover */
.ca-popover-content {
  --ca-overlay-bg:   var(--ca-surface-overlay);
  --ca-overlay-blur: none;
}

Surface layer tokens:

| Token | Components | Default | |---|---|---| | --ca-overlay-bg/blur/border/shadow | Popover, DropdownMenu | glass-thin | | --ca-panel-bg/blur/border/shadow | NotificationBell, CommandPalette | glass-thick | | --ca-chrome-bg/blur/border | Rail, BottomNav, AppShell | glass-chrome | | --ca-upload-bg/blur | FileUpload drop zone | glass-ultra-thin |


Theme Editor

Full visual customization — color, radius, spacing, typography, shadows, glass. Generates a CSS block you paste into your app.

import { editorTokensToCSS, DEFAULT_CONFIG } from '@codeatlasdev/ui';
import type { ThemeConfig } from '@codeatlasdev/ui';

const css = editorTokensToCSS({
  ...DEFAULT_CONFIG,
  hue:          260,        // Ocean blue
  chroma:       0.22,
  lightL:       0.50,
  radiusBase:   8,          // Tighter corners
  surfaceStyle: 'solid',    // No glass
  fontScale:    0.95,       // Slightly smaller
});
// Paste css into your app.css after the global.css import

ThemeConfig fields:

| Field | Type | Default | Description | |---|---|---|---| | hue | number | 55 | Brand hue 0–360 | | chroma | number | 0.21 | Brand saturation 0–0.32 | | lightL | number | 0.54 | Brand lightness 0.30–0.72 | | radiusBase | number | 10 | Base radius px — all sizes scale from this | | spacingBase | number | 4 | Spacing unit px — scale-1 through scale-16 | | fontScale | number | 1.0 | Font size multiplier | | fontSans | string | 'Inter, ...' | Sans-serif font stack | | fontMono | string | '"JetBrains Mono", ...' | Monospace font stack | | shadowIntensity | number | 1.0 | Shadow opacity multiplier 0–2 | | blurBase | number | 14 | Base blur px for glass effects | | surfaceStyle | SurfaceStyle | 'glass' | 'glass' \| 'frosted' \| 'solid' \| 'flat' | | pagePx | number | 24 | Page horizontal padding px | | pagePt | number | 20 | Page top padding px | | cardPadding | number | 20 | GlassCard padding px |


Key rules

  1. No inline styles — use CSS vars and classes. Only exception: dynamic CSS custom properties (style="--bar-w:{pct}%").
  2. No Stack gap={N} inside FormSection — use layout prop instead.
  3. No maxWidth/margin: 0 auto wrappers — AppList, AppForm, AppSettings fill available space. Width is controlled by the shell.
  4. No FormPage/ListPage — deprecated. Use AppForm/AppList.
  5. No global header — AppShellLayout has no header slot. Each page defines its own header through the layout component.

Deprecated

| Deprecated | Use instead | |---|---| | FormPage | AppForm | | ListPage | AppList |