Skip to content
Misoto22Public

About

Monochrome design system — CSS tokens and accessible React primitives

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

168 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Folio

Folio — the White Reset

The White Reset

Monochrome design system — CSS tokens and accessible React primitives


Documentation · 中文 · Report Issue


React TypeScript Tailwind CSS Radix UI


Features

  • 52 React primitives — Radix underneath wherever behaviour is involved, cmdk for the command palette, react-day-picker for the calendar. No router, no state library, no CSS-in-JS.
  • 15 data-visualisation primitives, from a separate entry (@misoto22/folio/charts) so an app that renders a Badge does not pay for a rendering engine — and four of them (Heatmap, Sparkline, BarList, BigNumber) need no engine at all. Texture carries series identity and the grey ramp supports it, which is what keeps two series apart in greyscale print, under forced colours and for a colour-blind reader. Every chart is announced, has an empty state, and puts its rows in a table.
  • 11 diagram components, from a third entry (@misoto22/folio/diagrams) — five server-rendered figures for architecture, workflow, sequence, data-flow and lifecycle, plus the chrome to explore one. They read archify's JSON schemas, so a specification authored for that tool renders here in this system's own monochrome terms. The kind of a node is carried by a drawn sigil AND a word, so it survives greyscale.
  • Two axes, both attributes (data-mode, data-density) — light and dark, comfortable and compact. Set either on any container and everything below it follows.
  • 178 tokens, machine-readable (@misoto22/folio/tokens) — every token with its light value, dark value, category and comment, as JSON and as a typed module.
  • RTL with no second stylesheet — every component is written in logical properties, so dir="rtl" mirrors the system. A test fails the build on a physical one.
  • Accessibility the build enforces — coverage.test.ts fails when a component has no fixture, so "every component is checked" is a property rather than a claim.
A console built from the system: sidebar, figure band, tabs, filterable table and status badges
The dashboard template — twelve primitives in one screen, and the only colour on it is state.

Tech Stack

PackageReact 19 · Radix UI · Tailwind CSS 4.3 · tsup
Docs siteNext.js 16.3 · TypeScript 6.0 · react-live · static export
Testingvitest · Playwright + axe-core (E2E) · esbuild size budget
Releaserelease-please · npm (@misoto22/folio)
DeployCloudflare Pages (folio-design)

Project Structure

The canonical tokens are CSS and TypeScript in src. Everything else — the compiled stylesheet, the JSON, the site's swatches and token tables — is built from them, which is why dist/ is never edited by hand.

flowchart LR
  A["styles/tokens.css<br/>tokens/brand.ts"] --> B["packages/design<br/>build"]
  B --> C["dist/<br/>JS · CSS · tokens.json"]
  C --> D["apps/docs"] & E["consuming apps"]
Loading
The directories behind that
packages/design/
├── src/
│   ├── components/         52 primitives, one directory each
│   ├── charts/             20 primitives + their shared lib/
│   ├── diagrams/           11 more + their shared lib/
│   ├── styles/             tokens.css · semantic.css · keyframes.css
│   ├── tokens/             brand.ts — hex mirrors for non-CSS surfaces
│   └── lib/                cn, control base, overlay container, svg export
└── scripts/                font vendoring, portable CSS, token emit, size budget
apps/docs/
├── src/content/            the hand-written part: grouping and summaries
├── src/generated/          parsed out of the package at build time
├── src/templates/          whole screens, not single components
└── e2e/                    axe · keyboard · RTL · density, in a browser
docs/                       component conventions · the site · releasing

Install

pnpm add @misoto22/folio

Prerequisites — Node.js 24+, React 19 and React DOM 19 as peers

// Once, at your app root — the compiled stylesheet carries the tokens, the
// utilities the components use, and the vendored faces.
import '@misoto22/folio/styles.css'

import { Button, Field, Input } from '@misoto22/folio'
An app that already compiles Tailwind

Take the portable layers instead and skip a second copy of the utilities:

@import 'tailwindcss';
@import '@misoto22/folio/tokens.css';    /* primitives  */
@import '@misoto22/folio/semantic.css';  /* roles       */
@import '@misoto22/folio/keyframes.css'; /* motion      */

@source '../node_modules/@misoto22/folio/dist';

@custom-variant dark (&:is([data-mode='dark'] *));

Note

