@supertype.ai/foundations 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +369 -0
- package/bin/foundations.mjs +713 -0
- package/dist/blocks/accordion.d.ts +23 -0
- package/dist/blocks/accordion.js +59 -0
- package/dist/blocks/callout.d.ts +57 -0
- package/dist/blocks/callout.js +61 -0
- package/dist/blocks/card.d.ts +34 -0
- package/dist/blocks/card.js +56 -0
- package/dist/blocks/index.d.ts +7 -0
- package/dist/blocks/index.js +7 -0
- package/dist/blocks/interactive-accordion.d.ts +13 -0
- package/dist/blocks/interactive-accordion.js +27 -0
- package/dist/blocks/segment.d.ts +37 -0
- package/dist/blocks/segment.js +37 -0
- package/dist/blocks/steps.d.ts +10 -0
- package/dist/blocks/steps.js +13 -0
- package/dist/blocks/tabs.d.ts +32 -0
- package/dist/blocks/tabs.js +69 -0
- package/dist/cjs/eslint.js +146 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cn.d.ts +2 -0
- package/dist/cn.js +5 -0
- package/dist/contrast.d.ts +47 -0
- package/dist/contrast.js +255 -0
- package/dist/eslint.d.ts +74 -0
- package/dist/eslint.js +138 -0
- package/dist/essay/contents.d.ts +10 -0
- package/dist/essay/contents.js +17 -0
- package/dist/essay/essay.d.ts +125 -0
- package/dist/essay/essay.js +92 -0
- package/dist/essay/index.d.ts +7 -0
- package/dist/essay/index.js +9 -0
- package/dist/essay/layout.d.ts +72 -0
- package/dist/essay/layout.js +77 -0
- package/dist/essay/rail.d.ts +15 -0
- package/dist/essay/rail.js +26 -0
- package/dist/essay/reading.d.ts +17 -0
- package/dist/essay/reading.js +31 -0
- package/dist/essay/scroll.d.ts +8 -0
- package/dist/essay/scroll.js +78 -0
- package/dist/essay/toc.d.ts +23 -0
- package/dist/essay/toc.js +50 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +33 -0
- package/dist/injection.d.ts +8 -0
- package/dist/injection.js +1 -0
- package/dist/mdx.d.ts +47 -0
- package/dist/mdx.js +68 -0
- package/dist/og.d.ts +18 -0
- package/dist/og.js +50 -0
- package/dist/rehype.d.ts +18 -0
- package/dist/rehype.js +41 -0
- package/dist/seo.d.ts +174 -0
- package/dist/seo.js +152 -0
- package/dist/typography/as.d.ts +15 -0
- package/dist/typography/as.js +8 -0
- package/dist/typography/header.d.ts +44 -0
- package/dist/typography/header.js +119 -0
- package/dist/typography/highlight.d.ts +33 -0
- package/dist/typography/highlight.js +98 -0
- package/dist/typography/index.d.ts +4 -0
- package/dist/typography/index.js +3 -0
- package/dist/typography/paragraph.d.ts +157 -0
- package/dist/typography/paragraph.js +229 -0
- package/llms.txt +125 -0
- package/package.json +140 -0
- package/src/prose.css +12 -0
- package/src/shiki.css +23 -0
- package/src/theme.css +272 -0
- package/src/tokens.css +43 -0
- package/src/type.css +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Supertype
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
# @supertype.ai/foundations
|
|
2
|
+
|
|
3
|
+
The shared design layer behind the Supertype projects: typography primitives,
|
|
4
|
+
content blocks, the long-form essay shell, the token and theme CSS, and the
|
|
5
|
+
build-time tooling that checks it all (SEO, OG cards, lint rules, contrast
|
|
6
|
+
checks).
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
yarn add @supertype.ai/foundations
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Start here:** [Install](#install) → [Your first page](#your-first-page).
|
|
13
|
+
|
|
14
|
+
**Reference:** [Typography](docs/typography.md) · [Blocks](docs/blocks.md) ·
|
|
15
|
+
[The essay shell](docs/essay.md) · [Build-time tooling](docs/tooling.md) ·
|
|
16
|
+
[The CLI](docs/cli.md)
|
|
17
|
+
|
|
18
|
+
**Working on the package itself:** [Contributing](docs/contributing.md), for
|
|
19
|
+
local iteration against a consumer and for releasing.
|
|
20
|
+
|
|
21
|
+
## See it running
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
yarn example:install # once, to install Next, the peers and the package
|
|
25
|
+
yarn example # then open http://localhost:3000
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
[`examples/site`](examples/site) renders every component next to the source that
|
|
29
|
+
produced it, carries whole-page [recipes](examples/site/app/_recipes) to copy,
|
|
30
|
+
and puts the `dark` and `.editorial` surfaces on a switch. It is also where
|
|
31
|
+
documentation changes get checked, so start here if you are improving the docs.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
Get step 2 or 3 wrong and nothing throws an error; the components just render
|
|
38
|
+
unstyled, or in the wrong typeface. So the package ships a CLI that writes the
|
|
39
|
+
CSS for you and checks the rest:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
npx @supertype.ai/foundations init # edits your CSS entry, prints the rest
|
|
43
|
+
npx @supertype.ai/foundations doctor # checks this app against everything below
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`init` edits one file: the CSS entry that imports Tailwind. It adds the imports
|
|
47
|
+
you are missing and reorders the ones you already have, since the imports are a
|
|
48
|
+
cascade. Run it with `--dry-run` first to see the patch. Everything else it
|
|
49
|
+
prints for you to paste — the font binding, and the `llms.txt` line for a coding
|
|
50
|
+
agent — because those belong in files the CLI has no business rewriting.
|
|
51
|
+
|
|
52
|
+
The steps are written out below anyway. `init` is a shortcut through them, not
|
|
53
|
+
a replacement for knowing what it changed. See [the CLI](docs/cli.md).
|
|
54
|
+
|
|
55
|
+
### 1. Add the package
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
yarn add @supertype.ai/foundations
|
|
59
|
+
# or: npm install @supertype.ai/foundations
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The package ships built, so there is no install-time build step. Peers are
|
|
63
|
+
React 19+, Next 15+, `next-view-transitions` 0.3+ and `@base-ui/react` 1.4+.
|
|
64
|
+
|
|
65
|
+
<details>
|
|
66
|
+
<summary>Installing from a git tag instead</summary>
|
|
67
|
+
|
|
68
|
+
Every release is tagged as well as published, so a commit can be installed
|
|
69
|
+
directly — useful for trying an unreleased fix. Pin a tag, never `#main`: an
|
|
70
|
+
untagged git dependency re-resolves to a different commit on any fresh install.
|
|
71
|
+
|
|
72
|
+
```jsonc
|
|
73
|
+
// package.json
|
|
74
|
+
"@supertype.ai/foundations": "https://github.com/supertypeai/foundations.git#v0.1.24"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
</details>
|
|
78
|
+
|
|
79
|
+
### 2. Import the CSS, in this order
|
|
80
|
+
|
|
81
|
+
```css
|
|
82
|
+
/* app/global.css */
|
|
83
|
+
@import "tailwindcss";
|
|
84
|
+
@import "@supertype.ai/foundations/tokens.css"; /* structural tokens + dark variant */
|
|
85
|
+
@import "@supertype.ai/foundations/theme.css"; /* the house palette */
|
|
86
|
+
@import "@supertype.ai/foundations/type.css"; /* the type ramp + font roles */
|
|
87
|
+
@import "@supertype.ai/foundations/prose.css"; /* inline-code rule */
|
|
88
|
+
@import "@supertype.ai/foundations/shiki.css"; /* only if you render code fences */
|
|
89
|
+
|
|
90
|
+
@source '../node_modules/@supertype.ai/foundations/dist/**/*.js';
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**The `@source` line is required.** Tailwind does not scan `node_modules` by
|
|
94
|
+
default, so without it every class the package ships is purged and the components
|
|
95
|
+
render with no styles at all.
|
|
96
|
+
|
|
97
|
+
**`theme.css` is required.** `tokens.css` names the colour roles; `theme.css` is
|
|
98
|
+
what gives them values. Without it every colour utility still generates and
|
|
99
|
+
resolves to nothing, so the page renders unpainted with no error. It also carries
|
|
100
|
+
`--secondary-ink`, `--subtle-foreground`, the four earth tones the marker
|
|
101
|
+
highlight uses, and the `accordion-down` and `accordion-up` keyframes. Skip it
|
|
102
|
+
only if you declare every role yourself; `foundations doctor` fails when neither
|
|
103
|
+
is true, and names the roles you left unpainted.
|
|
104
|
+
|
|
105
|
+
### 3. Bind the fonts
|
|
106
|
+
|
|
107
|
+
The package cannot load the typefaces for you. `next/font` runs in your app and
|
|
108
|
+
generates hashed variable names at build time, so each app loads the three fonts
|
|
109
|
+
and binds them to the roles `type.css` expects:
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
// app/layout.tsx
|
|
113
|
+
import { Ubuntu_Sans, Ubuntu_Sans_Mono, Average } from "next/font/google";
|
|
114
|
+
|
|
115
|
+
const sans = Ubuntu_Sans({ variable: "--font-ubuntu-sans", subsets: ["latin"] });
|
|
116
|
+
const mono = Ubuntu_Sans_Mono({ variable: "--font-ubuntu-sans-mono", subsets: ["latin"] });
|
|
117
|
+
const serif = Average({ variable: "--font-average", weight: "400", subsets: ["latin"] });
|
|
118
|
+
|
|
119
|
+
<html className={`${sans.variable} ${mono.variable} ${serif.variable} font-sans`}>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Bind with `.variable`, never `.className`.** A className sets `font-family` on
|
|
123
|
+
the element itself and leaves the roles unresolved, so the page renders one
|
|
124
|
+
typeface while every `font-sans` and `font-heading` utility on it renders
|
|
125
|
+
another.
|
|
126
|
+
|
|
127
|
+
### 4. Check the wiring
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
npx foundations doctor
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
It reads your CSS entry, your root layout and the installed tree, then reports
|
|
134
|
+
on import order, the `@source` path, the font bindings and the peer versions. It
|
|
135
|
+
exits non-zero on a real problem, so it works as a CI step too. Every check and
|
|
136
|
+
what it catches is listed in [the CLI](docs/cli.md).
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Your first page
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import {
|
|
144
|
+
TypographyH1,
|
|
145
|
+
TypographyH2,
|
|
146
|
+
TypographyProse,
|
|
147
|
+
TypographyEyebrow,
|
|
148
|
+
TypographyLink,
|
|
149
|
+
TypographyCaption,
|
|
150
|
+
} from "@supertype.ai/foundations";
|
|
151
|
+
import { Card, Cards, Callout } from "@supertype.ai/foundations/blocks";
|
|
152
|
+
|
|
153
|
+
export default function Page() {
|
|
154
|
+
return (
|
|
155
|
+
<main className="mx-auto max-w-3xl px-6 py-16">
|
|
156
|
+
<TypographyEyebrow>Guides</TypographyEyebrow>
|
|
157
|
+
<TypographyH1 variant="display" className="mt-2 text-balance">
|
|
158
|
+
Getting data out of Postgres
|
|
159
|
+
</TypographyH1>
|
|
160
|
+
<TypographyProse className="mt-4">
|
|
161
|
+
Three approaches, ordered by how much of your schema they need to know.
|
|
162
|
+
</TypographyProse>
|
|
163
|
+
|
|
164
|
+
<TypographyH2 divider className="mt-12">
|
|
165
|
+
Approaches
|
|
166
|
+
</TypographyH2>
|
|
167
|
+
|
|
168
|
+
<Cards>
|
|
169
|
+
<Card
|
|
170
|
+
href="/notes/logical-replication"
|
|
171
|
+
title="Logical replication"
|
|
172
|
+
description="Row-level changes, no schema coupling."
|
|
173
|
+
/>
|
|
174
|
+
<Card
|
|
175
|
+
href="https://www.postgresql.org/docs/current/sql-copy.html"
|
|
176
|
+
title="COPY"
|
|
177
|
+
description="Fastest bulk path. Leaves the app."
|
|
178
|
+
/>
|
|
179
|
+
</Cards>
|
|
180
|
+
|
|
181
|
+
<Callout tone="warn" title="Before you start" className="mt-8">
|
|
182
|
+
Replication slots hold WAL until they are consumed. An abandoned slot
|
|
183
|
+
fills the disk — see{" "}
|
|
184
|
+
<TypographyLink href="/ops/slots" addArrow>
|
|
185
|
+
slot hygiene
|
|
186
|
+
</TypographyLink>
|
|
187
|
+
.
|
|
188
|
+
</Callout>
|
|
189
|
+
|
|
190
|
+
<TypographyCaption as="p" className="mt-8">
|
|
191
|
+
Last reviewed March 2026
|
|
192
|
+
</TypographyCaption>
|
|
193
|
+
</main>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Two rules cover most of the API:
|
|
199
|
+
|
|
200
|
+
- **Do not write type styles by hand.** A paragraph carrying
|
|
201
|
+
`text-sm text-muted-foreground` is `<TypographyMuted>`. Using the primitives
|
|
202
|
+
keeps a size and a colour from drifting apart across a few hundred call sites.
|
|
203
|
+
- **Retune with CSS variables, not classes.** The package owns its own
|
|
204
|
+
classnames. Change a `--text-*` rung, `--heading-weight` or a colour token and
|
|
205
|
+
everything moves together.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## The example site
|
|
210
|
+
|
|
211
|
+
`yarn example` (above) builds the package, syncs it in and starts the dev
|
|
212
|
+
server. `yarn example:build` is what CI would run.
|
|
213
|
+
|
|
214
|
+
It installs the package from a git tag rather than from the registry — the
|
|
215
|
+
install path that has no lockfile-independent proof anywhere else — and updates
|
|
216
|
+
it with `yarn sync`, with no workspace and no symlink. Its `global.css`
|
|
217
|
+
and `layout.tsx` are the blocks above, unchanged, so an install instruction that
|
|
218
|
+
stops being true breaks the site.
|
|
219
|
+
|
|
220
|
+
`/recipes` holds whole pages rather than single components: a marketing hero, a
|
|
221
|
+
metrics panel, pricing tiers, a docs page, an article index, and the three files
|
|
222
|
+
that wire up MDX. Each one lives in
|
|
223
|
+
[`app/_recipes/`](examples/site/app/_recipes) as a complete file that imports
|
|
224
|
+
only from this package, so you can paste it into your app and it compiles.
|
|
225
|
+
`yarn example:build` fails if a recipe reaches for a local helper.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## For coding agents
|
|
230
|
+
|
|
231
|
+
The package ships an `llms.txt` with the public API, the rules, and the mistakes
|
|
232
|
+
that do not produce an error. Point your agent at it once and it stops
|
|
233
|
+
hand-writing `text-sm text-muted-foreground` where a primitive exists:
|
|
234
|
+
|
|
235
|
+
```md
|
|
236
|
+
<!-- CLAUDE.md, AGENTS.md, or your agent's equivalent -->
|
|
237
|
+
|
|
238
|
+
@node_modules/@supertype.ai/foundations/llms.txt
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`yarn build` fails if an export is missing from it, so it cannot fall behind the
|
|
242
|
+
package.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Entry points
|
|
247
|
+
|
|
248
|
+
| import | contains | docs |
|
|
249
|
+
| --------------------------------------------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------- |
|
|
250
|
+
| `@supertype.ai/foundations` | all typography primitives, `cn` | [Typography](docs/typography.md) |
|
|
251
|
+
| `@supertype.ai/foundations/blocks` | `Card`, `Callout`, `Steps`, `Tabs`, `Accordion`, `Disclosure`, `SEGMENT` | [Blocks](docs/blocks.md) |
|
|
252
|
+
| `@supertype.ai/foundations/mdx` | `proseMdxComponents` — the MDX element map | [In MDX](docs/blocks.md#in-mdx) |
|
|
253
|
+
| `@supertype.ai/foundations/essay` | the long-form shell, TOC, reading rail, post meta | [Essay](docs/essay.md) |
|
|
254
|
+
| `@supertype.ai/foundations/seo` | `createSeo(...)` — metadata + JSON-LD | [Tooling](docs/tooling.md#seo-and-og-images) |
|
|
255
|
+
| `@supertype.ai/foundations/og` | `ogCard`, `OG_SIZE` — an element for `next/og` | [Tooling](docs/tooling.md#seo-and-og-images) |
|
|
256
|
+
| `@supertype.ai/foundations/eslint` | the design rules as ESLint selectors | [Tooling](docs/tooling.md#lint-rules) |
|
|
257
|
+
| `@supertype.ai/foundations/rehype` | `rehypeProseCode` — **build-time only** | [In MDX](docs/blocks.md#in-mdx) |
|
|
258
|
+
| `@supertype.ai/foundations/contrast` | token resolution + legibility checks, build-time only | [Tooling](docs/tooling.md#contrast-checks) |
|
|
259
|
+
| `./tokens.css` `./theme.css` `./type.css` `./prose.css` `./shiki.css` | the style layer | [Tokens and theming](#tokens-and-theming) |
|
|
260
|
+
| `foundations` (bin) | `init` and `doctor` | [The CLI](docs/cli.md) |
|
|
261
|
+
|
|
262
|
+
The entries are split by what they pull in. Blocks and the MDX map stay out of
|
|
263
|
+
the root barrel so that importing a heading does not resolve `@base-ui/react` or
|
|
264
|
+
`next/image`, and `/rehype` and `/contrast` stay out of both so they can run in
|
|
265
|
+
bare Node, where React cannot be resolved.
|
|
266
|
+
|
|
267
|
+
None of the entry points can be imported from plain Node, though: typography
|
|
268
|
+
reaches `next/link` through `next-view-transitions`. Import them from a Next app,
|
|
269
|
+
or from a test runner that resolves Next — both consumers' vitest suites do.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Tokens and theming
|
|
274
|
+
|
|
275
|
+
`tokens.css` names the structural roles and nothing else: `--background`,
|
|
276
|
+
`--foreground`, `--card`, `--muted`, `--primary`, `--border` and `--ring`, plus
|
|
277
|
+
the status set. They are named for meaning rather than hue, so a project that
|
|
278
|
+
renders `success` in blue still reads correctly. It holds no values, so there is
|
|
279
|
+
only ever one palette in play.
|
|
280
|
+
|
|
281
|
+
Each status hue ships twice, on the same rule as the categorical tints:
|
|
282
|
+
`--success`, `--warn` and `--info` are **fills**, held to 3:1 against the page
|
|
283
|
+
and a card because a dot or a bar is a mark rather than words; `--success-ink`,
|
|
284
|
+
`--warn-ink` and `--info-ink` are the same hues as **text**, held to 4.5:1.
|
|
285
|
+
`--danger` ships as an ink only. `--destructive` keeps shadcn's shape, where
|
|
286
|
+
`--destructive-foreground` is the label printed on the fill — that is what
|
|
287
|
+
`-foreground` means throughout, and `-ink` means the hue used as words.
|
|
288
|
+
`checkSignals` in `@supertype.ai/foundations/contrast` measures all three bars.
|
|
289
|
+
|
|
290
|
+
`tokens.css` also binds the `dark:` variant to the `.dark` class. Do not skip
|
|
291
|
+
that import: Tailwind v4 otherwise follows the OS setting and quietly ignores
|
|
292
|
+
your toggle.
|
|
293
|
+
|
|
294
|
+
`theme.css` gives those roles the house latte and espresso palette, and adds the
|
|
295
|
+
editorial inks (`--secondary-ink`, `--subtle-foreground`, and the ochre,
|
|
296
|
+
terracotta, sage and fig pairs) along with the elevation shadows.
|
|
297
|
+
|
|
298
|
+
**No brand colours in the package.** Structural tokens only, with brand colours
|
|
299
|
+
left to the app. To repaint, override the raw variables after the imports rather
|
|
300
|
+
than patching the utilities:
|
|
301
|
+
|
|
302
|
+
```css
|
|
303
|
+
:root {
|
|
304
|
+
--primary: hsl(24 60% 42%);
|
|
305
|
+
}
|
|
306
|
+
.dark {
|
|
307
|
+
--primary: hsl(24 70% 62%);
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### `.editorial`
|
|
312
|
+
|
|
313
|
+
`type.css` names three font roles (`--font-sans`, `--font-mono` and
|
|
314
|
+
`--font-heading`) and the weight that goes with the heading face. `.editorial`
|
|
315
|
+
gives the heading role to the serif and drops the weight to 400, since Average
|
|
316
|
+
only has one:
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
<div className="editorial">…</div> {/* or on <html> for an editorial site */}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
It also retunes the whole heading ladder, which is the larger part of what it
|
|
323
|
+
does. Heading sizes are a _ratio_ to the body text under them, and the two
|
|
324
|
+
surfaces set body at different sizes: 13px in the product, 18px on `.editorial`. Scope the
|
|
325
|
+
class to whichever surfaces should be editorial, whether that is a marketing and
|
|
326
|
+
docs section or the whole site.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Design rules
|
|
331
|
+
|
|
332
|
+
1. **The package owns its final classnames.** Retune with CSS custom properties
|
|
333
|
+
(the `--text-*` ramp, `--heading-weight`, the colour tokens) rather than by
|
|
334
|
+
patching classes. A property the package declares is read by the package —
|
|
335
|
+
`test/tokens-live.test.ts` fails on one that is not, because a knob that
|
|
336
|
+
turns nothing is worse than no knob at all.
|
|
337
|
+
2. **No variant props on the MDX map.** Elements that MDX renders automatically
|
|
338
|
+
take no options, because there is no call site to make the choice. Components
|
|
339
|
+
you invoke by hand can have variants.
|
|
340
|
+
3. **Use the platform first, and a library only where it falls short.**
|
|
341
|
+
`Disclosure` is a `<details>`/`<summary>` pair: no JavaScript, correct before
|
|
342
|
+
hydration, and available to an MDX author. `Accordion` and `Tabs` use Base UI,
|
|
343
|
+
since animation and managed selection are beyond what the platform gives you.
|
|
344
|
+
4. **No brand colours.** Structural tokens only, with brand colours left to the
|
|
345
|
+
app.
|
|
346
|
+
5. **Put structure in CSS rather than the component map.** A host framework can
|
|
347
|
+
substitute its own element and strip the classes off it, but it cannot strip a
|
|
348
|
+
child combinator. Both the Shiki theming and the inline-code rule rely on
|
|
349
|
+
this.
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## In production
|
|
354
|
+
|
|
355
|
+
Sites running the package:
|
|
356
|
+
|
|
357
|
+
- [supertype.ai](https://supertype.ai) — Supertype, a regional-leading analytics engineering and data science consulting firm.
|
|
358
|
+
- [viably.app](https://viably.app) — Viably, an observability-first business operating system and CRM for automation-obsessed teams.
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## License
|
|
363
|
+
|
|
364
|
+
MIT. Copyright © 2026 Supertype. See [LICENSE](LICENSE).
|
|
365
|
+
|
|
366
|
+
Published to npm as
|
|
367
|
+
[`@supertype.ai/foundations`](https://www.npmjs.com/package/@supertype.ai/foundations),
|
|
368
|
+
and installable from this repository by tag. The MIT grant covers using,
|
|
369
|
+
modifying and redistributing it either way.
|