@archetypeai/ds-lib-tokens

中文文档
0.21.0发布于 2026/10/30MITES Module零依赖近 30 天下载 6928

Archetype AI Design System Tokens

原始使用文档
文档目录9 节
  1. @archetypeai/ds-lib-tokens
  2. Install
  3. Usage
  4. What's Included
  5. The 850 step
  6. Type scale
  7. Semantic HTML base layer
  8. Fonts
  9. Preloading

@archetypeai/ds-lib-tokens

Tailwind v4 theme for the Archetype AI Design System. Provides semantic design tokens, color palettes, and base styles for use with the design system component flavors.


Install

npm install @archetypeai/ds-lib-tokens tailwindcss

Usage

Import the theme before Tailwind in your global CSS:

@import '@archetypeai/ds-lib-tokens/fonts.css'; /* optional → PP Neue Montreal (requires font files in static/fonts/) */
@import '@archetypeai/ds-lib-tokens/theme.css';
@import 'tailwindcss';
<div class="bg-background text-foreground p-md border-border rounded-lg">
  Hello world
</div>

What's Included

FeatureDetails
Semantic TokensOKLCH CSS variables (shadcn-style): background, foreground, card, popover, primary, secondary, muted, accent, destructive, border, separator, scrollbar, scrollbar-track, input, ring, chart-1–5, sidebar, table, table-header, table-section, atai-neutral, atai-good, atai-warning, atai-critical, atai-always-black, atai-always-white
Brand colors4 flat OKLCH values, no scale: brand-babyblue, brand-yellow, brand-black, brand-white
Color palettes26 OKLCH ramps: Tailwind's 22 stock scales (red…rose, slate, gray, zinc, neutral, stone) plus 4 design-system neutrals (mauve, olive, mist, taupe). Each runs 50–950 plus an 850 step — see below
Spacing scale--spacing-xs (0.25rem) → --spacing-xl (1.5rem), used as p-md, gap-lg, …
Radius scale--radius-xs → --radius-xl, --radius-full, plus --atai-radius-interactive (radius for interactive elements, rounded-interactive)
Icon stroke widths--stroke-width-icon-{default,interactive,status,emphasis} (1 / 1.25 / 1.5 / 2) for Lucide icons
Width scale guard--max-width-*/--min-width-* alias Tailwind's --container-* scale, so max-w-md resolves to container sizes instead of the t-shirt spacing tokens
Dark mode.dark class via @custom-variant dark (&:where(.dark, .dark *))
TypographyFont-family stacks with metric-matched fallbacks, a paired type scale (--text-*--line-height / --letter-spacing on every step, plus --text-2xs), and a semantic HTML base layer
Scrollbars--scrollbar/--scrollbar-track (thumb + track colour, bg-scrollbar) and --scrollbar-width. Applied globally in the base layer, so every scroller follows the theme with no app code

Brand colors and palettes are defined in colors.css and loaded automatically via theme.css.

The 850 step

Every ramp carries an 850 shade that stock Tailwind does not have. Tailwind's scale is coarse at the dark end — zinc-800 → zinc-900 drops 0.064 in OKLCH lightness — which left dark mode with a single surface stop that --card and --popover both had to share, so a Card inside a Dialog was distinguishable only by its ring.

Each 850 is the per-component midpoint of its 800 and 900 neighbours in OKLCH, gamut-mapped back into sRGB where a straight midpoint fell outside it (emerald, sky, rose — chroma reduced, lightness and hue held). --card uses zinc-850 in dark mode, giving surfaces four steps instead of three:

Ltokensurface
0.141--backgroundpage
0.210--popover / --sidebar / --secondary / --table-headerdialog, dropdown menu, select, side panel, sidebar, table header
0.242--card / --tablecard, alert, item, charts, table
0.274--input / --muted / --borderfields, wells, edges

Light mode is unaffected: --card stays zinc-50 against a white --popover.

The table has its own surface: --table equals --card today, so a table reads as a panel, and is its own token so the two can part without touching Card. --table-header sits one step back from it in both themes (zinc-100 light, zinc-900 dark), so the header recedes from the body while the --border line under it stays visible. --table-section fills a section divider inside the body (zinc-200 light, zinc-950 dark), a step deeper than the header in both themes. Row hover and selection stay on --muted.

