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

@matthieuglaisner/react-ui-components-library

v1.1.0

Published

React + Tailwind CSS + TypeScript UI components

Readme

@matthieuglaisner/react-ui-components-library

React + Tailwind CSS + TypeScript UI components. Most building blocks are Tailwind-only; overlays, menus, tabs, and several form primitives wrap Radix UI for accessibility (focus traps, portals, keyboard support). Everything ships as compiled JS plus TypeScript declarations; your app must run Tailwind so utility classes in dist are generated.

Requirements

  • React 18 or 19 (react and react-dom)
  • Tailwind CSS in the host app (v3-style content config below; adapt if you use Tailwind v4)
  • Radix UI packages — required peers for components that import them. Install the @radix-ui/react-* packages you use (see peerDependencies for exact names and ranges). If you use every exported Radix-backed piece, install all listed Radix peers.
  • react-router-dom 6.28+ or 7.x is optional. Install it only if you use Link with as={NavLink} or as={RouterLink}.

This package does not ship a separate CSS bundle. Class names live in dist/**/*.js (and .cjs), and your Tailwind build must scan those files.

Installation

npm install @matthieuglaisner/react-ui-components-library

Install Radix peers as needed (example — matches current package.json peer ranges):

npm install @radix-ui/react-accordion @radix-ui/react-alert-dialog @radix-ui/react-dialog @radix-ui/react-popover @radix-ui/react-scroll-area @radix-ui/react-select @radix-ui/react-slider @radix-ui/react-switch @radix-ui/react-tabs @radix-ui/react-toast @radix-ui/react-toggle-group @radix-ui/react-tooltip

To install from Git instead of the registry:

npm install github:MattGlsn/ui-components-library

Adjust the URL to your fork or organization.

Tailwind setup (required)

Tailwind’s JIT compiler only emits utilities for class names it finds in the content paths you configure. Because this library publishes dist only, add a glob that includes the ESM and CJS bundles (.js and .cjs):

// tailwind.config.js (or .ts)
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
    "./node_modules/@matthieuglaisner/react-ui-components-library/dist/**/*.{js,cjs}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

Adjust the first entries to match your app. If the package is hoisted differently, point the glob at the folder that contains @matthieuglaisner/react-ui-components-library/dist.

Dark mode

