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

@human-synthesis/norns-ui

v0.0.10

Published

UI library for the Norns ecosystem — Pug + Civet components on Tailwind v4.

Downloads

1,179

Readme

@human-synthesis/norns-ui

UI library for the Norns ecosystem. Pug + Civet components on Tailwind v4, with custom headless behaviors built on @floating-ui/dom and Iconify behind the icon system.

Stack

  • Svelte 5 — components and runes
  • Pug — templates (in .n files)
  • Civet<script> language
  • Tailwind CSS v4 — styling, hard peer dep
  • @floating-ui/dom — overlay positioning (Popover, Dropdown, Tooltip, ContextMenu, pickers)
  • Custom in-tree headless behaviors (focus-trap, scroll-lock, click-outside, escape, portal, roving-tabindex) — exported at @human-synthesis/norns-ui/behaviors
  • Iconify — icons; ships with Lucide preset
  • tailwind-merge — class deduplication
  • @human-synthesis/norns — peer (nornsAutoImport)

Install

bun add -D @human-synthesis/norns-ui

Setup

vite.config.js:

import { nornsAutoImport } from '@human-synthesis/norns/auto-import';
import { presetUI } from '@human-synthesis/norns-ui/auto-import';

const ui = presetUI();

export default {
  plugins: [
    nornsCivetPlugin(),
    nornsAutoImport({
      componentDirs: ['src/lib/components'],
      components: ui.components
    }),
    tailwindcss(),
    sveltekit()
  ]
};

app.css:

@import 'tailwindcss';
@import '@human-synthesis/norns-ui/styles';

Dark mode

Toggle via <html data-theme="dark"> — every component swaps. Persist the choice with a small inline script in app.html to avoid FOUC:

<script>
  (function () {
    try {
      var t = localStorage.getItem('theme');
      if (t === 'dark' || (t === null && matchMedia('(prefers-color-scheme: dark)').matches)) {
        document.documentElement.dataset.theme = 'dark';
      }
    } catch (_) {}
  })();
</script>

Icons

The library ships @iconify/svelte with the Lucide collection bundled. Register the collection once in your app entry so icons render in SSR and the client:

// src/routes/+layout.svelte (or wherever fits)
import { addCollection } from '@iconify/svelte';
import lucide from '@iconify-json/lucide/icons.json';
addCollection(lucide);

Then use <Icon> anywhere:

Icon(name="lucide:check" size="size-5")
Btn(icon="lucide:save") Save

To mix in another icon set, install its JSON package (e.g. @iconify-json/heroicons) and addCollection(...) it the same way.

Usage

Form(action="?/save" form!="{form}")
  Field(label="Title" name="title" required)
    Input(name="title" placeholder="title…" required)
  Btn(type="submit" variant="primary" icon="lucide:save") Save

<Field name="title"> reads its error from the parent <Form>'s context map; no per-page boilerplate.

What's in here

  • Atoms (CSS-only @layer components): .btn, .input, .field, .form, .checkbox, .radio, .switch, .card, .surface-elevated, .btn-icon, .banner, .badge, .chip, .avatar, .skeleton, .progress, .norns-header, .hero, .stepper, .breadcrumbs, .pagination, .accordion, .carousel, plus variants/sizes.
  • Forms: Btn, Form, Field, FieldGroup, Input, Textarea, Select, Checkbox, Radio, Switch.
  • Behavior (custom on @floating-ui/dom): Dialog, Sheet, Popover, Dropdown, Tooltip, Tabs, Accordion, ContextMenu, Collapsible.
  • Display: Card, Surface, Banner, Badge, Chip, Avatar, Skeleton, Progress, ProgressCircular, Icon.
  • Composite: Header, HeroBanner, Stepper, Breadcrumbs, Pagination, Carousel.
  • Toast: ToastProvider + toast() / notify() / dismiss() from @human-synthesis/norns-ui/toast.

Hand-rolled .d.ts shims live under src/types/. Override any component by dropping src/lib/components/<Name>.n in your project — nornsAutoImport's first-match-wins shadows the library silently.

Behaviors

A small set of headless behaviors is exposed at @human-synthesis/norns-ui/behaviors for use in your own components:

import {
  portal, clickOutside, escape, focusTrap,
  scrollLock, useFloating, rovingTabindex
} from '@human-synthesis/norns-ui/behaviors';

These are Svelte 5 actions (use:portal, use:clickOutside={handler}, etc.) and a small useFloating() factory that wraps @floating-ui/dom. They're what every overlay component in this library is built on, so reaching for them in your own code keeps interactions consistent.

Migrating from 0.0.5 → 0.0.6

bits-ui has been removed; overlays are now built on @floating-ui/dom plus the in-tree behaviors module. Most APIs are unchanged. The breaking changes:

  • <Drawer> is gone. Use <Sheet side="left"> (it now defaults to 'right'; pass the side you want).
  • <RichTooltip> is gone. Use <Tooltip rich>.
  • <PreviewCard> is gone. Use <Tooltip> with the trigger as a link, e.g. <Tooltip rich content="...">{#snippet trigger()}<a href=...>{/snippet}</Tooltip>.
  • <ContextMenu> no longer renders nested submenus. The children field on items is accepted but ignored.
  • The svelte.config.js scopeToProject workaround is no longer needed (it existed only to keep svelte-preprocess from corrupting bits-ui's TypeScript source). Remove it from your config.

Theming

Tokens are in src/styles/tokens.css as a Tailwind v4 @theme block. The library exposes:

  • Color scales (50–950) for primary, success, warning, danger, info — all in oklch for perceptual uniformity. Use as bg-primary-500, text-danger-700, etc.
  • Role tokens that atoms reference (and that you should reach for in your own components): --color-fg, --color-fg-muted, --color-fg-subtle, --color-bg, --color-bg-muted, --color-bg-subtle, --color-bg-elevated, --color-border, --color-border-strong, --color-ring. These swap automatically on dark mode.
  • Feedback tokens: --color-{success,warning,danger,info}-{bg,fg,border} for tinted surfaces.
  • Typography tokens: --font-sans, --font-mono.
  • Sizing: --ui-radius-{sm,,lg,full}, --ui-h-{sm,md,lg} (full button heights), --ui-icon-btn-{sm,md,lg} (square icon-button sizes).
  • Motion: --ui-motion-{fast,med,slow} durations + --ui-motion-ease. All component transitions reference these.
  • Elevation: --ui-elev-{1,2,3} (subtle / floating / modal). Dark mode swaps to deeper shadows.
  • Focus: --ui-focus-ring — the single canonical focus indicator. Apply as box-shadow: var(--ui-focus-ring) on :focus-visible.

Override by re-declaring @theme { … } in your app.css after the library import.

License

MIT © Daniel Teodoroiu / Human Synthesis. Built on top of Svelte © Svelte Contributors, MIT licensed.