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

@roy-ui/ui

v0.0.17

Published

Free, animated React components built with TypeScript. Zero config, RSC-safe, sub-12 KB. Gradient button, popover, text morph and more.

Readme

@roy-ui/ui

A modern React component library for Next.js 15, Vite, Remix, TanStack Start, and any React 18+ bundler. Ships a fully-featured React data table with search, date range picker, analog & digital time picker, pagination, column reorder / resize / hide, CSV / JSON export & import, per-zone typography, plus animated micro-interaction primitives — TypeScript-first, RSC-safe, tree-shakable ESM, zero config.

npm version npm downloads bundle size types license

Open the live documentation →


Why @roy-ui/ui?

You're building a React dashboard, admin panel, internal tool, or product UI in Next.js 15 App Router, Vite, Remix, Astro, or TanStack Start. You want a production-grade table component with filtering, paginate, sort, drag-to-reorder columns, resize, hide, export — without wiring up TanStack Table, AG Grid, or React Table from scratch. You want clean, animated micro-interaction components — without installing Tailwind, configuring PostCSS, or pulling in Framer Motion. You want TypeScript and React Server Component support out of the box.

@roy-ui/ui is that library. One npm install. One import. Production-ready.

  • Drop-in React DataTable with search, date range, time, pagination, reorder, resize, hide, CSV / JSON IO
  • Built-in custom date range picker — 2-month modal, hover-preview, presets, no date-fns required
  • Built-in custom time picker — analog wristwatch and digital, AM / PM toggle, user-switchable
  • Animated primitives — gradient button with loading spinner, popover, text morph, tree nav, floating "Made by" badge
  • Zero runtime config — no Tailwind plugin, no theme provider, no design-token setup
  • TypeScript-first — tree-shakable ESM with first-class .d.ts types and source maps
  • RSC-safe (React Server Components-safe)"use client" boundary inside the bundle; import directly from a Next.js App Router server component
  • Framework-agnostic — Next.js, Vite, Remix, Astro (React island), TanStack Start, CRA, any ESM bundler

Install

npm install @roy-ui/ui
# or
pnpm add @roy-ui/ui
# or
yarn add @roy-ui/ui
# or
bun add @roy-ui/ui

Peer dependency: React 18 or newer (React 19 supported).

Quick start — React DataTable

'use client';

import { useState } from 'react';
import { DataTable, type Column } from '@roy-ui/ui';

type Order = {
  id: string;
  customer: string;
  total: number;
  placedAt: Date;
  status: 'paid' | 'pending' | 'refunded';
};

const columns: Column<Order>[] = [
  { key: 'id', header: 'Order', accessor: (r) => r.id, isRowHeader: true },
  { key: 'customer', header: 'Customer', accessor: (r) => r.customer },
  { key: 'status', header: 'Status', accessor: (r) => r.status },
  { key: 'placedAt', header: 'Placed', accessor: (r) => r.placedAt, type: 'date' },
  {
    key: 'time',
    header: 'Time',
    accessor: (r) => r.placedAt,
    type: 'time',
  },
  {
    key: 'total',
    header: 'Total',
    accessor: (r) => r.total,
    type: 'number',
    cell: (v) => `$${(v as number).toFixed(2)}`,
  },
];

export default function OrdersTable({ orders }: { orders: Order[] }) {
  const [data, setData] = useState(orders);

  return (
    <DataTable<Order>
      data={data}
      columns={columns}
      visibleRows={8}
      search={{ enabled: true, placeholder: 'Search orders' }}
      dateFilter={{ column: 'placedAt', monthsVisible: 2 }}
      timeFilter={{ column: 'time', variant: 'analog', toleranceMinutes: 60 }}
      pagination={{ pageSize: 25 }}
      dataIO={{
        export: { enabled: true, filename: 'orders' },
        import: { enabled: true, onImport: setData },
      }}
    />
  );
}

Using the Next.js App Router? Import directly from a Server Component — the interactive bits inside @roy-ui/ui carry their own "use client" boundary.

What's in the box

Display / Data