Components use Tailwind dark: variants (primary #6a7cbd in light, #8fa2e6 in dark). Set darkMode to "class" or "media" in your Tailwind config. Link is a styled text link (hover color only; use aria-current="page" or NavLink for the current route). For SPA routes use <Link as={RouterLink} to="…"> or <Link as={NavLink} to="…"> from react-router-dom when needed. See Storybook for per-component focus, error, and layout details.

Component catalog

Exports are named (tree-shakeable) from the package root, for example import { DialogRoot, Table } from "@matthieuglaisner/react-ui-components-library".

| Area | Components | | ---- | ---------- | | Layout | Container, Divider, Grid, Group, Section, Stack | | Typography | Label, Text, Title | | Feedback | Alert, Badge, Progress, Skeleton, Spinner, Toast | | Toasts (Radix) | ToasterProvider, ToasterViewport, ToasterRoot, ToasterTitle, ToasterDescription, ToasterClose, ToasterAction — stackable notifications; compose with Radix patterns (see Storybook). | | Overlays | DialogRoot, DialogTrigger, DialogContent, DialogTitle, DialogDescription, DialogClose, DialogPortal, DialogOverlay | | Confirm | AlertDialogRoot, AlertDialogTrigger, AlertDialogContent, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel, … | | Drawer | DrawerRoot, DrawerTrigger, DrawerContent, DrawerTitle, DrawerDescription, DrawerClose, DrawerOverlay | | Floating | PopoverRoot, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverPortal | | Tooltip | TooltipProvider, TooltipRoot, TooltipTrigger, TooltipContent, TooltipPortal — wrap the app (or layout) with TooltipProvider where you use tooltips. | | Select | SelectRoot, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGroup, SelectLabel, SelectSeparator, SelectPortal, SelectViewport | | Navigation | TabsRoot, TabsList, TabsTrigger, TabsContent; AccordionRoot, AccordionItem, AccordionHeader, AccordionTrigger, AccordionContent; Pagination; Stepper; Navbar; DropdownMenu; Breadcrumbs | | Data display | Card; Table, TableHeader, TableBody, TableRow, TableHeadCell, TableCell; Avatar; EmptyState | | Forms | Button, Input, TextArea, Checkbox, CheckboxList, Radio, RadioList, Form, Switch, Slider, FileInput, SegmentedControlRoot, SegmentedControlItem | | Content / chrome | Link | | Utility | ScrollArea; useClickAway |

Toast vs Toaster: Toast is a single presentational banner (variants, dismiss). Toaster* primitives are Radix-based and suit queued, viewport-anchored notifications; use them when you need provider + multiple live regions.

Usage

import { useState } from "react";
import {
  Breadcrumbs,
  Button,
  Checkbox,
  CheckboxList,
  DropdownMenu,
  Form,
  Input,
  Link,
  Navbar,
  TextArea,
  Title,
  Toast,
  type BreadcrumbItem,
} from "@matthieuglaisner/react-ui-components-library";

export function Example() {
  const [agree, setAgree] = useState(false);
  const [channels, setChannels] = useState<string[]>(["email"]);
  const [email, setEmail] = useState("");
  const [formError, setFormError] = useState<string | undefined>();

  const notifyItems = [
    { id: "email", label: "Email" },
    { id: "sms", label: "SMS" },
  ];

  const breadcrumbItems: BreadcrumbItem[] = [
    { label: "Home", href: "#" },
    { label: "Projects", href: "#" },
    { label: "Project Alpha" },
  ];

  return (
    <div className="flex flex-col gap-6">
      <Title as="h2" size="md" accent>
        Example
      </Title>
      <Toast type="info" title="Tip" onDismiss={() => {}}>
        Optional body text.
      </Toast>
      <Navbar
        aria-label="Example"
        brand={<span className="text-lg font-semibold text-[#6a7cbd]">Acme</span>}
        linksAlign="center"
        trailing={<Button size="sm">Sign in</Button>}
      >
        <Link href="#" aria-current="page">
          Home
        </Link>
        <Link href="#">Docs</Link>
      </Navbar>
      <Breadcrumbs items={breadcrumbItems} />
      <div className="flex flex-wrap gap-3">
        <Button variant="primary" size="md">
          Save
        </Button>
        <Button variant="secondary" size="sm">
          Cancel
        </Button>
        <Button variant="tertiary" fullWidth disabled>
          Disabled
        </Button>
        <Button className="uppercase tracking-wide">Custom classes</Button>
      </div>
      <div className="flex w-full max-w-sm flex-col gap-3">
        <Input
          label="Email"
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="[email protected]"
          helperText="We’ll only use this for account recovery."
        />
        <Input type="password" placeholder="Password" aria-label="Password" />
        <Input size="sm" invalid placeholder="Fix validation errors" aria-label="Invalid example" />
        <Input fullWidth placeholder="Full width in a block layout" aria-label="Wide field" />
      </div>
      <TextArea
        label="Notes"
        placeholder="Add details…"
        rows={4}
        helperText="Optional. Shown below the field when there is no error."
      />
      <TextArea error="This field is required." defaultValue="" rows={3} />
      <Form
        className="w-full max-w-sm"
        error={formError}
        onSubmit={(e) => {
          e.preventDefault();
          setFormError("Example error — change the field below to clear it.");
        }}
        submitLabel="Submit form"
      >
        <Input
          label="Field in Form"
          name="inForm"
          fullWidth
          placeholder="Type to clear the error"
          onChange={() => setFormError(undefined)}
        />
      </Form>
      <div className="flex flex-col gap-2">
        <Checkbox label="Remember me" defaultChecked />
        <Checkbox aria-label="Standalone option" />
        <Checkbox
          label="I agree (controlled)"
          checked={agree}
          onChange={(e) => setAgree(e.target.checked)}
        />
        <CheckboxList
          legend="Notifications"
          items={notifyItems}
          orientation="column"
          value={channels}
          onValueChange={setChannels}
          name="notify"
        />
        <CheckboxList
          aria-label="Layout row example"
          items={[
            { id: "a", label: "Alpha" },
            { id: "b", label: "Bravo" },
            { id: "c", label: "Charlie" },
          ]}
          orientation="row"
          defaultValue={["b"]}
        />
        <DropdownMenu
          triggerLabel="Actions"
          items={[
            { id: "edit", label: "Edit" },
            { id: "copy", label: "Copy" },
            { id: "remove", label: "Remove", disabled: true },
          ]}
        />
      </div>
    </div>
  );
}

Button props (summary)

| Prop | Description | | ------------ | --------------------------------------------------------------------------- | | variant | "primary" (default), "secondary", or "tertiary" | | size | "sm", "md" (default), or "lg" — text and padding scale together | | fullWidth | When true, the button spans the width of its container | | disabled | Native disabled behavior and muted appearance | | className | Merged with the component’s base classes | | … | Other native <button> attributes are forwarded (for example type, onClick, aria-*) |

Form props (summary)

| Prop | Description | | -------------------- | --------------------------------------------------------------------------- | | showSubmitButton | When false, the built-in submit Button is not rendered. Default true. | | submitLabel | Label for the default submit button. Default "Submit". | | submitDisabled | When true, disables the default submit (combined with submitButtonProps.disabled). | | submitButtonProps | Props forwarded to the default submit Button except type (always "submit") and children (from submitLabel). | | error | Form-level message (ReactNode). Empty or whitespace-only strings are ignored. Renders in role="alert" with error styling; sets aria-invalid on the form; merges into aria-describedby. While shown, the default submit is disabled — clear error to re-enable. | | className | Merged onto the <form>. | | … | Other native <form> attributes are forwarded (for example onSubmit, method, action, ref, aria-describedby). |

Input props (summary)

| Prop | Description | | ------------ | --------------------------------------------------------------------------- | | type | Any native input type (defaults to "text"). | | label | Optional ReactNode. When set, wraps the field in a <label> and wires id / htmlFor if you omit id. | | size | "sm", "md" (default), or "lg" — padding and text scale (not the HTML size attribute; use className / style for character width if needed). | | fullWidth | When true, the input spans the width of its container. | | helperText | Optional ReactNode rendered below the field and linked via aria-describedby (merged with your aria-describedby). Color follows status: invalid (enabled) is red; disabled is muted (wins over invalid). | | invalid | When true, sets aria-invalid and applies error border and focus ring. | | disabled | Native disabled behavior and muted appearance | | className | Merged with the component’s base classes | | … | Other native <input> attributes are forwarded. For checkboxes, consider the library Checkbox for tailored styling. |

TextArea props (summary)

| Prop | Description | | ------------- | --------------------------------------------------------------------------- | | label | Optional label; associates with the control via id or a generated id | | helperText | Hint below the field (hidden when error is a non-empty string) | | error | true sets aria-invalid; a string also shows that message below the field | | size | "sm", "md" (default), or "lg" — text, padding, and minimum height | | fullWidth | When true, the textarea spans the width of its container | | disabled | Native disabled behavior and muted appearance | | className | Merged with the component’s base classes | | … | Other native <textarea> attributes are forwarded (for example rows, value, onChange, aria-*) |

Title props (summary)

| Prop | Description | | ------------ | --------------------------------------------------------------------------- | | as | "h1" (default) through "h6" — semantic heading element | | children | Heading content | | size | "xs", "sm", "md" (default), "lg", or "xl" — visual scale | | align | "left" (default), "center", or "right" | | accent | When true, uses the library primary color for the text | | truncate | When true, single-line ellipsis overflow | | className | Merged with the component’s base classes | | … | Other native heading attributes are forwarded for the chosen as tag |

Radio props (summary)

| Prop | Description | | ------------ | --------------------------------------------------------------------------- | | children | Optional label content; when set, wraps the input in an associated <label>. | | className | Merged with the component’s base classes | | … | Other native <input> attributes are forwarded except type (always "radio"). |

RadioList props (summary)

| Prop | Description | | ----------------- | --------------------------------------------------------------------------- | | name | Shared name for each radio in the group. | | options | Array of { value, label, disabled? }. | | orientation | "vertical" (default) or "horizontal". | | value / defaultValue / onChange | Controlled or uncontrolled single selection (native change events). | | legend | Optional fieldset legend; otherwise set aria-label on the fieldset. | | disabled | When true, all options are non-interactive. | | className | Merged onto the <fieldset>. | | … | Other native <fieldset> attributes are forwarded (except children / onChange). |

DropdownMenu props (summary)

| Prop | Description | | ----------------- | --------------------------------------------------------------------------- | | items | Array of { id, label, disabled? }. | | onItemSelect | Optional (id: string) => void when an enabled item is chosen; menu closes afterward. | | triggerLabel | Use either this or renderTrigger: built-in <button> text. | | renderTrigger | (props: DropdownMenuTriggerProps) => ReactNode — spread props onto your button (ref, onClick, ARIA). | | align | "start" (default) or "end" — horizontal alignment of the panel under the trigger. | | open / onOpenChange | Optional controlled open state. | | menuClassName | Extra classes for the menu panel. | | className | Merged onto the outer wrapper <div>. | | … | Other native <div> attributes are forwarded (except children). |

Checkbox props (summary)

| Prop | Description | | ----------------- | --------------------------------------------------------------------------- | | label | Optional ReactNode. When set, wraps the input in a <label> so text is clickable and associated; label text is semibold while checked. | | className | Merged with the component’s base classes | | disabled | Native disabled behavior and muted appearance | | checked / onChange | Controlled usage: drive checked from state and update in onChange. | | defaultChecked | Uncontrolled default checked state | | … | Other native <input> attributes are forwarded except type (always "checkbox"). Use aria-label when there is no visible label. |

CheckboxList props (summary)

| Prop | Description | | ----------------- | --------------------------------------------------------------------------- | | items | Array of { id, label, disabled? } — ids are used for selection and form value. | | orientation | "column" (default) or "row" (horizontal with wrap). | | value / onValueChange | Controlled multi-select: selected ids and updater. | | defaultValue | Initial selected ids when uncontrolled. | | legend | Optional <legend> for the fieldset; otherwise set aria-label on the list. | | name | Optional shared name on each checkbox for HTML forms. | | className | Merged onto the <fieldset>. | | listClassName | Classes for the inner flex container. | | … | Other native <fieldset> attributes are forwarded (except children / onChange). |

Navbar props (summary)

| Prop | Description | | -------------- | --------------------------------------------------------------------------- | | brand | Optional left cluster (logo, title, etc.). | | children | Primary nav content; horizontal row between brand and trailing. | | trailing | Optional right cluster (e.g. Button). | | linksAlign | "left" (default), "center", or "right" — placement of children in the middle flex region. | | sticky | When true, adds sticky top-0 z-50 on the root <nav>. | | className | Merged onto the root <nav>. | | … | Other native <nav> attributes are forwarded (for example aria-label, ref). |

Link props (summary)

| Prop | Description | | ------------ | --------------------------------------------------------------------------- | | as | Optional React.ElementType; default "a". Use RouterLink or NavLink from react-router-dom for in-app navigation (to, etc.). | | className | Merged with the component’s base classes. | | aria-current | Set to "page" on the active route for current-page styling (or use NavLink, which sets this when active). | | … | Other props are forwarded to the underlying element (href for <a>, to for router links, target, rel, etc.). |

Breadcrumbs props (summary)

| Prop | Description | | ------------ | --------------------------------------------------------------------------- | | items | Ordered path segments from root to current. Each item supports label, optional href, optional onClick, and optional ariaCurrent: "page" (defaults to current page for the last item). | | separator | Separator between items (ReactNode). Defaults to /. | | maxItems | When set and exceeded, collapses the middle behind an ellipsis. | | renderItem | Optional custom render hook (item, { isCurrent }) => ReactNode. When provided, you control link/current styling and attributes. | | className | Merged onto the root <nav>. | | … | Other native <nav> attributes are forwarded (for example aria-label, ref). |

Toast props (summary)

| Prop | Description | | -------------------- | --------------------------------------------------------------------------- | | title | Short summary shown as the heading | | type | "error", "warning", "info", or "success" | | children | Optional body below the title | | role | Optional "status" or "alert"; defaults by type (alert for error/warning) | | onDismiss | When set, renders a dismiss button and calls this handler (you remove the toast from the UI) | | dismissButtonProps | Optional props for the dismiss button (aria-label, className, etc.) | | className | Merged onto the root | | … | Other native <div> attributes are forwarded (except title / children) |

useClickAway (summary)

| Argument | Description | | ---------- | --------------------------------------------------------------------------- | | ref | Ref to the element; the handler runs when pointerdown occurs outside it | | handler | (event: PointerEvent) => void | | options | { enabled?: boolean } — when false, document listeners are not attached |

Development

Clone the repo, install dependencies, then:

| Command | Description | | -------------------------- | -------------------------- | | npm run build | Build dist/ (ESM + CJS + types) | | npm test | Run tests | | npm run storybook | Component docs / playground | | npm run build-storybook | Static Storybook build |

See AGENTS.md for contribution conventions (structure, typing, tests, Storybook).

License

MIT