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

polymorph-ui-components

v0.5.0

Published

A themeable Svelte 5 UI component library with CSS custom property driven styling

Readme

polymorph-ui-components

One set of components. Every design system. Zero overrides.

A themeable Svelte 5 component library where every visual property is a CSS custom property. Unstyled by default — you bring the design system, the components render it.

npm Svelte 5 Web Components MCP 50+ components License: MIT

npm install polymorph-ui-components

Why it's different

Most component libraries ship with a fixed look. Re-skinning them means fighting !important, patching internals through :global(), or forking the whole thing.

polymorph takes the opposite stance: components own behavior, accessibility, and structure — and stay completely opinion-free about appearance. Every color, space, radius, shadow, and font is a var(--…) you control from your own stylesheet. No source changes. No wrapper divs. No fights.

<!-- The same Button, themed three different ways — no overrides -->
<div class="brand"><Button text="Continue" /></div>
<div class="danger"><Button text="Delete" /></div>
<div class="ghost"><Button text="Cancel" /></div>

<style>
  .brand {
    --button-color: #6d28d9;
    --button-text-color: #fff;
    --button-border-radius: 8px;
  }
  .danger {
    --button-color: #e11d48;
    --button-text-color: #fff;
  }
  .ghost {
    --button-color: transparent;
    --button-text-color: #111;
    --button-border: 1px solid #ddd;
  }
</style>

📐 The full reasoning behind this approach lives in DESIGN_PRINCIPLES.md.


✨ Highlights

| | | | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | 🎨 Theme with CSS variables | Every visual decision is a var(--component-element-property). Define a theme once on an ancestor; the whole subtree inherits it. | | 🧩 50+ behavioral primitives | Modals, sheets, menus, comboboxes, calendars, tables, toasts, steppers — focus traps, roving tabindex, and state machines included. | | 🌍 Framework-agnostic | Ships as a Svelte library and as native Web Components (<pui-*>). Use it in React, Vue, Angular, or plain HTML. | | 🤖 AI-native | A bundled MCP server exposes every component's props, events, and CSS variables to your AI coding assistant. | | ♿ Accessible by default | ARIA wiring, keyboard navigation, focus management, and semantic HTML are baseline — not a premium add-on. | | ⚡ Built on Svelte 5 | $props, $state, $derived, $bindable, and Snippet throughout. Fully typed, tree-shakeable. |


🚀 Quick Start

<script lang="ts">
  import { Button, Input, Toggle } from 'polymorph-ui-components';

  let dark = $state(false);
</script>

<Button text="Submit" onclick={() => console.log('clicked')} />

<Input
  value=""
  placeholder="Enter email"
  dataType="email"
  onstatechange={(state) => console.log(state)}
/>

<Toggle checked={dark} text="Dark mode" onclick={(on) => (dark = on)} />

🎨 Theming in 30 seconds

Every component reads its visuals from CSS variables with sensible neutral defaults. Define them on any ancestor and you have a theme:

<div class="my-design-system">
  <Button text="Save" onclick={save} />
  <Input value="" placeholder="Search…" />
</div>

<style>
  .my-design-system {
    --button-color: #0070f3;
    --button-text-color: #fff;
    --button-border-radius: 6px;
    --button-padding: 10px 20px;

    --input-background: #fafafa;
    --input-border: 1px solid #eaeaea;
    --input-radius: 6px;
    --input-focus-border: 1px solid #0070f3;

    --modal-border-radius: 12px;
    --modal-overlay-background-color: #00000066;
  }
</style>

