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

@sagtech_llc/ui

v2.4.0

Published

SagTech UI component library with Storybook

Readme

@sagtech_llc/ui

Internal React component library for SagTech products. Dark-mode-only, Tailwind v4, React 19 / Next 15+.

Storybook covers every component with live examples — run pnpm dev and open localhost:6006.

Building a new project with this library? See COMPONENTS.md — full component catalog with usage examples, designed for AI agents to quickly find the right component.

Migrating an existing React app to this library? See docs/AI_MIGRATION_PROMPT.md — a paste-ready prompt for Claude / Cursor / Copilot that walks an AI assistant through a phased, non-breaking migration (setup → forms → overlays → data → charts), with picker rules, worked examples, and anti-patterns. It also ships inside the package at node_modules/@sagtech_llc/ui/docs/AI_MIGRATION_PROMPT.md.


Install

# Published to public npm — no auth or registry config required.

pnpm add @sagtech_llc/ui

For local development against a checked-out copy:

# Clone as a sibling, depend via workspace:* or file:, then:
cd sagtech-ui
pnpm install
pnpm build

Peer dependencies

Required (install always): react@^19, react-dom@^19, classnames, framer-motion.

Optional (install only if you use the relevant component):

| Peer | Required by | |---|---| | next@^15 | Steps, InfoTabs, Point, CardWrapper (can be bypassed via <SagtechUIProvider imageComponent={...} linkComponent={...}>) | | react-hook-form | Form + FormField/FormLabel/FormControl/FormError/FormHint | | react-international-phone, libphonenumber-js | PhoneInput | | swiper | Timeline | | @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities | SortableList | | @tanstack/react-virtual | VirtualList | | @tiptap/react, @tiptap/core, @tiptap/starter-kit | RichTextEditor | | @tiptap/extension-mention, @tiptap/suggestion | RichTextEditorcreateMentionExtension / createSlashCommandExtension presets | | @tiptap/extension-image | RichTextEditorcreateImageUploadExtension preset | | @xyflow/react | VisualGraphEditor | | react-resizable-panels | PanelGroup / Panel / PanelResizeHandle | | three, @react-three/fiber, @react-three/drei | Globe3D, Scene3D, Mindmap3D | | three, @react-three/fiber, @react-three/drei, react-force-graph-3d | Network3D (in addition to the three packages above) |

Tokens and fonts

Import the design tokens (raw CSS @theme block) once at the top of your global stylesheet:

/* app/globals.css or similar */
@import '@sagtech_llc/ui/tokens';

The token scale covers: colors (black_1..4, white_1..4, grey_1..4, pr_purple, sec_purple, pr_blue, sec_blue, success, warning, error), spacing (4/6/7/8/10/11/12/15/16/20/23/24/30/32/40/48/52/56/60/62/64/72/88/117/157 px), z-index overlay layers (--z-dropdown/popover/modal/drawer/toast/tooltip), breakpoints, fonts, radii, shadows.

Typed constants are also exported as tokens:

import { tokens } from '@sagtech_llc/ui';
tokens.colors.pr_purple; // '#6D3EF1'
tokens.spacing['16px']; // '16px'

Fonts — --font-manrope, --font-orbitron, --font-roboto. In Next.js, wire via next/font and expose on :root. In non-Next projects, install @fontsource/manrope|orbitron|roboto and set the vars yourself.

Dark mode only. No light-mode equivalents in the palette; no prefers-color-scheme handling.

Quick start

import {
  SagtechUIProvider,
  ConfirmProvider,
  Toaster,
  Button,
  useConfirm,
  toast,
} from '@sagtech_llc/ui';
import Link from 'next/link';

export default function Root({ children }: { children: React.ReactNode }) {
  return (
    <SagtechUIProvider linkComponent={Link}>
      <ConfirmProvider>
        {children}
        <Toaster position="top-right" />
      </ConfirmProvider>
    </SagtechUIProvider>
  );
}

