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

@glyphui/ui

v0.8.0

Published

React components on Tailwind CSS v4 that take their entire look from one theme file. Forms, data tables, app layouts and async states included.

Readme

@glyphui/ui

React components on Tailwind CSS v4 that take their whole look from one typed theme file, with the parts every app rebuilds already solved: forms, data tables, app layout, and loading / empty / error states.

Docs · Components · Showcase · GitHub · Changelog

Install

npm install @glyphui/ui
# optional: forms and data tables (TanStack Table version 8)
npm install react-hook-form @hookform/resolvers zod @tanstack/react-table@8
# optional: charts from @glyphui/ui/chart
npm install recharts

Requires React 19 and Tailwind CSS 4.1 or later.

Set up

/* index.css */
@import "@glyphui/ui/fonts.css";      /* Geist, used by the default theme */
@import "tailwindcss";
@import "@glyphui/ui/styles.css";
@import "@glyphui/blocks/styles.css"; /* only with @glyphui/blocks */
// main.tsx
import { GlyphProvider, presets } from '@glyphui/ui'
import { reactRouter } from '@glyphui/ui/react-router'

createRoot(document.getElementById('root')!).render(
  <BrowserRouter>
    <GlyphProvider theme={presets.glyph} defaultMode="system" router={reactRouter} toaster>
      <App />
    </GlyphProvider>
  </BrowserRouter>,
)
  • router (optional) makes Glyph's links client-side and marks the current Sidebar, Navbar and NavigationMenu item automatically. For other routers, pass { Link, useIsActive }; the getting-started guide has TanStack Router and Next.js versions.
  • toaster mounts the toast container, so toast.success('Saved') works anywhere. useConfirm() needs no setup.

To avoid a light flash for dark-mode visitors, add the Vite plugin:

// vite.config.ts
import { glyphColorMode } from '@glyphui/ui/vite'

export default defineConfig({ plugins: [react(), tailwindcss(), glyphColorMode()] })

With an SSR framework, render <ColorModeScript /> in the document head instead.

Your theme, in one file

// glyph.theme.ts
import { defineTheme, presets } from '@glyphui/ui'

export default defineTheme({
  name: 'acme',
  extends: presets.glyph, // glyph · brutalist · editorial · playful
  colors: {
    light: { primary: 'oklch(55% 0.2 30)' },
    dark: { primary: 'oklch(70% 0.19 45)' },
  },
  radius: { md: '6px', lg: '10px' },
  font: { sans: '"Inter Variable", system-ui, sans-serif' },
  components: {
    Button: { defaultVariants: { size: 'lg' }, className: { base: 'tracking-tight' } },
  },
})

A theme controls:

  • colors, separately for light and dark, including a five-color chart palette
  • a nine-step type scale (size, line height, tracking, weight)
  • radius, shadows, border width, motion and control height
  • defaults and extra classes for each component

Everything is type-checked. A Button size or Card part that doesn't exist is a compile error.

The same tokens work in your own markup: bg-primary, text-muted-foreground, rounded-lg, shadow-md, text-h2, font-display.

Components

| Category | Components (132) | |---|---| | Actions | Button · CopyButton · Toggle | | Forms | Calendar · Checkbox · Combobox · DatePicker · Field · FileUpload · Input · InputOTP · Label · NumberInput · PasswordInput · RadioGroup · SegmentedControl · Select · Slider · Switch · TagInput · Textarea | | Overlays | Alert Dialog · ContextMenu · Dialog · Dropdown Menu · HoverCard · Modal · Popover · Sheet · Tooltip | | Navigation | Breadcrumb · CommandMenu · Link · NavigationMenu · Pagination · Stepper · Tabs | | Feedback | Alert · Banner · Progress · Skeleton · Spinner · Toast | | Data display | Accordion · Avatar · Badge · Carousel · Chart · ChartCard · Collapsible · DescriptionList · FunnelChart · Gauge · Heatmap · Kbd · PieChart · RadarChart · SankeyChart · ScatterChart · Sparkline · StatCard · Table · Timeline · Treemap · TreeView | | Typography | Blockquote · Code · Eyebrow · Heading · Prose · Text | | Layout | AspectRatio · Card · Container · Grid · Resizable · ScrollArea · Section · Separator · Stack · VisuallyHidden | | Patterns | AppShell · Async · DataTable · Form · Motion · Navbar · PageHeader · Router integration · Sidebar · Theming · Utilities · Virtual rows · Vite plugin | | Auth | Auth provider · AuthLayout · Clerk bridge · Code forms · Firebase adapter · Memory adapter · Password reset · Protected routes · REST adapter · Session dialogs · SignInForm · SignUpForm · SocialButtons · UserMenu | | Blocks (@glyphui/blocks) | AuthCard · Cta · Faq · FeatureGrid · FeatureSplit · Hero · LogoCloud · Newsletter · Pricing · SectionHeader · SiteFooter · Stats · Testimonials | | Viewers (@glyphui/viewers) | AudioPlayer · CodeViewer · CsvViewer · DiffViewer · FilePreview · ImageViewer · JsonViewer · MarkdownViewer · PdfViewer · SpreadsheetViewer · VideoPlayer |

