Skip to documentation

Product engineering

Design libraries

Other token sets for the same components: create, edit, build, check, pull and remove them with node src/cli.mjs library, and import one by name.

A design library is a named set of tokens — colours, dark colours, fonts, the type scale, weights, radii, spacing, shadows, motion — that the shared Wisent components are drawn with. The components are the same in every library; a library changes only the values they read. A product picks a library by the stylesheet and Tailwind theme it imports.

wisent is the package's own library: its tokens are measured from the Wisent Figma files and every existing import (@wisent-ai/components/styles.css, theme.css, tailwind-preset, tokens) is wisent. Other libraries never change it.

Use a library in a product

@import "@wisent-ai/components/libraries/forest/styles.css";
@import "tailwindcss";
@import "@wisent-ai/components/libraries/forest/theme.css";

For Tailwind 3, use @wisent-ai/components/libraries/<name>/tailwind-preset.cjs as the preset. styles.css is the whole component stylesheet with the library's tokens and the package's own fonts; React components are imported from @wisent-ai/components as before.

The libraries

Every value is a variable of the Wisent Figma library, set with figma: so the record names the variable it came from.

LibraryWhat it changesImport
wisentnothing: the package's own tokens, Brand green on Shaded Gray@wisent-ai/components/styles.css
wisent-characterthe brand ramp, light and dark, becomes the library's Character purple ramp@wisent-ai/components/libraries/wisent-character/styles.css
wisent-neutralthe canvas, borders and text, light and dark, become the library's neutral Grayscale ramp; the brand stays green@wisent-ai/components/libraries/wisent-neutral/styles.css

Choose a library by what people prefer

Preferences shows people two things and asks which they like more. library specimen NAME --out FILE.html draws one self-contained page of the real components with a library; library vote puts those pages to a Preferences vote in an html category, through the Preferences CLI and its own operator bearer.

preferences category create --arena wisent --id design-libraries --name "Design libraries" --kind html
node src/cli.mjs library vote wisent wisent-character wisent-neutral --arena wisent --category design-libraries --out .build/library-vote
node src/cli.mjs library vote --result --submission SUBMISSION

--result prints Preferences' ranking and exits 69 until the leader's 95% interval separates; a decided vote is recorded on the winning library. A product moves to a library by changing its import. vote refuses fewer than two libraries, a library named twice, missing --arena, --category or --out (2), and a library whose build is behind its record (1); a Preferences refusal is printed with its own sentence.

Create, edit and build a library

node src/cli.mjs library create forest --from wisent --title "Forest"
node src/cli.mjs library edit forest --set color.brand=#2f6b3a --set radius.lg=10px --approved-by "Łukasz Bartoszcze" --reason "Forest brand green, softer corners"
node src/cli.mjs library build forest
node src/cli.mjs library show forest

Run these in the wisent-components checkout. A library made --from another follows that library's changes and keeps its own overrides; each override records who approved it, why and when, and show prints it as from -> to. The build writes dist/libraries/<name>/: styles.css, theme.css, both Tailwind presets and the token modules. node src/cli.mjs build rebuilds every library after the package's own dist/.

VerbWhat it does
listevery library, its source, overrides and build state (current, not built, stale: <files>)
show NAMEsource, import paths, build state, each override, derived libraries, and the products whose committed source imports it
create NAME --from LIBRARYa library made of LIBRARY's tokens plus overrides
create NAME --figma URLa library measured from a Figma design file
edit NAME --set PATH=VALUE --unset PATH --approved-by WHO --reason TEXTrecord or drop overrides
build NAME, build --allwrite dist/libraries/NAME
check [NAME]refuse a build that is behind its record, naming each file
pull NAME --export-request FILEexport the Figma file through Weles, measure it, build, commit and push
remove NAMEdelete a library nothing uses
specimen NAME --out FILE.htmlone self-contained page of the real components drawn with NAME
vote NAME NAME… --arena A --category C --out DIRput the libraries to a Preferences vote; --result --submission ID reads it

Values an override takes

color and dark take #rrggbb or #rrggbbaa; radius and space a non-negative px length; shadow x y blur [spread] rgba(r, g, b, a); motion ms; weight a whole number 1–1000; font a CSS font-family list; type.<step>.size px, lineHeight px, em or normal, letterSpacing em or px. Only tokens the components already read can be set, so every component works in every library.

Pull a library from Figma

pull runs on the export host whose Skarbiec holds the Figma token for the Weles export workload. --export-request is that host's Weles request with remote, branch, credential and teamId. pull names the file and the output, libraries/<name>/figma; Weles exports, commits and pushes it (design exports). The file's variables and text styles are then read through the Figma MCP server, the tokens are bound by libraries/<name>/tokens.map.json, and a radius, spacing or shadow the file does not draw is refused. The library is built, committed and pushed.

Refusals

Exit 1 is a refusal and its message names the cause and the command to run; exit 2 is a malformed command.

  • a name that is not lower-case words joined by hyphens (2); a name that exists (1); both or neither of --from and --figma (2); an unknown parent library (1, listing every library); a URL that is not a Figma design file (2)
  • edit, build, pull or remove of wisent (1, naming the command that does it for wisent)
  • edit without --approved-by and --reason (2); a path no component reads (1, listing the group's names); a value of the wrong shape (1, naming the shape); --unset of a path without an override (1)
  • check of a stale or unbuilt library (1, naming each file and library build NAME)
  • remove of a library another library is made from, or that a product's committed source imports (1, naming each repository and file)
  • pull of a --from library; a request without teamId; Weles that cannot start or an export that fails; a token whose Figma variable or style is missing from the file (1)

Real test

node tests/library/lifecycle.test.mjs creates, edits, builds, checks and removes a library through the CLI, runs every refusal that needs no Figma file, resolves the packed package's libraries/<name>/ exports from a consumer, finds a real consumer checkout, and checks that wisent's dist/ holds the same bytes before and after. The guide in the repository is docs/design/libraries.md.

Migrated from wisent-ai/wisent-landing-new/src/data/docs-content.json