function DeleteButton({ onDelete }: { onDelete: () => Promise<void> }) {
  const confirm = useConfirm();
  return (
    <Button
      text="Delete"
      variant="danger"
      buttonSize="small"
      onClick={async () => {
        const ok = await confirm({
          title: 'Delete this item?',
          description: 'This action cannot be undone.',
          variant: 'danger',
          confirmText: 'Delete',
        });
        if (ok) {
          await onDelete();
          toast.success('Deleted');
        }
      }}
    />
  );
}

Imports & bundle isolation

The main entry re-exports everything, so import { ... } from '@sagtech_llc/ui' keeps working for all components. The package is marked "sideEffects": false, so a tree-shaking bundler (Webpack/Turbopack/Vite/Rollup) drops anything you don't import — importing only what you use keeps heavy peers (notably three) out of your bundle. CSS is shipped separately via the ./tokens export, so it is never tree-shaken away.

For explicit isolation of the heavy families, two additive subpath exports are available alongside the main entry:

// Main entry — everything (still works, non-breaking)
import { Button, AreaChart, Globe3D } from '@sagtech_llc/ui';

// 3D / WebGL family only (pulls in three + @react-three/* peers)
import { Network3D, Globe3D, Scene3D, Mindmap3D } from '@sagtech_llc/ui/3d';

// The 12 canvas charts only (no extra peers)
import { AreaChart, BarChart, GaugeChart } from '@sagtech_llc/ui/charts';

Reaching for the subpath makes the dependency boundary explicit and keeps the 3D peers off any code path that imports from @sagtech_llc/ui/3d nowhere. size-limit budgets guard each entry (main / icons / 3d / charts); run pnpm check:size to verify locally — CI runs it on every push and PR.


Component overview

Foundations

| Component | Purpose | |---|---| | Typography | Polymorphic text. tag: h1..h4/p/span/label (+htmlFor); type: BodyXL..BodyXS/Labels/LabelsS/Info/InfoBold/Buttons/ButtonsS/ButtonsBold/M3HeadlineSmall/MetricsTitle/MetricsXL/TabInfoTitle/HeroSubtitle/DisplayXL/DisplayL/SectionTitleL/SectionTitleM/SectionTitleS. | | Icon | 150+ icons (nav-chrome, status, tech-stack, social). <Icon icon="call" size={24} color="#6D3EF1" />. | | Skeleton | Loading placeholder + presets SkeletonText/SkeletonAvatar/SkeletonCard/SkeletonTable/SkeletonList. | | Divider | Horizontal/vertical with variant: 'solid' \| 'dashed'. | | KBD | Keyboard-shortcut chip group. <KBD keys={['Cmd', 'K']} size="sm" />. |

Form controls

