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

@andreagiugni/tailwind-dashboard-ui

v0.5.17

Published

Reusable React + Tailwind CSS v4 dashboard components extracted from TailAdmin.

Readme

@andreagiugni/tailwind-dashboard-ui

Reusable React + Tailwind CSS v4 dashboard components extracted from TailAdmin. Every primitive ships with its Tailwind styling, extends the underlying element's native HTML attributes (so onClick, onDoubleClick, aria-*, data-*, … just work), exposes named style variants, and — where visually meaningful — accepts inline bgColor / textColor / borderColor overrides.

Dual ESM + CJS builds with TypeScript types. Every component — including the data-viz widgets (charts, calendar, map) — is exported from the single package entry point.

Live preview

TailDashboardUI component library preview

Explore every component with interactive previews, copy-ready snippets and complete prop references at taildashboardui.com.

Install

npm i @andreagiugni/tailwind-dashboard-ui

Peer dependencies

The core package requires:

  • React 18 or 19 (react, react-dom)
  • Tailwind CSS v4 (tailwindcss@^4)

clsx, tailwind-merge, and flatpickr (used by DatePicker) are bundled runtime dependencies — you do not need to install them yourself.

The following heavy libraries are optional peers, only needed if you use the matching data-viz component:

| Component | Optional peer deps | |---|---| | BarChart, LineChart | apexcharts, react-apexcharts | | Calendar | @fullcalendar/core, @fullcalendar/react, @fullcalendar/daygrid, @fullcalendar/timegrid, @fullcalendar/list, @fullcalendar/interaction | | CountryMap | @react-jvectormap/core, @react-jvectormap/world | | Editor (WYSIWYG) | @tiptap/react, @tiptap/pm, @tiptap/starter-kit, @tiptap/extension-link, @tiptap/extension-placeholder, @tiptap/extension-superscript, @tiptap/extension-subscript |

Install only the ones for the components you use, e.g.:

npm i apexcharts react-apexcharts          # for BarChart / LineChart
npm i @tiptap/react @tiptap/pm @tiptap/starter-kit @tiptap/extension-link @tiptap/extension-placeholder @tiptap/extension-superscript @tiptap/extension-subscript  # for Editor

SSR note: the data-viz components and the Editor touch window/the DOM at render time. In server-rendered frameworks (e.g. Next.js) render them client-only — for example with next/dynamic(() => import('@andreagiugni/tailwind-dashboard-ui').then(m => m.BarChart), { ssr: false }). They are code-split into their own chunks and never executed unless you actually import them, so the rest of the library stays SSR-safe and light.

ColorPicker

