@lovett/ui

中文文档
0.6.0发布于 2026/11/02TypeScriptES Module

Design system primitives, tokens, layouts, and patterns for the Lovett portfolio.

原始使用文档
文档目录7 节
  1. Canonical home: here, and only here (ADR-CE-0151, Accepted …
  2. Cutover (ADR-CE-0151 D1, D4)
  3. Develop
  4. Themes
  5. 0.6.0: one tree, published from the family (2026-11-01)
  6. 0.5.0: the owner's UI rules, fixed at the source (2026-10-1…
  7. Known gaps

@lovett/ui

Primitives, tokens, layouts and patterns: the component library ignite-workspace's apps, Lightwork and ads-engine install. Its subsystems include thread, detail, filter-core, data-grid, data-table, meta-previews, file-upload, icons and lib.

Canonical home: here, and only here (ADR-CE-0151, Accepted 2026-11-01)

This directory in edwinlov3tt/lovett-packages is the only source and the only publisher of @lovett/ui. It was imported from ignite-workspace packages/ui with its full history at ignite main @ 2675a1440c6e5b61da21659fd00e1251594fbd65 (2026-10-16), replacing the stale 0.0.9 fork that used to live here. The decision is ADR-CE-0151 in ~/engines/docs/decisions/_active/; packages-pm releases it.

  • Change a primitive here, publish, and consumers bump. A consumer never links this tree with workspace: or file: (ADR-CE-0041).
  • A release is a tag on main (ui-v<version>), packed, the tarball installed and checked, then published. Never from a branch. Every publish must be above the registry's highest version, read at publish time (npm view @lovett/ui versions).

Cutover (ADR-CE-0151 D1, D4)

  1. Publish 0.6.0 from main here. Done when npm's latest equals a pnpm pack of the tag.
  2. ignite-workspace stops publishing (its seat, discoverypro-pm): delete .github/workflows/publish-ui.yml and move npm's trusted publisher off that repo. Until then a ui-v* tag pushed there would publish, and npm would point latest at it.
  3. Lightwork (lw-pm): retire scripts/ui-release.sh or point its LOVETT_UI_DIR here.
  4. Each consumer moves to a family release at the version it chooses: Admium off its vendored tarball, the directory off npm's employer-built 0.5.0, ads-engine off 0.3.4.

Develop

pnpm install          # own lockfile; not a pnpm workspace
pnpm typecheck
pnpm test             # vitest, jsdom
pnpm build            # tsup -> dist/ (ESM, split chunks, bundled .d.ts, CSS + fonts copied)
pnpm check:dist-esm   # refuses a dist Node's ESM resolver cannot load; runs in prepublishOnly

The source exports (main/exports -> ./src) are what a source consumer resolves; publishConfig swaps them to ./dist for the published tarball. Both maps must change together.

scripts/check-dist-esm.mjs scans every dist/*.js. It exists because a deep specifier without a file extension (react-syntax-highlighter/dist/esm/styles/prism) builds green under Vite and fails at import under Node. That shipped as 0.0.7 and 0.0.8, was fixed here at 0.0.9, was lost in ignite's tree (the published 0.4.2 carries it), and is fixed again in 0.5.0.

Themes

One kit, several looks. A theme is a scoped stylesheet that re-points the kit's own token names; no component knows which theme it is in. Import tokens.css and styles.css first, then the theme.

ThemeImportOpt in
kit (dark default, light)@lovett/ui/tokens.cssdata-theme="light" (or combo) on <html>; none means dark
v2@lovett/ui/theme-v2.cssdata-ds="v2" on any element
Lovett (Lightwork)@lovett/ui/theme-lovett.cssdata-ds="lovett" below <html>
Admium (0.5.0)@lovett/ui/theme-admium.cssdata-ds="admium" on <html> or any element, under <html data-theme="light">

Admium is the warm palette with an orange accent (#EF6820 fill, #E04F16 pressed, #FFF0E5 tint, #C2410C orange text), approved by the owner on 2026-10-17 in Admium's lab. It is a token override of the kit's light theme, so it applies only under data-theme="light"; under dark it matches nothing. It adds three things beyond tokens, all scoped to it:

  • The raised primary button: a 1px white inner highlight (12% to 0, top to bottom), a 1px ring in its own orange, a 0 1px 2px rgba(13,18,27,0.24) shadow, a semibold label, and the same radius as every other button. No lift and no glow on hover.
  • Control hairlines: secondary and icon buttons and the search bar rest on #E6E4E2 (--border-control), while dividers stay #F2F1F0.
  • State chips re-resolved in scope, so their tinted borders follow the warm ink.

0.6.0: one tree, published from the family (2026-11-01)

No component changes its look for markup that existed in either 0.5.0. 0.6.0 is the union of the two different 0.5.0s (ADR-CE-0151 D2):

  • The family's 0.5.0 (lovett-packages feat/ui-home b12a8d4, never published; Admium vendors it): the Admium theme and the owner's UI rules below.
  • npm's 0.5.0 (ignite-workspace packages/ui 8f3ae0d1, published 2026-10-18; the directory installs it): the at-risk desk's kit gaps. That is the only ignite commit to touch packages/ui after the split at 2675a144.

What a consumer must know when it moves:

  • From npm's 0.5.0 (the directory): you gain the owner's UI rules below (no bold, no colour transitions, chip borders at 30% of their ink, concentric radii). Those are the owner's intended changes; check your screenshots for them. Every export you had is still there.
  • From the family's 0.5.0 (Admium): you gain StateChip icon and bare, DropdownMenuRadioGroup and DropdownMenuRadioItem, SegmentedPill ariaLabelledBy, ariaDescribedBy and item title, Tray size="wide", Button variant="danger-text", aria-disabled on Button and Switch, readOnly on Switch and Checkbox, Toaster closeButtonLabel and dismissOnEscape. The Lovett-scope ink changes apply only under data-ds="lovett".
  • Replace the dependency with "@lovett/ui": "0.6.0". Tailwind is still needed over the package's source (@source at node_modules/@lovett/ui/src); 0.7.0 removes that need.

Files the merge resolved. npm's commit applied without conflict onto the family tree, so every file carries both sides' changes:

FileFrom the family (b12a8d4)From npm (8f3ae0d1)
src/badge.tsxaccent text reads --accent-inkStateChip icon and bare
src/checkbox.tsxno colour transitionreadOnly
src/dropdown-button.tsxmenu padding 6px to 4px (concentric radii)the danger-text variant's class
src/dropdown-menu.tsxmenu padding, no colour transitionsradio group and radio item; the new radio item's transition-colors removed here, to match the owner's rule (the one edit 0.6.0 makes to npm's code)
src/floating-drawer.tsxno colour transitionTray size="wide"
src/segmented-pill.tsxno colour transitionARIA props, item title
src/styles.cssno colour transitions on buttons, inputs and linksdanger-text, aria-disabled and readOnly styles
src/theme-lovett.csssearch field transitions its shadow onlyLovett-scope inks, disabled primary, danger-text, 16px fields below 640px
package.json0.5.0, the Admium theme export0.5.0

npm's commit alone also changed button.tsx, switch.tsx, toast.tsx and index.ts, and touched nine test files (four of them new). The family's alone touched 73 other files: the rules below, and the new theme-admium.css.

Also in 0.6.0, none of it visible:

  • Lint runs. eslint.config.js extends @lovett/elint/migrating, with react-hooks and the test tsconfig wired. Fixed to pass the hard rules: promise-returning handlers are voided (calculator shells, code block, copy field, file drop zone, folder picker, profile section), and upload ids come from crypto.getRandomValues instead of Math.random.
  • Tests: 1,793 pass, the token-shape test among them.

0.5.0: the owner's UI rules, fixed at the source (2026-10-17)

These change how every consumer renders once it upgrades to 0.5.0. Consumers pin versions, so nothing moves until then. src/__tests__/ui-rules.test.ts greps src/ for the checkable ones so they cannot come back.

  • No bold. font-bold / font-extrabold / font-weight: 700 became font-semibold (600) on headings, titles, labels and figures, and font-medium (500) on inline emphasis (the Markdown strong, the floating status bar's label). Exempt: meta-previews/, which reproduces Facebook / Instagram / Messenger chrome, and the 700 @font-face those previews use.
  • No colour transitions. transition-colors and colour members of transition-[...] lists are gone, transition-all names the property it animated (width, opacity), and the CSS fallbacks for --btn-transition, --input-transition, --pager-transition and --search-transition keep only box-shadow / transform (or none). Colour, background, border-colour, fill and stroke now change immediately. Kept on purpose: geometry tweens (bar widths, chart paths, collapse rows) and the fading scrollbar's scrollbar-color.
  • Tinted chip borders. A chip's border is its own ink at 30%, never a neutral grey: the default --state-*-border tokens (were --border / --border-strong) and DeltaChip's neutral tone. Badge and MetricCard's accent tone now read --accent-ink (identical in the kit's light theme).
  • Concentric radii. Where a rounded element sits 8px or less inside another, the outer radius is the inner radius plus the gap. Fixed in both the kit and the Lovett scope: DropdownMenuContent, DropdownButton, the collapsed-sidebar flyout and the Select / Combobox listbox pad 4px (was 6) around md rows; the FilterDropdown list is lg / 4px / md (was md / 6px / 8px); Modal's tray is lg inside the xl panel (was md); the bubble-menu toolbar and the link group are lg around sm buttons (was sm, rounder inside than out); the data table's filter and column-manager popovers are xl (was md); board column head buttons are lg in the 2xl column; the file preview thumbnail, ChipNav's track (12 default, 10 compact), CopyField's button (now also centred), SegmentedChoice, FilterChip's remove button, TaskCard media and grip, thread suggestions and sort pills, TagChipInput / FolderTreePicker options and chip remove buttons, StatRow's inner panel, the owner strip, FolderCard's checkbox, the attachments drop overlay and the prompt ring's error edge use calc(var(--radius-X) - gap) (or +) so they hold in both themes. Left alone on purpose: controls in a padded footer or field (thread composer footer, attachment chips, chips inside Combobox / TagChipInput fields), where the concentric answer is a square control; hover-only rows (FieldRow, filter-menu rows); and Lovett's search hint, whose concentric radius is a square keycap (Lightwork's call).
  • No conditionally rendered dialogs. The kit had no {x && <Dialog|Modal|Sheet|Drawer>; the test keeps it that way.

Known gaps

  • TODO(ui-tray-exit): Tray (floating-drawer.tsx) has an enter animation but returns null when open is false, so its close animation never runs; Modal also unmounts when closed (it has no animation to lose). Both are driven by their open prop, which is what the dialog rule asks of consumers; keeping Tray mounted through its exit is a separate behaviour change.
  • TODO(ui-lint-backlog): lint runs on @lovett/elint's migrating preset since 0.6.0, with zero errors. Twelve strict rules over code written under ignite's looser config warn instead of failing; they are listed in eslint.config.js and burn down release by release.
  • The ds x ui overlap (60 names, six tokens with clashing formats) is sanctioned coexistence under ADR-CE-0034 D1. Converging the two is a separate decision.

版本与发布记录

@lovett/ui 共发布 31 个版本,首次发布于 2026/06/21;过去 12 个月发布了 31 个版本。

版本发布日期距今
0.6.0latest2026/11/021 天前
0.5.02026/10/1915 天前
0.4.22026/10/0925 天前
0.4.12026/10/0925 天前
0.4.02026/10/0925 天前
0.3.42026/09/291 个月前

关于 @lovett/ui 的常见问题

@lovett/ui 是什么?

为Lovett组合设计系统原语、令牌、布局和模式。

如何安装 @lovett/ui?

在项目目录运行 npm install @lovett/ui,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^19.0.0)、react-dom(^19.0.0)、lucide-react(^0.469.0)、react-router-dom(^7.1.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@lovett/ui 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@lovett/ui 支持 ESM 还是 CommonJS?

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

@lovett/ui 可以商用吗?

@lovett/ui 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@lovett/ui 还在维护吗?

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