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

@forthtilliath/forth-ui

v0.2.1

Published

Higher-level, opinionated React components built on top of [`@forthtilliath/shadcn-ui`](../shadcn-ui) primitives. Where shadcn-ui gives you the building blocks (`Button`, `Popover`, `Command`, ...), forth-ui assembles them into complete, batteries-include

Readme

@forthtilliath/forth-ui

Higher-level, opinionated React components built on top of @forthtilliath/shadcn-ui primitives. Where shadcn-ui gives you the building blocks (Button, Popover, Command, ...), forth-ui assembles them into complete, batteries-included patterns — a Combobox built from Popover + Command, a PasswordInput with a strength meter, a Dropdrawer that's a DropdownMenu on desktop and a Drawer on mobile — so you don't have to wire the same recipe from scratch in every project.

58 components across 8 categories, styled with Tailwind CSS and class-variance-authority, fully typed, and browsable in Storybook (pnpm run dev:sb from the repo root).

Table of contents

Why forth-ui

  • Complete patterns, not just primitives. Every component solves a whole problem — form field wiring (Field), file upload with previews (Dropzone, ImageInput), an imperative confirm dialog (useConfirm) — instead of leaving the composition to each consumer.
  • Consistent variants. Every component that has visual variants uses the same class-variance-authority shape (variant, size, look, shape, ...), so once you've learned one component's API, the others feel familiar.
  • One folder, one subpath import. No barrel file dragging in the whole library — import { Combobox } from "@forthtilliath/forth-ui/components/combobox" pulls in exactly that component's code.
  • Distributable like shadcn. Every component (but Grid, see Registry) is also published as a shadcn-compatible registry item, so it can be vendored source-first into a consuming project instead of installed as an opaque node_modules dependency.

Installation

Via npm

npm install @forthtilliath/forth-ui

@forthtilliath/shadcn-ui (the primitives forth-ui is built on) is a regular dependencies entry, not a peer — it's installed automatically, no need to add it yourself.

Import the compiled stylesheet once, alongside your component imports:

import "@forthtilliath/forth-ui/styles/globals.css";

As a workspace package (this monorepo)

Within this monorepo, forth-ui is consumed the same way, just via the pnpm workspace protocol instead of a published version range:

{
  "dependencies": {
    "@forthtilliath/forth-ui": "workspace:*"
  }
}

Components are built to dist/ (./components/*./dist/components/*/index.js), so run pnpm run build (or dev) in this package after source changes for consumers to pick them up.

Via the shadcn registry

Every component also ships as a shadcn registry item — the source files land directly in your project (components/forth-ui/<name>/), import-rewritten to your own components.json aliases, exactly like npx shadcn add button does for the official shadcn/ui components:

npx shadcn add <registry-url>/combobox.json

Add forth-ui as a named registry in your components.json to use the short form instead:

{
  "registries": {
    "@forth-ui": "<registry-url>/{name}.json"
  }
}
npx shadcn add @forth-ui/combobox

Cross-component dependencies (e.g. Combobox depending on another forth-ui component) and shadcn primitives (e.g. Popover) are declared as registryDependencies and resolve automatically — shadcn add cascades and installs everything the component needs. See apps/shadweb for how the registry itself is built.

Usage

import { Field } from "@forthtilliath/forth-ui/components/field";
import { Combobox } from "@forthtilliath/forth-ui/components/combobox";

function Example() {
  return (
    <Field label="Framework" description="Pick the one you use most.">
      <Combobox
        options={[
          { value: "react", label: "React" },
          { value: "vue", label: "Vue" },
        ]}
        placeholder="Select a framework..."
      />
    </Field>
  );
}

Components

Grouped the same way as the Storybook sidebar (forth-ui/<Category>/...).

Layout

| Component | Import | Description | | ------------------- | ---------------------------- | ----------------------------------------------------------------------------- | | Accordion | components/accordion | A vertically stacked set of interactive headings that each reveal a section. | | BentoGrid | components/bento-grid | A CSS-grid layout for unevenly-sized cards ("bento box" layouts). | | Collapsible | components/collapsible | An interactive component which expands/collapses a single panel. | | Grid, Grid.Item | components/grid | CSS-grid layout helpers with a built-in debug overlay. | | InfiniteScroll | components/infinite-scroll | Calls onLoadMore once a sentinel scrolls into view. | | Marquee | components/marquee | Infinitely scrolls its children (a logo wall, a ticker). | | Reparent | components/reparent | Moves children between different container elements at different breakpoints. | | Repeat | components/repeat | Repeats a component a specified number of times. | | ScrollShadow | components/scroll-shadow | A vertically-scrollable container with fade-out edge shadows. | | Separator | components/separator | Visually or semantically separates content. | | Spacer | components/spacer | Adds space between components — a flexible filler or a fixed gap. | | Stepper | components/stepper | A numbered sequence of steps for a multi-stage flow. |