Type scale

Every stock text-* step carries its own line-height and optical letter-spacing, so text-sm alone is on-brand — never pair a text-* utility with leading-* or tracking-*; the ramp already supplies both. Tracking tightens as size grows; leading loosens as size shrinks.

stepsizeline-heightletter-spacing
text-2xs10px14px0.02em
text-xs12px16px0.01em
text-sm14px20px0
text-base16px24px0
text-lg18px26px-0.005em
text-xl20px28px-0.01em
text-2xl24px30px-0.015em
text-3xl30px36px-0.02em
text-4xl36px40px-0.025em
text-5xl48px52px-0.03em
text-6xl–text-9xl60–128px1-0.035 / -0.04em

Line-heights are whole pixels at the root size so adjacent rows and cells share a pixel grid.

text-2xs (10px) is the floor for dense metadata — use it instead of arbitrary text-[10px]/text-[11px]. Letter-spacing is keyed by size, not family, so font-mono at lg and above inherits the negative tracking; at the sizes mono is used in the design system (xs/sm) it is 0 or positive.

The primitives follow the same rule: no leading-* or tracking-* sits beside a text-* anywhere in ds-ui-svelte. The one deliberate off-scale construct is Counter's digit roller (text-[1em] + leading-(--counter-row) in counter.svelte), which needs em-relative glyphs and a fixed row height to animate a rolling digit; it is the only place arbitrary sizing is accepted. At size="inherit" that row is 1lh, so a bare counter set in running text rolls on the line height it inherits rather than on a pill's fixed row.

Semantic HTML base layer

theme.css styles a small set of authored-content elements so plain markup is on-brand without utility classes. code and pre need no rule: Tailwind preflight already gives them --font-mono, and PP Neue Montreal Sans and Mono share identical x-height and cap-height, so inline code sits at the same size as the text around it.

elementstyles
bodybg-background text-foreground font-sans text-sm — the base size is set once here and inherited
h1 / h2 / h3text-primary, text-3xl / text-2xl / text-xl, font-normal, text-balance; h1 also capitalize
h4 / h5 / h6text-muted-foreground, text-lg / text-base / text-sm, font-normal
ptext-primary text-pretty (inherits size)
smalltext-primary text-xs
strongfont-medium (inherits size)
blockquoteborder-s-2 ps-6 italic
acursor-pointer — affordance only, no colour and no size

Only h1–h6 and small carry a font-size; everything else inherits, so a size on a parent always wins.

Deliberately unstyled: span, label, em, code, pre. They are structural — they appear inside third-party widgets, form libraries and highlighted code — and an element rule on them beats the parent's size in every consumer, which forced apps to restate text-* on every inline child. They inherit from their parent instead. a is in the same family and carries no typography for the same reason, but it does get cursor-pointer: the UA sheet gives the pointer only to a[href], so an anchor wired to a click handler — or handed to a router through a child snippet before the href lands — would otherwise read as plain text. Consequences: bare links are still visually flat (Tailwind preflight gives a color: inherit; text-decoration: inherit) until the app styles them, and a purely decorative anchor now shows a pointer it has not earned; <label> typography is owned by the Label primitive. h1 is title-cased (capitalize, override with normal-case); no other heading carries a text-transform — uppercase is opt-in via Label variants and the typography="mono" axis. All elements default to border-border and outline-ring/50.

Scrollbars are governed by the base layer too: the universal * rule sets scrollbar-color / scrollbar-width from --scrollbar / --scrollbar-track / --scrollbar-width, so every overflow box — including ones in your own app — gets a themed bar with no classes. The declaration sits on * rather than :root on purpose: both properties are inherited, but var() substitutes where the declaration lives, so * is what lets a .dark on any subtree flip that subtree's scrollbars.

Only the standard scrollbar properties are used. In Chromium 121+ / WebKit 18.2+ a non-auto scrollbar-color or scrollbar-width opts an element out of the legacy ::-webkit-scrollbar pseudo-elements, so the two are mutually exclusive rather than layered — and the standard pair is the only one Chromium, WebKit and Gecko all implement. Consequences: thumb radius and an explicit hover colour are not expressible (engines derive hover from the thumb colour), --scrollbar-width takes only auto | thin | none, and macOS renders overlay scrollbars that take no layout space and ignore thickness. Retheme by redefining the tokens; hide a single scroller's bar with [scrollbar-width:none].


