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

@plumile/ui

v0.2.3

Published

Shared React UI primitives and theme for Kronex applications

Readme

@plumile/ui

Shared React UI primitives, layouts, and theme foundations for Kronex applications.

Status

Specialized public package. This package is intended for teams adopting the Kronex design language and component conventions. It is not a generic UI kit for arbitrary React applications.

Purpose

@plumile/ui is the visual layer of the Kronex ecosystem. It provides:

  • theme contracts and tokens
  • low-level form and feedback primitives
  • shared layouts and page shells
  • data-heavy and admin-oriented widgets
  • reusable backoffice visual components

It does not provide:

  • application business logic
  • GraphQL orchestration
  • router orchestration beyond consuming router links where needed

Installation

npm install @plumile/ui

Peer dependencies:

npm install react react-dom i18next react-i18next

If you use components that depend on typed Plumile router links, also install @plumile/router. Applications using another router can use the router-neutral ButtonLink render adapter and AnchorButton.

Main Public Surface

The package entry point groups exports by UI family instead of exposing a single flat mental model.

Theme and styling

  • ThemeProvider
  • BackofficeThemeProvider
  • useTheme
  • theme contracts, tokens, and accessibility helpers
  • sprinkles, stateSprinkles, and shared style recipes such as focusRing, controlFocusRing, disabledControl, surfaceInteractive, interactiveControlSurface, interactiveLinkSurface, ghostIconButton, pillLink, entityReferenceLink, insetFocusRing, truncate, iconBox, iconBoxCompact, loadingShimmer, and visuallyHidden

Primitives and forms

  • Button, ButtonLink, AnchorButton, LinkButton, Input, Textarea, NativeSelect, Checkbox
  • Label, Form, FormField, TextareaField, SelectField, FormGroup. The complete fields generate stable IDs and connect descriptions and errors through aria-describedby.
  • TokenField provides a controlled token editor with Enter/comma commit, IME-safe keyboard handling, Backspace removal, focus recovery, and polite add/remove announcements. Applications retain normalization, validation, ordering, and submission ownership through onTokenCommit and their token state; the draft input is intentionally not serialized as form data.
  • ErrorMessage is the field-level error text primitive. Use it for messages tied to a single control through aria-describedby.
  • FormError is the canonical form-level error block for submit failures and validation summaries inside form surfaces.
  • InlineBanner is the canonical general notice/banner primitive for non-field feedback. It supports info, success, warning, and danger tones, titles, descriptions, actions, dismiss controls, and explicit live-region overrides. Its opt-in focusOnMount contract supports interruptive error summaries without rebuilding focus behavior in applications.
  • EmptyState is the canonical empty-state component. Use variant="framed" for card-backed surfaces, variant="plain" for inline backoffice-style surfaces, density="compact" for dense lists, and tone for neutral, muted, info, success, warning, or danger emphasis.
  • LoadingState and ErrorState provide canonical page, panel, and lazy boundary presentation. Both support plain or framed rendering, compact density, alignment, and long descriptions; ErrorState can render a standard retry action without owning the retry lifecycle.
  • ErrorBoundary contains render failures with a node or render-function fallback, reset callbacks, and resetKey recovery. AsyncBoundary composes that contract with Suspense for lazy and Relay-adjacent views without owning data fetching or product telemetry.
  • ToastProvider, ToastViewport
  • ProgressBar exposes bounded progress semantics and optional visible value text. PaginationControls provides labelled previous/next navigation for cursor- and page-based lists.
  • SliderField and NumberStepper cover labelled bounded numeric controls; applications provide localized value and action labels while the library owns layout, focus, disabled states, and native form participation.

Dialogs and action menus

  • Modal preserves the established controlled API while delegating modal focus confinement, outside inertness, Escape dismissal, scroll locking, and focus restoration to Base UI. Use initialFocus for the entry strategy and finalFocusRef only when a workflow has an explicit return target.
  • Drawer applies the same focus, dismissal, scroll-lock, and restoration contract to a side panel positioned at the start or end of the viewport.
  • ConfirmDialog renders an interruptive alertdialog, focuses its safe cancel action first, supports async confirmation/error states, and accepts returnFocusRef for explicit focus restoration.
  • DropdownMenu is the canonical flat action menu. It provides roving focus, disabled items, typeahead, collision handling, and default/danger tones. Keep grouped navigation menus local until the public contract exposes semantic groups and router-native link items.