Navigation

| Component | Import | Description | | ---------------------------- | ----------------------- | ------------------------------------------------------------------------- | | Breadcrumb | components/breadcrumb | Displays the path to the current resource using a hierarchy of links. | | Link, LinkPreview | components/link | A styled hyperlink, plus a hover-triggered metadata preview card. | | Navbar | components/navbar | A fixed, floating page header that shrinks on scroll, plus a mobile menu. | | Pagination | components/pagination | Navigates between pages, computing visible page numbers and ellipses. | | Scrollspy (useScrollspy) | components/scrollspy | Tracks which element id is currently scrolled into view. |

Buttons & Actions

| Component | Import | Description | | ----------------------- | ------------------- | ------------------------------------------------------------------------------ | | Button, ButtonGroup | components/button | A button, or a component that looks like one, plus joined button rows/columns. | | Chip | components/chip | A compact, interactive element for status, categories, or filters. |

Forms

| Component | Import | Description | | ------------------------- | --------------------------- | ------------------------------------------------------------------------ | | CheckboxGroup | components/checkbox | A group of checkboxes sharing a single array value. | | ColorPicker | components/color-picker | A color swatch + hex input, synced with the native color picker. | | Combobox, MultiSelect | components/combobox | An autocomplete/searchable select, and its multi-value variant. | | DatePicker | components/date-picker | A single-date picker built on a Popover + Calendar recipe. | | Dropzone | components/dropzone | A drag-and-drop file upload zone, listing accepted files below. | | Field | components/field | Wires a label, description and error message to a single form control. | | ImageInput | components/image-input | A click-to-upload image picker with a live preview. | | NumberInput | components/number-input | A numeric input with increment/decrement stepper buttons. | | PasswordInput | components/password-input | A password Input with a show/hide toggle, plus a strength meter. | | RadioCard | components/radio | A card-style RadioGroup item — the whole card is the clickable target. | | Rating | components/rating | A star rating control with keyboard navigation and hover preview. | | SubmitButton | components/submit-button | A submit Button that shows its own loading state via useFormStatus. | | TagsInput | components/tags-input | A flexible input for adding/removing multiple tags. |

Feedback

| Component | Import | Description | | -------------------- | -------------------------------- | ----------------------------------------------------------------------- | | Alert | components/alert | Displays a callout for user attention. | | Badge | components/badge | Displays a badge or a component that looks like a badge. | | Banner | components/banner | A full-width, page-level announcement bar. | | CountAnimation | components/count-animation | Animates a number counting up (or down) to a value whenever it changes. | | MultiStepLoader | components/multi-step-loader | A full-screen overlay stepping through loading messages. | | NotificationCenter | components/notification-center | A bell-icon trigger with an unread badge, opening a notification list. | | Progress | components/progress | Displays an indicator showing the completion progress of a task. | | ScrollProgress | components/scroll-progress | A fixed bar tracking scroll percentage of the page or a container. | | Spinner | components/spinner | An accessible loading indicator, in one of a few visual styles. |

Overlays

| Component | Import | Description | | ---------------- | ---------------------------- | ----------------------------------------------------------------------------------- | | CommandPalette | components/command-palette | A global command menu (Cmd/Ctrl+K to open). | | useConfirm | components/confirm-dialog | An imperative await confirm({...}) alternative to hand-wiring an AlertDialog. | | Dropdrawer | components/dropdrawer | A menu that renders as a DropdownMenu on desktop and a bottom Drawer on mobile. |

Data Display

| Component | Import | Description | | ----------------------- | ----------------------------- | ------------------------------------------------------------------------ | | Avatar, AvatarGroup | components/avatar | An image with a fallback, status/badge indicators, and stacked grouping. | | DescriptionList | components/description-list | A description list, with terms and descriptions. | | FileList | components/file-list | Displays a list of files with name, size, and upload progress. | | Kbd | components/kbd | Displays which key or combination of keys performs a given action. | | QrCode | components/qr-code | Generates a QR code from a string, rendered as inline SVG. | | RelativeTime | components/relative-time | Displays a live-updating time, defaulting to the local timezone. | | Sortable | components/sortable | A drag-to-reorder list built on native HTML5 drag events. | | Timeline | components/timeline | A vertical sequence of dated events, connected by a line. | | Tree | components/tree | A hierarchical, expandable/collapsible list of nodes. |

