Skip to content

Repository files navigation

hifi

High-fidelity grammars for multi-dimensional interfaces.

hifi is a TypeScript-first suite of React libraries for building interfaces with a strong and coherent visual language. Each language is packaged as a grammar: a set of primitives, components, tokens, motion, and interaction rules that work together as one material system.

The project is in its foundation phase. The first grammar is liquid, a glassmorphic system built with liquid-dom.

What is a grammar?

A theme changes values within a visual language. A grammar defines the language itself.

For example, a glass grammar and a print grammar differ in their treatment of depth, light, edges, texture, typography, motion, and interaction—not just in their color tokens. Each grammar should make those dimensions feel intentional across everything from a button to a complete application surface.

A grammar owns:

  • design tokens and semantic variables;
  • React primitives and composed components;
  • layout, depth, motion, and interaction rules;
  • one or more themes;
  • accessibility behavior and reduced-effect fallbacks;
  • examples, usage guidance, and tests.

Themes are variants inside a grammar. In liquid, themes describe clear, tinted, frosted, prismatic, blurred, or smoked glass while preserving the same underlying component vocabulary and behavior.

Initial grammars

Grammar Language Example themes Status
liquid Layered, refractive glass surfaces clear, tinted, frosted, prismatic, smoked First priority
texture Tactile and material-rich surfaces paper, canvas, grain, fabric Experimental
print Editorial composition inspired by physical print broadsheet, magazine, technical, poster Experimental
mosaic Modular color and geometry composed into readable regions modular, tessellated, stained, pixel Experimental
kinetic Physical controls governed by force and consequence precision, sprung, magnetic, viscous Experimental

These are the starting points, not a closed set. A new grammar belongs in hifi when it offers a distinct, reusable visual language rather than a one-off component skin.

Principles

  • Coherence over collection. Components within a grammar should look, move, and respond as if they belong to the same world.
  • Fidelity is multi-dimensional. Color, material, light, depth, typography, motion, sound, and interaction are parts of the same system.
  • Themes preserve the grammar. A theme can tune the material without changing its fundamental rules or component API.
  • React APIs stay composable. Consumers should be able to extend primitives without fighting hidden structure or state.
  • Accessibility is part of fidelity. Keyboard behavior, contrast, reduced motion, reduced transparency, and non-GPU fallbacks are design inputs.
  • The styleguide is the specification. Every public primitive, state, theme, and fallback should be observable there.

Repository shape

hifi is a Turborepo monorepo with pnpm workspaces.

.
├── apps/
│   └── styleguide/          # TanStack Router development and showcase app
├── packages/
│   ├── core/                # Shared grammar contracts and utilities
│   ├── kinetic/             # Physical interaction grammar
│   ├── liquid/              # Glassmorphic React grammar
│   ├── mosaic/              # Modular mosaic grammar
│   ├── texture/             # Textured React grammar
│   └── print/               # Print-inspired React grammar
├── tooling/                 # Shared TypeScript configuration
├── flake.nix                # Reproducible Node.js development shell
├── justfile                 # Developer task interface
├── package.json
├── pnpm-workspace.yaml
└── turbo.json

Grammar packages should expose React components, tokens, theme definitions, and public types from deliberate entry points. Shared code belongs in core only when it describes a capability common to multiple grammars; grammar-specific abstractions stay with their grammar.

Packages

The independently consumable packages are:

Package Purpose React support
@hifi/core Grammar contracts and programmable-material utilities None required
@hifi/liquid WebGPU liquid glass with a CSS fallback React 19
@hifi/texture Tactile substrate and pattern surfaces React 18.2–19
@hifi/print Editorial composition and print surfaces React 18.2–19
@hifi/mosaic Modular surfaces and explicit-contrast content tiles React 18.2–19
@hifi/kinetic Physical surfaces, controls, and dense analytical tables driven by a response model React 18.2–19