Base UI is an internal behavior dependency. Consumers import the styled Plumile contracts above, not @base-ui/react directly.

Layouts and shells

  • Stack, Inline, Grid, and Container provide the token-based layout foundation for vertical rhythm, wrapping horizontal groups, fixed or auto-fitting grids, and centered content widths. Their native div attributes and refs are forwarded without a polymorphic generic API.
  • Heading renders an explicit semantic level from h1 through h6, with optional token-based visual size, weight, tone, and alignment. Text renders a paragraph by default and supports the simple p, span, and div text roots.
  • PageShell, AdminShellLayout, Sidebar, ProfileDropdown (intended for the sidebar footer slot)
  • Surface is the canonical structured surface primitive for titled content, optional descriptions, actions, body content, and footers. It supports div, section, and article roots plus visual variants for brand, neutral, muted, and plain surfaces.
  • SurfaceSection wraps Surface for accessible titled sections and wires aria-labelledby automatically when a title is present.
  • ContentLayout supports optional contentWidth (full or narrow), fillHeight, bodyScroll, and a toolbar slot for list-oriented pages.
  • SplitRowList and SplitRowListItem render a two-column list row with sidebar-like hover and focus treatment. Export splitRowListStyles when a page needs the shared primaryLink class.
  • PropertyList is the neutral semantic definition-list pattern for product and record metadata. It supports split, stack, and responsive grid layouts, plain or surfaced rows, and explicit empty-value labels.
  • ResizableSplitView, PanelShell
  • PageHeader is the generic page heading composition for optional leading, description, metadata, and action slots. BackofficePageHeader remains the compatibility adapter for its narrower historical API.
  • ResourceDetailHeader presents a resource identity, compact metadata, semantic status indicators, and explicit actions. Applications own business tone mapping and provide translated labels for the status and action groups; use the slot-based DetailSummaryHeader for a subordinate h3 summary.
  • PageShellRuntimeProvider, usePageShellRuntime, usePageShellContentClassName, and usePageShellSidePanel provide optional runtime state for layouts where descendant pages register a content class or side panel while the shell stays owned by a parent layout.
  • ResizableSplitView is the canonical split-view primitive for optional, resizable side panels. It supports controlled and persisted widths, start/end panel placement, direction-correct pointer and keyboard resizing, stacked layouts below a breakpoint, and accessible separator semantics.
  • Toolbar, ToolbarGroup, ToolbarSpacer, ToolbarSeparator
  • StepIndicator renders a semantic ordered list for known multi-step flows, including current and completed states; applications retain step labels, navigation, validation, and workflow state. If currentId is absent from a non-empty item set, the first step is the explicit current-step fallback.
  • Disclosure wraps native details/summary semantics for optional content, with plain or outlined presentation and compact or regular density.
  • CompactMetadataList and CompactMetadataListItem provide a wrapping semantic list for terse labels with optional supporting metadata.
  • SettingsLayout for settings-oriented content with local navigation. Its surface and flush presentations and static/sticky sidebar policy cover both framed settings cards and full-height application settings.
  • SegmentedControl is the mandatory single-selection control for display modes and view preferences. Use Tabs instead when each choice owns a tabpanel.
  • Card, PanelShell, ActionPanel, and BackofficeFormSection remain compatible wrappers or specialized compositions on top of the canonical surface primitives.

Router destinations

Components that render router links accept a structured RouterLinkDestination alongside their legacy href or to field:

const closedTasks = {
  pathname: '/tasks',
  filters: { view: { eq: 'closed' } },
  query: { panel: 'summary' },
} satisfies RouterLinkDestination;

<Tabs
  items={[{ id: 'closed', label: 'Closed tasks', destination: closedTasks }]}
/>;

Structured destinations are supported by tabs, sidebars, breadcrumbs, PageShell, relation menus, dashboard links, and interactive InfoTile instances. Their filters are serialized with the destination route schema by @plumile/router; explicit to.search still takes precedence. LinkButton already forwards all router Link props and exports LinkButtonProps for wrappers that need the same contract.