| Component | Purpose | |---|---| | Button | variant: 'primary' \| 'secondary' \| 'danger' \| 'tabButton' \| 'tabButtonWhite', buttonSize: 'small' \| 'large' \| 'tabSize', loadingType, disabled. | | Input | Dark text input with state='default'\|'active', isError + errorMessage (wired to aria-invalid/aria-describedby), static label + floating floatingLabel. | | TextArea | Same contract as Input, multi-line. | | Checkbox | Controlled; label rendered inside a native <label>. | | Toggle | checked + onChange(boolean), size: 'sm' \| 'md'. | | Switch | Labeled form switch — checked + onCheckedChange(boolean), label slot, disabled. Use when you need an inline <label> association; Toggle for the bare control. | | Slider / RangeInput | Single-thumb Slider and two-thumb RangeInputmin/max/step, marks, keyboard nav, RTL, ARIA slider. | | TimePicker | Standalone hours + minutes picker (timeStep default 5). Extracted from DatePicker.showTime; compose either independently. | | ColorPicker | HSL + alpha editing via reused Slider inside a Popover, validated hex input, preset swatches. | | RadioGroup | options: { label, value }[] + value + onChange. | | SelectInput | Controlled select with optional multi-select. Full keyboard nav (Arrow/Home/End/Enter/Esc, open-to-selected). Deprecated onSelect alias. | | Combobox | Searchable single/multi select with async-options support, portal dropdown. | | Form + FormField / FormItem / FormLabel / FormControl / FormError / FormHint | react-hook-form wrappers. Works with any of the inputs above. | | DatePicker | Controlled date with optional showTime (hours+minutes, timeStep default 5). | | DateRangePicker | Same as DatePicker but { start, end }. Shares calendar helpers. | | Dropzone | Basic drag-and-drop zone, returns File[] via onDrop. | | FileDropzone | Opinionated uploader: controlled files: FileUploadItem[] with per-file status/progress/errorMessage, image preview, retry, maxFiles/maxSize. | | Attachment | Single-file inline upload (paperclip-style). | | PhoneInput | International phone input with auto country-detection (detectCountry() returns CountryIso2). | | TagInput | Token/tag editor with comma + Enter to add. | | DropdownMenu | Trigger + menu items (danger, disabled, divider). Full keyboard nav (Arrow/Home/End/Enter/Esc, type-ahead). | | SearchBar | Debounced search input. | | InlineEdit | Click-to-edit. Enter/Esc to save/cancel, multiline with Cmd+Enter, validate, async onSave. | | VariablePicker | Modal with searchable + source-filtered list of template variables. Double-click / Insert returns the picked token. | | RichTextEditor | TipTap wrapper with bold/italic/strike/heading/list/quote/code/undo/redo toolbar. Extensions prop for custom nodes. Extension presets (all tree-shakable, exported from main entry): createMentionExtension({ items, char }) (@-trigger mentions, sync or async items), createSlashCommandExtension({ commands }) + defaultSlashCommands (H2/H3/lists/quote/code, built on @tiptap/suggestion), createImageUploadExtension({ upload, accept, maxSize, onError }) (paste/drop with file-boundary validation, inline base64 fallback) + validateImageFile helper. | | SegmentedControl | iOS-style segmented toggle group. Controlled value/onChange, sizes, full-width, disabled, keyboard arrow navigation. |

Layout & overlays

| Component | Purpose | |---|---| | Modal | Portal dialog with size: 'sm' \| 'md', optional title / footer slots. Full a11y — role="dialog", aria-modal, focus-trap (Tab cycles), autofocus first focusable, focus-restore on close. Stack-aware — nested modals get correct z-index and Escape closes topmost. | | Drawer | Side panel (position: 'left' \| 'right') with backdrop, animated via framer-motion. | | ConfirmDialog + ConfirmProvider + useConfirm + useConfirmWithNote | Imperative await confirm({ … })Promise<boolean>. useConfirmWithNote adds a TextArea and returns { confirmed, note }. | | CommandPalette + CommandPaletteProvider + useRegisterCommand | Cmd+K palette. Provider registers hotkey + collects commands from the subtree via useRegisterCommand. | | Sidebar | Desktop nav with items, collapsed, optional header / footer. | | CardWrapper | Bordered container with gradient stroke + optional href (hover-lift, purple glow). | | Container | Page centering with size: 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'. | | SectionTag | Small badge-like section label. | | Breadcrumbs | Nav crumb trail. | | CookieBanner | Accept/Decline banner with local cookie write. | | Popover | Trigger + floating content (position + align). Escape closes, focus returns to trigger. | | Tooltip | Hover/focus tooltip. | | Sheet | Side panel (left/right/top/bottom) with full ModalStack stacking, focus-trap, scroll-lock. Use over Drawer when stacking with other sheets/modals matters. | | BottomSheet | Mobile-first bottom drawer with drag-to-dismiss + multi-snap-points (framer-motion drag="y"). | | FAB | Floating action button anchored to viewport (bottom-right/bottom-left/top-right/top-left), optional extended pill with label, loading state. | | Toolbar (+ Toolbar.Separator / ToolbarSeparator) | Action bar — group of buttons with arrow-key roving focus, role="toolbar", optional separators. | | Carousel | Peer-free slider on CSS scroll-snap. Autoplay (honors prefers-reduced-motion), dots/arrows, keyboard nav, RTL. No swiper peer required. | | PanelGroup (+ Panel / PanelResizeHandle) | Resizable split layout — horizontal/vertical, drag handles, optional persistence. Wraps react-resizable-panels (optional peer). |

