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

@tabcommerceio/tabui

v0.1.5

Published

Standalone admin UI component library, demoed in Storybook.

Readme

@tabcommerceio/tabui

A standalone admin UI component library, demoed in Storybook.

It was forked from apps/irodia/packages/web/console-ui and is now maintained independently: there is no shared code, no shared build, and no sync process back to the original. Changing one side never changes the other.

What is in here

  • src/components/* — components with their own CSS, tests and stories
  • src/screens/* — whole-page specimens composed from those components
  • src/styles/* — design tokens (tokens.css), the CSS entry (globals.css) and the Tailwind preset (tabuiPreset)
  • src/lib/cn.ts — the cn() class merger

Development

pnpm install
pnpm storybook      # http://localhost:6007

Port 6007 keeps Storybook clear of console-ui's 6006 if both run at once.

Scripts

| script | what it does | | --- | --- | | pnpm storybook | Storybook dev server on 6007 | | pnpm build-storybook | static Storybook into storybook-static/ | | pnpm build | library build into dist/ via tsup (cjs + esm + d.ts) | | pnpm dev | tsup in watch mode | | pnpm test | vitest run | | pnpm typecheck | tsc --noEmit over src and .storybook |

Consuming it

Install the library and its React and Tailwind CSS peers:

npm install @tabcommerceio/tabui react react-dom tailwindcss
import { Button, Card, Page } from "@tabcommerceio/tabui"
import "@tabcommerceio/tabui/styles.css"

Tailwind consumers extend the preset:

import { tabuiPreset } from "@tabcommerceio/tabui/preset"

export default { presets: [tabuiPreset], content: [...] }

Design reference

The visual language tracks the Shopify admin. The current values were read off a live admin session (Polaris 25.98, September 2026) rather than copied from documentation, so they include the 2025-26 redesign:

| | before | now | | --- | --- | --- | | app frame | light canvas, full-width top bar | near-black #0a0a0a chrome, no top bar, content on an inset white sheet at 16px | | navigation | 240px light column | 220px dark column holding brand, search, nav, Settings and the account row | | fields | 1px border + 2px offset outline on focus | no border, no outline — one box-shadow stack per state | | buttons | 8px radius, bevelled | pill, flat secondary, lit primary | | cards | 12px radius + 1px ring | 20px, four-layer soft shadow | | controls | 8px radius | 12px (inputs, selects, menu items, nav) | | popovers / dialogs | 12px / 16px | 16px / 24px | | text | #303030 / #616161 | #101010 / #4a4a4a | | borders | #8a8a8a / #e3e3e3 | a single hairline #dddddd | | link / focus | #005bd3 | #1650d0 / #5083f0 | | status | muted teal + amber | lime success #b3f782, orange warning | | page titles | 18px semibold | 13px / 500 — the admin de-emphasised them | | weights | optical 450 / 550 / 650 | plain 400 / 500 / 600 (no 700) |

Shell anatomy

ConsoleShell mirrors the admin's own frame. There is no utility bar: the navigation column owns everything except the page.

.tabui-Shell                     grid, 220px + 1fr, background #0a0a0a
├── .tabui-Sidebar               grid: header / search / nav / footer
│   ├── .tabui-Sidebar__Header       brand + collapse control      48px
│   ├── .tabui-Sidebar__Search       a button dressed as a field   28px
│   ├── .tabui-Sidebar__Nav          the only part that scrolls
│   └── .tabui-Sidebar__Footer       Settings, then the account row
│       └── .tabui-Sidebar__Account  store switcher + help + notifications
└── .tabui-Workspace             the sheet: white, 16px, inset 4px
    ├── .tabui-Workspace__Chrome     save-bar slot; 0px until a page claims it
    └── .tabui-Workspace__Content    the scrollport

The nav group with id: "system" is pinned into the footer rather than scrolling with the rest, which is where the admin keeps Settings. Below 768px the column becomes a drawer and the sheet goes full bleed, growing a header strip for the drawer's trigger.

Page still reaches the chrome strip through useConsoleChromeSlot(); only the node's position moved, so the save bar now floats at the top of the sheet instead of in a bar above it.

Floating surfaces

Popovers, dropdown menus, selection menus, the column menu, the store menu and the date range picker all draw the same surface, because the admin does:

white · 16px radius · no border · 4px padding · --p-shadow-popover
items  12px radius · 4px 6px · 32px min-height · 13/20 regular
       hover #f2f2f2 · pressed / selected #ebebeb

Reach for --p-shadow-popover rather than writing a shadow; the one-pixel ring is the shadow's last layer, so nothing needs a border as well. (Before this pass there were four different treatments, and the dropdown drew both a border and a ring.)

Fields

A field is drawn entirely with box-shadow — no border and no outline. That is what the admin does, and it matters: the box never changes size between rest, hover, focus and error, and the focus halo can bleed outside the control instead of being clipped to an outline rectangle. The stack lives in --p-shadow-input{,-hover,-focus,-error,-error-focus,-disabled}.

Hover is scoped with :hover:not(:focus-within). A field is hovered and focused the instant you click into it, and the hover selector carries more classes than the focus one, so without that guard hover wins the cascade and the focus ring only appears once the pointer leaves.

Date range

DateRangeSelect is the admin's reporting range control: a preset rail beside a two-month calendar, with the staged range summarised above Cancel / Apply. Nothing is reported until Apply, so dismissing the popover always leaves the merchant where they were, and the trigger keeps naming the committed range while a draft is in progress. Presets are data — pass your own presets, each with a resolve(today) — and the trigger names the preset whenever the committed range matches one. Use variant="filled" to give the trigger a surface background when it sits directly on the page canvas; the default plain trigger stays transparent.

The rail ends with Custom range, which is a mode rather than a preset: touching the calendar or typing in either endpoint switches to it, and it stays custom even if the dates drift back onto a preset. In custom mode the range summary gives way to two endpoint fields.

Those fields read as dates and edit as dates. At rest they show August 3, 2026; on focus they swap to 2026-08-10, which is the only shape they accept — the admin does the same, and it is what lets the field be strict about input. Anything that is not a digit or a dash is dropped as it is typed, the value is capped at ten characters, and on commit the date must survive a round trip (so 2026-02-31 is refused rather than rolling into March) and fall inside the allowed range. A rejected edit leaves the committed date alone.

Tokens live in two layers in src/styles/tokens.css:

  1. --p-* — the Polaris surface the components already consume, so a rule written as var(--p-color-text) picks up Shopify's colour untouched.
  2. --tabui-* — the public, renameable surface the Tailwind preset and the shell read; it resolves through layer 1.

Every hard-coded fallback in the components matches the token beside it, so the library still renders correctly if tokens.css is never imported.

Naming

The design-token and class prefix is tabui, not console:

  • CSS variables — --tabui-color-surface, --tabui-radius-md, --tabui-font-sans
  • component classes — tabui-Page, tabui-CartEditor, tabui-Sidebar__Nav
  • Tailwind colors — bg-tabui-surface, text-tabui-text-subdued

The React API is deliberately unchanged from the fork point, so component names, props and exports still match console-ui one-for-one — including ConsoleShell and CONSOLE_NAV. Renaming those is a separate pass.

src/screens/* are Irodia-flavoured page specimens carried over with the fork. They are demo material, not product truth; delete or rewrite them freely.