@formancy/themes

中文文档
0.13.0发布于 2026/11/06Apache-2.0ES Module零依赖构建来源已验证近 30 天下载 4263

Reference themes for formancy renderers — four unrelated looks targeting data-formancy-part hooks — with the builders' stylesheet and the admin's palette. CSS only.

原始使用文档
文档目录6 节
  1. What they are for
  2. Use
  3. The builders: workbench.css
  4. The room: room.css
  5. Right to left, and your bundler
  6. Writing your own

@formancy/themes

Four reference themes, the builders' stylesheet and the admin's palette. CSS only — no JavaScript, no build step, no dependency on any renderer.

What they are for

The renderers ship zero CSS. That claim is easy to make and hard to trust, so these files exist to test it: the same markup and the same engine, dressed as four products that do not look related.

BlueprintDuskPopPaper
Feels likea technical drawinga dark appa sticker sheeta printed page
Groundwhitedarkcream or whitepaper or white
Controlsboxes, 3px cornersinset wells, 10px cornersoutlined, hard shadowa line to write on
TypeIBM Plex SansSpace GroteskArchivo, heavyFraunces, spaced small capitals for labels
Choicesdrawn boxes and circleslit wellschipshairline boxes, italic when chosen
Invalid shown asa bar on the leading edgea ring around the controla pink stickera vermilion line and an italic note
Required shown asan asteriskthe word "required"a stara footnote asterisk
Active wizard stepa numbered, underlined worda lit dot on a tracka yellow badgea roman numeral, underlined

If supporting any of them had required changing a component, the headless claim would be false. None did.

Use

import '@formancy/themes/blueprint.css'
import '@formancy/themes/dusk.css'
import '@formancy/themes/pop.css'
import '@formancy/themes/paper.css'
<div data-formancy-theme="blueprint">…your form…</div>

Every theme is scoped under [data-formancy-theme], so a page can load all of them and switch by changing one attribute — which is what the playground and the landing page do. workbench.css and room.css, below, are not themes and are not scoped: each sets its variables on :root, for the whole page.

Each theme sets its own text colour, colour scheme and box-sizing on its subtree, so it does not depend on the host page's reset. It does not paint the page behind the form: Pop and Paper look best on the ground colour they declare as --fm-ground, and fine on white.

Fonts are referenced, not bundled, and every theme falls back to a system stack. formancy.ai serves its faces itself from Fontsource's packages rather than from a font service, so opening a page tells no other site who opened it. Fontsource names a variable face <Family> Variable, so Pop asks for Archivo then Archivo Variable, and Paper for Fraunces then Fraunces Variable: either spelling of the face, whichever way a page loads it.

The builders: workbench.css

workbench.css dresses both builders — the tree, the palettes, the inspector, the logic panel, the prompt pane and the relay beside it, the scenarios, blocks, a datagrid's columns and the translations — through the data-formancy-part hooks they emit, and every part they emit has a rule here. It is not a form theme and nothing depends on it. Change how it looks through its tokens rather than with rules of your own:

TokenWhat it colours
--wb-ink, --wb-mutedtext, and quiet text
--wb-bench, --wb-panel, --wb-surfacethe ground, a pane, a control or a card
--wb-rulelines and borders
--wb-signalthe selection, focus and the primary action
--wb-derivedwhat the builder worked out rather than what was typed: a type, a path
--wb-invalid, --wb-ok, --wb-cautionbroken, fine, and costing something
--wb-sans, --wb-monothe two faces

The room: room.css

room.css is the palette formancy.ai's self-hosted admin is drawn in — a dark ground, glass panels, violet for what a person acts on and teal for what the system did — so that an application meant to be the same room imports it rather than copying the values. The admin imports it the same way. It is custom properties on :root and color-scheme: dark, and nothing else: no rule for any element, and no face loaded. Your own stylesheet reads them.

import '@formancy/themes/workbench.css'
import '@formancy/themes/room.css' // after the workbench
VariableWhat it is
--groundthe page, behind everything
--glassa panel over the ground, which shows it through
--text, --mutedtext, and quiet text
--edge, --edge-stronga line, and a line that bounds a panel
--clientviolet: what the person acts on
--serverteal: what the system did
--invalid, --ok, --warnbroken, fine, and half-way
--displaythe face for headings: Archivo, then IBM Plex Sans

