@versable-git/ui 0.2.2

One kit. Every Versable screen.

The component kit, the design language it obeys, and the patterns proven in Speedway and Walmart, browsable in one place. Corrections caught on a shipping screen flow back here as law; nothing flows the other way.

Components
45
every export, all states
Patterns
27
proven on shipping screens
Agent docs
146
canon, contracts, method
Apps on the kit
2
walmart-mvp, speedway

SEE IT LIVE

See it live

The strip below is not a screenshot: every tile is the real, interactive component.

Buttons

Completerunning3Needs attention

Chips, one click each

1 of 5 fields selected ·
Parts enriched
4,212+968 today
one dashboard tile, click-through and all
Every tile here is the real component
Same imports the apps use, no mockups.

Identity

ACAakarsh ChopraOwner · versable

Pipeline tabs

Active: Enrichment, running · 61%. Each tab carries its status and a detail line.

/components

Components

Every export, all states, both themes, the tsx source beside each render.

Button

variants, presets, promisify, badges

Table

lean core, look contract, row expand

Card

surfaces, shadows, skeleton

StatusPill / StatusDot

the status vocabulary

/patterns

App-level composites proven on a shipping screen, rebuilt from kit parts on fixture data.

Dashboard stat groups

headline numbers as stat tiles, auto-fit grid

Split cards

two-pane split, hairline row dividers

Workflow stepper

numbered knobs, completion-colored connectors

Top loading bar

90ms grace, eased trickle, completes on arrival

/docs

Agent docs

The scripture, the design language, the app patterns, and every kit contract, read in place.

Scripture

The intent layer: why this project exists, what it must achieve, how it works.

  • Abstractions are born from evidence, never ahead of it: a hack lives in an app until it earns graduation, two or more real consumers.
  • Do not invent exceptions to the ground rules. Stop and flag instead.
Design language

The twelve traits, the layer-relation table, and the pin caveat.

  • The canon says what a surface should be and why; what props a component takes lives in the kit docs, never restated here.
  • Deviation is legitimate and never free: a surface that deviates records the reason in its own doc, never silently.
Do-nots

Every banned combination and canon do-not in one place, regenerated from source.

  • A rule filed under one component's contract is invisible to a builder who never opens that doc; check here before shipping.
  • A button that cannot act is hidden or explains itself, never silently disabled.
CONTRIBUTING.md

How to set up, run, and extend this repo: a component, a pattern, a doc.

  • A component is never one file: source, contract doc, showcase page, registry entry and the do-nots regen travel together.
  • Never publish the kit by hand from a laptop; it races the workflow, which then finds the version present and skips.
/demo

Product demo

The whole app chrome on mock data: catalog, modules, review, schemas.

speedway shell · /demo/jobs
Jobs

every module run across the workspace

Manual review

attributes the normalizer refused to guess

Workflow

the full agentic pipeline, ingest to export

Upload

drop a loadsheet, map its columns, watch it turn into rows

/demo/admin

Admin demo

The operator console one level above the workspace: every team on the installation, the machinery under them, and the controls that reach across all of them.

admin shell · /demo/admin
Team dashboard

installation totals, the team ledger, recent activity

Workers

what is running right now, and the feed that never answered

System health

provider usage, scheduled jobs, feeds, the last deploy

Credits and plans

plan preset, per-metric limits, issued credits

PACKAGES

Packages

Two more layers under the kit, both real, working code: framework-free utilities and the URL half of the table sync seam.

@versable-git/toolkitFramework-free utilities shared across every app and package here.

date · download · event · file · iter · number · object · promise · random · result · sampling · security · string · text · types · url · validation

import { listToMap, getHumanReadableNumber, truncateMiddle, getRelativeTime } from "@versable-git/toolkit";
const rows = [{ id: "x", n: 1 }, { id: "y", n: 2 }];
// Build an id-lookup map from a list (the default key)
listToMap(rows);
// { x: { id: "x", n: 1 }, y: { id: "y", n: 2 } }
// Key by any other field on the row
listToMap(rows, "n");
// { 1: { id: "x", n: 1 }, 2: { id: "y", n: 2 } }
// Shape each value with a transform, not just the key
listToMap(rows, "id", (r) => r.n);
// { x: 1, y: 2 }
// Compact a raw count for a stat tile or a table cell
getHumanReadableNumber(1500);
// "1.5K"
getHumanReadableNumber(2340000);
// "2.3M"
// Keep a long filename recognizable at a fixed width
truncateMiddle("a-very-long-generated-filename-from-the-pipeline.csv", 24);
// "a-very-long...peline.csv"
// "5 minutes ago", not a raw timestamp
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
getRelativeTime(fiveMinutesAgo);
// "5 minutes ago"
@versable-git/qsyncThe URL half of the kit's table sync seam.

applyOps · createUrlSyncAdapter · createHistorySyncAdapter

import { applyOps, createUrlSyncAdapter } from "@versable-git/qsync";
const base = new URLSearchParams("a=1&b=2");
// Delete a key by writing null
applyOps(base, new Map([["a", null]]));
// "b=2" (base itself is untouched: applyOps returns a copy)
// Add a brand-new key
applyOps(base, new Map([["c", "3"]]));
// "a=1&b=2&c=3"
// Delete and add in the same batch
applyOps(base, new Map([["a", null], ["c", "3"]]));
// "b=2&c=3"
// createUrlSyncAdapter owns the batching: writes made in the same
// tick coalesce into ONE commit, never one per write
const adapter = createUrlSyncAdapter({
read: () => "sort=name",
commit: (next) => console.log("commit:", next.toString()),
});
adapter.write("dir", "asc");
adapter.write("dir", "desc"); // last write to a key wins
adapter.read("dir");
// "desc" (a read before the flush still sees the pending value)
await Promise.resolve(); // one microtask later, the batch flushes
// commit: "sort=name&dir=desc", a single commit call, not two