Variants are your CSS classes, not our props. Need a danger button? Write .btn-danger { --button-color: #e11d48 } and pass classes="btn-danger". Because variables cascade, you can even scope different themes to different parts of the same page.

The naming convention is predictable everywhere:

--{component}-{element}-{property}

--button-color · --input-error-msg-text-color · --modal-footer-primary-button-border-radius

Each component documents its complete variable surface in docs/.


🌍 Use it anywhere (Web Components)

The same components compile to framework-agnostic custom elements — theming works identically because it's pure CSS.

<script type="module" src="polymorph-ui-components/wc"></script>

<pui-button text="Save"></pui-button>
<pui-input placeholder="Search…"></pui-input>

<style>
  pui-button {
    --button-color: #0070f3;
    --button-text-color: #fff;
  }
</style>

Drop them into React, Vue, Angular, Astro, or a plain .html file — no build step required.


🤖 AI-native (MCP server)

A companion Model Context Protocol server ships as a separate package so your AI assistant can query the component catalogue directly — props, events, types, and every CSS variable.

npm install polymorph-ui-components-mcp
// .mcp.json (or any MCP client config)
{
  "mcpServers": {
    "polymorph-ui": {
      "command": "npx",
      "args": ["-y", "polymorph-ui-components-mcp"]
    }
  }
}

Now you can ask: "Using the polymorph-ui MCP, theme the Select to match my brand and map my custom option rendering onto its snippets." — and the assistant has the real API in context.


🧩 Components

| Component | Description | | | --------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------- | | Button | Action trigger with circular loader, progress bar, icon/children snippets, and aria-expanded. | docs | | Input | Text field with built-in validation (email, phone, password, custom patterns), text transformers, and textarea mode. | docs | | InputButton | Input fused with action buttons — search bars, OTP entry, coupon codes. | docs | | Select | Dropdown with searchable single-select and multi-select (dismissible pills) plus custom content slots. | docs | | Combobox | Autocomplete input with filtered listbox, aria-activedescendant, and keyboard navigation. | docs | | Toggle | Labeled on/off switch with sliding animation. | docs | | Checkbox | Tri-state checkbox with custom SVG checkmark and aria-checked=mixed. | docs | | Radio | Grouped radio with custom indicator over a native input. | docs | | Slider | Range slider with min/max/step and derived fill. | docs | | Choicebox | Selectable option box with radio/checkbox semantics and custom content. | docs | | SplitInput | Segmented input (OTP / PIN) with paste distribution and auto-advance. | docs | | ColorPicker | HSV color picker with pointer-drag saturation panel and hue slider. | docs | | Calendar | Date / range picker with roving-tabindex grid and Intl formatting. | docs |

| Component | Description | | | ----------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------ | | Modal | Dialog overlay with size/alignment, header, footer, transitions, scroll-lock, and back-press support. | docs | | Sheet | Slide-in panel from any edge with header, scrollable body, footer, and focus trap. | docs | | Menu | Dropdown action menu with keyboard navigation, typeahead, disabled/danger items, and separators. | docs | | ContextMenu | Right-click menu with separators, disabled/danger items, and keyboard navigation. | docs | | CommandMenu | Command palette (Ctrl/Cmd+K) with search, grouped commands, and keyboard navigation. | docs | | Tooltip | Hover/focus tooltip with configurable position and delay. | docs | | ModalAnimation / OverlayAnimation | Fly/fade transition wrappers. | docs |

| Component | Description | | | ---------------------------------- | ----------------------------------------------------------------------- | ----------------------------- | | Table | Sortable data table with sticky headers and per-cell scrolling. | docs | | ListItem | Multi-section list row with images, labels, and accordion expansion. | docs | | Avatar | Circular avatar with image fallback or derived initials. | docs | | Badge | Icon with a numeric/text badge overlay. | docs | | Pill | Compact label/tag, optionally clickable with a11y. | docs | | Icon / IconStack / Img | Clickable icon, overlapping icon stack, image with load-error fallback. | docs | | GridItem | Grid cell with icon, label, and loading overlay. | docs | | RelativeTime | Auto-updating "5 minutes ago" with locale support. | docs | | KeyboardInput | Keyboard-shortcut display with styled key caps. | docs |

| Component | Description | | | ---------------------- | -------------------------------------------------------------------- | ----------------------------- | | Tabs | Tabbed interface with animated indicator and overflow scrolling. | docs | | Pagination | Windowed page navigation with ellipsis truncation. | docs | | Stepper / Step | Multi-step progress indicator with completed/active/pending states. | docs | | Accordion | Collapsible container with CSS grid animation. | docs | | Carousel | Swipeable content slider with autoplay and pagination dots. | docs | | Scroller | Overflowing list with arrow nav, gradient edges, and drag-to-scroll. | docs | | CheckListItem | Checklist row with checkbox, label, and checked state. | docs | | Toolbar | Header bar with back button, title, and customizable content areas. | docs | | ThemeSwitcher | Segmented light/dark/system control with prefers-color-scheme. | docs |

| Component | Description | | | ------------------------------------------ | ----------------------------------------------------------------------- | ------------------------ | | Toast | Animated slide-in notification with auto-dismiss and per-direction fly. | docs | | Banner | Notification banner with icon snippet, link text, and dismiss. | docs | | Progress | Animated horizontal progress bar (determinate / indeterminate). | docs | | Gauge | Full-circle ring gauge (0–100) with animated SVG arc. | docs | | Loader / LoadingDots / Shimmer | Spinner, animated dots, and skeleton shimmer — all CSS-variable themed. | docs |

| Component | Description | | | ---------------------------------- | ------------------------------------------------------------------------------------------ | --------------------------- | | SplitButton | Primary action button with a dropdown of secondary actions. | docs | | Snippet | Code/command block with a copy button. | docs | | Book / Browser / Phone | Decorative frames — flip-book, browser chrome, device mockup — for previews and marketing. | docs |


♿ Accessibility & Svelte 5

Interactive components own their accessibility: focus traps (Modal, Sheet), roving tabindex (Calendar, Menu, Tabs), aria-activedescendant wiring (Combobox, Select), live regions (Toast), and internal Enter/Space handling on every custom control.

Under the hood it's modern Svelte 5 — $props(), $state()/$derived(), $bindable() two-way props, and Snippet content slots:

<script lang="ts">
  import { Sheet } from 'polymorph-ui-components';
  let open = $state(false);
</script>

<button onclick={() => (open = true)}>Open</button>

<Sheet bind:open title="Settings" side="right">
  {#snippet content()}
    <p>Sheet body goes here.</p>
  {/snippet}
  {#snippet footer()}
    <button onclick={() => (open = false)}>Done</button>
  {/snippet}
</Sheet>

Every component exports its types:

import type {
  ButtonProperties,
  InputProperties,
  ModalProperties,
  SelectProperties,
  MenuItem
} from 'polymorph-ui-components';

🛠 Development

pnpm install   # install dependencies
pnpm dev       # dev server with hot reload (component playground)
pnpm build     # build library (vite + svelte-package + publint)
pnpm test      # integration + unit tests
pnpm lint      # formatting + lint
src/lib/{Component}/{Component}.svelte   # implementation
src/lib/{Component}/properties.ts        # typed props
src/lib/index.ts                         # public exports
src/wc/                                  # Web Component wrappers
docs/                                    # one markdown reference per component
mcp/                                     # MCP server package

Releases are automated: pushing to release lints, derives the semver bump from the conventional-commit message, bumps the version, generates a changelog, builds, tags a GitHub release, and publishes to npm.


🙏 Credits

polymorph-ui-components is built on top of @juspay/svelte-ui-components — it began as that library and carries forward its CSS-variable-driven theming foundation. It no longer depends on or pulls from the upstream package; instead it builds on that groundwork and evolves independently. Thanks to the original authors for the foundation. 🙌


📄 License

MIT — peer dependencies: svelte ^5.41.2.