It also sets every colour of workbench.css to the room's — --wb-ink, --wb-bench, --wb-panel, --wb-surface, --wb-rule, --wb-muted, --wb-signal, --wb-derived, --wb-invalid, --wb-ok and --wb-caution — and leaves its faces as the workbench sets them. Those take effect only after workbench.css: both say :root, so whichever loads later wins, and loaded first the builder keeps its light panes in the dark room.

The faces are not loaded. --display names Archivo and IBM Plex Sans, and the workbench's faces are IBM Plex; a page loads them itself, as the admin does from Fontsource, or falls back to the system's.

The names are what you write var() around, so they are this package's API, and a value is the room: a change to one changes every page that imports it, and the changelog says so.

Right to left, and your bundler

Every file here that lays anything out — the four themes, and workbench.css, which styles the two builders — says which side a thing is on in reading order: logical properties, and :dir(rtl) where CSS has no logical form, as for an icon's background-position or the bar an inset shadow draws down one side of a selected item. Set dir="rtl" on the page, or on anything above the form or the builder, and the layout follows.

That holds only while :dir() reaches the browser as written. A bundler targeting browsers older than the ones :dir() shipped in rewrites it. Vite's default target had Lightning CSS turn every :dir(rtl) into :is(:lang(ar), :lang(he), …), which follows the page's language instead: dir="rtl" on a page whose lang is not on that list changes nothing, and the builder's marks stay on the left. Measured in this repository's own playground. Set the CSS target to the browsers these stylesheets are written for — each the first release with both :dir() and color-mix():

// vite.config.ts
export default defineConfig({
  build: { cssTarget: ['chrome120', 'edge120', 'firefox113', 'safari16.4', 'ios16.4'] },
})

A stylesheet loaded with a plain <link> is not rewritten and needs nothing.

Writing your own

Copy one and change it. The surface is data-formancy-part attributes, and every part either renderer emits that has anything to draw is styled in every form theme shipped here — apps/docs/src/themes.test.ts fails on one that is not — so a copy already names them all. These are where to start, not the whole list:

  • fields: field (with data-state="invalid|valid"), label, error, required-hint, radio-option, checkbox-option, static
  • repeaters: repeater, repeater-legend, row
  • layouts: layout-row, layout-column, layout-section, layout-section-heading, layout-table (with data-columns), layout-tabs, tablist, tab, tabpanel
  • wizard and submit: stepper, wizard-nav, submit
  • errors: error-summary, error-summary-heading
  • rich text: richtext-toolbar, richtext-button, richtext-preview, richtext, visually-hidden
  • files: file-list, file-item, file-status, file-unavailable

visually-hidden has to be hidden by every theme — it is the only name the rich text toolbar's buttons have, so it is moved off screen, never removed.

Controls are plain input, select and textarea inside [data-formancy-part="field"]. Nothing is a class, so nothing collides with your design system.

版本与发布记录

@formancy/themes 共发布 13 个版本,首次发布于 2026/09/21;过去 12 个月发布了 13 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.13.0latest2026/11/0610 天前
0.12.02026/11/0115 天前
0.11.02026/10/3016 天前
0.10.02026/10/3017 天前
0.9.02026/10/3017 天前
0.8.02026/10/2918 天前

关于 @formancy/themes 的常见问题

@formancy/themes 是什么?

Reference themes for formancy renderers — four unrelated looks targeting data-formancy-part hooks — with the builders' stylesheet and the admin's palette. CSS only.

如何安装 @formancy/themes?

在项目目录运行 npm install @formancy/themes,或使用 pnpm add / yarn add / bun add。

@formancy/themes 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/formancy__themes 是否存在。

@formancy/themes 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@formancy/themes 可以商用吗?

@formancy/themes 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@formancy/themes 的下载量有多少?

根据 npm 官方下载统计,@formancy/themes 在 2026/10/16 – 2026/11/14 这 30 天内被下载 4,263 次,日均约 142 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@formancy/themes 还在维护吗?

最新版本 0.13.0 发布于 2026/11/06(10 天前);至今共发布 13 个版本,其中过去 12 个月发布了 13 个;首次发布于 2026/09/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。