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

@ware-square/components

v0.1.2

Published

Shared React component library for `@ware-square` projects. Being built up by porting the common App "shell" from [Binorama](https://github.com/justinware/binorama), plus other reusable primitives as they're extracted from that app.

Readme

@ware-square/components

Shared React component library for @ware-square projects. Being built up by porting the common App "shell" from Binorama, plus other reusable primitives as they're extracted from that app.

Porting philosophy

  • State-agnostic: ported components take plain props (and, where needed, their own local useState) instead of reading a Zustand store directly. Each port re-maps the original component's store usage to callback/value props, so the state layer is swappable per consuming app.
  • Number-system logic excluded: anything under Binorama's BaseView hierarchy (numeral system input/breakdown/visualization/explainer) is out of scope for this package — it's product logic specific to Binorama, not generic shell chrome.
  • Copy is prop-driven: components that used to hardcode Binorama's name/tagline/links (Footer, AboutDialog) take that content as props instead, so they read as generic across future Ware Square tools.
  • Binorama itself is untouched: porting is copy-and-adapt, not move-and-delete. Binorama keeps its own local copies of everything until it's ready to actually switch over to this package.
  • The full Binorama Shell component (the thing that composes all of this) is intentionally not ported yet — it has more dependencies and concerns to work through, and may end up as its own package. It'll come after the individual components are settled.
  • String union types get named constants, not inline literals — see the root CLAUDE.md for the pattern (ThemeMode, ViewToggleValue, SlidingPanelPosition all follow it). Use the exported constant everywhere the value is produced or compared, including in tests.

What's here

Grouped by functional area rather than one flat folder:

  • hooks/useIsMobile/useIsCompact (breakpoint match hooks) and the useMatchesMaxWidth/BREAKPOINT_XS/BREAKPOINT_MD they're built on. Plain hooks, no Zustand — ported as-is per the house rule that a non-Zustand hook travels with whatever component needs it rather than being lifted to a prop. Not yet consumed by anything else in this package; ported ahead of need since they're generic and small.
  • icons/SizedIcon (renders a lucide icon at a --scaling-aware size) and shared icon size constants.
  • overlays/IconPopover, a generic icon-triggered popover.
  • theme/ThemeModeToggle, AccentPickerPanel, PaletteMenu.
  • layout/ColumnDivider, a divider between two swappable columns with an optional swap control. (Simplified from Binorama's SystemDivider — its "=" badge was positioned against numeral-system digit-row geometry that doesn't generalize outside that layout, so it was dropped here; Binorama keeps its own richer version locally.)
  • navigation/Navigation (top app bar, with centerSlot/endSlot extension points for app-specific controls like a view toggle or settings menu that aren't part of this package), Footer, AboutDialog, LinkIconButton.
  • toggle/ViewToggle, the rolling-arrow / sliding-underline two-way switch (Binorama's math ↔ table view control). Ported generic: it takes an icon + tooltip for each of viewA/viewB, a value: 'a' | 'b', and an onChange — it has no idea what "A" and "B" mean, so it's reusable for any two-way view switch. disabled is a plain prop too; the original's mobile/no-value disabling logic was Binorama-specific and stays there.
  • panels/SlidingPanel + SlidingPanelGroup, the generic "hub and one sub-panel" construct behind Binorama's settings popover: a root panel and any number of named sub-panels, each only ever entered from root and exited back to it, sliding in the same way SettingsMenu's Theme & Accent panel does. getSlidingPanelPosition(panelId, activePanelId) is the pure function that decides each panel's active / off-left / off-right position — own the activePanelId state yourself (see SettingsMenu for the pattern) and this construct is reusable for any app's own setting group + sub-menu, not just this package's.
  • settings/SettingsMenu, SettingsRow, SettingsLinkRow. SettingsMenu only covers the settings that are actually generic across apps: Appearance (light/dark) and Theme & Accent (built on panels/ + theme/AccentPickerPanel). It takes children for anything app-specific — rendered after a separator, and only when given — so an app supplies its own rows built from the exported SettingsRow/SettingsLinkRow and gets identical layout for free. (Binorama's exponent-notation and explainer-playback-speed rows are exactly that kind of app-specific content now — they stay in Binorama, passed in as children, rather than being ported here.)

The click-away/Escape-to-close behavior on SettingsMenu (and every other IconPopover-based menu) comes from Radix's Popover for free — nothing bespoke to port. SettingsMenu also takes a plain onClose callback so a consumer (and eventually a shared Shell coordinating multiple menus) can hook into that dismissal.

No build step: the package ships raw TypeScript (main/exports/types all point at .ts/.tsx files under src/). This works because every intended consumer is a Vite or Bun project that already transpiles its dependencies' TS — see the root README before publishing anywhere that assumption doesn't hold.

Depends on @ware-square/brand for the Accent type/ACCENTS list (used by theme/) — that package was renamed from @ware-square/logo; see its own README/CHANGELOG.

Testing

Component tests use Vitest + React Testing Library (bun run test, or bun run test from the repo root to run every package's tests). Config lives in vitest.config.ts (jsdom environment, pool: 'vmThreads' so the suite reuses one jsdom instance per worker instead of paying setup cost per file) and src/vitest.setup.ts (jest-dom matchers, plus stubs for browser APIs jsdom doesn't implement — ResizeObserver, pointer capture, scrollIntoView — that Radix Themes' Popover/Dialog/Tooltip touch when opening/closing).

Every test renders through src/test-utils.tsx's render (not @testing-library/react's own) — it wraps the tree in Radix's <Theme>, which Tooltip/Popover/Dialog require as context even outside of visual styling. rerender from that helper re-wraps for the same reason.

Test IDs: every component takes an optional testId prop (defaulting to its own kebab-case name, e.g. Navigation'navigation') rendered as data-testid. Sub-parts are suffixed off that base — ${testId}-title, ${testId}-trigger, ${testId}-swatch-${color}, etc. — and a parent composing a named child instance overrides the child's testId to keep the hierarchy readable, e.g. Navigation renders its PaletteMenu with testId="navigation-palette-menu", so its swatches resolve to navigation-palette-menu-swatch-cyan. Repeated list items (footer/about-dialog links) are suffixed by index rather than a value, since hrefs aren't safe id fragments.

Usage in a consuming project

bun add @ware-square/components
import { Footer, Navigation } from '@ware-square/components';

License

UNLICENSED for now — set an explicit license before publishing publicly.