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

@matthewsreis/ui

v0.2.0

Published

Matthews UI component library

Readme

@matthewsreis/ui

UI component library for the Matthews Reis design system. Publishes React components (and future framework targets) as a single scoped package with subpath exports.

Installation

npm install @matthewsreis/ui

React 18 or later and react-dom are required as peer dependencies.

Usage

Two import styles are officially supported. They're functionally equivalent and both work with modern bundlers — pick based on the tradeoff below.

// Per-component subpath (recommended)
import { Button } from '@matthewsreis/ui/button'
import { Dialog, DialogTrigger, DialogContent } from '@matthewsreis/ui/dialog'
import { cn } from '@matthewsreis/ui/utils'

// Main barrel (convenience)
import { Button, Dialog, DialogTrigger, cn } from '@matthewsreis/ui'

Tree-shaking and import patterns

Prefer per-component subpaths for production code. The package is built with bundle: false — every source file maps to exactly one dist file — so subpath imports load only the files they actually need. Importing @matthewsreis/ui/button physically touches ~7 files; importing the same component through the main barrel causes your bundler to parse the entire ~30-file barrel graph before tree-shaking it back down.

Final bundle size is identical either way for modern bundlers (Turbopack, Vite, Rollup, Webpack 5+, Bun, esbuild) — tree-shaking eliminates unused exports correctly from both paths because the package uses named re-exports only and declares precise sideEffects. The real difference is dev-time parse cost and robustness against bundlers that can't fully trust sideEffects.

Rule of thumb:

| Situation | Use | | -------------------------------------------------------- | -------------------------------- | | Production app, one or two components per file | @matthewsreis/ui/<component> | | Pulling in five+ components at once (e.g. a layout file) | @matthewsreis/ui (main barrel) | | Dev sandbox, scratch file, experimenting | Either — it doesn't matter |

Avoid runtime star patterns when re-exporting from this package. Runtime export * and import * as X force bundlers to eagerly resolve every binding in the target module to figure out what's reachable, which can defeat tree-shaking:

// Don't — runtime wildcard re-export. Consumers' bundlers now have to trace
// every export in @matthewsreis/ui even if your file uses only one.
export * from '@matthewsreis/ui'

// Don't — runtime namespace import used as a value.
import * as UI from '@matthewsreis/ui'
<UI.Button />

// Do — named re-export + named import.
export { Button } from '@matthewsreis/ui'
import { Button } from '@matthewsreis/ui'

Type-only star patterns are fine. export type * and import type * as X are erased at compile time — they exist only in .d.ts output and have zero impact on the runtime bundle:

// Fine — type-only re-export, no runtime cost.
export type * from '@matthewsreis/ui/button'

// Fine — type-only namespace import.
import type * as UI from '@matthewsreis/ui'
type ButtonProps = UI.ButtonProps

The distinction is runtime star vs type-only star. The runtime form participates in tree-shaking analysis; the type-only form is erased. This rule applies when you're authoring a file that re-exports from our package — e.g. a shared-UI wrapper in your app.

Exports

