Skip to main content

Hourglass

A monochrome design system: one set of tokens and 23 components, built eight times over so any project can take the one that matches its framework.

Every library is standalone. One command copies the folder into your repository and it works — no package to install, no build step, no configuration, and no dependency beyond the framework itself. See Installation.

The eight libraries

LibraryDependenciesNotes
lib/htmlNonePlain HTML, CSS and a little vanilla JavaScript. The canonical web implementation.
lib/reactreactTypeScript components for React 18+.
lib/nextjsnext, reactThe React set, generated with "use client" where the App Router needs it.
lib/vuevueTypeScript single-file components for Vue 3.5+.
lib/sveltesvelteSvelte 5, using runes.
lib/angular@angular/core, @angular/commonStandalone components, signal inputs, OnPush.
lib/webcomponentsNoneNative custom elements. Work in any framework, or none.
lib/reactnativereact, react-nativeCore Animated only — no Reanimated, Skia, SVG or gesture library.

What is in the box

  • Tokens — colour (OKLCH with an sRGB fallback, light and dark), type, spacing, radius, elevation, motion and hit targets, as CSS custom properties, a typed TS object, a React Native theme, and an optional Tailwind preset.
  • 23 components — actions, forms, controls, content, data and overlays. Every one of them in every library.
  • One implementation per concern. lib/html/hourglass.css is the web stylesheet; the six web libraries all render the same hg-* markup, so a border radius is decided once rather than six times. The reel engine and the calendar arithmetic are shared the same way.

The rules the components follow

  • Generic and stateless. Presentational only — no data fetching, no domain types, no knowledge of what the app is for.
  • Controlled. A component takes its value as a prop and reports what the user asked for; it never owns the state it displays. A control that flips itself becomes a second copy of your state, and the two disagree the first time a save fails.
  • Nothing formats anything. Durations, currencies and dates arrive as text you have already formatted, because all three differ per locale.
  • Monochrome. accent is near-black in light and near-white in dark — the same neutral scale, not a hue. Status is never colour-coded: an icon, a label and weight carry it, which survives printing, screenshots and screen readers.
  • Framework-native. React Native uses the built-in Animated API, not Reanimated or Skia. The web uses CSS transitions and inline SVG, not a motion or charting library.
  • Accessible. 4.5:1 body and 3:1 large text in both modes, 44/48px hit targets, visible focus rings, and spoken labels on every mono numeral.

Repository layout

chronsyn/ui
├── tokens/ tokens.json · CSS custom properties · TS theme · RN theme · Tailwind preset
├── shared/ reel.ts (the odometer engine) · datetime.ts (calendar arithmetic)
├── tools/ sync.mjs (write the copies) · verify.mjs (fail if they drift)
├── docs_src/ this site
├── docs/ this site, built
└── lib/
├── html/ react/ nextjs/
├── vue/ svelte/ angular/
└── webcomponents/ reactnative/

Why the duplication is deliberate. Each library carries its own copy of the theme, because a folder you can drop somewhere cannot reach back up to a shared parent. tools/sync.mjs writes those copies from tokens/, and tools/verify.mjs fails if one has been edited in place, if a library imports something it may not have, or if the CSS and tokens.json disagree.

Fonts

The system asks for Inter (display and body) and JetBrains Mono , and falls back to the platform's own faces if they are not loaded. No font files ship with it — a folder you copy into someone else's project has no business carrying licensed binaries.

The mono is not a code style here. Every numeral, time, duration, eyebrow and caption is set in it; it is the loudest signal the system has.

Next

Installation — how to get the library for your framework into a project.

Design system — the foundations, and the decisions behind them.

Tokens — every value, and the name it answers to.

Components — all 23, with props, types and code samples.

github.com/chronsyn/ui — the source.