Data display

| Component | Purpose | |---|---| | Table | Simple table with columns + data, optional local sort. Generic over row type. | | DataTable | Richer version — controlled sort, selection (checkbox column), sticky header, loading skeleton, empty state. | | Badge | variant: 'filled' \| 'outlined' \| 'subtle', color, size, optional dot. | | Avatar / AvatarCard | Picture + initials fallback. Card variant adds name + role. | | AvatarGroup | Overlapping avatar stack with a +N overflow counter (max cap). | | TreeView | ARIA tree — expandable nodes, roving tabindex + type-ahead, lazy-loaded children, controlled-first, RTL. | | Calendar | Standalone date grid (Monday-first, RTL) extracted from DatePicker. Use directly for inline date selection. | | Tabs | In-app tab navigation (controlled). | | InfoTabs | Marketing tabs with icons + rich content panes. | | Timeline | Swiper-based horizontal image timeline. | | GanttTimeline | Project Gantt: scale day/week/month, ISO-week labels, lane grouping with automatic sub-row packing when tasks overlap, optional detail-modal via renderItemDetail. | | Steps | Presentational stepper with animated progress line. | | Wizard + useWizard | Multi-step flow. Compound (Wizard.Root/Progress/Content/Footer) + hook for custom layouts. | | Point | Small dot + label marker. | | ResultPill | Chip showing a labelled result (status + value). | | Image / LazyImage | Plain <img> wrappers with shimmer placeholder + error fallback. | | Pagination | Compact paginator with next/prev + page-jump. | | StatCard | KPI card with label, value, trend indicator. | | DataTable | (see above) | | Rate | Read-only N-star rating with auto or explicit tone. | | FaqDropdown + FaqList | Accordion FAQ. | | Timeline | (see above) | | SortableList | Drag-and-drop reorderable list on @dnd-kit. Vertical/horizontal/grid. | | VirtualList | Windowed list on @tanstack/react-virtual for 10k+ items. | | VisualGraphEditor | ReactFlow wrapper — nodes/edges/handles/minimap/controls + readOnly. | | AreaChart | Canvas-based stacked/non-stacked area chart with optional gradient fill, hover crosshair + tooltip. | | BarChart | Canvas bar/column chart — vertical/horizontal, stacked, grouped. | | HeatmapChart | Discrete cell matrix with linear color ramp (default pr_purplesec_purple). | | RadarChart | Polygon chart with grid rings + axis labels. | | SparklineChart | Tiny inline trend line (default 80×24) with tone: 'success'\|'warning'\|'error'\|'neutral'. Use inside StatCard. | | ScatterChart | Bubble scatter with optional per-point size. | | GaugeChart | Half-circle speedometer with min/max/thresholds. | | SankeyChart | Layered flow diagram (no d3-sankey peer — layout inlined on canvas). | | TreemapChart | Squarified treemap with optional padding. | | FunnelChart | Vertical/horizontal funnel showing conversion % per stage. | | Stepper | Richer step indicator — per-step status: 'pending'\|'active'\|'complete'\|'error', description, click-to-jump, vertical or horizontal. |

3D / WebGL

| Component | Purpose | |---|---| | Network3D | 3D force-directed network graph backed by react-force-graph-3d. | | Globe3D | Interactive globe with raised lat/lng markers (@react-three/fiber + @react-three/drei). | | Scene3D | Generic <Canvas> wrapper for ad-hoc 3D scenes (orbit controls + default lighting). | | Mindmap3D | Hierarchical 3D mindmap rendered as nodes + edges around a sphere. |

Feedback

