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

@magnet-js/shadcn

v0.2.0

Published

shadcn-style components for Magnet, built on ZagJS primitives.

Readme

@magnet/shadcn

shadcn-style components for Magnet, built on ZagJS primitives.

@magnet/shadcn is a component library: the shadcn/ui component set ported to Magnet. Machine-backed components (dialog, select, tabs, and friends) run on ZagJS state machines via @magnet/zag; purely visual components (button, card, badge, and friends) apply shadcn's Tailwind class strings directly. Every component is an auto-curried function that takes the Magnet context first, follows shadcn v4's markup and data-slot attributes, and reads its props reactively — the props bag, variant, size, and class may all be signals.

Install

JSR

deno add jsr:@magnet/shadcn

npm via JSR

npx jsr add @magnet/shadcn

npm

npm install @magnet-js/shadcn

Usage

Components take the Magnet context first. Create it with @magnet/ui and a signal implementation, and carry the icon set and the cn class composer from @magnet/class on it (needed by the class-composed components):

import { tc39 as signal } from "@magnet/signal";
import { cn } from "@magnet/class";
import { magnet } from "@magnet/ui";
import { button, checkbox, lucide } from "@magnet/shadcn";

const m = magnet({ window, icons: lucide, cn: cn(signal), ...signal });

// Pure-CSS component: (props?, children?) after the context; props may be
// signals and re-compose reactively.
const saveButton = button(m, { variant: "destructive", size: "sm" }, [
  "Delete",
]);

// Machine-backed component: returns the assembled root element and the
// machine's stop cleanup (ride Magnet's cleanup idiom for teardown).
const [root, stop] = checkbox(m, { id: "subscribe", defaultChecked: true });

Multi-part machine components return the running ZagJS service extended with tag functions pre-bound to each part, with shadcn's classes pre-applied:

import { dialog } from "@magnet/shadcn";

const dlg = dialog(m, { id: "confirm" });
const view = [
  dlg.trigger(["Open"]),
  dlg.backdrop(),
  dlg.positioner([
    dlg.content([
      dlg.closeTrigger()(["Close"]),
      dlg.header([dlg.title(["Title"]), dlg.description(["Description"])]),
      dlg.footer(["Footer"]),
    ]),
  ]),
];
// ... later: dlg.stop()

Icons

Components that render glyphs require a full IconSet in their context type (icons: IconSet); each shipped set provides every canonical glyph, with path data vendored from the collection at a pinned version. Inject a set at magnet creation as above, or supply any object satisfying IconSet. Per instance, an icon option replaces the context default ({ icon: MyIcon }) or suppresses the glyph ({ icon: false }).

Seven sets are shipped, all covering the same canonical keys:

  • lucidelucide, ISC licensed (copyright Lucide Contributors).
  • tablerTabler Icons, MIT licensed (copyright Paweł Kuna).
  • hugeiconsHugeicons free stroke-rounded set, MIT licensed (copyright Hugeicons); the Pro sets are commercially licensed and not vendored.
  • phosphorPhosphor Icons, MIT licensed (copyright Phosphor Icons).
  • remixRemix Icon, Apache-2.0 licensed (copyright Remix Icon); attribution preserved in the module header.
  • carbonCarbon Icons, Apache-2.0 licensed (copyright IBM Corp); attribution preserved in the module header.
  • solarSolar Icon Set bold style, CC-BY-4.0 licensed (copyright 480 Design); attribution provided in the module header.

All seven modules are generated by scripts/build-icons.ts from the collections' pinned upstream sources; re-run it to regenerate them.

Managers in the context: theme and locale selectors

themeSelector and localeSelector are self-contained dropdowns composed from the menu machine and shadcn's DropdownMenu styling. They read their managers from the Magnet context — theme for the theme manager, locale for the locale manager — so apps register them once at magnet creation:

import { theme, themeManager, ThemeTag } from "@magnet/theme";
import { locale, localeManager } from "@magnet/locale";
import { localeSelector, themeSelector } from "@magnet/shadcn";

const m = magnet({ window, icons: lucide, cn: cn(signal), ...signal }).extend({
  theme: themeManager(m0, [
    theme("paper", [ThemeTag.Light]),
    theme("ink", [ThemeTag.Dark]),
  ], document.documentElement),
  locale: localeManager(m0, [
    locale("en", "English"),
    locale("pt", "Português"),
  ], document.documentElement),
});

// In a nav bar (or a sheet on smaller screens):
themeSelector(m, { names: { ink: "Tinta" } });
localeSelector(m, { tag: true });

Both mirror the current selection in the trigger (plus a chevron), lay out their entries on a shared grid with subgrid columns, and take order and visibility options for their parts. The theme selector offers a no-theme entry (sun/moon/system glyphs by theme kind, details.icon overriding per theme) that clears the pick back to system resolution; display names come from the names record, falling back to the theme id. The locale selector shows the endonym by default, with the tag, translated name, and details.icon opt-in per the options.

Theming

Class strings are shadcn v4's, so the package expects shadcn's Tailwind setup and theme CSS variables (--primary, --background, and so on) to be present globally, exactly as a shadcn app provides them. Styled parts carry shadcn's data-slot attributes (plus reactive data-variant/data-size where shadcn has them). A user class is composed LAST via cn — joined with spaces, with no tailwind-merge deduplication, so conflicting classes resolve by the stylesheet's cascade rules.

Public API

Components (each with its Props/variant types, and multi-part families exporting their member functions):

  • Actions: button, buttonGroup, toggle, toggleGroup.
  • Forms: checkbox, combobox, datePicker, input, inputGroup, inputOtp, label, radioGroup, select, slider, switch, textarea.
  • Overlays: contextMenu, dialog, drawer, dropdownMenu, hoverCard, menubar, navigationMenu, popover, sheet, tooltip.
  • Data display: accordion, avatar, badge, calendar, card, carousel, table, tabs.
  • Feedback: alert, progress, skeleton, toaster.
  • Layout: aspectRatio, breadcrumb, collapsible, pagination, resizable, scrollArea, separator.

Icons:

  • lucide — the canonical icon set, covering exactly the glyphs the components render by default.
  • tabler, hugeicons, phosphor, remix, carbon, solar — the same canonical glyphs vendored from six more collections (see the Icons section above for provenance and licenses).
  • Icon / IconSet — the glyph factory type and the canonical icon keys, for supplying a custom set.

Composition helpers, for building custom shadcn-style parts:

  • classed — wraps a tag function so it always carries the given classes.
  • withAttrs / withSlot — wraps a tag function so it always carries the given attributes / a data-slot.
  • withGlyph — wraps a tag function so a glyph renders after its children.
  • attributes — composes a pure-CSS component's reactive attributes bag.

Context types:

  • ComponentContext / MachineComponentContext — the context shapes the pure-CSS and machine-backed components require.
  • PartiallyApplied — the auto-curried component signature (re-exported from @magnet/common).

License

MIT © 2026 Fernando G. Vilar.