Skip to content

qeetgroup/qeetrix

Repository files navigation

🎨 Qeetrix

The Qeet Group design system — one package, every surface

Premium · Accessible · Token-driven · Built on Base UI + Tailwind v4


npm CI React 19 Tailwind CSS v4 Base UI Storybook 10 Bun Biome

🚀 Install · 🏗 Architecture · 🧩 Components · 🎨 Tokens · 🌍 i18n & motion · 📖 Storybook · 🚢 Release


🧩 140+ components 📦 1 install 🎨 WCAG-AA tokens 🌗 Light + dark 🌍 i18n + RTL ⚛️ React 19
shadcn + Base UI @qeetrix/ui OKLCH · Style Dictionary .dark class 6 blocks · 5 brands Tailwind v4

Status — v1.0.0, live on npm. 🎉 The first stable release: 140+ components, 6 composable blocks, an i18n + motion layer, and status color-token triads — all in a single package. Tokens, brand, and blocks are folded into @qeetrix/ui; the API is stable (breaking changes now require a major bump). Already a production dependency of Qeet ID (admin · login · website), qeet-docs, qeet-notify, and qeet-logs.


✨ Why Qeetrix

📦 One install, everything in it @qeetrix/ui ships components + design tokens + brand + blocks + i18n — no peer packages to wire up
Accessible by construction Built on Base UI (WAI-ARIA APG behavior) + Vitest/axe on every interactive component; visible focus, reduced-motion, AA contrast
🎨 Token-driven theming W3C DTCG JSON → Style Dictionary → CSS + JSON; OKLCH colour, light/dark via the .dark class, 5 per-product brand overlays
💎 Premium by default Layered elevation, refined focus rings, tasteful hover-lift micro-interactions, self-hosted Qeet + Fira Code fonts
🌍 Global-ready Optional I18nProvider (locale + {var} interpolation) composes with DirectionProvider for RTL
🌗 First-class dark mode Every component themed through semantic tokens — no hard-coded greys
🏢 Enterprise breadth Data tables, command palette, rich-text editor, charts, sidebar shells, date/time pickers, QR codes, guided tours, and more
🧱 Consistent foundation Shared cva + cn() conventions, data-slot hooks, tree-shakeable named exports
🔒 Quality-gated Typecheck + Biome + Vitest/axe + WCAG contrast + Storybook build run in CI on every PR

🏗 Architecture

A Bun workspace monorepo that publishes a single consumable package. Tokens are the source of truth; everything downstream is generated or composed from them.

flowchart TB
    subgraph src["packages/qeetrix-ui — @qeetrix/ui"]
        direction LR
        tokens["Design tokens<br/>W3C DTCG JSON · OKLCH<br/>tokens/"]
        sd["Style Dictionary<br/>scripts/build-tokens.mjs<br/>→ semantic + raw --qx-* CSS + JSON"]
        comps["140+ components<br/>shadcn + Base UI<br/>src/components/ui/"]
        blocks["6 blocks + i18n + motion<br/>src/blocks/ · src/i18n/"]
        brand["Brand<br/>QeetLogo + 10 icons<br/>src/brand/"]
        tokens --> sd --> comps
        brand --> comps --> blocks
    end

    consumers["Qeet ID · qeet-docs · qeet-notify · qeet-logs<br/>· future Qeet products"]
    story["apps/qeetrix-story — Storybook 10 workshop"]
    docs["apps/qeetrix-docs — ui.qeet.in (Next.js 16)"]

    comps --> consumers
    comps --> story
    comps --> docs
Loading

Build pipeline (@qeetrix/ui): build-tokens (Style Dictionary) → tsctsc-aliaspostbuild (inlines the token CSS, copies fonts + styles into dist/). The shared root package.json workspaces.catalog pins React / Tailwind / TS across the repo.

Packages

Package What it is Published
@qeetrix/ui The component library + tokens + brand + blocks + i18n — the one package consumers install npm
apps/qeetrix-story (@qeetrix/stories) Storybook 10 workshop — foundations gallery + a story per component (:6006) private
apps/qeetrix-docs (qeetrix-docs) ui.qeet.in — the docs & developer platform, Next.js 16 + React 19 (:3006), dogfoods @qeetrix/ui private
packages/qeetrix-mcp (@qeetrix/mcp) MCP server exposing the component + token manifest to AI coding agents private

Tooling is unified: linting + formatting run entirely on Biome (ESLint + Prettier removed); orchestration is plain bun run --filter (no Turbo); TypeScript presets are self-contained per package (no shared config package). @qeetrix/tokens and @qeetrix/brand were once separate packages — now folded into @qeetrix/ui and exposed as subpaths.