Code & Content

| Component | Import | Description | | ----------- | ----------------------- | ---------------------------------------------------------------- | | CodeBlock | components/code-block | A syntax-highlighted code block with a copy-to-clipboard button. | | Snippet | components/snippet | Displays and copies code in a tabbed interface. |

Conventions

  • One folder per component, matching the exports: "./components/*" map — folders that export more than one related component (Avatar + AvatarGroup, Combobox + MultiSelect, Button + ButtonGroup, Link + LinkPreview) still ship as a single import path.
  • Variants via class-variance-authority. Components with visual variants keep them in a co-located variants.ts, exporting both the cva() call and its VariantProps type (e.g. BadgeVariants).
  • Multi-part className. Components with more than one internal element accept className as an object instead of a string, keyed by part ({ root?, trigger?, content?, ... }), so you can target exactly the part you need without fighting specificity.
  • fallback/children-first fallbacks, not silent empty states — e.g. Avatar's fallback prop is required, not optional.

Theming

forth-ui has no styles of its own beyond Tailwind utility classes and the CSS variables (--primary, --muted, --border, ...) already defined by @forthtilliath/shadcn-ui's theme. Theming forth-ui means theming shadcn-ui — swap the CSS variables (or the whole theme preset) and every forth-ui component follows.

Setup

In your app's CSS entry point, import the base stylesheet, then a theme from @forthtilliath/shadcn-ui/styles/themes/*.css — each one just redeclares the same :root custom properties, so importing it after the base file overrides the default colors via normal CSS cascade:

@import "@forthtilliath/shadcn-ui/styles/globals-static.css";
@import "@forthtilliath/shadcn-ui/styles/themes/rose.css";

@source "../node_modules/@forthtilliath/*/dist/**/*.js";

Don't add your own @import "tailwindcss";globals-static.css already does that internally.

What that @source line does, and why it's needed: Tailwind only generates CSS for class names it can actually find, as literal text, in the files it scans — by default your own project source, honoring .gitignore (which is why node_modules is skipped: scanning every dependency would be slow and mostly pointless). But forth-ui and shadcn-ui ship pre-built, and their component code — the literal "bg-primary", "rounded-md", etc. strings — only exists inside their already-compiled node_modules/@forthtilliath/*/dist/**/*.js files. Without pointing Tailwind at them explicitly, none of those classes would be generated and every forth-ui/shadcn-ui component would render completely unstyled. This one line, with a wildcard for the package name, covers both packages (and any other @forthtilliath/* package added later) — confirmed to produce the exact same generated CSS as listing each package's path separately. This isn't a workaround specific to forth-ui: it's the documented, standard way Tailwind v4 expects any npm-distributed component library to be consumed.

Available themes

11 tweakcn-generated themes ship under @forthtilliath/shadcn-ui/styles/themes/, all rendered here with the same components:

| default | blue | bubblegum | | ------------------------------------------- | ------------------------------------- | ----------------------------------------------- | | default theme | blue theme | bubblegum theme |

| claymorphism | green | orange | | ----------------------------------------------------- | --------------------------------------- | ----------------------------------------- | | claymorphism theme | green theme | orange theme |

| red | rose | twitter | | ----------------------------------- | ------------------------------------- | ------------------------------------------- | | red theme | rose theme | twitter theme |

| violet | yellow | | ----------------------------------------- | ----------------------------------------- | | violet theme | yellow theme |

Development

pnpm run dev            # concurrently: tsc --watch + tailwind --watch
pnpm run build          # tsc + tailwind build -> dist/
pnpm run check-types    # tsc --noEmit
pnpm run lint           # eslint

Every component has a matching Storybook story under apps/react-sb/src/stories/forth-ui — run pnpm run dev:sb from the repo root to browse them all, organized into the same 8 categories as this README.

Registry

apps/shadweb/scripts/generate-forth-ui-registry.ts regenerates the registry from this package's source — never hand-edit apps/shadweb/registry/forth-ui/** directly. From apps/shadweb:

pnpm run registry:generate  # source -> apps/shadweb/registry/forth-ui + registry.json
pnpm run registry:build     # registry.json -> public/r/*.json (shadcn build)
pnpm run registry:sync      # both, in order

Grid is intentionally excluded — it depends on @forthtilliath/react-kit and @forthtilliath/ts-types, external npm packages that aren't inlined into the registry item yet.

License

MIT