Fonts

fonts.css is included in this package with two kinds of @font-face declarations: 13 WOFF2 faces of PP Neue Montreal Sans + Mono (font-display: swap) pointing to /fonts/*.woff2, plus 20 metric-matched fallback faces (per-OS base × per weight). The font binaries themselves are not part of the npm package - the CLI (ds create / ds init / ds add --fonts <path>) copies them into your project's static/fonts/. The 13 files total ~820 KB (the foundry's TTF/OTF were 2.1 MB); regenerate them from the originals with fontTools if the brand font is ever updated:

python3 -c "from fontTools.ttLib import TTFont; from pathlib import Path
for src in sorted(Path('.').glob('PPNeueMontreal*.[to]tf')): f = TTFont(src); f.flavor = 'woff2'; f.save(src.with_suffix('.woff2'))"

When the binaries are absent, the fallback faces take over: each re-shapes a local system font to PP Neue Montreal's own metrics — x-height, average character width, and line box — via size-adjust + ascent/descent/line-gap-override, so an un-provisioned project still renders at the brand font's proportions and lays out identically. When the binaries are present, the same faces make the fallback→brand-font swap shift-free (no layout shift / CLS).

The fallback bases are chosen per operating system (the stacks in theme.css order them so each platform resolves its closest native font, all confirmed local()-reachable):

AppleWindowsAndroid
SansHelvetica NeueArialRoboto
MonoMenloConsolas / Cascadia MonoRoboto Mono

SF Mono is intentionally not used — it is not reachable via local(). Override numbers are generated with @capsizecss from the Regular weights (regenerate if the brand font's metrics change).

Preloading

font-display: swap plus the metric-matched fallbacks make the swap shift-free, but the first paint still happens in the fallback face unless the browser is told to fetch the brand font before it discovers the @font-face rule. The CLI therefore inserts three preloads above %sveltekit.head% in src/app.html whenever it installs fonts - the faces the first paint uses: Book (400 sans, body), Medium (500 sans, strong and emphasis) and Mono Book (400 mono, labels, badges, counts). Every other face is fetched lazily when rendered text first needs it.

<link rel="preload" as="font" type="font/woff2" crossorigin href="/fonts/PPNeueMontreal-Book.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="/fonts/PPNeueMontreal-Medium.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="/fonts/PPNeueMontrealMono-Book.woff2" />

crossorigin is mandatory even for same-origin fonts - font requests are always CORS-mode, and a preload without it does not match, so the browser downloads the file twice. If your host has no src/app.html (or a custom one without the placeholder) the CLI prints these tags for you to paste into <head>.

Weights are declared per instance: local('Helvetica Neue') always resolves to the Regular cut regardless of the font-weight descriptor, so a single face would silently render Medium as Regular and faux-bold 700. Each weight therefore names its real cut (local('HelveticaNeue-Medium') / -Bold, etc.). Bases without a true Medium (Arial, Menlo, Cascadia) omit 500, so it matches down to Regular.

版本与发布记录

@archetypeai/ds-lib-tokens 共发布 64 个版本,首次发布于 2026/03/10;过去 12 个月发布了 64 个版本。

版本发布日期距今
0.21.0latest2026/10/308 天前
0.20.02026/10/2315 天前
0.19.02026/10/1622 天前
0.18.12026/10/081 个月前
0.18.02026/10/031 个月前
0.17.02026/09/181 个月前

关于 @archetypeai/ds-lib-tokens 的常见问题

@archetypeai/ds-lib-tokens 是什么?

Archetype AI Design System Tokens

如何安装 @archetypeai/ds-lib-tokens?

在项目目录运行 npm install @archetypeai/ds-lib-tokens,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:tailwindcss(^4.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@archetypeai/ds-lib-tokens 支持 TypeScript 吗?

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

@archetypeai/ds-lib-tokens 支持 ESM 还是 CommonJS?

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

@archetypeai/ds-lib-tokens 可以商用吗?

@archetypeai/ds-lib-tokens 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@archetypeai/ds-lib-tokens 的下载量有多少?

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

@archetypeai/ds-lib-tokens 还在维护吗?

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