🚀 Install & use

bun add @qeetrix/ui        # components + tokens + brand + blocks + i18n, all in one
bun add react react-dom    # peers (>= 19)

In your Tailwind v4 global stylesheet:

@import "@qeetrix/ui/styles.css";                    /* tokens + fonts + base layer */
@source "../node_modules/@qeetrix/ui/dist/**/*.js";  /* let Tailwind see component classes */

Then wrap the app and compose:

import { ThemeProvider, Button, Card, CardContent } from "@qeetrix/ui";
import { QeetLogo } from "@qeetrix/ui/brand";

export function App() {
  return (
    <ThemeProvider defaultTheme="system">
      <Card>
        <CardContent className="flex items-center gap-3">
          <QeetLogo size={28} />
          <Button>Authenticate with Qeet</Button>
        </CardContent>
      </Card>
    </ThemeProvider>
  );
}

Light/dark is driven by the .dark class (managed by ThemeProvider). Need raw values? @qeetrix/ui/tokens.css (the --qx-* ramp) and @qeetrix/ui/tokens.json.

Import surfaces

Surface Contents
@qeetrix/ui Components, providers, hooks, cn — the barrel
@qeetrix/ui/styles.css Tokens + fonts + base layer (side-effect import)
@qeetrix/ui/tokens.css · /tokens.json Raw --qx-* custom properties · resolved-per-theme JSON
@qeetrix/ui/qeetrix.css Semantic token layer only
@qeetrix/ui/brands/<brand>.css Per-product brand overlays (qeet-id · qeet-logs · qeet-notify · qeet-people · qeet-mail)
@qeetrix/ui/brand QeetLogo + 10 custom Qeet icons
@qeetrix/ui/blocks (+ /blocks/*) Composable multi-component patterns
@qeetrix/ui/i18n I18nProvider · useTranslations · useI18n
@qeetrix/ui/components/* · /lib/* · /hooks/* · /fonts/* Deep per-file imports

🧩 What's inside

140+ React components across the full enterprise surface — every one with a Storybook story; interactive ones with Vitest + axe tests. New in 1.0.0

  • Overlays & popovers — Dialog · AlertDialog · Sheet · Drawer · Popover · DropdownMenu · ContextMenu · Menubar · HoverCard · PreviewCard⭐ · Tooltip · ToggleTip⭐ · CommandPalette · NavigationMenu · Tour⭐ · Portal⭐ · FocusTrap⭐
  • Inputs & controls — Button · ButtonGroup⭐ · IconButton⭐ · CloseButton⭐ · Input · PasswordInput⭐ · MaskInput⭐ · Textarea · Select · NativeSelect⭐ · Combobox · MultiSelect · Autocomplete · Checkbox · CheckboxCard⭐ · Radio · RadioCard⭐ · Switch · Toggle · Slider · AngleSlider · OTPInput · NumberField · CurrencyInput · Rating · Field / Form · Chip · TagInput · SegmentedControl · ColorPicker · ColorSwatch⭐ · Editable⭐ · Date / DateTime / TimeRange / Timezone pickers · Calendar
  • Data & navigation — Table · DataTable · ActionBar⭐ · Tabs · Breadcrumb · Pagination · Sidebar · TreeView · Timeline · Accordion · Collapsible · Listbox · TableOfContents · Carousel · Charts (Area · Bar · Line · Donut · Radial · Sparkline) · OrgChart · MasterDetail · OverflowList · Resizable · ScrollArea
  • Feedback & status — Card · Alert · Callout⭐ · Banner · Notification · NotificationCenter · Toast · Stat · Badge · StatusPill · PresenceIndicator · Skeleton · Progress · ProgressCircle⭐ · Meter · Spinner · EmptyState · DataState · Feed · Spoiler · Marquee · Timer⭐
  • Content & utility — Typography / Prose · Blockquote · Highlight · Kbd · CodeBlock · DiffViewer · JSONTree · RichTextEditor · NumberFormatter · RollingNumber · Avatar · AspectRatio · Separator · VisuallyHidden⭐ · SkipNav⭐ · Link⭐ · CopyButton⭐ · CopyableSecret · QRCode⭐ · FileUpload · FileCard · LogoUploader · Icon
  • Providers & hooksThemeProvider · BrandProvider · DirectionProvider · I18nProvider · SidebarProvider · TooltipProvider · hooks useIsMobile · usePrefersReducedMotion · useMotion · useCopyToClipboard · useFocusTrap · useTimer · useTour
  • BrandQeetLogo (theme-adaptive) + 10 custom Qeet icons, at @qeetrix/ui/brand
  • Blocksauth · dashboard-shell · onboarding-wizard · page-state · pricing-table · settings-layout, at @qeetrix/ui/blocks

🎨 Design tokens

The single source of truth lives in packages/qeetrix-ui/tokens/ as W3C DTCG JSON (primitives → light/dark semantic + shadcn bridge). Style Dictionary compiles them to:

  • @qeetrix/ui/styles.css — the full entry (semantic :root / .dark vars, baked in)
  • @qeetrix/ui/tokens.css — the raw --qx-* ramp · @qeetrix/ui/tokens.json — resolved per theme
  • @qeetrix/ui/qeetrix.css — semantic layer only

Colour is authored in OKLCH; elevation uses a layered shadow ladder (rest · hover · popover · modal); the four status colours (success · warning · error · info) each ship a full foreground + background + border triad. Every semantic text/surface pair is held to WCAG-AA contrast by a build gate (bun run tokens:validate) — across all 5 brand overlays, in both themes.

The brand palette is Qeet orange (#F26D0Eorange.500), ratified as OD-DS-03. The --qx-color-brand-* ramp and the shadcn --primary / --ring bridge resolve to the OKLCH orange ramp (dark on-brand foreground for AA). Re-brand by re-pointing the color.brand aliases in tokens/primitive/color.json.


🌍 Theming, i18n & motion

import { ThemeProvider, DirectionProvider, I18nProvider, useMotion } from "@qeetrix/ui";

<ThemeProvider defaultTheme="system">        {/* .dark class → semantic tokens        */}
  <DirectionProvider dir="rtl">              {/* LTR / RTL, flows through components    */}
    <I18nProvider locale="hi" messages={hi}>  {/* {var} interpolation, English fallback  */}
      <App />
    </I18nProvider>
  </DirectionProvider>