All packages are ESM-only, support Node.js 20 or newer, publish TypeScript declarations, and expose versioned material parsers and serializers. Their package-level READMEs document the public entry points and basic use.

Getting started

Install React 19 and the Liquid grammar:

pnpm add @hifi/liquid react react-dom

Start with a typed preset, then tune only the material properties your interface needs:

import {
  LiquidSurface,
  liquidThemeMaterials,
  type LiquidMaterial,
} from '@hifi/liquid'

const material: LiquidMaterial = {
  ...liquidThemeMaterials.clear,
  name: 'Cool clear glass',
  blur: 12,
  tint: { r: 0.72, g: 0.9, b: 1, a: 0.14 },
}

export function StatusPanel() {
  return (
    <LiquidSurface material={material}>
      <section aria-labelledby="status-title">
        <small>System status</small>
        <h2 id="status-title">All systems nominal</h2>
        <p>Your workspace is calibrated and ready.</p>
      </section>
    </LiquidSurface>
  )
}

For an unchanged preset, pass theme="clear" directly to LiquidSurface. Material JSON exported by the styleguide can be validated with parseLiquidMaterial before rendering.

Styleguide

The sample application is both a development harness and the living specification for the packages. It uses TanStack Router, StyleX for all authored application styles, and builds to static assets in apps/styleguide/dist.