| Component | What it does | | --- | --- | | DataTable<T> | Generic, fully-featured React data table. Search across columns, sort, paginate, drag headers to reorder, drag the right edge to resize, Columns menu to hide & restore, CSV / JSON export & import, per-zone typography for headers / row-headers / cells, optional fitColumns to disable horizontal scroll, optional localStorage persistence. | | Table + parts | Standalone primitive — Table, TableHeader, TableBody, TableRow, TableHead, TableCell. Scrollable rows (visibleRows, default 7), sticky header, density scale (compact / cozy / comfortable), inline Spinner. | | TableSearch | Debounced search input, clear button, controlled & uncontrolled modes. | | Pagination | Numbered pages with text Prev / Next, ellipsis, optional Page X of Y summary. | | DateRangePicker | Custom React date range picker — 2 (or N) months side-by-side in a popover, hover-preview the range, preset sidebar (Today / Last 7d / Last 30d / This month / Last month), min / max bounds, zero date-fns dependency. | | TimePicker | Custom React time picker with two variants — analog clock face (drag the hour & minute hands, AM / PM segmented pill) and digital (scroll-wheel or arrow keys per segment). User can switch between them. 12h or 24h cycle, configurable minute step. | | Spinner | Inline animated SVG spinner. Used as the default loading state across the library. | | TreeNav + TreeNavItem | Sidebar sub-nav with file-explorer-style L-shaped branch connectors. Router-agnostic via asChild, active state driven by aria-current. | | TextMorph | Character-by-character text diff animation — great for live counters, currency tickers, status text. | | MadeBy | Floating "Made by ___" attribution badge with corner positioning. |

Inputs / Overlay

| Component | What it does | | --- | --- | | GradientButton | Animated blue → cyan → blue gradient CTA with a built-in loading spinner. | | Popover | Accessible click-to-open popover with corner alignment (left / right) and width presets. |

DataTable feature matrix

| Feature | Prop / API | Notes | | --- | --- | --- | | Search across all columns | search={{ enabled: true }} | Debounced; override matcher with search.predicate | | Date range filter on a column | dateFilter={{ column, monthsVisible }} | 2-month modal by default; pass any N | | Time-of-day filter on a column | timeFilter={{ column, variant, toleranceMinutes }} | variant: 'analog' \| 'digital', both user-switchable | | Click-to-sort | always on | Tri-state per column: asc → desc → off | | Pagination | pagination={{ pageSize }} or false | Text Prev / Next + numbered pages | | Column drag-to-reorder | reorderable (default true) | Native HTML5 DnD, drop indicator | | Column resize | resizable (default true) | Drag right edge of header; double-click resets | | Column hide / restore | columnMenu (default true) | "Columns" popover + hidden-count chip for instant restore | | Pinned columns | pinned: 'left' \| 'right' per column | Excluded from reorder | | CSV export | dataIO.export | Built-in RFC 4180 writer | | JSON export | dataIO.export | Native JSON.stringify | | CSV / JSON import | dataIO.import | File picker → parsed rows → onImport | | Per-zone fonts | headerFont, rowHeaderFont, cellFont | Plus per-column font | | Persist layout | storageKey | Order, sizes, hidden state in localStorage | | Disable horizontal scroll | fitColumns | Columns auto-distribute; cells wrap | | Loading state | loading | Dims body, overlays inline Spinner | | Custom empty slot | empty | Any ReactNode | | Generic over row type | DataTable<T> | Full TypeScript inference |

Custom date range picker — standalone

'use client';

import { useState } from 'react';
import { DateRangePicker, type DateRange } from '@roy-ui/ui';

export function BookingPicker() {
  const [range, setRange] = useState<DateRange>({ from: null, to: null });

  return (
    <DateRangePicker
      value={range}
      onChange={setRange}
      monthsVisible={2}
      weekStartsOn={1}
      minDate={new Date()}
    />
  );
}

Custom time picker — analog and digital

'use client';

import { useState } from 'react';
import { TimePicker, type TimeValue } from '@roy-ui/ui';

export function ShiftStartPicker() {
  const [time, setTime] = useState<TimeValue | null>(null);

  return (
    <TimePicker
      value={time}
      onChange={setTime}
      variant="analog"     // or "digital" — user can also switch from the panel
      hourCycle={12}       // or 24
      minuteStep={5}
    />
  );
}

Standalone table primitives

If DataTable is more than you need, the primitives ship on their own.

import {
  Table,
  TableHeader,
  TableBody,
  TableRow,
  TableHead,
  TableCell,
} from '@roy-ui/ui';

<Table visibleRows={5} stickyHeader>
  <TableHeader>
    <TableRow>
      <TableHead>Order</TableHead>
      <TableHead>Customer</TableHead>
      <TableHead align="right">Total</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    {orders.map((o) => (
      <TableRow key={o.id}>
        <TableCell isRowHeader>{o.id}</TableCell>
        <TableCell>{o.customer}</TableCell>
        <TableCell align="right">${o.total.toFixed(2)}</TableCell>
      </TableRow>
    ))}
  </TableBody>
</Table>

React data table comparison — @roy-ui/ui vs TanStack Table vs AG Grid vs Material React Table