Data-heavy and dashboard components

  • DataTable is the canonical high-level table for static and paginated data.
  • DataTableRoot, DataTableHeader, DataTableBody, DataTableRow, and DataTableEmptyRow expose the same public rendering primitives for advanced table composition without duplicating cell, header, density, breakpoint, empty state, or contained-scroll behavior.
  • VirtualizedConnectionTable is the specialized table for virtualized connection lists and infinite loading. It shares the DataTable primitives for table rendering while keeping virtualization and scroll-trigger behavior separate from the base table API.
  • ResponsiveRecordList adapts the same table columns between table and mobile card layouts. renderAction supplies one action column across both presentations unless the caller already declares an action/actions column; actionColumnLabel overrides its translated header.
  • TechnicalIdentifierValue and TechnicalIdentifierList normalize, abbreviate, display, and copy opaque identifiers. Fingerprints retain their leading and trailing groups; empty values render nothing.
  • CopyableText is the generic copy-with-feedback primitive used by technical identifiers, metrics, and backoffice compatibility facades.
  • BackofficeDataTable composes selection, bulk actions, and toolbar behavior on top of DataTable; virtualized backoffice lists use VirtualizedConnectionTable directly.
  • MetricCard and MetricTileGroup are the canonical KPI primitives. They support metric tones, compact density, copyable values, and configurable responsive tile widths without changing their default rendering.
  • DashboardPanel, DashboardMetricGroup, DashboardQuickActions, and DashboardStatusList provide the canonical visual widgets for dashboard panels, linked metric groups, shortcut lists, and status summaries.
  • StatusSummaryPanel
  • ActivityFeed, TimelineEventRow, InfoTile
  • TimelineEventRow is the reusable dashboard timeline row primitive. It uses the canonical event vocabulary (title, time or timestamp, description, meta, metrics, details, and semantic tone) while keeping relative timestamp rendering available through RelativeTimeText.

Formatting helpers

  • HighlightCode is the general code-display primitive. It supports a badge, copy action, placeholder text, highlighted HTML/React content, and a plain preformatted fallback.
  • MarkdownRenderer always disables raw HTML parsing and supports explicit image policies: render images, keep only their alternative text, or omit them. Applications can therefore render text-only legal and policy content without maintaining a second Markdown component.
  • FormActions owns the wrapped, trailing form-action layout and supports both submit-only and submit-with-cancel forms, including the shared button loading treatment.
  • copyTextToClipboard, copyRichClipboard, and useClipboardCopy provide shared clipboard behavior with rich multi-format writes where browsers support them and text fallbacks everywhere else.
  • BackofficeJsonViewer is the canonical structured JSON viewer for backoffice surfaces. It safely stringifies unknown values, exposes copy and collapse/expand controls, and accepts max-height and label overrides.
  • BackofficePayloadViewer is the canonical backoffice payload viewer for json, markdown, text, and code payloads. Use it inside detail sections or tool output surfaces for empty states, summaries, collapsible details, copyable text/code, markdown rendering, and JSON rendering through BackofficeJsonViewer.
  • MoneyAmount renders a currency amount from amount and currency props with fixed two-decimal formatting.
  • formatCurrencyAmount({ amount, currency }) provides the same formatting for plain-text usage such as charts, table configs, and tooltips.
  • buildUtcDayRange, toUtcDayKey, toUtcDailyCategorySeries, and the mapped time-series helpers provide generic UTC day bucketing and zero-filled chart series without embedding product category names or billing vocabulary.
  • usePersistentBooleanState persists boolean UI preferences such as collapsed panels or sidebars while staying SSR-safe and storage-key agnostic.