| Subpath | Resolves to | | ------------------------------------ | ------------------------------------------------------------------ | | @matthewsreis/ui | main barrel (every public component + cn) | | @matthewsreis/ui/react | same as above (explicit framework alias) | | @matthewsreis/ui/<component> | one per public component, kebab-case names | | @matthewsreis/ui/utils | cn helper only | | @matthewsreis/ui/tailwind-preset | shared Tailwind preset (extend in consumer's tailwind.config.ts) | | @matthewsreis/ui/styles | compiled + minified CSS (tokens, typography, utilities all in one) | | @matthewsreis/ui/styles/tokens | raw tokens.css (layer into your own Tailwind build à la carte) | | @matthewsreis/ui/styles/typography | raw typography.css | | @matthewsreis/ui/styles/utilities | raw utilities.css |

Component subpaths cover every publicly exported component: breadcrumb, button, card, checkbox, command, dialog, input, input-group, label, popover, scroll-area, sheet, switch, table, tabs, textarea, toggle, toggle-group (plus autocomplete, combobox as they stabilize).

Design conventions

Violet is reserved for AI. The violet-* palette is used only for AI features — Artemis GPT, generative UI, sparkle/AI icons, anything that signals "this is AI." Don't pick it for generic status, alerts, or decorative accents. Reach for primary, sky, indigo, or zinc instead. Components stay low-level; AI surfaces compose the violet tokens directly (bg-violet-500, text-violet-500) rather than through a dedicated ai variant.

Avoid gradients unless a Figma design explicitly calls for one. Artemis DS prohibits gradients on surfaces. The gradient-* tokens we ship exist for charts, progress bars, and specific banners that the source design specifies — not as decorative accents.

Icons: Lucide only, 2px stroke, size-icon-md (16px) inline / size-icon-lg (20px) chevrons & status / size-icon-xl (24px) nav & empty-states. Icons inherit text color.

Interaction defaults: hover = hover:bg-default-buttonFieldHover; focus = shadow-focus + border-primary-500; press darkens fill but never scales; transitions are 120–180ms ease-out (use tailwindcss-animate utilities from the preset).

Directory structure

packages/ui/
├── src/
│   └── react/             # One directory per framework - see "src/ convention" below
│       ├── components/
│       │   └── button/
│       │       ├── Button.tsx
│       │       └── Button.test.tsx
│       ├── hooks/         # Internal - exported via index.ts, NOT a top-level entry
│       └── index.ts       # Public API for this framework - export everything consumers need
├── test/
│   └── setup.ts           # Shared test setup (@testing-library/jest-dom/vitest)
├── dist/                  # Built output (not committed)
│   └── react/
│       ├── index.js       # ESM
│       ├── index.cjs      # CJS
│       └── index.d.ts     # Types
├── eslint.config.ts       # Package-scoped ESLint flat config
├── package.json
├── tsconfig.json
├── tsup.config.ts         # Auto-discovers framework entries via readdirSync + existsSync
└── vitest.config.ts

Prettier config and ignore rules are inherited from ../../.prettierrc.js and ../../.prettierignore at the workspace root. ESLint config is package-scoped (eslint.config.ts).

src/ convention

Only framework root directories belong directly under src/.

tsup.config.ts treats every src/<name>/ directory that contains an index.ts as a published entry point, compiling it to dist/<name>/ and making it importable as @matthewsreis/ui/<name>. This means:

  • src/react/ - correct, this is a framework entry
  • src/vue/ - correct, this would be a new framework entry
  • src/hooks/ - wrong - would accidentally publish @matthewsreis/ui/hooks as a standalone entry

Internal utilities, hooks, shared logic, and sub-components must live inside a framework directory and be exported through that framework's index.ts:

src/
└── react/
    ├── components/    # components
    ├── hooks/         # internal hooks, exported via index.ts
    ├── utils/         # internal utilities, exported via index.ts
    └── index.ts       # the only public surface for @matthewsreis/ui/react

Commands

Run from packages/ui/:

# Build (ESM + CJS + types for all framework entries)
pnpm build

# Watch mode
pnpm dev

# Run tests
pnpm test
pnpm test:watch

# Validate the packed tarball (publint + arethetypeswrong)
pnpm test:package

# Lint
pnpm lint

# Format
pnpm format

# Check formatting without writing
pnpm format:check

# Component sandbox (Ladle)
pnpm sandbox
pnpm sandbox:build
pnpm sandbox:preview

Figma tooling (Claude Code)

This package has a paired Figma design system. To use Figma tools directly inside Claude Code (inspect designs, implement components), install the official Figma plugin for Claude:

Install the plugin

  1. Open Claude Code (CLI or desktop app)
  2. Run /plugins to open the plugin manager
  3. Search for Figma and install the official Figma plugin
  4. Authenticate: Claude will prompt you to connect your Figma account — follow the OAuth flow

Once installed, the plugin persists across sessions. You don't need to reinstall it per project.

Note: The plugin is per-user — each dev installs it once in their own Claude account. There is no project-level auto-install for plugins. The .mcp.json in this repo does not configure Figma; the plugin is the only Figma integration in use.

Available tools (Pro plan)

These tools work with our current Figma Pro plan:

| Tool | What it does | | ---------------------------- | ----------------------------------------------------------------------------------- | | get_design_context | Primary tool — fetches a node's design, screenshot, and code hints from a Figma URL | | get_screenshot | Screenshot of a specific Figma node | | get_metadata | File/component metadata | | get_variable_defs | Design tokens and variables defined in the file | | search_design_system | Search components across the design system | | get_figjam | Read FigJam boards | | generate_diagram | Create diagrams in FigJam | | create_design_system_rules | Generate project-specific design system rules | | use_figma | Write designs back to Figma canvas | | create_new_file | Create a new Figma file | | generate_figma_design | Generate a design from a description | | whoami | Verify which Figma account is authenticated |

Gated tools (Organization/Enterprise only)

These Code Connect tools are not available on Pro and will return an error if called:

| Tool | | ------------------------------ | | get_code_connect_map | | add_code_connect_map | | get_code_connect_suggestions | | get_context_for_code_connect | | send_code_connect_mappings |

Typical workflow

1. Grab a Figma node URL (right-click a frame → Copy link)
2. Paste it into Claude: "implement this component: <url>"
3. Claude calls get_design_context and adapts the output to this package's patterns

Adding a component

  1. Create src/react/components/<name>/<Name>.tsx
  2. Export it from src/react/index.ts
  3. Add tests in <Name>.test.tsx alongside the component

Adding a new framework

To add support for a new framework (e.g., Vue), follow these steps exactly:

  1. Create the framework directory and entry point:

    src/
    └── vue/
        └── index.ts    # public API for @matthewsreis/ui/vue

    tsup.config.ts will automatically detect src/vue/index.ts on the next build — no changes to tsup.config.ts needed.

  2. Add the subpath export to package.json:

    "./vue": {
      "types": "./dist/vue/index.d.ts",
      "import": "./dist/vue/index.js",
      "require": "./dist/vue/index.cjs"
    }
  3. Add peer dependencies for the new framework to package.json if needed.

  4. Add a changeset and open a PR.

Note: do not create utility or shared directories (src/hooks/, src/utils/, etc.) directly under src/. These belong inside the framework directory they support. See the src/ convention section above.

Build output

Each src/<framework>/index.ts compiles to its own dist/<framework>/ directory:

dist/
└── react/
    ├── index.js    # ESM
    ├── index.cjs   # CJS
    └── index.d.ts  # Types

Adding src/vue/index.ts automatically produces dist/vue/ on the next build.