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

@paradox-design/components

v0.3.0

Published

Paradox Design System components — framework-agnostic web components built with Lit

Readme

@paradox-design/components

Paradox Design System components as web components built with Lit. They work in any framework and without one.

Installation

npm install @paradox-design/components @paradox-design/tokens @paradox-design/themes

Tokens and a theme are required — components contain no hard-coded values; every color and dimension is read from CSS custom properties.

lit is a peer dependency: npm 7+ and pnpm install it automatically, and the application ends up with a single copy shared by all components. If your project already uses Lit, it must be version 3.

Upgrade all @paradox-design/* packages together, to their latest versions. In 0.x a minor release may introduce breaking changes between packages.

Quick start

import '@paradox-design/tokens/css';
import '@paradox-design/themes';
import '@paradox-design/components/define';
<html data-pdx-theme="default">
  <pdx-button variant="primary">Save</pdx-button>
</html>

Registering individual components

Importing @paradox-design/components/define registers everything. When bundle size matters, register only what you use:

import '@paradox-design/components/button/define';

Importing from the package root (import { PdxButton } from '@paradox-design/components') gives you the classes only, without registration — useful when you want to extend a component or give it your own tag name.

<pdx-button>

Properties

| Attribute | Type | Default | Description | | ------------ | ----------------------------------------------- | --------- | ------------------------------------- | | variant | primary | secondary | danger | ghost | primary | Family of action tokens | | size | sm | md | lg | md | Height, spacing and icon size | | disabled | boolean | false | Disables the button natively | | loading | boolean | false | Operation in progress — blocks clicks | | full-width | boolean | false | Stretches to the container width | | type | button | submit | reset | button | Behavior towards the form | | href | string | — | Turns the button into a link (<a>) | | target | string | — | As in a native <a> | | aria-label | string | — | Required for an icon-only button |

Slots

| Slot | Purpose | | --------- | --------------------- | | default | Label | | prefix | Icon before the label | | suffix | Icon after the label |

Parts

base, label, prefix, suffix, spinner — available through ::part().

Forms

The button works with forms despite Shadow DOM:

<form>
  <input name="title" required />
  <pdx-button type="submit">Save</pdx-button>
</form>

Why this needed dedicated work A native <button type="submit"> hidden in a shadow root cannot see the outer <form> — the shadow boundary cuts it off from its owner. The button looks correct and does absolutely nothing. The component solves this with formAssociated and ElementInternals, calling requestSubmit(), which runs native validation. form.submit() would skip it and submit the form despite errors.

Loading state vs disabled state

They are not the same, and the component deliberately keeps them apart:

  • disabled — the action is unavailable, the element leaves keyboard navigation;
  • loading — an operation is in progress, the element stays in the focus order and reports aria-disabled and aria-busy.

If the loading state set native disabled, focus would jump to the start of the document mid-operation, and the screen reader would lose context.

<pdx-icon>

An icon from the active icon set. Out of the box that is the Paradox set (@paradox-design/icon-set) — no configuration needed:

<pdx-icon name="check" label="Done"></pdx-icon>

A client with their own icons replaces the set entirely, once, before the first render:

import { setIconSet } from '@paradox-design/icons';

setIconSet({
  check: '<svg viewBox="0 0 24 24">…</svg>',
});

Sets are never mixed — see @paradox-design/icons. Already rendered icons re-resolve after setIconSet().

| Attribute | Description | | --------- | --------------------------------------------------------------------------- | | name | Name in the active icon set | | label | Label for screen readers. Without it the icon is decorative (aria-hidden) |

Size and color are inherited from the text, so inside a button it adapts on its own.

Customizing the look

From the least to the most invasive:

  1. Theme tokens — change the look of all components at once;

  2. Component tokens — work through plain CSS custom properties:

    pdx-button {
      --pdx-button-radius: 0;
    }

    Full list for <pdx-button>:

    | Token | Meaning | | ----------------------------- | -------------------------------- | | --pdx-button-bg | Background | | --pdx-button-bg-hover | Background on hover | | --pdx-button-bg-active | Background while pressed | | --pdx-button-bg-disabled | Background in the disabled state | | --pdx-button-fg | Text and icon color | | --pdx-button-fg-disabled | Text color in the disabled state | | --pdx-button-border-color | Border color | | --pdx-button-border-width | Border width | | --pdx-button-radius | Corner radius | | --pdx-button-height | Height | | --pdx-button-padding-inline | Horizontal padding | | --pdx-button-gap | Gap between icon and label | | --pdx-button-icon-size | Icon size | | --pdx-button-font-family | Font family | | --pdx-button-font-size | Font size | | --pdx-button-font-weight | Font weight |

    For <pdx-icon>: --pdx-icon-size and --pdx-icon-color.

  3. ::part() — full control over a selected internal element:

    pdx-button::part(base) {
      letter-spacing: 0.05em;
    }

License

MIT © Paradox Software