Backoffice visual components

  • Badge is the low-level inline visual marker. It supports neutral, info, success, warning, danger, and accent tones plus a loading shimmer.
  • StatusBadge maps semantic status tones to badge tones and can show an optional status dot.
  • Tag is the compact pill component for short labels and optional removable filters. Use title, onRemove, and removeLabel for accessible removable tags.
  • EnvironmentBadge and BackofficeIdBadge remain specialized public badge compositions for environment labels and copyable IDs.
  • Detail badge/value compositions are available for backoffice entity pages: BackofficeStatusMetaBadge, BackofficeStatusGroup, BackofficeDetailFlagTag, BackofficeDetailTaggedValue, BackofficeReferenceValue, and BackofficeEnumLabel.
  • BackofficeKeyValueList is the canonical definition-list renderer for backoffice label/value metadata. It supports surface or plain rendering, split, stack, and grid layouts, custom empty labels, and React node values.
  • spinners and skeletons
  • BackofficeToolbar is the canonical list/table toolbar for search, filters, sorting, actions, and active chips.
  • BackofficeListFilterToolbar composes that toolbar with the canonical filter trigger, active chips, searchable drawer, reset behavior, and keyed session-scoped drawer state. Applications provide filter sections and own only their domain filter values.
  • BackofficeListFooter is the canonical infinite-list footer for status-only loading flows. Its discriminated state covers idle, loading, completion, and retryable incremental errors. Keep load-more status, loaded counts, spinners, and manual load buttons there rather than rebuilding list footers.
  • InfiniteScrollTrigger observes the viewport or an explicit scrollRootRef, keeps a manual keyboard-accessible action, and announces loading and list completion. Use Modal.scrollRootRef for collections inside modal content.
  • BreadcrumbNavigation menus accept either static searchable items or a composed content element. Composed content mounts only while the dropdown is open, so applications can own lazy data loading and pagination without blocking their page or navigation shell.
  • BackofficeEmptyState is a compatibility wrapper around EmptyState with the plain, compact backoffice defaults.
  • BackofficePickerShell, BackofficePickerList, and BackofficePickerRow are the canonical visual primitives for searchable backoffice pickers. They own the search input layout, listbox/option rendering, empty state, and row truncation; application integrations should pass already-resolved picker items and keep manifest, Relay, and domain behavior outside @plumile/ui.
  • filter drawers and confirm dialogs stay separate from picker primitives because their navigation, action, and confirmation semantics differ.
  • backoffice data-table wrappers and detail visual helpers, including BackofficeDetailField and BackofficeDetailSection for generic titled detail sections and copyable field values, plus BackofficeScopeStack and BackofficeAuditMetadataPanel for canonical scope/context and audit metadata sections
  • AuditTimeline is the canonical visual timeline for backoffice lifecycle and audit history. It renders ordered ol/li events with title, time, description, actor, source, meta, metrics, details, density, custom renderEvent, and neutral/info/success/warning/danger tones. Empty timelines render null unless emptyState is supplied.
  • DetailPageTemplate, DetailPageTemplateContent, and ListPageTemplate are the canonical backoffice page templates for detail and list screens.
  • Sidebar, the canonical navigation rail with two states (expanded and collapsed), unified light/dark tokens for public and backoffice surfaces, a fixed Kronex brand header with a collapse control, optional search and footer slots, collapsible section groups, and optional sortable sections for backoffice navigation. SidebarNavigation remains as a deprecated alias.

Breaking changes in this line: BackofficeTableToolbar, TableToolbar, BackofficeFiltersBar, BackofficeLoadMore, BackofficeInfiniteListStatus, BackofficeVirtualizedConnectionTable, BackofficeDetailLayout, DetailPage, DetailPageContent, SegmentedNav, and SectionNav were removed in favor of the canonical components above and Tabs.

For the complete export list, see src/index.ts.

Quick Start

import { Button, ThemeProvider, Toolbar, ToolbarGroup } from '@plumile/ui';

export function ExampleScreen(): JSX.Element {
  return (
    <ThemeProvider defaultMode="light">
      <Toolbar ariaLabel="Screen actions">
        <ToolbarGroup>
          <Button>Save</Button>
        </ToolbarGroup>
        <ToolbarGroup justify="end">
          <Button variant="secondary">Cancel</Button>
        </ToolbarGroup>
      </Toolbar>
    </ThemeProvider>
  );
}

Foundation composition stays explicit and uses the shared spacing and type scales:

import { Container, Grid, Heading, Stack, Text } from '@plumile/ui';