| | @roy-ui/ui (DataTable) | TanStack Table v8 | AG Grid Community | Material React Table | | --- | --- | --- | --- | --- | | Ships visual styles | Yes | No (headless) | Yes | Yes (Material UI required) | | Built-in date range filter | Yes | No (build it) | Enterprise only | No | | Built-in time picker filter | Yes (analog + digital) | No | No | No | | Built-in CSV / JSON export | Yes | No | Yes | Partial | | Drag-to-reorder columns | Yes (native, no deps) | Manual + DnD lib | Yes | Yes (Material UI) | | Column resize | Yes | Manual | Yes | Yes | | Column hide / show menu | Yes | Manual | Yes | Yes | | Required dependency tree | React only | React only | @ag-grid-community/* | @mui/* + @tanstack/* | | RSC-safe with Next.js App Router | Yes | Manual | Manual | Manual | | TypeScript-first generic over row type T | Yes | Yes | Partial | Yes | | License | MIT | MIT | MIT (community) | MIT |

When to use each:

  • Need maximum flexibility, no styles, you wire everything? Use TanStack Table v8.
  • Need Excel-style spreadsheet with pivot, master-detail, infinite scroll, enterprise license? Use AG Grid.
  • Already deep in Material UI? Use Material React Table.
  • Need a clean, modern React data table with search + date range + time + paginate + reorder + resize + hide + CSV / JSON working out of the box in a Next.js app, zero setup? Use @roy-ui/ui.

React UI library comparison — @roy-ui/ui vs shadcn/ui vs Aceternity vs MUI vs Radix

| | @roy-ui/ui | shadcn/ui | Aceternity / Magic UI | Radix / Headless UI | MUI | | --- | --- | --- | --- | --- | --- | | Single npm install (no CLI, no copy) | Yes | No (copy-paste CLI) | No (copy-paste) | Yes | Yes | | Ships visual styles | Yes | Yes | Yes | No | Yes | | RSC-safe out of the box | Yes | Yes | Manual | Manual | Manual | | Tailwind required | No | Yes | Yes | No | No | | Framer Motion required | No | No | Yes | No | No | | Animation built in | Yes | Sometimes | Yes | No | Sometimes | | Ships a full DataTable | Yes | No (build it) | No | No | Partial (DataGrid is paid) |

Theming

Every component exposes its visual surface as CSS custom properties. Override on the component, on a parent class, or globally on :root.

.royui-table {
  --royui-table-bg: #ffffff;
  --royui-table-fg: #141414;
  --royui-table-border: rgba(20, 20, 20, 0.1);
  --royui-table-header-bg: #f7f7f7;
  --royui-table-cell-size: 14px;
  --royui-table-cell-font: 'Inter', system-ui, sans-serif;
}

A dark scheme override ships under @media (prefers-color-scheme: dark) for every component.

Framework support

| Framework | Status | | --- | --- | | Next.js 13 / 14 / 15 (App Router) | Supported | | Next.js (Pages Router) | Supported | | Vite + React 18 / 19 | Supported | | Remix | Supported | | Astro (React island) | Supported | | TanStack Start | Supported | | Create React App | Supported | | Plain React 18+ + ESM bundler | Supported |

FAQ

Is this a free React data table library? Yes. MIT licensed, free for personal and commercial use, no paid tier.

Does the DataTable work with React Server Components? Yes. The component carries its own "use client" boundary inside the published bundle, so you can render <DataTable /> from a Next.js App Router server component without manually marking the file.

Is Tailwind CSS required? No. Styles are scoped CSS, side-effect imported by each component. No Tailwind plugin, no PostCSS config, no theme provider.

Can I use this with TanStack Table? Yes, but you don't need to — the DataTable here ships its own state pipeline (search → date filter → time filter → sort → paginate) and column-layout state (order, sizes, hidden). If you already use TanStack Table, use the Table, TableHead, TableRow, TableCell primitives from @roy-ui/ui for styles and wire your TanStack instance to them.

How do I render every column without a horizontal scrollbar? Pass fitColumns to <DataTable /> — columns will share the container width and cell content wraps instead of overflowing.

Can I persist the user's column layout? Yes — pass storageKey="orders-table" to <DataTable /> and column order, sizes, and hidden state are saved to localStorage.

Is there a CSV import / export built in? Yes. dataIO.export.enabled adds an Export button; dataIO.import.enabled adds an Import button with a file picker. CSV writer is RFC 4180; parser handles quoted fields and escaped quotes. JSON IO is also built in. Bring your own parser via dataIO.import.parse for Excel / Parquet / etc.

Links

License

MIT © Dibbayajyoti Roy