The mode is an attribute rather than a class so an inline script can write it before the first paint and never flash the wrong theme. Density is the only other axis: 44px targets by default (what WCAG 2.5.5 asks for), 36px compact (which clears 2.5.8 but not 2.5.5, so it is for a dense desktop tool).


Development

git clone https://github.com/Misoto22/folio.git
cd folio
pnpm install
pnpm build:design           # the docs site reads the package from dist
pnpm dev                    # → http://localhost:4023

Prerequisites — Node.js 24+, pnpm 11+

pnpm lint                                        ESLint, both workspaces
pnpm typecheck                                   tsc --noEmit, both workspaces
pnpm test                                        vitest, both workspaces
pnpm build                                       the package, then the site
pnpm --filter @misoto22/folio-docs test:e2e     axe + keyboard, in a browser
pnpm --filter @misoto22/folio check:size        size and tree-shaking budget

The site's Tailwind compiles from the package's source, so styling changes are live; a changed component needs pnpm build:design before pnpm dev sees it.


Documentation

ui.misoto22.com is the gallery, the foundations, the principles and the templates, in English and — under /zh — in Chinese. The engineering notes live in docs/: component conventions, the documentation site, releasing.

Nothing about the library is written twice. Prop tables are parsed out of the package's TypeScript at build time, token tables out of the CSS, and every example is a real .tsx module that the page renders and that the code block beneath it was read from — so a preview cannot drift from the code printed under it. The API reference is translated too, and each Chinese entry records a fingerprint of the English it was made from: editing a doc comment in the package fails the build until the translation beside it is updated, rather than quietly telling a Chinese reader something that stopped being true.

The site also serves itself to a reader that does not render CSS — /llms.txt as an index, /llms-full.txt inline, and one file per component. Not a scrape of the HTML: the same generated data the pages read, arranged for one sequential pass.


Release

The pull-request title is the release. Write it as a Conventional Commit and merge it; release-please reads the subjects that reached main, opens a release pull request holding the version bump and the changelog, and merging that tags, publishes the GitHub Release and sends the package to npm.

feat(button): add a loading state      → next minor
fix(sidebar): stop the rail collapsing → next patch
feat(tokens)!: drop the m22 prefix     → next major

Below 1.0.0 this package is still treated as if SemVer's guarantees held: a removed export, a changed default, or a token that no longer resolves is a major. See docs/releasing.md.


Deployment

Two entry points, named after what triggers them, over two shared definitions:

pr-title.yml on: pull_request_target  →  pr-title
pr.yml       on: pull_request         →  verify → browser
release.yml  on: push to main         →  verify → browser → deploy · release → publish
                                                     ↑         ↑        ↑         ↑
                               verify.yml · browser.yml   Cloudflare  release-  npmjs
                                                                       please

verify.yml is lint, typecheck, tests, both builds and the size and tree-shaking budget; browser.yml is the axe, keyboard and RTL suite against the built export. Both are workflow_call definitions, so a pull request and a release are gated by the same file rather than by two that drift — and nothing deploys or publishes that they have not both passed.

deploy uploads the exact directory verify built to the folio-design Cloudflare Pages project and smoke-tests the deployed routes; ui.misoto22.com is a proxied CNAME onto it. release opens and maintains the release pull request, and publish sends the tarball to npmjs when that pull request merges — see docs/releasing.md.

pr-title.yml calls the fleet's shared Conventional Commit check. It is its own file because it triggers on pull_request_target, which a fork's pull request needs and which nothing that checks out a branch may use.


What this repository does not own

The primitives serve both misoto22.com and its admin console, and neither host's routes, data access or business logic lives here. A component that needs to know about a route, a session or a database has been built in the wrong repository.

This package is also the source for the misoto22 Claude Design project — run the /design-sync skill from the repository root to push verified components up, after the local gates pass. See .design-sync/NOTES.md.


Built by Henry Chen · MIT

Website compositions

@misoto22/folio/website adds 17 composition families for complete editorial websites. Presentation and accessible interactions live in the package; content, router adapters and backend integrations remain with each consumer. Import website.css beside styles.css or the portable layers — styles.css does not include it — and add website-base.css when the whole page is a website, for its body type, heading margins and site-wide focus ring. The offline CLI documents every family and public part.

About

Monochrome design system — CSS tokens and accessible React primitives

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages