Get Started

Overview

crisp — a design system built by measuring a live production UI pixel-for-pixel.

crisp is a small design system built by measuring a live production UI pixel-for-pixel — heights, radii, color, spacing, shadows. This documentation renders every example with crisp's actual generated CSS (dist/styles.css), not hand-approximated styles.

Foundations

Before the components: Foundations — the measured dimensional scale (spacing, radius, sizing) that every component references instead of raw px, plus the rule for when a divider is warranted.

Components

  • Button — 4 intents · 3 sizes · text/icon shape
  • Badge — 5 tones · 3 sizes · soft/solid
  • Input — 2 sizes · invalid state
  • Avatar — 4 sizes · circle/rounded · 6 tones

Product

A separate product/ layer holds faithful, pixel-measured rebuilds of specific screens — Sidebar, Board, RecordPage, Inbox and more. Use them as-is, or as composition references; for records/data grids reach for DataTable (paired with TableToolbar, or Table for hand-laid cells).

Installation

bun add @crisp-ui-kit/crisp react react-dom

Import the stylesheets once, at your app's entry point:

import "@crisp-ui-kit/crisp/base.css";   // optional, but import it first
import "@crisp-ui-kit/crisp/styles.css";

styles.css is the component CSS and the design tokens. base.css is the app baseline — it puts the token font, background and text colour onto body, sets box-sizing, and matches color-scheme to the theme. It is optional only in the sense that you can write those four rules yourself; without it a fresh app renders in Times New Roman on a transparent background.

When your own styles need to win

crisp's rules are plain classes at low specificity, so whether your override wins comes down to stylesheet order. If that is inconvenient, import the layered build instead:

import "@crisp-ui-kit/crisp/styles.layered.css"; // instead of styles.css

It is the same CSS wrapped in @layer crisp-components. Anything you write outside a layer beats anything inside one, whatever the order and whatever the specificity — so a single .card rule of your own wins without !important and without counting selectors.

Components tree-shake, so importing from the package root costs no more than a deep import:

import { Button } from "@crisp-ui-kit/crisp";        // 8 KB bundled
import { Button } from "@crisp-ui-kit/crisp/button"; // identical

Every component below is a small React wrapper around a statically-generated CSS recipe — variant props map directly to class names, resolved ahead of time. No CSS-in-JS at render time.

On this page