| Component | Purpose | |---|---| | Alert | Inline banner (info/success/warning/error), optional title/body/icon/action/close, optional autoDismiss ms. role="alert" for error, role="status" otherwise. | | Banner | Page-level sticky banner (top/bottom). Variants like Alert but persistent and viewport-anchored — distinct from inline Alert and legal CookieBanner. | | Spotlight | Onboarding/feature highlight — clip-path-style cutout around a targetRef + tooltip card with optional Next/Skip + step counter. | | Toaster + toast | Global toast API — toast.success()/.error()/.info()/.warning()/.loading() + toast.promise(). Compact layout, auto-sized to content. | | NotificationCenter | Bell icon + dropdown with notifications list, badge count, mark-as-read / mark-all-read / clear-all. Prop-driven (consumer owns data fetching). | | EmptyState | Empty placeholder — variant: 'inline' \| 'card', optional icon/description/action. | | ProgressBar | Determinate bar with variants + optional animation. | | CodeBlock | Syntax-highlighted code (ts/tsx/js/jsx/json/bash/css/html built-in; plug Prism/Shiki via highlight prop). Copy button, line numbers, maxHeight. | | AnimationButton | Branded pill-style CTA with hover expand (desktop only). | | CookieBanner | (also in Layout) | | SliderArrow | Reusable nav arrow for Swiper carousels. | | LineChart / DonutChart | Canvas/SVG charts (theme-aware) with the SagTech palette. |

Providers & hooks

| Export | Purpose | |---|---| | SagtechUIProvider | Injects linkComponent / imageComponent slot replacements so non-Next projects can drop-in the library without aliasing next/image etc. | | ConfirmProvider | Root provider for imperative confirm modals. | | CommandPaletteProvider | Global Cmd+K palette provider. | | useWindowSize, useDeviceType, useIntersectionObserver, useOutsideClick, useModals, useStatusColor | Utility hooks. | | useRovingTabindex, useTypeahead | A11y primitives behind TreeView / list-style keyboard nav — reusable in custom widgets. | | useThemeColors | Reads the active palette from CSS custom properties and re-reads on data-theme change. Powers theme-aware canvas charts; usable in any canvas/SVG renderer. | | useConfirm, useConfirmWithNote | Imperative dialog APIs. | | useCommandPalette, useRegisterCommand | Register/open command palette. | | useWizard | Stand-alone hook (with Wizard compound). |

Icons

Icons live at @sagtech_llc/ui/icons:

import { content as iconContent, type IAvailableIcons } from '@sagtech_llc/ui/icons';

Or render via the <Icon> component: <Icon icon="menu" size={20} color="#CDCDD0" />. Available keys include app-chrome (menu, plus, edit, trash, eye, filter, search, settings, calendar, users, document, lock), status (info, warning, error, success, checkCircle, alertTriangle), navigation (arrow, chevrondown, chevronLeft, chevronRight, close, paginationArrow), and a large tech-stack catalogue (React, TypeScript, PostgreSQL, Docker, AWS, OpenAI, Anthropic, …).


Scripts

| Command | Purpose | |---|---| | pnpm dev | Storybook dev server on port 6006 | | pnpm build | tsup build → dist/ (ESM + CJS + types). Runs generate:tokens via prebuild | | pnpm build-storybook | Static Storybook build | | pnpm test | Vitest run (happy-dom + React Testing Library, 164 tests) | | pnpm test:watch | Watch mode | | pnpm typecheck | tsc --noEmit | | pnpm lint | ESLint | | pnpm generate:tokens | Parses src/tokens/theme.csssrc/tokens/tokens.ts (typed constants) | | pnpm check:size | size-limit budgets for the main / icons / 3d / charts entries (also run in CI) |

Docs

  • docs/ROADMAP.md — completed + planned work with audit references
  • docs/API_CONVENTIONS.md — callback-naming, prop-shape, ref-forwarding rules
  • docs/MIGRATION.md — breaking changes per version + package-name migration
  • docs/COMPONENT_PICKER.md — shortcut for choosing between Dropzone/Attachment/FileDropzone, Tabs/InfoTabs, Modal/Drawer/CommandPalette, Toast/Alert/NotificationCenter, etc.
  • CLAUDE.md — agent-readable overview for Claude Code / other assistants

Publishing

Tag-driven via .github/workflows/publish.yml:

  1. Bump version in package.json on main.
  2. git tag v1.0.0 && git push --tags.
  3. CI verifies the tag matches package.json#version, builds, and publishes to public npm (@sagtech_llc scope).

Tags that don't match package.json#version fail the publish step.