Every component has a page with live examples and props in the docs. Accessible behavior comes from Radix UI. Every component accepts className, and most accept asChild.

Patterns

Layout

import { AppShell, Sidebar, SidebarContent, SidebarItem, PageHeader } from '@glyphui/ui'

<AppShell sidebar={<Sidebar><SidebarContent>
  <SidebarItem href="/inbox" icon={<Inbox />} badge={3}>Inbox</SidebarItem>
</SidebarContent></Sidebar>}>
  <PageHeader title="Inbox" actions={<Button>New</Button>} />
</AppShell>

The sidebar collapses to an icon strip on desktop and opens as a focus-trapped drawer on mobile. Navbar builds a responsive site header from links data. With router on GlyphProvider, the item for the current URL is marked active; pass active to override.

Forms: @glyphui/ui/form

import { Form, FormField, FormSubmit, useForm } from '@glyphui/ui/form'

const form = useForm({ schema, defaultValues: { email: '' } }) // zod, valibot, arktype...

<Form form={form} onSubmit={async (values) => {
  const res = await api.signup(values)
  if (res.taken) return { errors: { email: 'Already registered' } }
}}>
  <FormField control={form.control} name="email" label="Email">
    {(field) => <Input {...field} />}
  </FormField>
  <FormSubmit>Sign up</FormSubmit>
</Form>

Field names are checked against the schema. Server errors you return appear on their fields. If onSubmit throws, the error appears above the form in <FormError />.

Modals and confirmations

<Modal title="New invoice" trigger={<Button>New invoice</Button>}
  footer={<FormSubmit form={form}>Create</FormSubmit>}>   {/* outside <Form>, so pass form */}
  <Form form={form} onSubmit={save}>…</Form>
</Modal>

const confirm = useConfirm()
if (await confirm({ title: 'Delete invoice?', tone: 'danger' })) remove()

For a plain form, pass onSubmit to Modal and a type="submit" button in the footer.

Data tables: @glyphui/ui/data-table

import { createColumnHelper, DataTable, useTableUrlState } from '@glyphui/ui/data-table'

const col = createColumnHelper<Invoice>()
const columns = [
  col.accessor('number', { header: 'Invoice' }),
  col.accessor('status', { header: 'Status', meta: { filter: { type: 'multi', options } } }),
  col.accessor('total', { header: 'Total', meta: { align: 'right', filter: { type: 'range' } } }),
]

// Client mode: pass every row; the table searches, filters, sorts and pages them.
<DataTable data={invoices} columns={columns} search selectable exportCsv
  bulkActions={(selection) => <Button onClick={() => archive(selection.ids)}>Archive</Button>} />

// Server mode: the table hands you its state; you pass back one page and the total.
const url = useTableUrlState() // page, sort, search and filters in the URL
<DataTable mode="server" data={page?.rows} rowCount={page?.total} loading={isFetching}
  columns={columns} {...url} />

Filter chips (select, multi with counts, range, date range, text), multi-column sorting, page numbers and page size, select-all across pages with a floating bulk bar, column hiding, resizing, pinning and reordering, density, clickable or linked rows, expandable rows, inline editing with editableCell(), CSV export, cards on phones, and loading, empty, no-results and error states. For 10,000+ rows, pass a virtualRows() virtualizer from @glyphui/ui/data-table/virtual to virtualize.

Charts: @glyphui/ui/chart

<ChartCard title="Revenue" period={{ options: periods, value, onValueChange }}>
  <AreaChart title="Revenue" data={revenue} index="month" stacked
    series={[{ key: 'recurring', label: 'Recurring' }, { key: 'oneOff', label: 'One-off' }]}
    referenceLines={[{ y: 40000, label: 'Target' }]} />
</ChartCard>

Line, area, bar, composed, pie and donut, radar, radial bar, scatter and bubble, funnel, treemap, Sankey, calendar heatmap, gauge and sparkline charts. Series use the theme's chart-1 to chart-5 colors and animate at the theme's motion level. Legends toggle series, brush zooms, and every chart takes loading, error and an empty state. ChartCard adds a period selector, a "view as table" toggle and PNG/SVG download; exportChart() exports any chart with its theme colors baked in. Every chart includes a data table for screen readers. Needs recharts.

Async states

<Async result={useQuery({ queryKey: ['projects'], queryFn })}>
  {(projects) => <ProjectList projects={projects} />}
</Async>

License

MIT