The ColorPicker is built on react-beautiful-color, which is a bundled dependency (installed automatically — you don't add it yourself). It is client-only and code-split like the data-viz widgets, so render it client-only under SSR. It ships its own stylesheet — import it once in your app:

import 'react-beautiful-color/dist/react-beautiful-color.css';

Tailwind setup

The library ships its design tokens as an importable stylesheet. Add this line to your app's Tailwind entry CSS (the file that already contains @import 'tailwindcss';):

@import '@andreagiugni/tailwind-dashboard-ui/theme.css';

theme.css registers the full TailAdmin token set (brand / blue-light / gray / orange / success / error / warning palettes, --text-theme-*, --shadow-theme-*, --z-index-*) inside an @theme block, plus base layer rules.

Dark mode is driven by the .dark class. The theme defines a custom dark variant against an ancestor .dark, so toggle dark mode by adding/removing the dark class on <html> (or any ancestor):

<html class="dark">

The ThemeToggleButton component is controllable for this purpose (theme + onToggle props).

Importing components

Everything is exported from the single package entry point:

import {
  Button,
  Badge,
  Alert,
  Input,
  Select,
  Modal,
  Table,
  TableHeader,
  TableBody,
  TableRow,
  TableCell,
  // hero-ui parity additions
  Accordion,
  AccordionItem,
  Tabs,
  Tab,
  Tooltip,
  Popover,
  Drawer,
  Chip,
  Progress,
  Spinner,
  Skeleton,
  Slider,
  Code,
  Snippet,
  // data viz + editor (see SSR note above)
  BarChart,
  LineChart,
  Calendar,
  CountryMap,
  Editor,
} from '@andreagiugni/tailwind-dashboard-ui';

Props model

Three conventions apply across the library:

  1. Native handlers via HTML-attribute extension. Each component's props extend the root element's React HTML attribute type (e.g. ButtonHTMLAttributes), so every native handler and attribute (onClick, onDoubleClick, onMouseEnter, aria-*, data-*, …) is available with zero extra wiring and is forwarded onto the underlying element.
  2. Named variants. Visual states are selected with discrete props such as variant, size, and color instead of class strings.
  3. Inline color overrides. Where meaningful, components accept bgColor, textColor, and borderColor. These map to inline style (backgroundColor / color / borderColor) and let you escape the named palette for one-off colors. A consumer-supplied style prop always wins.
import { Button, Badge } from '@andreagiugni/tailwind-dashboard-ui';
import '@andreagiugni/tailwind-dashboard-ui/theme.css'; // in your Tailwind entry CSS

<Button variant="primary" onDoubleClick={handle}>Save</Button>
<Button bgColor="#ff5722" textColor="#fff">Custom</Button>
<Badge color="success">Active</Badge>

Component reference

Legend: (+native) = also extends the element's native HTML attributes. (+override) = accepts bgColor / textColor / borderColor.

Core UI

| Component | Key props | |---|---| | Button | variant (primary/outline), size (sm/md), startIcon, endIcon, disabled, (+native button) (+override) | | Badge | variant (light/solid), color (primary/success/error/warning/info/light/dark), size (sm/md), startIcon, endIcon, (+native span) (+override) | | Ribbon | variant (corner/rounded/flag), color (primary/success/error/warning/info/dark), position (top-left/top-right/bottom-left/bottom-right), children (label), (+native span) (+override) — place inside a relative host (corner needs overflow-hidden) | | Alert | variant (success/error/warning/info), title, message, showLink, linkHref, linkText, icon? (override icon), (+native div) | | Avatar | src, alt, size (xsmall…xxlarge), status (online/offline/busy/none), statusColor?, (+native img) | | AvatarText | children, className, (+native div) | | Dropdown | isOpen, onClose, children, portal? (default true, prevents clipping inside tables/overflow containers), (+native div) | | DropdownItem | variant (default/primary/outline, like Button), icon?, bgColor/textColor/borderColor overrides, tag (a/button), href, onClick, onItemClick, baseClassName (full override) | | Modal | isOpen, onClose, title? (wrapping header aligned with close button), showCloseButton, isFullscreen, closeOnBackdrop?, closeOnEsc?; alert presetvariant (success/info/warning/danger) + title, description, actionText?, onAction?; (+native div) | | Table (composable) | TableHeader / TableBody / TableRow / TableCell with children, isHeader (cell), (+native table elements; onClick / onDoubleClick on rows & cells) | | Table (data-driven) | pass data + columns (key, header, sortable?, align?, render?, className?) to get search + three-state per-column sort (neutral/ascending/descending) + pagination: rowsPerPage? (max rows/page, default 10), rowsPerPageOptions?, searchKeys? (search box shown only when provided), searchPlaceholder?, defaultSortKey? / defaultSortDirection?, pagination?, paginationAlign? (left/center/right/full, default right), showSizeSelector?, onRowClick?, getRowId?, emptyContent? | | Pagination | currentPage, totalPages, onPageChange, align? (left/center/right/fullfull pins Previous/Next to the edges with page indices centered) | | Breadcrumb | pageTitle, items?, (+native) | | ThemeToggleButton | theme? (controlled), onToggle?, (+native button) | | Card | title?, description?, icon?, image?, imageAlt?, horizontal?, footer?, children?, (+native div) (+override) | | Accordion / AccordionItem | selectionMode (single/multiple), expandedKeys / defaultExpandedKeys, onExpandedChange; item: itemKey, title, startContent?, disabled | | Tabs / Tab | variant (underline/solid/pill), selectedKey / defaultSelectedKey, onSelectionChange, color?; tab: tabKey, title, disabled | | Chip | color, variant (light/solid), size, startIcon, endIcon, avatar?, onClose?, (+native span) (+override) | | Code | color (primary/success/error/warning/info/default), size (sm/md), (+native code) (+override) | | Snippet | code (string | string[]), symbol?, hideCopyButton?, hideSymbol?, size, (+override) | | Progress | value, maxValue?, color, size (sm/md/lg), label?, showValueLabel?, isIndeterminate? | | Spinner | size (sm/md/lg), color, label? | | Skeleton | isLoaded, width?, height?, className, children? | | Toast | variant (success/danger/warning/info), title, message?, icon?, hideIcon?, showCloseButton?, onClose?, hideAccentBar?, (+native div) (+override) |

Overlays

| Component | Key props | |---|---| | Tooltip | content, placement (top/right/bottom/left), delay?, disabled?, (+native span) (+override) | | Popover | trigger, placement, isOpen? / defaultOpen? / onOpenChange?, closeOnOutsideClick?, closeOnEsc? | | Drawer | isOpen, onClose, placement (left/right/top/bottom), showCloseButton?, closeOnBackdrop?, closeOnEsc?, size?, (+native div) |

Form controls

| Component | Key props | |---|---| | Input | type, value / defaultValue, onChange, success, error, hint, disabled, (+native input) (+override) | | Label | htmlFor, children, (+native label) | | Select | options ({ value, label, icon? }[]), placeholder, defaultValue, onChange(value), disabled | | MultiSelect | options, selected / defaultSelected, onChange, placeholder, disabled | | Checkbox | label, checked, onChange(checked), disabled, checkedColor? | | Radio / RadioSm | id, name, value, checked, label, onChange(value), disabled | | Switch | label, checked / defaultChecked, onChange(checked), color (blue/gray), disabled | | TextArea | value, onChange, rows, success, error, hint, disabled | | FileInput | onChange, accept, multiple, (+native input) | | PasswordInput | password field with a show/hide eye toggle, (+native input attrs) | | Dropzone | onDrop(files), accept?, multiple?, title?, description?, browseLabel? — drag-and-drop upload, dependency-free | | DatePicker | id, mode (single/multiple/range/time), defaultDate, onChange, label, placeholder | | DateTimePicker | id, label?, placeholder?, defaultDate?, defaultTime? ("HH:MM"), onChange?({ date, time }) — flatpickr date calendar + a compact HH:MM time input | | Slider | value / defaultValue, onChange(value), min, max, step, color, label?, showValue?, disabled | | ColorPicker | defaultValue? (hex), defaultFormat? / formats? (hex/rgb/rgba/hsl/hsla), showInput?, withEyeDropper?, label?, onChange?(value, color) — compact swatch + formatted value trigger opening a saturation/hue/alpha popup with a value input and format switcher; built on react-beautiful-color (bundled), client-only, import its CSS (see ColorPicker note above) | | Editor (WYSIWYG) | content, onChange(html), placeholder?, editable?, toolbar? (ordered tool ids or custom buttons), editorClassName? — optional Tiptap peers; render client-only (see Data viz) |

Data viz

These wrap optional heavy peer deps and must be rendered client-only under SSR (see the SSR note in Peer dependencies).

| Component | Key props | |---|---| | BarChart | series, categories, colors?, height?, options? (merged over defaults) | | LineChart | series, categories, colors?, height?, options? | | Calendar | events, onEventClick, onDateSelect, initialView | | CountryMap | markers, markerColor?, mapColor? | | Editor (WYSIWYG) | content, onChange(html), placeholder?, editable?, toolbar? — Tiptap-powered, customizable toolbar |

The data-viz components default their data to sensible demo values, so they render out-of-the-box and are fully overridable via the props above.

The Editor is a Tiptap-powered rich-text editor with a fully customizable toolbar. Pass an ordered toolbar array of built-in tool ids ("bold" | "italic" | "strike" | "code" | "superscript" | "subscript" | "heading1" | "heading2" | "heading3" | "bulletList" | "orderedList" | "blockquote" | "codeBlock" | "link" | "undo" | "redo" | "divider") or custom { id, icon, title, onClick, isActive? } button objects. Set editable={false} for a read-only view (toolbar hidden).

import dynamic from 'next/dynamic';
const Editor = dynamic(
  () => import('@andreagiugni/tailwind-dashboard-ui').then((m) => m.Editor),
  { ssr: false }
);

<Editor
  content="<p>Hello <strong>world</strong></p>"
  onChange={(html) => save(html)}
  toolbar={['bold', 'italic', 'divider', 'bulletList', 'orderedList', 'link']}
/>

Table

Table has two modes, both under the same component:

  1. Composable — use Table / TableHeader / TableBody / TableRow / TableCell as thin, styled wrappers around the native table elements when you want full control over the markup.
  2. Data-driven — pass a data array and a columns definition and you get live search, per-column click-to-sort, a "Show N entries" selector and pagination out of the box. The mode switches on automatically as soon as columns is provided.
import { Table, type TableColumn } from '@andreagiugni/tailwind-dashboard-ui';

type Person = { name: string; office: string; salary: number };

const people: Person[] = [
  { name: 'Abram Schleifer', office: 'Edinburgh', salary: 89500 },
  { name: 'Carla George', office: 'London', salary: 15500 },
  // …
];

const columns: TableColumn<Person>[] = [
  { key: 'name', header: 'User', sortable: true },
  { key: 'office', header: 'Office', sortable: true },
  {
    key: 'salary',
    header: 'Salary',
    sortable: true,
    align: 'right',
    render: (row) => `$${row.salary.toLocaleString()}`, // custom cell
  },
];

<Table
  data={people}
  columns={columns}
  rowsPerPage={5}              // max rows per page (default 10)
  rowsPerPageOptions={[5, 10, 25]}
  defaultSortKey="name"
  searchKeys={['name', 'office']} // omit to hide the search box
  onRowClick={(row) => console.log(row)}
/>

Key data-driven props: data, columns (each: key, header, sortable?, align?, render?, className?), rowsPerPage (default 10), rowsPerPageOptions (default [5,10,25,50]), searchKeys / searchPlaceholder, defaultSortKey / defaultSortDirection, pagination, paginationAlign (left / center / right / full, default right), showSizeSelector, onRowClick, getRowId, emptyContent.

Search visibility: the search input renders only when you pass a non-empty searchKeys array — those are also the exact fields the query matches. Omit searchKeys (or pass []) to hide search entirely.

License

MIT © Andrea Giugni