Style definitions live beside the components they describe in apps/styleguide/src/stylex/*.stylex.ts. The official StyleX Vite integration compiles them into a single atomic CSS asset in development and production; the repository does not maintain handwritten .css files. Runtime material values remain programmable data expressed through typed custom properties, while structural and stateful rules are composed with StyleX.

Each grammar owns an explicit route component, its own art direction, and its own theme-responsive control treatment. The routes share a fourteen-section specimen contract—material, typography, color, spacing, layout, icons, buttons, forms, badges, cards, tables, lists, feedback, and composition—so the same interface vocabulary can be compared without forcing every grammar into the same page design.

Each grammar has a stable route:

/styleguide/liquid
/styleguide/texture
/styleguide/print
/styleguide/mosaic
/styleguide/kinetic

The page at /styleguide/{grammar} should include:

  • a theme switcher for that grammar;
  • tokens and visual foundations;
  • every public component and meaningful state;
  • interaction, motion, and layering examples;
  • accessibility and reduced-effect examples;
  • implementation notes and copyable usage examples.

Theme selection is represented by the theme search parameter so that a specific variant can be shared without adding a separate route tree. Static deployments must support direct navigation to every grammar route, either by prerendering those routes or by providing an SPA fallback. The current build includes a Netlify-compatible _redirects file.

Liquid

liquid is the first active grammar and will be the first one completed. It uses @liquid-dom/react to provide real-time liquid-glass rendering through a React API.

The upstream renderer currently targets React 19 and requires WebGPU for rendering. DOM content rendered into the glass canvas also relies on experimental browser support. The liquid styleguide should document the browser setup it expects and demonstrate an accessible fallback when GPU rendering or the required browser feature is unavailable.

The first themes should explore a useful range without fragmenting the API:

  • clear — neutral, highly transparent glass;
  • tinted — glass whose color participates in hierarchy and mood;
  • frosted — diffuse glass with stronger separation from its background;
  • prismatic — high-dispersion glass that holds a frozen spectrum at its edge;
  • blurred — soft, depth-forward glass with restrained refraction;
  • smoked — dark absorptive glass with reduced transmission and hard highlights.

Theme names and parameters should describe material behavior rather than a single product or color palette.

Programmable materials

Materials are portable, versioned data rather than values trapped inside a component. Each grammar owns a live theme generator that edits the same material object its route and surface renderers consume: optical parameters in Liquid, substrate and pattern parameters in Texture, paper, ink, grid, type, and composition parameters in Print, tile palette, joints, rhythm, and contrast pairs in Mosaic, and mass, stiffness, damping, friction, travel, and actuation in Kinetic. A change is applied to the complete styleguide grammar—not only the generator preview—before the resulting theme is copied or downloaded as JSON.

An exported material can be validated and applied directly in an application:

import { LiquidSurface, parseLiquidMaterial } from '@hifi/liquid'
import materialJson from './luminous-field-024.json'

const material = parseLiquidMaterial(materialJson)

export function Panel() {
  return <LiquidSurface material={material}>Calibrated surface</LiquidSurface>
}

The shared ProgrammableMaterial envelope supplies the grammar, name, and version fields, while each package validates its own parameters. Every grammar package exports matching parse…Material and serialize…Material functions; parsers reject incompatible input and serializers produce the canonical JSON used by the styleguide exporters.

Kinetic keeps vibration and synthesized actuation feedback opt-in; its visual response model works without either capability.

Development environment

The canonical development environment is a Nix flake. It provides Node.js 24, pnpm, and just; the flake and workspace lockfiles pin the complete toolchain.

With Nix and flakes enabled:

nix develop
just bootstrap
just dev

The development server listens on all interfaces at port 5713. Open http://localhost:5713, or use the machine's network hostname, such as http://kawasaki.local:5713. All *.local hostnames are accepted.

Developer tasks

The justfile is the supported entry point for routine work. It remains small and delegates workspace orchestration to Turbo. Run just without arguments to print the available commands.

Command Purpose
just bootstrap Install the pinned workspace dependencies
just dev Run the styleguide and watched package builds
just build Build all packages and the static styleguide
just test Run the Vitest suite
just typecheck Type-check every workspace package
just lint Run repository lint checks
just format Format supported source and configuration files
just check Run the full local validation suite

Testing

Vitest is the default test runner for packages and applications. Tests should live near the behavior they protect and cover:

  • public component contracts and composition;
  • theme and token resolution;
  • interaction and accessibility behavior;
  • grammar registration and styleguide routing;
  • graceful behavior when optional rendering capabilities are unavailable.

GPU rendering quality is difficult to establish with DOM-only unit tests. The initial Vitest suite should validate deterministic application behavior; browser smoke tests and visual regression coverage can be added as the visual contract stabilizes.

just check is the expected pre-push gate.

The final stage of that gate packs all six libraries, installs the tarballs into a clean temporary consumer, checks their declarations with TypeScript, imports them directly with Node, and bundles a React application with Vite. This prevents source aliases in the styleguide from masking distribution errors.

Releases

Consumer-facing changes use Changesets. The six packages form a fixed version group so compatible releases move together and internal @hifi/core ranges remain coordinated.

pnpm changeset
pnpm version-packages
pnpm release

pnpm release runs the complete validation and downstream tarball smoke test before publishing the public scoped packages. Publishing still requires registry credentials with access to the @hifi scope.

Adding a grammar

Before a grammar is considered part of the suite, it should:

  1. define its visual premise and the dimensions governed by that premise;
  2. expose a typed React package with at least one complete theme;
  3. register itself with the styleguide at /styleguide/{grammar};
  4. document its tokens, components, states, interactions, and fallbacks;
  5. include Vitest coverage for its public contracts;
  6. pass just check and produce a static styleguide build.

Roadmap

  • Scaffold the Nix, pnpm, Turbo, TypeScript, React, TanStack Router, and Vitest foundation.
  • Define the initial shared grammar and theme contracts.
  • Build out the liquid component vocabulary and mature its initial theme variants.
  • Publish the static styleguide with reliable deep links.
  • Establish complete texture and print grammars from the shared contracts.
  • Develop mosaic into a full modular-composition component vocabulary.
  • Develop kinetic into a full force- and response-driven component vocabulary.
  • Add browser-level accessibility, rendering, and visual regression coverage.

Status

hifi is experimental and its package APIs are not yet stable. The immediate goal is to prove the grammar model through liquid, then use that experience to refine the shared contracts before expanding the suite.

About

A high fidelity grammar for multi-dimensional interfaces

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages