@eduardoalvarez/arrecife 0.6.0 → 0.8.0
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/CHANGELOG.md +112 -0
- package/README.md +288 -49
- package/dist/brand/index.cjs +2 -2
- package/dist/brand/index.js +3 -3
- package/dist/chart/index.cjs +129 -2
- package/dist/chart/index.d.cts +114 -4
- package/dist/chart/index.d.ts +114 -4
- package/dist/chart/index.js +129 -5
- package/dist/{chunk-PMN7NR3G.js → chunk-5A5GH2PF.js} +1 -1
- package/dist/{chunk-DKCN7BAL.js → chunk-6IGD5REB.js} +1 -1
- package/dist/{chunk-XKYHTOUJ.js → chunk-FAAGZG7A.js} +1 -1
- package/dist/{chunk-O4TAH7YJ.js → chunk-FGFNK72B.js} +29 -5
- package/dist/chunk-HOADZ6GS.js +72 -0
- package/dist/chunk-LXRGQKMG.js +145 -0
- package/dist/{chunk-6O3KWB6P.js → chunk-MPZBF2TZ.js} +2 -2
- package/dist/{chunk-JMOOFZ3B.js → chunk-TRPBID2W.js} +1 -1
- package/dist/{chunk-25YNFCIF.js → chunk-XXDATT3A.js} +6 -3
- package/dist/doctor.mjs +248 -0
- package/dist/form/index.cjs +2 -2
- package/dist/form/index.d.cts +1 -1
- package/dist/form/index.d.ts +1 -1
- package/dist/form/index.js +4 -4
- package/dist/icons/index.cjs +149 -0
- package/dist/icons/index.d.cts +94 -0
- package/dist/icons/index.d.ts +94 -0
- package/dist/icons/index.js +28 -0
- package/dist/index-BbRplw_B.d.cts +58 -0
- package/dist/index-BbRplw_B.d.ts +58 -0
- package/dist/index.cjs +425 -251
- package/dist/index.d.cts +303 -104
- package/dist/index.d.ts +303 -104
- package/dist/index.js +283 -285
- package/dist/{label-MgHFKnFy.d.ts → label-DJ4HuD-R.d.cts} +3 -2
- package/dist/{label-MgHFKnFy.d.cts → label-DJ4HuD-R.d.ts} +3 -2
- package/dist/og/index.cjs +3 -2
- package/dist/og/index.js +1 -1
- package/dist/shiki/index.js +1 -1
- package/dist/social/data.cjs +161 -0
- package/dist/social/data.d.cts +161 -0
- package/dist/social/data.d.ts +161 -0
- package/dist/social/data.js +2 -0
- package/dist/social/index.cjs +153 -0
- package/dist/social/index.d.cts +2 -0
- package/dist/social/index.d.ts +2 -0
- package/dist/social/index.js +3 -0
- package/dist/tokens/index.cjs +29 -5
- package/dist/tokens/index.d.cts +37 -10
- package/dist/tokens/index.d.ts +37 -10
- package/dist/tokens/index.js +2 -2
- package/dist/tokens/theme.css +79 -22
- package/dist/variants/index.cjs +6 -3
- package/dist/variants/index.d.cts +6 -3
- package/dist/variants/index.d.ts +6 -3
- package/dist/variants/index.js +1 -1
- package/llms.txt +530 -80
- package/package.json +29 -2
package/llms.txt
CHANGED
|
@@ -41,7 +41,7 @@ Radix, `clsx`, `tailwind-merge`, `class-variance-authority`, `date-fns` and
|
|
|
41
41
|
`react-day-picker` come as dependencies of the library. You do not need to
|
|
42
42
|
install or declare them.
|
|
43
43
|
|
|
44
|
-
**It ships no
|
|
44
|
+
**It ships no icon set.** The glyphs the components
|
|
45
45
|
need are inline, inherit `currentColor` and measure 1em.
|
|
46
46
|
|
|
47
47
|
## Tailwind configuration
|
|
@@ -116,23 +116,27 @@ that only whoever uses them installs.
|
|
|
116
116
|
| `@eduardoalvarez/arrecife/og` | **no** | — | The Open Graph templates for Satori |
|
|
117
117
|
| `@eduardoalvarez/arrecife/shiki` | **no** | — | The syntax highlighting theme |
|
|
118
118
|
| `@eduardoalvarez/arrecife/brand` | yes | — | Logo, isotype and mascot as components |
|
|
119
|
+
| `@eduardoalvarez/arrecife/social` | yes, on the server only | — | The ten social icons, loose. No `"use client"` |
|
|
120
|
+
| `@eduardoalvarez/arrecife/social/data` | **no** | — | The same ten as shapes, plus `socialSvg`. For a template that mounts no React |
|
|
121
|
+
| `@eduardoalvarez/arrecife/icons` | yes | `@phosphor-icons/react` | `Icon`, which draws a Phosphor icon at the system's size, and at the weight its role asks for |
|
|
119
122
|
| `@eduardoalvarez/arrecife/form` | yes | `react-hook-form` | The form layer: labels, errors and `aria-*` |
|
|
120
|
-
| `@eduardoalvarez/arrecife/chart` | yes | `recharts` | The chart chassis
|
|
123
|
+
| `@eduardoalvarez/arrecife/chart` | yes | `recharts` | The chart chassis, the series palette and the three chart types |
|
|
121
124
|
| `@eduardoalvarez/arrecife/assets/*` | — | — | The brand PNGs |
|
|
122
125
|
|
|
123
126
|
Importing the root from a build script to get one token is the mistake the
|
|
124
127
|
subpaths exist to prevent: it drags all of React into a worker that never mounts
|
|
125
128
|
it.
|
|
126
129
|
|
|
127
|
-
`./form` and `./
|
|
128
|
-
hung off the main index, the projects that draw no charts
|
|
129
|
-
Form would have to install those dependencies anyway so
|
|
130
|
-
resolve an import they never execute.
|
|
130
|
+
`./form`, `./chart` and `./icons` sit outside the root for the symmetric reason:
|
|
131
|
+
if they hung off the main index, the projects that draw no charts, use no React
|
|
132
|
+
Hook Form and need no icons would have to install those dependencies anyway so
|
|
133
|
+
their bundler could resolve an import they never execute. Two of the five consume
|
|
134
|
+
zero icons.
|
|
131
135
|
|
|
132
136
|
### Next, Server Components and `"use client"`
|
|
133
137
|
|
|
134
138
|
The root, `./brand`, `./form` and `./chart` ship `"use client"` in the published
|
|
135
|
-
`dist
|
|
139
|
+
`dist/`, and they are the only four. They render React and their Radix primitives call `createContext` at
|
|
136
140
|
module scope, so without the directive a Next project with the App Router cannot
|
|
137
141
|
import them at all: it fails at build time with
|
|
138
142
|
`TypeError: (0 , r.createContext) is not a function`.
|
|
@@ -143,9 +147,13 @@ import in an adapter of your own marked `"use client"` — that was the workarou
|
|
|
143
147
|
before 0.6.0 and it pulled 272 KB of client chunk in for components that never
|
|
144
148
|
needed it.
|
|
145
149
|
|
|
146
|
-
The
|
|
147
|
-
matters in a Server Component: `./tokens`, `./theme`, `./variants`, `./
|
|
148
|
-
`./shiki` stay on the server.
|
|
150
|
+
The six portable subpaths do NOT carry the directive, and that is the half that
|
|
151
|
+
matters in a Server Component: `./tokens`, `./theme`, `./variants`, `./social/data`,
|
|
152
|
+
`./og` and `./shiki` stay on the server. Neither does `./social`, which is a third
|
|
153
|
+
case: it renders React — it is ten `<svg>` — so it can never be portable, but it
|
|
154
|
+
holds no state and nothing about it needs a client boundary. It is the only way to put a
|
|
155
|
+
social icon in a Server Component, and § «The social icons come from `./social`»
|
|
156
|
+
below says why the grouped form cannot do it. If all you need are classes — for a `<div>`, an
|
|
149
157
|
`<a>` or an Astro island you do not want to hydrate — import them from
|
|
150
158
|
`./variants` and nothing crosses to the client:
|
|
151
159
|
|
|
@@ -202,21 +210,324 @@ It has to go INLINE. A `<script src>`, even a synchronous one, gets downloaded,
|
|
|
202
210
|
and the flash comes back. The script re-attaches on `astro:after-swap` because
|
|
203
211
|
view transitions replace the whole `<html>`.
|
|
204
212
|
|
|
205
|
-
###
|
|
213
|
+
### `npx arrecife` — run it once after installing
|
|
214
|
+
|
|
215
|
+
Two things break with **no error at all**, and the command catches both.
|
|
216
|
+
|
|
217
|
+
**Tailwind purges everything the components emit** unless the stylesheet has
|
|
218
|
+
`@source "<path>/node_modules/@eduardoalvarez/arrecife/dist"`. It does not scan
|
|
219
|
+
`node_modules`. There is no console error and no undefined class: the card mounts
|
|
220
|
+
with no padding, no radius and no border. The path is relative to the SHEET, not
|
|
221
|
+
to the project root, and the command computes it.
|
|
222
|
+
|
|
223
|
+
**A `--color-*` of yours silently replaces ours.** A project coming from shadcn
|
|
224
|
+
has `@theme inline { --color-accent: var(--accent); }` — shadcn's `--accent` is
|
|
225
|
+
the hover surface, `#17303E`, and ours is the brand turquoise, `#35D6C0`. That
|
|
226
|
+
one line repainted 88 classes inside the library's own components grey. Five
|
|
227
|
+
names collide in total; four agree on the value and are harmless, and the command
|
|
228
|
+
tells them apart.
|
|
229
|
+
|
|
230
|
+
Do not silence it by removing the `@import`: the fix is the `@source` line, or
|
|
231
|
+
renaming your own token.
|
|
232
|
+
|
|
233
|
+
### `Nav` is two slots and one height
|
|
234
|
+
|
|
235
|
+
Almost everything an app shell wants from a site bar is already a slot:
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
<Nav
|
|
239
|
+
size="compact" // 56px, for a shell with a sidebar
|
|
240
|
+
brand={<a href="/"><Logo /><span><span className="text-accent">~/</span>cursos</span></a>}
|
|
241
|
+
actions={session ? <UserMenu /> : <Button size="sm" asChild><Link href="/login">Entrar</Link></Button>}
|
|
242
|
+
>
|
|
243
|
+
<NavItem href="/cursos" active>cursos</NavItem>
|
|
244
|
+
</Nav>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`brand` and `actions` are `ReactNode`, so a wordmark, a user menu, a theme toggle
|
|
248
|
+
or a search box go in without the library knowing anything about sessions.
|
|
249
|
+
**Session state does not get a prop** — it is project infrastructure, and the
|
|
250
|
+
library takes none.
|
|
251
|
+
|
|
252
|
+
`size="compact"` is 56px instead of 64, for a bar that shares the screen with a
|
|
253
|
+
sidebar. It is a prop and not a class because the height lives on `Nav`'s inner
|
|
254
|
+
container: `className` reaches the `<header>` and stops there, so passing `h-14`
|
|
255
|
+
does nothing.
|
|
256
|
+
|
|
257
|
+
**One `Nav` per page.** It renders the site's `banner` landmark, and two banners
|
|
258
|
+
on one page is an accessibility failure — which is also why `PageHeader` goes
|
|
259
|
+
inside `<main>` and is not a landmark. See `decisions/0.7.md` § 30.
|
|
260
|
+
|
|
261
|
+
### Icons are yours, the way they are drawn is not
|
|
262
|
+
|
|
263
|
+
The library ships no icon set and `lib/glyphs.tsx` is not exported: it is the
|
|
264
|
+
minimum set the primitives need and it does not grow. What the library does ship
|
|
265
|
+
is the drawing.
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
import { GraduationCap, Trash } from '@phosphor-icons/react';
|
|
269
|
+
import { Icon } from '@eduardoalvarez/arrecife/icons';
|
|
270
|
+
|
|
271
|
+
// 1em, and `tone="action"` by default — `regular`, the stroke the document names
|
|
272
|
+
<Icon as={GraduationCap} />
|
|
273
|
+
|
|
274
|
+
// Inside a control with no text, the name goes on the CONTROL
|
|
275
|
+
<Button size="icon-sm" variant="secondary" aria-label="Borrar la fila">
|
|
276
|
+
<Icon as={Trash} />
|
|
277
|
+
</Button>
|
|
278
|
+
|
|
279
|
+
// Alone and meaning something on its own, it gets a name
|
|
280
|
+
<Icon as={Trophy} label="Curso completado" />
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Do not size them by hand.** `size-4`, `size-3.5`, `size-6` scattered through a
|
|
284
|
+
codebase is what this replaces: at 1em the icon takes the size of the text it
|
|
285
|
+
sits in — 13px beside `text-label`, 15px beside `text-ui` — and nobody picks a
|
|
286
|
+
number.
|
|
287
|
+
|
|
288
|
+
**The weight is not yours to pick either, but it is not one value.** `tone` names
|
|
289
|
+
what the icon is doing and the weight follows from it. There are three and there
|
|
290
|
+
is no fourth:
|
|
291
|
+
|
|
292
|
+
| `tone` | Weight | What it is |
|
|
293
|
+
| --- | --- | --- |
|
|
294
|
+
| `action` · the default | `regular` | An icon that is a control or names one. It is the system's line: 16 on a 256 grid = 0.0625em, against the document's 1.6 on a 24 grid = 0.0667em. Six per cent apart, which is no pixel on any screen |
|
|
295
|
+
| `current` | `fill` | The one of a set you are on — the nav item carrying `aria-current` |
|
|
296
|
+
| `quiet` | `light` | Furniture: a marker in a metadata row, not a control and not a state |
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
<NavItem href="/cursos" active icon={<Icon as={GraduationCap} tone="current" />}>
|
|
300
|
+
cursos
|
|
301
|
+
</NavItem>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
`current` is the one that earns the axis. An active item already paints itself
|
|
305
|
+
biolume, and colour on its own is the channel WCAG 1.4.1 says may not carry
|
|
306
|
+
meaning alone; the fill is the second channel, and it is the one that survives a
|
|
307
|
+
forced-colours mode. `weight` is deliberately **not** a prop: Phosphor ships six
|
|
308
|
+
and this system reads three, because `thin`, `bold` and `duotone` have no role
|
|
309
|
+
behind them here.
|
|
310
|
+
|
|
311
|
+
`@phosphor-icons/react` is an **optional** peer dependency. If your project uses
|
|
312
|
+
no icons you install nothing; two of the five do exactly that.
|
|
313
|
+
|
|
314
|
+
**An icon is not illustration, and the two never substitute for each other.**
|
|
315
|
+
Tiburoncín — the faces, the poses, the fin — is the mascot; it comes from
|
|
316
|
+
`./brand`, and the manual says where a face may appear: empty states,
|
|
317
|
+
confirmations, errors, course progress, celebration, and nowhere else. An icon is
|
|
318
|
+
functional vocabulary and goes wherever a control needs a label it cannot spell.
|
|
319
|
+
Do not put an icon where the system asks for a face, and do not put a face where
|
|
320
|
+
a control wants an icon.
|
|
321
|
+
|
|
322
|
+
**In Next, import from `@phosphor-icons/react/ssr` inside a Server Component.**
|
|
323
|
+
Phosphor's default build reads `IconContext` through `useContext`, and a hook in
|
|
324
|
+
a Server Component throws. It ships no `"use client"` to stop you, so the failure
|
|
325
|
+
arrives at render rather than at build. The `/ssr` entry is the same icons
|
|
326
|
+
without the context read, and `Icon` works with either.
|
|
327
|
+
|
|
328
|
+
See `decisions/0.7.md` § 29 and § 35.
|
|
329
|
+
|
|
330
|
+
### `Stat`'s delta says direction, not judgement
|
|
206
331
|
|
|
207
332
|
```tsx
|
|
208
|
-
|
|
333
|
+
<Stat
|
|
334
|
+
label="alumnos"
|
|
335
|
+
value="1.284"
|
|
336
|
+
delta={{ value: '+12 esta semana', direction: 'up' }}
|
|
337
|
+
/>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
`direction` picks the arrow and **never the colour**. «+12 alumnos» and «+12
|
|
341
|
+
errores» point the same way and mean opposite things, so whether a number is good
|
|
342
|
+
news is `tone`'s job and yours: `neutral` for a datum, `alert` when the number IS
|
|
343
|
+
the problem, `achievement` when it is the reward. `alert` and `achievement` paint
|
|
344
|
+
the same sand on purpose — the API is the meaning, the colour is the
|
|
345
|
+
implementation. See `decisions/0.7.md` § 28.
|
|
346
|
+
|
|
347
|
+
`delta.value` arrives already formatted, like `value`: the library imposes no
|
|
348
|
+
locale and computes no percentage. `spark` is a `ReactNode` and the library ships
|
|
349
|
+
no sparkline — pass your own, exactly like `icon`.
|
|
350
|
+
|
|
351
|
+
**Do not colour the number.** A neutral `Stat` renders its value in primary ink,
|
|
352
|
+
and biolume goes on the icon badge and the sparkline instead: three accents in
|
|
353
|
+
one card and the figure stops being the loudest thing in it. `alert` and
|
|
354
|
+
`achievement` DO paint the number sand, which is how «this number is not just a
|
|
355
|
+
number» is said. See `decisions/0.7.md` § 31.
|
|
356
|
+
|
|
357
|
+
**`icon` is a badge in the corner opposite the title**, in a circle tinted at
|
|
358
|
+
10 % of the tone. You pass the glyph; the circle, the tint and the size are the
|
|
359
|
+
component's.
|
|
360
|
+
|
|
361
|
+
### The two shapes of `EmptyState`
|
|
362
|
+
|
|
363
|
+
```tsx
|
|
364
|
+
// The empty state IS the screen: a search with no results, a 404, a section
|
|
365
|
+
// with nothing in it yet. It carries the face, and `expression` is mandatory.
|
|
366
|
+
<EmptyState expression="waiting" title="Sin resultados" description="…" />
|
|
367
|
+
|
|
368
|
+
// The hole INSIDE something else: a table page, a dashboard widget. No face, no
|
|
369
|
+
// surface, no border — the table or the card already draws the region.
|
|
370
|
+
<EmptyState variant="inline" title="No hay lecciones en esta página" />
|
|
371
|
+
|
|
372
|
+
// ❌ does not compile: the props are a union, and `inline` has no face
|
|
373
|
+
<EmptyState variant="inline" expression="waiting" title="…" />
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
`inline` takes an optional `icon` — a `ReactNode` the project passes and sizes,
|
|
377
|
+
at 1em and in `currentColor`, like `Stat`'s. The library ships no icons.
|
|
378
|
+
|
|
379
|
+
Do not reach for `page` inside a table because the face is «nicer»: an admin
|
|
380
|
+
screen with a dozen empty regions gets a dozen mascots, which is what made every
|
|
381
|
+
consuming project write its own empty state instead of using this one.
|
|
382
|
+
|
|
383
|
+
### The two shapes of `Footer`
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
// The default. Stacked rows, signature level with the first one.
|
|
387
|
+
<Footer brand={<Logo />} social={SOCIAL} />
|
|
388
|
+
|
|
389
|
+
// `full`. Brand and description on the left, link columns on the right,
|
|
390
|
+
// signature closing the piece behind a hairline.
|
|
391
|
+
<Footer
|
|
392
|
+
variant="full"
|
|
393
|
+
brand={<Logo />}
|
|
394
|
+
description="Cursos para construir con IA, directos y al grano."
|
|
395
|
+
columns={[
|
|
396
|
+
{ title: 'Aprendizaje', links: [{ label: 'Cursos', href: '/cursos' }] },
|
|
397
|
+
{ title: 'Legal', links: [{ label: 'Términos', href: '/terminos' }] },
|
|
398
|
+
]}
|
|
399
|
+
social={SOCIAL}
|
|
400
|
+
action={<Button variant="tertiary" size="sm">Reportar un problema</Button>}
|
|
401
|
+
linkAsChild={({ href, children }) => <Link href={href}>{children}</Link>}
|
|
402
|
+
/>
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
**Passing no `variant` is the default shape, and it is not a fallback**: two of
|
|
406
|
+
the three sites that draw a footer want exactly that, and it has not changed.
|
|
407
|
+
|
|
408
|
+
`columns`, `description`, `action` and `linkAsChild` exist ONLY on `full`. The
|
|
409
|
+
props are a discriminated union, like `EmptyState`'s, so the default form cannot
|
|
410
|
+
be handed one — if `tsc` rejects a `columns` you passed, you meant to pass
|
|
411
|
+
`variant="full"` as well.
|
|
412
|
+
|
|
413
|
+
Reach for `full` whenever the footer has links at all. **There is no other
|
|
414
|
+
place to put them**: `Footer` takes no `children`, so a row of loose text links
|
|
415
|
+
does not compile. That row existed until 0.8.0 and no project ever passed it —
|
|
416
|
+
and columns are also the only way to say «this block changes with who is
|
|
417
|
+
looking», an admin block against an account block, because they are data you
|
|
418
|
+
build and not markup the library walks.
|
|
419
|
+
|
|
420
|
+
The `./` in front of each column link is the component's, like `NavItem`'s, and
|
|
421
|
+
it is `aria-hidden`. The column titles render as `<h3>`. Pass `linkAsChild` to
|
|
422
|
+
plug in the router's `Link`; without it the columns are plain `<a>` and every
|
|
423
|
+
navigation costs a page load.
|
|
424
|
+
|
|
425
|
+
### `Table` brings its own surface
|
|
426
|
+
|
|
427
|
+
```tsx
|
|
428
|
+
// ✅ this is the whole thing
|
|
429
|
+
<Table>…</Table>
|
|
430
|
+
|
|
431
|
+
// ❌ two borders. The radius, the border and the clip are the component's
|
|
432
|
+
<div className="rounded-lg border border-border bg-card overflow-hidden">
|
|
433
|
+
<Table>…</Table>
|
|
434
|
+
</div>
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
`Table` draws `rounded-card`, `border-hairline` and the clip on the same
|
|
438
|
+
container that scrolls it horizontally. Do not wrap it in a surface of your own,
|
|
439
|
+
and do not add `overflow-hidden`: `TableRow`'s hover tint is already clipped by
|
|
440
|
+
the corners, which is what the wrapper used to be for.
|
|
441
|
+
|
|
442
|
+
`className` reaches the `<table>`, not the container, so a `rounded-none` from
|
|
443
|
+
the call site does nothing.
|
|
444
|
+
|
|
445
|
+
### The three chart types, and the names they took
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
import { AreaChart, BarChart, LineChart } from '@eduardoalvarez/arrecife/chart';
|
|
449
|
+
|
|
450
|
+
<AreaChart
|
|
451
|
+
label="Registros nuevos por día"
|
|
452
|
+
summary="Sube de 24 a 52 con una caída en mayo."
|
|
453
|
+
height={200}
|
|
454
|
+
data={data}
|
|
455
|
+
series={[{ key: 'count', label: 'Registros' }]}
|
|
456
|
+
xKey="day"
|
|
457
|
+
/>
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
`data`, `series` and `xKey`, plus the mandatory `label`. The gradient, the grid,
|
|
461
|
+
the axes and the tooltip belong to the component — that composition is the system
|
|
462
|
+
drawing, and writing it at the call site is how it drifts.
|
|
463
|
+
|
|
464
|
+
**These are NOT Recharts' components of the same name.** Import ours; do not
|
|
465
|
+
import both in one file. Recharts' `Area`, `Line` and `XAxis` are still not
|
|
466
|
+
re-exported, because they are unchanged and wrapping them buys nothing.
|
|
467
|
+
|
|
468
|
+
`BarChart`'s `orientation` is named for what you see: `horizontal` lays the bars
|
|
469
|
+
down for a ranking. Recharts calls that same thing `layout="vertical"` — if you
|
|
470
|
+
are porting code, the value flips.
|
|
471
|
+
|
|
472
|
+
`stacked` on `AreaChart` and `BarChart` adds the series up. Without it areas
|
|
473
|
+
overlap, which is honest and rarely what you want with more than one series: to
|
|
474
|
+
COMPARE rather than add up, the type is `LineChart`.
|
|
475
|
+
|
|
476
|
+
Anything that is not a series over a category axis has no type and is not missing
|
|
477
|
+
one. A doughnut is `ChartContainer` plus Recharts' `Pie` with `SERIES_COLORS`.
|
|
478
|
+
|
|
479
|
+
### The social icons come from `./social`
|
|
480
|
+
|
|
481
|
+
```tsx
|
|
482
|
+
// ❌ does not exist: the root publishes them grouped, not loose
|
|
209
483
|
import { GitHub } from '@eduardoalvarez/arrecife';
|
|
210
484
|
|
|
211
|
-
// ✅
|
|
485
|
+
// ✅ the normal form
|
|
486
|
+
import { GitHub } from '@eduardoalvarez/arrecife/social';
|
|
487
|
+
|
|
488
|
+
// ✅ for iterating the catalogue
|
|
212
489
|
import { social } from '@eduardoalvarez/arrecife';
|
|
213
490
|
<social.GitHub />
|
|
214
491
|
```
|
|
215
492
|
|
|
216
|
-
All
|
|
217
|
-
`Email`, `Newsletter`.
|
|
218
|
-
`
|
|
219
|
-
|
|
493
|
+
All ten: `GitHub`, `LinkedIn`, `X`, `Instagram`, `Discord`, `YouTube`, `Rss`,
|
|
494
|
+
`Email`, `Newsletter`, `Website`. `Newsletter` is the bell: a way to follow, like
|
|
495
|
+
`Rss`, named for what it means. `Website` is «my other site» — the personal
|
|
496
|
+
domain in a footer full of networks — and it is what replaces borrowing a globe
|
|
497
|
+
from an icon set, which brings its own stroke weight and its own margins.
|
|
498
|
+
|
|
499
|
+
Six are brands and go SOLID, four are functional and use a 1.6 stroke. A row that
|
|
500
|
+
mixes the two pens is the normal case, not a defect: a brand is somebody else's
|
|
501
|
+
silhouette and cannot be outlined, and a symbol the system draws itself has no
|
|
502
|
+
owner to be faithful to.
|
|
503
|
+
|
|
504
|
+
**In a Server Component the subpath is mandatory, not preferred.** The root
|
|
505
|
+
carries `"use client"`, and a client reference crosses the boundary per EXPORT —
|
|
506
|
+
the properties of a plain object are not exports, so `social.LinkedIn` is
|
|
507
|
+
`undefined` on the server and `undefined` as an element type kills the build at
|
|
508
|
+
prerender. `./social` carries no directive: it renders on the server and ships no
|
|
509
|
+
client JS. Use `social` only when mapping a list of names onto icons.
|
|
510
|
+
|
|
511
|
+
The root keeps the group because one of them is called `X`, and loose at the root
|
|
512
|
+
it collides. In the subpath, alias it: `import { X as XIcon }`.
|
|
513
|
+
|
|
514
|
+
**If you mount no React, the shapes are published too.** `./social/data` imports
|
|
515
|
+
nothing, so an `.astro` that ships no framework JavaScript can draw the same
|
|
516
|
+
glyph instead of pasting the `<path>` into the project:
|
|
517
|
+
|
|
518
|
+
```astro
|
|
519
|
+
---
|
|
520
|
+
import { socialSvg } from '@eduardoalvarez/arrecife/social/data';
|
|
521
|
+
---
|
|
522
|
+
<Fragment set:html={socialSvg('GitHub', { class: 'size-[19px]' })} />
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
`socialGlyphs` is the catalogue keyed by name, `socialNames` is the ten names in
|
|
526
|
+
order, and every glyph is exported on its own — `gitHubGlyph`, `websiteGlyph` —
|
|
527
|
+
if you want the shapes rather than the markup. The React components are drawn
|
|
528
|
+
from that same file, so the two renderings cannot disagree. Reaching for
|
|
529
|
+
`socialGlyphs` or `socialSvg` names all ten, which is the price of iterating a
|
|
530
|
+
catalogue; `import { LinkedIn }` still costs one shape.
|
|
220
531
|
|
|
221
532
|
The internal glyphs — `Close`, `ChevronDown`, `Sun` — are **not exported** and
|
|
222
533
|
are not going to be: they are the primitives' minimum set. A component that needs
|
|
@@ -240,7 +551,7 @@ same value is available in both places and they cannot disagree.
|
|
|
240
551
|
| `control.md` | `--spacing-control-md` | `px-control-md` |
|
|
241
552
|
| `control.icon` | `--spacing-control-icon` | `size-control-icon` (42×42) |
|
|
242
553
|
| `gradient[mode].hero` | `--gradient-hero` | `gradient-hero` |
|
|
243
|
-
| `size.nav` | `--spacing-nav` | `h-nav` |
|
|
554
|
+
| `size.nav` / `size.navCompact` | `--spacing-nav` / `--spacing-nav-compact` | `h-nav` / `h-nav-compact` |
|
|
244
555
|
| `size.content` / `size.wide` | `--container-content` / `--container-wide` | `max-w-content` / `max-w-wide` |
|
|
245
556
|
| `limits.measure` | `--container-measure` | `max-w-measure` |
|
|
246
557
|
| `shadow.standard` | `--shadow-standard` | `shadow-standard` |
|
|
@@ -256,7 +567,7 @@ They carry a prefix because `xs, sm, md, lg, xl` are the names of Tailwind's
|
|
|
256
567
|
`--container-*` scale, and a `--spacing-md` of our own was swallowing `max-w-md`
|
|
257
568
|
across the whole project with nothing warning about it. `max-w-*`, `w-*` and
|
|
258
569
|
`h-*` belong to Tailwind and are used as they are. Migration guide from 0.2.0:
|
|
259
|
-
<https://github.com/Proskynete/arrecife/blob/main/docs/migration-0.3.md>.
|
|
570
|
+
<https://github.com/Proskynete/arrecife/blob/main/docs/runbooks/migration-0.3.md>.
|
|
260
571
|
|
|
261
572
|
## System rules the consuming code must not break
|
|
262
573
|
|
|
@@ -269,10 +580,16 @@ compiles and looks wrong, or that fails the project's accessibility audit.
|
|
|
269
580
|
3. **`Button variant="destructive"` is for the irreversible only.** Never for
|
|
270
581
|
«cancel» on a form, and not inside an `AlertDialog` — there the confirm button
|
|
271
582
|
stays `primary`, because the title, the focus on cancel and the no-click-outside
|
|
272
|
-
already carry the weight. See `
|
|
583
|
+
already carry the weight. See `decisions/0.6.md` § 21.
|
|
273
584
|
4. **`secondary` is never filled.** It is border and text.
|
|
274
585
|
5. **No entrance animations.** Modals, menus, tooltips and toasts appear where
|
|
275
|
-
they will stay.
|
|
586
|
+
they will stay. There are five declared exceptions, all behind `motion-safe`
|
|
587
|
+
and all with a reason written down: the `Button loading` spinner, `Sheet`'s
|
|
588
|
+
side panel, `Skeleton`'s shimmer, `Accordion`'s height and the `pulse-accent`
|
|
589
|
+
halo the footer signature ends in. All five are the same criterion — feedback
|
|
590
|
+
about progress or about spatial continuity — and a sixth lands on it or it
|
|
591
|
+
does not exist. The `caret` blink 0.6.0 shipped is removed in 0.8.0; it was
|
|
592
|
+
the only member of the second criterion § 23 opened for it.
|
|
276
593
|
6. **Semantics and scale are independent.** An `h2` that has to look small is
|
|
277
594
|
`<Text as="h2" variant="h3">`, never an `h3` that lies about the hierarchy.
|
|
278
595
|
7. **`textMuted` never goes over `surfaceRaised`**: it gives 4.07 in dark. Over a
|
|
@@ -288,6 +605,11 @@ compiles and looks wrong, or that fails the project's accessibility audit.
|
|
|
288
605
|
11. **The mascot's faces only appear** in empty states, confirmations, errors,
|
|
289
606
|
course progress and celebration. Never in a hero, pricing, services, contact
|
|
290
607
|
or the CV.
|
|
608
|
+
**And not in every empty state either**: `EmptyState variant="inline"` is the
|
|
609
|
+
hole inside a table page or a dashboard widget, and it carries no face — the
|
|
610
|
+
type does not accept one. `page`, the default, is the one that IS the screen,
|
|
611
|
+
and there `expression` stays mandatory. A dozen mascots on one admin screen is
|
|
612
|
+
not the humour contract. See `decisions/0.7.md` § 27.
|
|
291
613
|
12. **The fin is not a free parameter**: `foam` on a dark background, `color` on a
|
|
292
614
|
light one. The components already choose it from the background.
|
|
293
615
|
|
|
@@ -586,7 +908,7 @@ Source: `src/primitives/date-field.tsx`
|
|
|
586
908
|
|
|
587
909
|
A date field on the native control, not on a calendar of our own.
|
|
588
910
|
|
|
589
|
-
- Extends: `Omit<
|
|
911
|
+
- Extends: `Omit<ComponentProps<'input'>, 'type'>`
|
|
590
912
|
|
|
591
913
|
| prop | type | req. | default | what it does |
|
|
592
914
|
| --- | --- | --- | --- | --- |
|
|
@@ -675,7 +997,9 @@ No entrance animation: the menu appears, it does not unfold.
|
|
|
675
997
|
|
|
676
998
|
Source: `src/primitives/input.tsx`
|
|
677
999
|
|
|
678
|
-
|
|
1000
|
+
`ComponentProps` and not `ComponentPropsWithoutRef`, and the difference is a bug and not a preference.
|
|
1001
|
+
|
|
1002
|
+
- Extends: `ComponentProps<'input'>`
|
|
679
1003
|
|
|
680
1004
|
| prop | type | req. | default | what it does |
|
|
681
1005
|
| --- | --- | --- | --- | --- |
|
|
@@ -687,7 +1011,7 @@ Source: `src/primitives/label.tsx`
|
|
|
687
1011
|
|
|
688
1012
|
The `label` scale: 13px, which is the system's absolute minimum on screen.
|
|
689
1013
|
|
|
690
|
-
- Extends: `
|
|
1014
|
+
- Extends: `ComponentProps<typeof LabelPrimitive.Root>`
|
|
691
1015
|
- No own props: it passes through those of the element or primitive it wraps.
|
|
692
1016
|
|
|
693
1017
|
### Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext, PaginationEllipsis
|
|
@@ -871,7 +1195,7 @@ The knob changes position, but is not animated while doing so: the position IS t
|
|
|
871
1195
|
Source: `src/primitives/table.tsx`
|
|
872
1196
|
|
|
873
1197
|
**Table**
|
|
874
|
-
The
|
|
1198
|
+
The table, and the surface it sits on. The two are one piece.
|
|
875
1199
|
|
|
876
1200
|
- No own props: it passes through those of the element or primitive it wraps.
|
|
877
1201
|
|
|
@@ -894,6 +1218,8 @@ The container scrolls horizontally: the page never does.
|
|
|
894
1218
|
- No own props: it passes through those of the element or primitive it wraps.
|
|
895
1219
|
|
|
896
1220
|
**TableCaption**
|
|
1221
|
+
The caption, at the bottom and INSIDE the surface.
|
|
1222
|
+
|
|
897
1223
|
- No own props: it passes through those of the element or primitive it wraps.
|
|
898
1224
|
|
|
899
1225
|
### Tabs, TabsList, TabsTrigger, TabsContent
|
|
@@ -917,7 +1243,9 @@ Source: `src/primitives/tabs.tsx`
|
|
|
917
1243
|
|
|
918
1244
|
Source: `src/primitives/textarea.tsx`
|
|
919
1245
|
|
|
920
|
-
|
|
1246
|
+
`ComponentProps` carries `ref`, which React 19 passes as a prop. See `InputProps`.
|
|
1247
|
+
|
|
1248
|
+
- Extends: `ComponentProps<'textarea'>`
|
|
921
1249
|
|
|
922
1250
|
| prop | type | req. | default | what it does |
|
|
923
1251
|
| --- | --- | --- | --- | --- |
|
|
@@ -968,7 +1296,7 @@ Source: `src/primitives/typography.tsx`
|
|
|
968
1296
|
|
|
969
1297
|
## Components
|
|
970
1298
|
|
|
971
|
-
Imported from `@eduardoalvarez/arrecife`.
|
|
1299
|
+
Imported from `@eduardoalvarez/arrecife`. 21 exports.
|
|
972
1300
|
|
|
973
1301
|
### ArticleCard
|
|
974
1302
|
|
|
@@ -976,7 +1304,7 @@ Source: `src/components/article-card/index.tsx`
|
|
|
976
1304
|
|
|
977
1305
|
The metadata line uses `meta` and not `eyebrow`: `18 ago 2026 · 8 min de lectura` is a datum, not an overline, and in small caps it was neither.
|
|
978
1306
|
|
|
979
|
-
- Extends: `Omit<CardShellProps,
|
|
1307
|
+
- Extends: `Omit<CardShellProps, "children" \| "title">`
|
|
980
1308
|
|
|
981
1309
|
| prop | type | req. | default | what it does |
|
|
982
1310
|
| --- | --- | --- | --- | --- |
|
|
@@ -1078,17 +1406,17 @@ Source: `src/components/course-card/index.tsx`
|
|
|
1078
1406
|
|
|
1079
1407
|
Source: `src/components/empty-state/index.tsx`
|
|
1080
1408
|
|
|
1081
|
-
The
|
|
1082
|
-
|
|
1083
|
-
- Extends: `Omit<ComponentPropsWithoutRef<'div'>, 'title'>`
|
|
1409
|
+
- Extends: `EmptyStateBase & ( \| { /** `page`, the default: the empty state IS the screen or the section, and it carries the face. */ variant?: 'page' \| undefined; /** * The face. Mandatory on `page` and impossible on `inline` — the props * are a union, so the generated table cannot show a per-variant «req.» * and the sentence has to carry it. Without it, `page` is a centred * paragraph. */ expression: Face; /** Where the brand PNGs are served from. */ basePath?: string \| undefined; icon?: never; } \| { /** `inline`: the hole inside a table or a widget. No face, and no way to pass one. */ variant: 'inline'; /** * A glyph above the line. It measures 1em and inherits `currentColor`, * like `Stat`'s: the project passes its own and sizes it, because the * system has no icon library and is not getting one. */ icon?: ReactNode; expression?: never; basePath?: never; } )`
|
|
1084
1410
|
|
|
1085
1411
|
| prop | type | req. | default | what it does |
|
|
1086
1412
|
| --- | --- | --- | --- | --- |
|
|
1087
1413
|
| `action` | `ReactNode` | | | The action that gets you out of the empty state. Usually a tertiary button. |
|
|
1088
1414
|
| `basePath` | `string` | | | Where the brand PNGs are served from. |
|
|
1089
1415
|
| `description` | `ReactNode` | | | One line explaining what is missing or what to do. |
|
|
1090
|
-
| `expression` | `"annoyed" \| "confused" \| "hearts" \| "laughing" \| "shades" \| "waiting" \| "wink"` |
|
|
1416
|
+
| `expression` | `"annoyed" \| "confused" \| "hearts" \| "laughing" \| "shades" \| "waiting" \| "wink"` | | | The face. Mandatory on `page` and impossible on `inline` — the props are a union, so the generated table cannot show a per-variant «req.» and the sentence has to carry it. Without it, `page` is a centred paragraph. |
|
|
1417
|
+
| `icon` | `ReactNode` | | | A glyph above the line. It measures 1em and inherits `currentColor`, like `Stat`'s: the project passes its own and sizes it, because the system has no icon library and is not getting one. |
|
|
1091
1418
|
| `title` | `ReactNode` | yes | | |
|
|
1419
|
+
| `variant` | `"inline" \| "page"` | | | `page`, the default: the empty state IS the screen or the section, and it carries the face. `inline`: the hole inside a table or a widget. No face, and no way to pass one. |
|
|
1092
1420
|
|
|
1093
1421
|
### EventCalendar
|
|
1094
1422
|
|
|
@@ -1108,26 +1436,24 @@ Source: `src/components/event-calendar/index.tsx`
|
|
|
1108
1436
|
| `onUpdateEvent` | `(event: CalendarEvent) => void` | | | |
|
|
1109
1437
|
| `selected` | `Date` | | | Selected day, if the project controls it. Without it, it starts on today. |
|
|
1110
1438
|
|
|
1111
|
-
### Footer
|
|
1439
|
+
### Footer
|
|
1112
1440
|
|
|
1113
1441
|
Source: `src/components/footer/index.tsx`
|
|
1114
1442
|
|
|
1115
|
-
|
|
1116
|
-
- Extends: `ComponentPropsWithoutRef<'footer'>`
|
|
1443
|
+
- Extends: `FooterBase & ( \| { /** The shape the library has always had: stacked rows and the signature at the top right. */ variant?: 'default' \| undefined; columns?: never; description?: never; action?: never; linkAsChild?: never; } \| { /** `full`: brand and description on the left, link columns on the right, signature closing it. */ variant: 'full'; /** The link columns. Mandatory: without them `full` is the default form with extra steps. */ columns: readonly FooterColumn[]; /** One line under the brand, saying what the site is. */ description?: ReactNode; /** An action under the row of icons — «Reportar un problema». Usually a tertiary button. */ action?: ReactNode; /** * Renders the column links through the child, to plug in the framework's * `Link`. It receives each `href` in the Slot's `props`. * * It is § 24's rule applied where it now bites: a column turns data into * markup, so without a slot the only way to reach one of those links * from a project is to select it by structure or by a style class, and * neither is a contract. `Breadcrumb` and `ArticleCard` have the same * signature on purpose. * * It is also what a client-side transition needs: `cursos` reached for * it the moment its columns stopped being `<a>` tags. */ linkAsChild?: ((props: { href: string; children: ReactNode }) => ReactNode) \| undefined; } )`
|
|
1117
1444
|
|
|
1118
1445
|
| prop | type | req. | default | what it does |
|
|
1119
1446
|
| --- | --- | --- | --- | --- |
|
|
1447
|
+
| `action` | `ReactNode` | | | An action under the row of icons — «Reportar un problema». Usually a tertiary button. |
|
|
1120
1448
|
| `brand` | `ReactNode` | | | The brand row: the fin and the wordmark, at the very top. |
|
|
1449
|
+
| `columns` | `readonly FooterColumn[]` | | | The link columns. Mandatory: without them `full` is the default form with extra steps. |
|
|
1450
|
+
| `description` | `ReactNode` | | | One line under the brand, saying what the site is. |
|
|
1451
|
+
| `linkAsChild` | `(props: { href: string; children: ReactNode; }) => ReactNode` | | | Renders the column links through the child, to plug in the framework's `Link`. It receives each `href` in the Slot's `props`. |
|
|
1452
|
+
| `signatureHref` | `string` | | | Makes the domain inside the signature a link, keeping the `$`, the path and the prompt's mark as text. |
|
|
1121
1453
|
| `social` | `readonly SocialLink[]` | | | |
|
|
1454
|
+
| `variant` | `"full" \| "default"` | | | The shape the library has always had: stacked rows and the signature at the top right. `full`: brand and description on the left, link columns on the right, signature closing it. |
|
|
1122
1455
|
| `year` | `number` | | `new Date().getFullYear()` | The signature's year. |
|
|
1123
1456
|
|
|
1124
|
-
**FooterLink**
|
|
1125
|
-
- Extends: `ComponentPropsWithoutRef<'a'>`
|
|
1126
|
-
|
|
1127
|
-
| prop | type | req. | default | what it does |
|
|
1128
|
-
| --- | --- | --- | --- | --- |
|
|
1129
|
-
| `asChild` | `boolean \| undefined` | | `false` | |
|
|
1130
|
-
|
|
1131
1457
|
### Hero
|
|
1132
1458
|
|
|
1133
1459
|
Source: `src/components/hero/index.tsx`
|
|
@@ -1167,7 +1493,7 @@ Migrated from `links/src/components/Card.astro`. The original scaled the card to
|
|
|
1167
1493
|
Source: `src/components/nav/index.tsx`
|
|
1168
1494
|
|
|
1169
1495
|
**Nav**
|
|
1170
|
-
The site bar: 64px, abyss at 86 % and a 14px blur behind it.
|
|
1496
|
+
The site bar: 64px, abyss at 86 % and a 14px blur behind it — 56 when it shares the screen with a sidebar.
|
|
1171
1497
|
|
|
1172
1498
|
- Extends: `ComponentPropsWithoutRef<'header'>`
|
|
1173
1499
|
|
|
@@ -1175,6 +1501,7 @@ The site bar: 64px, abyss at 86 % and a 14px blur behind it.
|
|
|
1175
1501
|
| --- | --- | --- | --- | --- |
|
|
1176
1502
|
| `actions` | `ReactNode` | | | Actions on the right: conversion, theme switch, search. |
|
|
1177
1503
|
| `brand` | `ReactNode` | | | The logo, on the left. |
|
|
1504
|
+
| `size` | `"compact" \| "default"` | | `default` | `compact` is 56px instead of 64, for a bar that shares the screen with a sidebar: at 64 the two compete for the same corner and together they eat the top of the content area. |
|
|
1178
1505
|
|
|
1179
1506
|
**NavItem**
|
|
1180
1507
|
The `./` is put there by the component, not by whoever uses it.
|
|
@@ -1198,10 +1525,10 @@ Source: `src/components/newsletter-form/index.tsx`
|
|
|
1198
1525
|
| `basePath` | `string` | | | |
|
|
1199
1526
|
| `description` | `ReactNode` | | | |
|
|
1200
1527
|
| `disclaimer` | `ReactNode` | | | The small print. It is the «sin spam», which is why it accepts a face. |
|
|
1201
|
-
| `errorMessage` | `ReactNode` | | `No se pudo suscribir ese
|
|
1528
|
+
| `errorMessage` | `ReactNode` | | `No se pudo suscribir ese correo. Revísalo y vuelve a intentar.` | |
|
|
1202
1529
|
| `expression` | `"annoyed" \| "confused" \| "hearts" \| "laughing" \| "shades" \| "waiting" \| "wink"` | | | |
|
|
1203
1530
|
| `fieldErrors` | `{ name?: ReactNode; email?: ReactNode; }` | | | A message under one specific field, instead of the single alert. |
|
|
1204
|
-
| `fieldLabel` | `string` | | `
|
|
1531
|
+
| `fieldLabel` | `string` | | `Correo electrónico` | |
|
|
1205
1532
|
| `nameField` | `boolean` | | `false` | Adds the name field ahead of the email one. |
|
|
1206
1533
|
| `nameInputProps` | `Omit<InputProps, "id" \| "disabled" \| "name">` | | | Whatever the project needs to hang off the name field: `minLength`, `maxLength`, `pattern`. The library imposes none of the three. |
|
|
1207
1534
|
| `nameLabel` | `string` | | `Nombre` | |
|
|
@@ -1212,7 +1539,7 @@ Source: `src/components/newsletter-form/index.tsx`
|
|
|
1212
1539
|
| `resetOnSuccess` | `boolean` | | `true` | Empties the fields after a successful subscription. On by default. |
|
|
1213
1540
|
| `state` | `"success" \| "error" \| "idle" \| "sending"` | | `idle` | |
|
|
1214
1541
|
| `submitLabel` | `string` | | `Suscribirme` | |
|
|
1215
|
-
| `successMessage` | `ReactNode` | | `Ya estás dentro. Te llega un
|
|
1542
|
+
| `successMessage` | `ReactNode` | | `Ya estás dentro. Te llega un correo cada dos semanas, y nada más.` | |
|
|
1216
1543
|
| `title` | `ReactNode` | yes | | |
|
|
1217
1544
|
|
|
1218
1545
|
### PageHeader
|
|
@@ -1246,29 +1573,6 @@ How much you have read. It is NOT `Progress` under another name.
|
|
|
1246
1573
|
| `target` | `RefObject<HTMLElement \| null>` | | | The element being measured. Without it, the whole document. |
|
|
1247
1574
|
| `tone` | `"accent" \| "warm"` | | `accent` | Sand instead of biolume, to match course progress. |
|
|
1248
1575
|
|
|
1249
|
-
### SidebarItem, SidebarNav
|
|
1250
|
-
|
|
1251
|
-
Source: `src/components/sidebar-nav/index.tsx`
|
|
1252
|
-
|
|
1253
|
-
**SidebarItem**
|
|
1254
|
-
The blog admin's sidebar.
|
|
1255
|
-
|
|
1256
|
-
- Extends: `ComponentPropsWithoutRef<'a'>`
|
|
1257
|
-
|
|
1258
|
-
| prop | type | req. | default | what it does |
|
|
1259
|
-
| --- | --- | --- | --- | --- |
|
|
1260
|
-
| `active` | `boolean \| undefined` | | `false` | |
|
|
1261
|
-
| `asChild` | `boolean \| undefined` | | `false` | |
|
|
1262
|
-
| `badge` | `ReactNode` | | | Counter on the right: pending drafts, unused media. |
|
|
1263
|
-
|
|
1264
|
-
**SidebarNav**
|
|
1265
|
-
- Extends: `ComponentPropsWithoutRef<'nav'>`
|
|
1266
|
-
|
|
1267
|
-
| prop | type | req. | default | what it does |
|
|
1268
|
-
| --- | --- | --- | --- | --- |
|
|
1269
|
-
| `branch` | `ReactNode` | | | |
|
|
1270
|
-
| `version` | `ReactNode` | | | Version and branch, at the bottom. |
|
|
1271
|
-
|
|
1272
1576
|
### Stat
|
|
1273
1577
|
|
|
1274
1578
|
Source: `src/components/stat/index.tsx`
|
|
@@ -1279,11 +1583,13 @@ A large metric: the number in the `stat` scale and its name underneath.
|
|
|
1279
1583
|
|
|
1280
1584
|
| prop | type | req. | default | what it does |
|
|
1281
1585
|
| --- | --- | --- | --- | --- |
|
|
1586
|
+
| `delta` | `StatDelta` | | | How the number moved since last time. |
|
|
1282
1587
|
| `description` | `ReactNode` | | | The standfirst: the nuance the number alone does not give. «12 aplicaciones» does not say whether that is a lot, and this is where that gets said. |
|
|
1283
|
-
| `icon` | `ReactNode` | | | Glyph
|
|
1588
|
+
| `icon` | `ReactNode` | | | Glyph in a tinted circle, in the corner opposite the title. At 1em, and it inherits `currentColor` from the badge, so it takes the tone without being tinted separately. |
|
|
1284
1589
|
| `label` | `ReactNode` | yes | | What is being counted. It goes in mono small caps. |
|
|
1285
1590
|
| `progress` | `number` | | | With `progress`, the metric reads as progress and adds the bar. |
|
|
1286
|
-
| `
|
|
1591
|
+
| `spark` | `ReactNode` | | | The number's shape over time, under it. A `ReactNode` and not a data prop: a sparkline needs a charting library, and this component lives in the barrel that four projects install. The one project that draws them passes its own, exactly like `icon`. |
|
|
1592
|
+
| `tone` | `"neutral" \| "alert" \| "achievement"` | | `neutral` | `alert` ONLY when the number is the problem, and `achievement` when it is the opposite — the diplomas issued, the modules finished. The two paint the same sand today and they are still two names: a system that names by meaning cannot make «this is bad» the only way to say «this stands out». See `docs/decisions/0.7.md` § 28. |
|
|
1287
1593
|
| `value` | `ReactNode` | yes | | The number, already formatted. The library imposes no locale. |
|
|
1288
1594
|
|
|
1289
1595
|
### TalkCard
|
|
@@ -1315,7 +1621,7 @@ The control that was missing. The library defined the whole theming system and e
|
|
|
1315
1621
|
|
|
1316
1622
|
| prop | type | req. | default | what it does |
|
|
1317
1623
|
| --- | --- | --- | --- | --- |
|
|
1318
|
-
| `label` | `string` | | `Cambiar de
|
|
1624
|
+
| `label` | `string` | | `Cambiar de tema` | Accessible name. The button has no visible text, so it is the only thing naming it. |
|
|
1319
1625
|
| `onThemeChange` | `(theme: Theme) => void` | | | Fires with whichever theme ended up set, in case the project wants to record it. |
|
|
1320
1626
|
| `size` | `"sm" \| "md" \| "lg" \| "icon" \| "icon-sm"` | | `icon` | |
|
|
1321
1627
|
| `variant` | `"primary" \| "conversion" \| "secondary" \| "tertiary" \| "destructive" \| "destructiveOutline"` | | `secondary` | |
|
|
@@ -1389,6 +1695,64 @@ Tiburoncín's head, with an expression.
|
|
|
1389
1695
|
| `basePath` | `string` | | `ASSETS_PATH` | |
|
|
1390
1696
|
| `expression` | `"annoyed" \| "confused" \| "hearts" \| "laughing" \| "shades" \| "waiting" \| "wink"` | yes | | |
|
|
1391
1697
|
|
|
1698
|
+
## Social icons
|
|
1699
|
+
|
|
1700
|
+
Imported from `@eduardoalvarez/arrecife/social` · or grouped as `social` from the root. 10 exports.
|
|
1701
|
+
|
|
1702
|
+
### GitHub, LinkedIn, X, Instagram, Discord, YouTube, Rss, Email, Newsletter, Website
|
|
1703
|
+
|
|
1704
|
+
Source: `src/social/index.tsx`
|
|
1705
|
+
|
|
1706
|
+
**GitHub**
|
|
1707
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1708
|
+
|
|
1709
|
+
**LinkedIn**
|
|
1710
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1711
|
+
|
|
1712
|
+
**X**
|
|
1713
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1714
|
+
|
|
1715
|
+
**Instagram**
|
|
1716
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1717
|
+
|
|
1718
|
+
**Discord**
|
|
1719
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1720
|
+
|
|
1721
|
+
**YouTube**
|
|
1722
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1723
|
+
|
|
1724
|
+
**Rss**
|
|
1725
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1726
|
+
|
|
1727
|
+
**Email**
|
|
1728
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1729
|
+
|
|
1730
|
+
**Newsletter**
|
|
1731
|
+
The newsletter. It plays the same role as `Rss` — a way to follow, not a social network — which is why it belongs in this catalogue and does not open the door to an icon library.
|
|
1732
|
+
|
|
1733
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1734
|
+
|
|
1735
|
+
**Website**
|
|
1736
|
+
«My other site»: the personal domain in a footer full of social networks.
|
|
1737
|
+
|
|
1738
|
+
- No own props: it passes through those of the element or primitive it wraps.
|
|
1739
|
+
|
|
1740
|
+
## Icons
|
|
1741
|
+
|
|
1742
|
+
Imported from `@eduardoalvarez/arrecife/icons` · requires `@phosphor-icons/react`. 1 exports.
|
|
1743
|
+
|
|
1744
|
+
### Icon
|
|
1745
|
+
|
|
1746
|
+
Source: `src/icons/index.tsx`
|
|
1747
|
+
|
|
1748
|
+
- Extends: `Omit<PhosphorIconProps, 'size' \| 'weight' \| 'ref'>`
|
|
1749
|
+
|
|
1750
|
+
| prop | type | req. | default | what it does |
|
|
1751
|
+
| --- | --- | --- | --- | --- |
|
|
1752
|
+
| `as` | `Icon` | yes | | The Phosphor icon itself, passed as a component: `<Icon as={Books} />`. |
|
|
1753
|
+
| `label` | `string` | | | The accessible name. WITHOUT it the icon is decorative and gets `aria-hidden`, which is the right default: most icons sit beside their own label and announcing them twice is noise. |
|
|
1754
|
+
| `tone` | `"action" \| "current" \| "quiet"` | | `action` | WHAT THE ICON IS DOING, which is what picks the weight. Three values, and there is no fourth: `action` is the default and the system's line, `current` is the one of a set you are on, `quiet` is furniture that is not a control. `weight` is deliberately not a prop — see `TONE_WEIGHT`. |
|
|
1755
|
+
|
|
1392
1756
|
## Forms
|
|
1393
1757
|
|
|
1394
1758
|
Imported from `@eduardoalvarez/arrecife/form` · requires `react-hook-form`. 7 exports.
|
|
@@ -1434,9 +1798,9 @@ The layer that ties the controls to a form with validation and messages.
|
|
|
1434
1798
|
|
|
1435
1799
|
## Charts
|
|
1436
1800
|
|
|
1437
|
-
Imported from `@eduardoalvarez/arrecife/chart` · requires `recharts`.
|
|
1801
|
+
Imported from `@eduardoalvarez/arrecife/chart` · requires `recharts`. 8 exports.
|
|
1438
1802
|
|
|
1439
|
-
### ChartContainer, ChartTooltip, ChartLegend, ChartTooltipContent, ChartLegendContent
|
|
1803
|
+
### ChartContainer, ChartTooltip, ChartLegend, ChartTooltipContent, ChartLegendContent, AreaChart, BarChart, LineChart
|
|
1440
1804
|
|
|
1441
1805
|
Source: `src/chart/index.tsx`
|
|
1442
1806
|
|
|
@@ -1483,12 +1847,85 @@ The legend, with the tooltip's same square swatch and the `label` scale.
|
|
|
1483
1847
|
| `className` | `string` | | | |
|
|
1484
1848
|
| `payload` | `readonly ChartPayloadItem[]` | | | |
|
|
1485
1849
|
|
|
1850
|
+
**AreaChart**
|
|
1851
|
+
A series over time, with the fill fading out underneath it.
|
|
1852
|
+
|
|
1853
|
+
- Extends: `SeriesChartProps`
|
|
1854
|
+
|
|
1855
|
+
| prop | type | req. | default | what it does |
|
|
1856
|
+
| --- | --- | --- | --- | --- |
|
|
1857
|
+
| `data` | `readonly ChartDatum[]` | yes | | |
|
|
1858
|
+
| `formatter` | `(value: unknown) => ReactNode` | | | Formats the value in the tooltip. The library imposes no locale. |
|
|
1859
|
+
| `height` | `number` | | | Height in pixels. Recharts needs a concrete one to measure itself. |
|
|
1860
|
+
| `label` | `string` | yes | | What the chart shows, in one sentence. Mandatory, like `Progress`'s `label`: a bar `<svg>` with no accessible name is not «a chart without a label», it is an empty region. |
|
|
1861
|
+
| `legend` | `boolean \| undefined` | | | Shows the legend. It defaults to «only when there is more than one series»: a legend naming the one line already named by the chart's own heading is a row of pixels that says nothing. |
|
|
1862
|
+
| `series` | `readonly ChartSeries[]` | yes | | |
|
|
1863
|
+
| `stacked` | `boolean \| undefined` | | `false` | Adds the series up instead of overlaying them. |
|
|
1864
|
+
| `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
|
|
1865
|
+
| `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
|
|
1866
|
+
|
|
1867
|
+
**BarChart**
|
|
1868
|
+
Bars, upright or lying down.
|
|
1869
|
+
|
|
1870
|
+
- Extends: `SeriesChartProps`
|
|
1871
|
+
|
|
1872
|
+
| prop | type | req. | default | what it does |
|
|
1873
|
+
| --- | --- | --- | --- | --- |
|
|
1874
|
+
| `data` | `readonly ChartDatum[]` | yes | | |
|
|
1875
|
+
| `formatter` | `(value: unknown) => ReactNode` | | | Formats the value in the tooltip. The library imposes no locale. |
|
|
1876
|
+
| `height` | `number` | | | Height in pixels. Recharts needs a concrete one to measure itself. |
|
|
1877
|
+
| `label` | `string` | yes | | What the chart shows, in one sentence. Mandatory, like `Progress`'s `label`: a bar `<svg>` with no accessible name is not «a chart without a label», it is an empty region. |
|
|
1878
|
+
| `legend` | `boolean \| undefined` | | | Shows the legend. It defaults to «only when there is more than one series»: a legend naming the one line already named by the chart's own heading is a row of pixels that says nothing. |
|
|
1879
|
+
| `orientation` | `"horizontal" \| "vertical"` | | `vertical` | `vertical` grows the bars upwards, which is the default. `horizontal` is a ranking. |
|
|
1880
|
+
| `series` | `readonly ChartSeries[]` | yes | | |
|
|
1881
|
+
| `stacked` | `boolean \| undefined` | | `false` | Stacks the series instead of putting them side by side. |
|
|
1882
|
+
| `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
|
|
1883
|
+
| `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
|
|
1884
|
+
|
|
1885
|
+
**LineChart**
|
|
1886
|
+
Lines, for comparing series against each other.
|
|
1887
|
+
|
|
1888
|
+
- Extends: `SeriesChartProps`
|
|
1889
|
+
|
|
1890
|
+
| prop | type | req. | default | what it does |
|
|
1891
|
+
| --- | --- | --- | --- | --- |
|
|
1892
|
+
| `data` | `readonly ChartDatum[]` | yes | | |
|
|
1893
|
+
| `formatter` | `(value: unknown) => ReactNode` | | | Formats the value in the tooltip. The library imposes no locale. |
|
|
1894
|
+
| `height` | `number` | | | Height in pixels. Recharts needs a concrete one to measure itself. |
|
|
1895
|
+
| `label` | `string` | yes | | What the chart shows, in one sentence. Mandatory, like `Progress`'s `label`: a bar `<svg>` with no accessible name is not «a chart without a label», it is an empty region. |
|
|
1896
|
+
| `legend` | `boolean \| undefined` | | | Shows the legend. It defaults to «only when there is more than one series»: a legend naming the one line already named by the chart's own heading is a row of pixels that says nothing. |
|
|
1897
|
+
| `series` | `readonly ChartSeries[]` | yes | | |
|
|
1898
|
+
| `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
|
|
1899
|
+
| `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
|
|
1900
|
+
|
|
1486
1901
|
## Exports that are not components
|
|
1487
1902
|
|
|
1488
1903
|
The root re-exports everything from `./tokens` and `./brand` for convenience.
|
|
1489
1904
|
Each one appears exactly once, under the most specific subpath that publishes
|
|
1490
1905
|
it: if the code does not mount React, that subpath is the one to import.
|
|
1491
1906
|
|
|
1907
|
+
### `@eduardoalvarez/arrecife/social/data`
|
|
1908
|
+
|
|
1909
|
+
| export | type | what it is |
|
|
1910
|
+
| --- | --- | --- |
|
|
1911
|
+
| `discordGlyph` | `SocialGlyph` | Discord's mark. Brand, so it is a solid silhouette. |
|
|
1912
|
+
| `emailGlyph` | `SocialGlyph` | The envelope. Functional, so it is a 1.6 stroke. |
|
|
1913
|
+
| `gitHubGlyph` | `SocialGlyph` | GitHub's mark. Brand, so it is a solid silhouette. |
|
|
1914
|
+
| `instagramGlyph` | `SocialGlyph` | Instagram's mark. Brand, so it is a solid silhouette. |
|
|
1915
|
+
| `linkedInGlyph` | `SocialGlyph` | LinkedIn's mark. Brand, so it is a solid silhouette. |
|
|
1916
|
+
| `newsletterGlyph` | `SocialGlyph` | |
|
|
1917
|
+
| `rssGlyph` | `SocialGlyph` | The feed. Functional, so it is a 1.6 stroke — with one filled dot, because a ring that small reads as a smudge. |
|
|
1918
|
+
| `SOCIAL_STROKE_WIDTH` | `1.6` | The stroke width of a functional glyph, from the document. |
|
|
1919
|
+
| `SOCIAL_VIEW_BOX` | `"0 0 24 24"` | The grid every glyph is drawn on. |
|
|
1920
|
+
| `socialGlyphs` | `{ Discord, Email, GitHub, Instagram, LinkedIn, Newsletter, Rss, Website, X, YouTube }` | The whole catalogue, keyed by the name each glyph is exported under in `./social`. |
|
|
1921
|
+
| `socialNames` | `readonly ("Discord" \| "Email" \| "GitHub" \| "Instagram" \| "LinkedIn" \| "Newsletter" \| "Rss" \| "Website" \| "X" \| "YouTube")[]` | The ten names, in the order the catalogue declares them. |
|
|
1922
|
+
| `socialSvg` | `(name: "Discord" \| "Email" \| "GitHub" \| "Instagram" \| "LinkedIn" \| "Newsletter" \| "Rss" \| "Website" \| "X" \| "YouTube", extra?: Readonly<Record<string, string \| number>>): string` | One glyph as a complete `<svg>` string, for a template that cannot mount React. |
|
|
1923
|
+
| `websiteGlyph` | `SocialGlyph` | «My other site», and the reason it is here rather than borrowed. |
|
|
1924
|
+
| `xGlyph` | `SocialGlyph` | X's mark. Brand, so it is a solid silhouette. |
|
|
1925
|
+
| `youTubeGlyph` | `SocialGlyph` | YouTube's mark. Brand, so it is a solid silhouette. |
|
|
1926
|
+
|
|
1927
|
+
Types (3): `SocialGlyph`, `SocialGlyphShape`, `SocialName`.
|
|
1928
|
+
|
|
1492
1929
|
### `@eduardoalvarez/arrecife/variants`
|
|
1493
1930
|
|
|
1494
1931
|
| export | type | what it is |
|
|
@@ -1521,7 +1958,7 @@ it: if the code does not mount React, that subpath is the one to import.
|
|
|
1521
1958
|
| `radius` | `{ readonly chip: 6; readonly control: 10; readonly card: 14; readonly panel: 16; readonly pill: 999; }` | |
|
|
1522
1959
|
| `series` | `{ readonly dark: readonly ["#35D6C0", "#F2A65A", "#3E7CB1", "#71919C"]; readonly light: readonly ["#0D7C6F", "#A65B27", "#3E7CB1", "#626A75"]; }` | The chart series palette. FOUR, for the same reason as the syntax palette: the system communicates with color and border, not with chromatic noise. |
|
|
1523
1960
|
| `shadow` | `{ readonly standard: "0 1px 2px rgba(0, 0, 0, 0.35)"; }` | A single level. There is no elevation scale. |
|
|
1524
|
-
| `size` | `{ readonly nav: 64; readonly content: 760; readonly wide: 1180; }` | |
|
|
1961
|
+
| `size` | `{ readonly nav: 64; readonly navCompact: 56; readonly sidebar: 256; readonly sidebarRail: 56; readonly content: 760; readonly wide: 1180; }` | |
|
|
1525
1962
|
| `spacing` | `{ readonly stepXs: 8; readonly stepSm: 12; readonly stepMd: 16; readonly stepLg: 26; readonly stepXl: 40; readonly section: 96; }` | Page rhythm. All five steps carry `step` in the name, and that is not decoration: it is the fix for a bug that never surfaced anywhere. |
|
|
1526
1963
|
| `syntax` | `{ background, identifier, literal, keyword, comment, invalid }` | The syntax highlighting palette. |
|
|
1527
1964
|
| `tagline` | `{ long, short, en }` | |
|
|
@@ -1530,6 +1967,10 @@ it: if the code does not mount React, that subpath is the one to import.
|
|
|
1530
1967
|
|
|
1531
1968
|
Types (13): `BrandToken`, `ColorMode`, `ColorToken`, `ControlToken`, `FontToken`, `GradientToken`, `RadiusToken`, `SeriesToken`, `SizeToken`, `SpacingToken`, `SyntaxToken`, `Tokens`, `TypeScaleToken`.
|
|
1532
1969
|
|
|
1970
|
+
### `@eduardoalvarez/arrecife/social`
|
|
1971
|
+
|
|
1972
|
+
Types (1): `SocialIconProps`.
|
|
1973
|
+
|
|
1533
1974
|
### `@eduardoalvarez/arrecife/theme`
|
|
1534
1975
|
|
|
1535
1976
|
| export | type | what it is |
|
|
@@ -1561,6 +2002,15 @@ Types (2): `Theme`, `ThemeOptions`.
|
|
|
1561
2002
|
|
|
1562
2003
|
Types (8): `Background`, `Face`, `Fin`, `IsotypeProps`, `LogoProps`, `MascotFaceProps`, `MascotProps`, `Pose`.
|
|
1563
2004
|
|
|
2005
|
+
### `@eduardoalvarez/arrecife/icons`
|
|
2006
|
+
|
|
2007
|
+
| export | type | what it is |
|
|
2008
|
+
| --- | --- | --- |
|
|
2009
|
+
| `ICON_WEIGHT` | `"light" \| "fill" \| "thin" \| "regular" \| "bold" \| "duotone"` | Phosphor's own name for the system's line. It is what `tone="action"` resolves to. |
|
|
2010
|
+
| `TONE_WEIGHT` | `Record<IconTone, IconWeight>` | The three roles, and the weight each one is drawn at. This is the whole of the weight axis: Phosphor ships six and this system reads three, because the other three — `thin`, `bold`, `duotone` — have no role behind them here. |
|
|
2011
|
+
|
|
2012
|
+
Types (2): `IconProps`, `IconTone`.
|
|
2013
|
+
|
|
1564
2014
|
### `@eduardoalvarez/arrecife/shiki`
|
|
1565
2015
|
|
|
1566
2016
|
| export | type | what it is |
|
|
@@ -1576,7 +2026,7 @@ Types (1): `ShikiTheme`.
|
|
|
1576
2026
|
| `SERIES_COLORS` | `string[]` | All four, in order, to hand to a `Pie` with `Cell` in one go. |
|
|
1577
2027
|
| `seriesColor` | `(index: number): string` | The color of series `index`, as a custom property. |
|
|
1578
2028
|
|
|
1579
|
-
Types (
|
|
2029
|
+
Types (10): `AreaChartProps`, `BarChartProps`, `ChartContainerProps`, `ChartDatum`, `ChartLegendContentProps`, `ChartPayloadItem`, `ChartSeries`, `ChartTooltipContentProps`, `LineChartProps`, `SeriesChartProps`.
|
|
1580
2030
|
|
|
1581
2031
|
### `@eduardoalvarez/arrecife/form`
|
|
1582
2032
|
|
|
@@ -1602,11 +2052,11 @@ Types (6): `ArticleData`, `BaseData`, `CourseData`, `DefaultData`, `SatoriNode`,
|
|
|
1602
2052
|
| export | type | what it is |
|
|
1603
2053
|
| --- | --- | --- |
|
|
1604
2054
|
| `cn` | `(...inputs: ClassValue[]): string` | |
|
|
1605
|
-
| `social` | `typeof import("src/
|
|
2055
|
+
| `social` | `typeof import("src/social/index")` | |
|
|
1606
2056
|
| `toast` | `(message: ReactNode, options?: ToastOptions \| undefined): string` | Fires a notice. It returns its id, which is what you keep in order to close it by hand — the «guardando…» case that gets replaced when the request finishes. |
|
|
1607
2057
|
| `useTheme` | `(): Theme` | The theme set right now, for a project that needs to branch in React — a different logo per mode, an image with no light version. |
|
|
1608
2058
|
|
|
1609
|
-
Types (60): `AccordionProps`, `AccordionTriggerProps`, `AlertProps`, `ArticleCardProps`, `AudioPlayerMode`, `AudioPlayerProps`, `AuthorCardProps`, `AvatarProps`, `AvatarUploadProps`, `BadgeProps`, `BlockquoteProps`, `BreadcrumbProps`, `ButtonProps`, `CalendarEvent`, `CalendarProps`, `CategoryBadgeProps`, `CheckboxProps`, `CodeBlockProps`, `CodeProps`, `CourseCardProps`, `Crumb`, `DateFieldProps`, `EmptyStateProps`, `EventCalendarProps`, `
|
|
2059
|
+
Types (60): `AccordionProps`, `AccordionTriggerProps`, `AlertProps`, `ArticleCardProps`, `AudioPlayerMode`, `AudioPlayerProps`, `AuthorCardProps`, `AvatarProps`, `AvatarUploadProps`, `BadgeProps`, `BlockquoteProps`, `BreadcrumbProps`, `ButtonProps`, `CalendarEvent`, `CalendarProps`, `CategoryBadgeProps`, `CheckboxProps`, `CodeBlockProps`, `CodeProps`, `CourseCardProps`, `Crumb`, `DateFieldProps`, `EmptyStateProps`, `EventCalendarProps`, `FooterColumn`, `FooterColumnLink`, `FooterProps`, `HeroProps`, `InputProps`, `LabelProps`, `LinkRowProps`, `MetricBadgeProps`, `NavItemProps`, `NavProps`, `NewsletterFormProps`, `NewsletterState`, `PageHeaderProps`, `PaginationLinkProps`, `PopoverContentProps`, `ProgressProps`, `RadioGroupItemProps`, `RadioGroupProps`, `ScrollingProgressBarProps`, `SeparatorProps`, `SheetContentProps`, `SkeletonProps`, `SocialLink`, `StatDelta`, `StatProps`, `SwitchProps`, `TableOfContentsProps`, `TabsProps`, `TalkCardProps`, `TextProps`, `TextareaProps`, `ThemeToggleProps`, `ToastOptions`, `ToastVariant`, `ToasterProps`, `TocEntry`.
|
|
1610
2060
|
|
|
1611
2061
|
# Where to look if this is not enough
|
|
1612
2062
|
|
|
@@ -1614,8 +2064,8 @@ Types (60): `AccordionProps`, `AccordionTriggerProps`, `AlertProps`, `ArticleCar
|
|
|
1614
2064
|
generated from the types.
|
|
1615
2065
|
- The repo's `README.md`: the reasoning behind each decision, the contrast
|
|
1616
2066
|
correction table and the release cycle.
|
|
1617
|
-
- `
|
|
2067
|
+
- `architecture/design-system.md` and `architecture/brand-manual.md`: the identity documents,
|
|
1618
2068
|
greppable.
|
|
1619
|
-
- `
|
|
2069
|
+
- `decisions/`: the points where the code and the document did not say the
|
|
1620
2070
|
same thing, each with its resolution.
|
|
1621
2071
|
- `AGENTS.md`: for working inside the library's repo.
|