export function ProjectSummary(): JSX.Element {
  return (
    <Container size="5xl">
      <Stack space="lg">
        <Heading level={1}>Project summary</Heading>
        <Text tone="secondary">Current delivery signals.</Text>
        <Grid columns="auto">
          <div>Build</div>
          <div>Tests</div>
          <div>Release</div>
        </Grid>
      </Stack>
    </Container>
  );
}

ThemeProvider stores the public shell preference in plumile-theme-mode. BackofficeThemeProvider stores the backoffice preference separately in plumile-backoffice-theme-mode, so a backoffice can resolve light, dark, or system mode independently inside a public page.

For embedded or nested surfaces, compose ThemeModeProvider with ThemeScope; this keeps mode state independent and scopes theme variables to the wrapper. DocumentThemeClass is the explicit adapter for applications that need the selected class on body or documentElement. All three accept controlled or uncontrolled modes, a storage key, and an optional caller-owned storage adapter.

Custom theme pairs use the public vanilla-extract contract:

import { createTheme } from '@vanilla-extract/css';
import {
  vars,
  type ThemeClassPair,
  type ThemeValues,
} from '@plumile/ui/theme/index.js';

const lightValues = {/* complete token tree */} satisfies ThemeValues;
const darkValues = {/* complete token tree */} satisfies ThemeValues;

export const productTheme = {
  light: createTheme(vars, lightValues),
  dark: createTheme(vars, darkValues),
} satisfies ThemeClassPair;

Package Layout

  • theme/* canonical source of shared design tokens and theme primitives
  • atomic/* low-level reusable React building blocks
  • components/* generic cross-application layouts and widgets
  • backoffice/* specialized data-heavy visual components for admin and backoffice screens

Public Family Owners

The inventory guard derives these families from public source owners. The matching Storybook navigation is the visual catalogue; focused tests remain the behavioral owner. The comments are stable machine-readable reconciliation keys.

| Family | Discoverable owner | | -------------------------------------------- | ------------------------------------------------------------------------- | | Actions | Atomic/Atoms and action-group stories | | Backoffice | Backoffice and Admin stories | | Data display | table, record-list, tile, metric, timeline, and chart stories | | Feedback | banner, empty, toast, spinner, skeleton, and status stories | | Forms | input, checkbox, radio, switch, select, and field stories | | Icons | generated icon exports and icon catalogue stories | | Layout | foundation, shell, surface, card, and panel stories | | Navigation | navigation tabs, interactive tabs, breadcrumbs, sidebar, and menu stories | | Overlay | modal, dialog, popover, and preview stories | | Theme | public/backoffice theme provider stories | | Typography | heading, text, Markdown, and code stories | | Utilities | remaining focused public helpers and their owner stories |

Validation Notes

  • public UI behavior should be covered by targeted tests for stable components
  • visual breadth is large, so documentation and examples should stay organized by component families rather than exhaustive component-by-component prose
  • Storybook stories are useful for visual review, but they do not replace behavioral tests for stable public components
  • npm run ui-css:check from the repository root records and enforces the published stylesheet's raw, gzip, and rule-count budgets after a package build
  • npm run ui-contracts:audit emits the root export, known-consumer, and local owner-evidence matrix as JSON; npm run ui-contracts:check also rejects consumer imports absent from the public root contract
  • npm run ui-sprinkles:audit emits every known Sprinkles helper, property, responsive condition, and unresolved dynamic call as JSON; npm run ui-sprinkles:check verifies that the audit remains executable
  • styling should prefer shared sprinkles and theme style recipes; raw vanilla-extract style() is reserved for selectors, pseudo-elements, keyframes, container queries, CSS variables, calc(), color-mix(), or highly specific grid/layout cases
  • shared UI styling is sprinkles-first: add recurring token-sized values and reusable interactive/link/icon classes to theme/styleRecipes.css.ts before creating local one-off style() blocks

Limitations

  • this package assumes Kronex theme tokens and styling conventions
  • it is intentionally opinionated for backoffice and admin-style interfaces
  • it does not try to be a framework-agnostic design system
  • some components assume other Kronex packages, especially @plumile/router

Related Docs