</ThemeProvider>
  • Brands<BrandProvider brand="qeet-id"> sets data-qx-brand on <html>, re-skinning primary/accent surfaces from the matching overlay.
  • MotionuseMotion() + transition() / DURATION / EASING collapse to no-motion under prefers-reduced-motion.

🛠 Develop

Toolchain: Node ≥ 20 · Bun ≥ 1.3 (sole package manager). Biome for lint + format.

bun install
bun run build            # @qeetrix/ui (tokens → tsc → postbuild) + Storybook + docs
bun run tokens:build     # regenerate only the design tokens (Style Dictionary)
bun run tokens:validate  # WCAG-AA contrast gate on the generated semantic pairs
bun run lint             # biome check .
bun run format           # biome format --write .
bun run typecheck
bun run --filter @qeetrix/ui test   # Vitest + vitest-axe (675 tests)
bun run story:dev        # Storybook component workshop → http://localhost:6006
bun run docs:dev         # ui.qeet.in docs & platform      → http://localhost:3006

Adding a component? Drop it in packages/qeetrix-ui/src/components/ui/ (one flat file — cva + cn(), data-slot, Base UI for anything interactive), export it from src/index.ts, add a Storybook story + a Vitest/axe test, then record a changeset. See CONTRIBUTING.md.


🚢 Release

Versioning + npm publishing run on Changesets:

bun run changeset          # record a change (pick packages + bump)
bun run version:patch      # or version:minor / version:major — apply a bump + changelog
bun run publish-packages   # changeset publish (publishes changed public packages to npm)
bun run release            # build all, then publish — the one-shot release

CI runs Biome + typecheck + build + Vitest/axe + token contrast + Storybook on every PR (ci.yml), visual regression on stories (vrt.yml), and publishing to the @qeetrix npm org (release.yml, needs NPM_TOKEN). Scoped packages publish with publishConfig.access: "public".


📚 Documentation · 🤝 Contributing · 📄 License

Topic Where
📦 Package on npm @qeetrix/ui
🧱 Component workshop bun run story:devhttp://localhost:6006
🌐 Docs & platform bun run docs:devhttp://localhost:3006 (ui.qeet.in)
🤖 For AI assistants CLAUDE.md — commands, architecture, gotchas
🔧 Contributing CONTRIBUTING.md
📝 Changelog packages/qeetrix-ui/CHANGELOG.md

Part of the Qeet Group workspace alongside Qeet ID. Licensed UNLICENSED (private to Qeet Group) pending the public-release decision.

Releases

Packages

Contributors

Languages