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

@hollis-labs/sysop-ui

v0.9.0

Published

Sysop UI — the System Operations React kit + canonical [data-theme] palette for Hollis Labs apps.

Readme

@hollis-labs/sysop-ui

Sysop UI — the System Operations React kit. A shared package of generic shell components, shadcn/ui primitives, the canonical [data-theme] palette, and data hooks, extracted from the most-evolved app frontends (Torque's GUI and Fragments Engine's Sysop).

  • React 19 · Vite 5 · Tailwind v4 · shadcn/ui (base-nova style)
  • The [data-theme] + Tailwind @theme token system is canonical — the single styling lineage every Hollis Labs app converges to. The hand-rolled "HUD" CSS in older apps is retired in favour of it.

What's in the kit

| Area | Exports | | --- | --- | | Theme | theme.css (4 palettes + tokens), applyTheme, THEME_OPTIONS, ThemeSwitcher, … | | Shell | NavRail, PageHeader, SummaryCards, EmptyState, DetailDialog/DetailSection | | Layout | ListPageLayout, DetailPageLayout, DetailHeader, TabStrip, OperationsTablePage preset, CollapsibleSection | | Data table | DataTable<T> + ColumnDef<T> (sortable, windowed, selectable), RowActionMenu | | Filters | FilterBar shell + FilterSearchInput, FilterCycleToggle, FilterChipGroup, FilterEntityCombobox | | Primitives | CopyableId, CopyButton, StatusBadge, Pill, LiveDot, Callout, Combobox, MetaList, Metric, ProgressBar (indeterminate), JsonViewer, FormDialog, ConfirmDialog, + shadcn ui/ (table, button, badge, card, checkbox, input, textarea, label, dialog, alert-dialog, dropdown-menu, popover, command, input-group, scroll-area, select, separator, sheet, switch, tabs, tooltip, skeleton, sonner) | | Widgets | TimeSeriesChart (stacked bar/area, day-bucketed), DonutChart, BarMeter, ActivityHeatmap (calendar heatmap), HourlyPulse (last-24h strip), RecentList | | Hooks / API | usePoll, useCopy, useElapsed (seconds-elapsed ticker), useArrowNav (window ←/→ nav), useSSE (EventSource subscription), createApiContext, createApiClient, normalizeKeys, … | | Utils / toasts | formatDuration (seconds → 1h 03m), formatRelativeTime, formatShortDate, formatCount, notifySuccess / notifyError (sonner toast helpers — mount a <Toaster />) | | Storage / cursor | createScopedStorage (namespaced, fault-tolerant localStorage), createListCursor + listCursorNeighbors (list-cursor pagination — prev/next neighbors) |

App-specific domain code (fragment/route/task models, app dialogs) is not in the kit — it stays in each app. The kit is the generic shell.

The dashboard widgets pull in recharts (a bundled dependency) — it backs TimeSeriesChart's stacked bar/area rendering. The other widgets (DonutChart, BarMeter, ActivityHeatmap, HourlyPulse, RecentList) are dependency-free hand-rolled SVG/markup.

Import surfaces

The root entrypoint is intentionally narrow and mirrors ui:

import { Button, PageHeader, applyTheme } from '@hollis-labs/sysop-ui'

Optional domains live behind explicit subpaths:

| Entry | Use for | | --- | --- | | @hollis-labs/sysop-ui/ui | Theme helpers, shell chrome, formatters, visual primitives, shadcn ui/* | | @hollis-labs/sysop-ui/api | API client/context helpers, normalizers, polling/SSE hooks, storage/list cursor helpers | | @hollis-labs/sysop-ui/layout | Page skeletons such as ListPageLayout, DetailPageLayout, TabStrip | | @hollis-labs/sysop-ui/data | DataTable, RowActionMenu, filter-bar pieces | | @hollis-labs/sysop-ui/widgets | Lightweight SVG/markup widgets that do not use recharts | | @hollis-labs/sysop-ui/charts | TimeSeriesChart and any future charting components backed by recharts |

Recommended rule:

  • treat the root entrypoint as ui
  • import app transport/client plumbing from api
  • import page layouts from layout
  • import table/filter features from data
  • import charts only inside pages that actually render charts
  • import widgets explicitly for dashboard-only SVG widgets

Consuming the kit

Install from the public npm registry:

In an app

npm install @hollis-labs/sysop-ui

If you need an explicit version, pin a published tag:

npm install @hollis-labs/[email protected]

Local development

When working on the kit and a consuming app together, link the working copy:

# from the consuming app
npm install file:../../libs/sysop-ui

Run npm run build in libs/sysop-ui after changes (or npm run build -- --watch) so the linked dist/ stays fresh.

Wire it up

// 1. Import the canonical theme once (e.g. in main.tsx)
import '@hollis-labs/sysop-ui/theme.css'

// 2. Apply the persisted palette before first paint
import { applyTheme, getInitialTheme } from '@hollis-labs/sysop-ui/ui'
applyTheme(getInitialTheme())

The kit's components rely on the theme's semantic Tailwind tokens (bg-panel, text-text-subtle, border-border-strong, text-status-*, …), so the consuming app's Tailwind build must process theme.css.

theme.css also locks the document shell — html, body, and #root are pinned to the viewport with overflow disabled, so the fixed NavRail + PageHeader chrome never scrolls. Apps mount into #root and let page regions scroll internally; no per-app index.css reset is needed.

App structure

Default Sysop app shape:

  • eager shell: nav, page header, providers, theme boot, route state
  • lazy routes: each page loaded through React.lazy(() => import('./pages/...'))
  • page-local feature code: charts, dialogs, tables, and heavy inspectors stay with the page that uses them
  • shared shell imports: ui and layout
  • transport/client imports: api
  • optional heavy domains: charts only where needed

Minimal shell example:

import { Suspense, lazy } from 'react'
import { NavRail, PageHeader } from '@hollis-labs/sysop-ui/ui'

const OperationsPage = lazy(() =>
  import('./pages/operations').then((module) => ({ default: module.OperationsPage })),
)

export function AppShell() {
  return (
    <>
      <NavRail items={[]} />
      <PageHeader title="Operations" />
      <Suspense fallback={<div>Loading...</div>}>
        <OperationsPage />
      </Suspense>
    </>
  )
}

Adding a page

A page is generic kit chrome + app-specific content:

import {
  PageHeader, SummaryCards, EmptyState, StatusBadge,
} from '@hollis-labs/sysop-ui/ui'
import { DataTable, type ColumnDef } from '@hollis-labs/sysop-ui/data'

interface Widget { id: string; name: string; status: string }

const columns: ColumnDef<Widget>[] = [
  { key: 'name', header: 'Name', width: 'fill', cell: (w) => w.name,
    sortValue: (w) => w.name },
  { key: 'status', header: 'Status', cell: (w) => <StatusBadge status={w.status} /> },
]

export function WidgetsPage({ widgets }: { widgets: Widget[] }) {
  return (
    <>
      <PageHeader title="Widgets" />
      <SummaryCards cards={[{ label: 'Total', value: widgets.length }]} />
      {widgets.length === 0 ? (
        <EmptyState variant="empty" title="No widgets" description="Nothing here yet." />
      ) : (
        <DataTable items={widgets} columns={columns} getRowId={(w) => w.id} />
      )}
    </>
  )
}

Page layouts are full-bleed — chrome divides, content blocks frame

Reach for a layout component instead of hand-assembling the skeleton:

  • OperationsTablePage — the whole list/operations page (header + summary + filters + table) as one preset.
  • ListPageLayout / DetailPageLayout — slot-based shells for bespoke pages.

These fill the viewport edge-to-edge. Their structure comes from the pinned region dividersPageHeader, SummaryCards, FilterBar, and TabStrip each carry a bottom border — plus the NavRail's edge. That is the frame. Do not wrap a layout, or the DataTable inside it, in a bordered panel: the scroll body and table sit flush, exactly as Torque's and Fragments Engine's /operations routes do.

Borders belong to content blocks — a card, a callout, a grouped section inside the scroll body. Those opt in via the hud-panel class (rounded-md border bg-panel). Rule of thumb: page chrome divides with bottom borders; content blocks frame with hud-panel.

For the API layer, build a concrete client on createApiClient and a typed context with createApiContext:

import { createApiClient, createApiContext } from '@hollis-labs/sysop-ui/api'

const http = createApiClient({ baseUrl: '' })
export const apiClient = {
  listWidgets: () => http.get<Widget[]>('/v1/widgets'),
}
export const { ApiProvider, useApi } = createApiContext(apiClient)

Bundle inspection

Use route-level lazy imports first. If a Sysop app still has a large initial chunk, inspect the app build rather than guessing:

npm run analyze

Questions to answer in the report:

  • which modules are in the entry chunk
  • which pages moved into route chunks after React.lazy
  • whether recharts appears only in the page chunks that import @hollis-labs/sysop-ui/charts

Scripts

| Command | Purpose | | --- | --- | | npm run build | Type-check + emit dist/ (ES module + .d.ts) | | npm run demo | Component gallery — every export, live theme switch (visual reference) | | npm run typecheck | Type-check only | | npm run lint | ESLint | | npm test | Vitest (watch) | | npm run test:run | Vitest (single run) |

License

MIT — see LICENSE.