@eduardoalvarez/arrecife 0.7.0 → 0.9.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +115 -41
  3. package/dist/brand/index.cjs +2 -2
  4. package/dist/brand/index.js +3 -3
  5. package/dist/chart/index.cjs +155 -2
  6. package/dist/chart/index.d.cts +136 -4
  7. package/dist/chart/index.d.ts +136 -4
  8. package/dist/chart/index.js +155 -5
  9. package/dist/{chunk-TA7TLWW4.js → chunk-5A5GH2PF.js} +1 -1
  10. package/dist/{chunk-727HCBD4.js → chunk-6IGD5REB.js} +1 -1
  11. package/dist/{chunk-2WPWEIMD.js → chunk-FAAGZG7A.js} +1 -1
  12. package/dist/{chunk-OMKSESQB.js → chunk-FGFNK72B.js} +3 -3
  13. package/dist/chunk-HOADZ6GS.js +72 -0
  14. package/dist/chunk-LXRGQKMG.js +145 -0
  15. package/dist/{chunk-JN3IS5OS.js → chunk-MPZBF2TZ.js} +2 -2
  16. package/dist/{chunk-WGNIRIN7.js → chunk-TRPBID2W.js} +1 -1
  17. package/dist/{chunk-E6KFUSKB.js → chunk-XXDATT3A.js} +1 -1
  18. package/dist/doctor.mjs +95 -13
  19. package/dist/form/index.cjs +2 -2
  20. package/dist/form/index.d.cts +1 -1
  21. package/dist/form/index.d.ts +1 -1
  22. package/dist/form/index.js +4 -4
  23. package/dist/icons/index.cjs +2 -2
  24. package/dist/icons/index.d.cts +2 -2
  25. package/dist/icons/index.d.ts +2 -2
  26. package/dist/icons/index.js +2 -2
  27. package/dist/{index-DlAO2JZs.d.cts → index-BbRplw_B.d.cts} +15 -4
  28. package/dist/{index-DlAO2JZs.d.ts → index-BbRplw_B.d.ts} +15 -4
  29. package/dist/index.cjs +264 -264
  30. package/dist/index.d.cts +212 -126
  31. package/dist/index.d.ts +212 -126
  32. package/dist/index.js +153 -236
  33. package/dist/{label-MgHFKnFy.d.ts → label-DJ4HuD-R.d.cts} +3 -2
  34. package/dist/{label-MgHFKnFy.d.cts → label-DJ4HuD-R.d.ts} +3 -2
  35. package/dist/og/index.js +1 -1
  36. package/dist/shiki/index.js +1 -1
  37. package/dist/social/data.cjs +161 -0
  38. package/dist/social/data.d.cts +161 -0
  39. package/dist/social/data.d.ts +161 -0
  40. package/dist/social/data.js +2 -0
  41. package/dist/social/index.cjs +124 -38
  42. package/dist/social/index.d.cts +1 -1
  43. package/dist/social/index.d.ts +1 -1
  44. package/dist/social/index.js +2 -1
  45. package/dist/tokens/index.cjs +3 -3
  46. package/dist/tokens/index.d.cts +5 -5
  47. package/dist/tokens/index.d.ts +5 -5
  48. package/dist/tokens/index.js +2 -2
  49. package/dist/tokens/theme.css +46 -19
  50. package/dist/variants/index.cjs +1 -1
  51. package/dist/variants/index.d.cts +2 -2
  52. package/dist/variants/index.d.ts +2 -2
  53. package/dist/variants/index.js +1 -1
  54. package/llms.txt +264 -140
  55. package/package.json +6 -1
  56. package/dist/chunk-45HVCTB7.js +0 -70
package/llms.txt CHANGED
@@ -116,10 +116,11 @@ 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 nine social icons, loose. No `"use client"` |
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 |
120
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 |
121
122
  | `@eduardoalvarez/arrecife/form` | yes | `react-hook-form` | The form layer: labels, errors and `aria-*` |
122
- | `@eduardoalvarez/arrecife/chart` | yes | `recharts` | The chart chassis and the series palette |
123
+ | `@eduardoalvarez/arrecife/chart` | yes | `recharts` | The chart chassis, the series palette and the three chart types |
123
124
  | `@eduardoalvarez/arrecife/assets/*` | — | — | The brand PNGs |
124
125
 
125
126
  Importing the root from a build script to get one token is the mistake the
@@ -146,11 +147,11 @@ import in an adapter of your own marked `"use client"` — that was the workarou
146
147
  before 0.6.0 and it pulled 272 KB of client chunk in for components that never
147
148
  needed it.
148
149
 
149
- The five portable subpaths do NOT carry the directive, and that is the half that
150
- matters in a Server Component: `./tokens`, `./theme`, `./variants`, `./og` and
151
- `./shiki` stay on the server. Neither does `./social`, which is a third case: it
152
- renders React — it is nine `<svg>` — so it can never be portable, but it holds no
153
- state and nothing about it needs a client boundary. It is the only way to put a
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
154
155
  social icon in a Server Component, and § «The social icons come from `./social`»
155
156
  below says why the grouped form cannot do it. If all you need are classes — for a `<div>`, an
156
157
  `<a>` or an Astro island you do not want to hydrate — import them from
@@ -229,59 +230,6 @@ tells them apart.
229
230
  Do not silence it by removing the `@import`: the fix is the `@source` line, or
230
231
  renaming your own token.
231
232
 
232
- ### `SidebarNav` groups, and the icon replaces the prompt
233
-
234
- ```tsx
235
- <SidebarNav aria-label="Administración" brand={<>…</>} version="v0.6.0" branch="main">
236
- <SidebarItem href="/admin" icon={<Icon as={SquaresFour} />} active>Resumen</SidebarItem>
237
-
238
- <SidebarGroup label="Ventas">
239
- <SidebarItem href="/admin/ventas" icon={<Icon as={CreditCard} />}>Ventas</SidebarItem>
240
- <SidebarItem href="/admin/cupones" icon={<Icon as={Ticket} />}>Cupones</SidebarItem>
241
- </SidebarGroup>
242
- </SidebarNav>
243
- ```
244
-
245
- Past about eight items a flat sidebar stops being readable. Each `SidebarGroup`
246
- is a nested list named by its label, so a screen reader says «lista Ventas, 3
247
- elementos» instead of one list of eleven. The label is a paragraph and **not** a
248
- heading on purpose: a sidebar is navigation, and a heading here would land in the
249
- page's own outline.
250
-
251
- **`icon` replaces the `▸`, it does not join it.** Do not pass a glyph and expect
252
- the prompt as well. A sidebar with no icons keeps the prompt on every item, which
253
- is what a four-section blog admin wants.
254
-
255
- **`brand` does not replace `title`.** `title` is the eyebrow and also the `nav`'s
256
- accessible name when it is a string; a logo is not an accessible name, so pass
257
- `aria-label` when you use `brand`. See `docs/decisions.md` § 32.
258
-
259
- **It collapses to a rail, and the toggle is CONTROLLED:**
260
-
261
- ```tsx
262
- const [collapsed, setCollapsed] = useState(false);
263
-
264
- <SidebarNav
265
- collapsed={collapsed}
266
- onCollapsedChange={setCollapsed}
267
- brand={<Wordmark />}
268
- mark={<Isotype className="h-6" />}
269
- user={<Avatar … />}
270
- >
271
- ```
272
-
273
- There is no uncontrolled mode: this state is almost always persisted, and an
274
- internal one would fight the cookie you already keep. `onCollapsedChange` is also
275
- what makes the toggle appear — `collapsed` on its own is a rail with no way out,
276
- which is a layout and not an accident.
277
-
278
- Collapsed, the widths become `w-sidebar-rail` (56) and `w-sidebar` (256), and the
279
- component owns them only when it can collapse. It does **not** transition, on
280
- purpose. `brand` is hidden and `mark` takes its place, because a wordmark does
281
- not fit in a rail. Every label stays in the accessibility tree as `sr-only`, so
282
- do not «simplify» by dropping the children of a collapsed item. See
283
- `docs/decisions.md` § 34.
284
-
285
233
  ### `Nav` is two slots and one height
286
234
 
287
235
  Almost everything an app shell wants from a site bar is already a slot:
@@ -308,7 +256,7 @@ does nothing.
308
256
 
309
257
  **One `Nav` per page.** It renders the site's `banner` landmark, and two banners
310
258
  on one page is an accessibility failure — which is also why `PageHeader` goes
311
- inside `<main>` and is not a landmark. See `docs/decisions.md` § 30.
259
+ inside `<main>` and is not a landmark. See `decisions/0.7.md` § 30.
312
260
 
313
261
  ### Icons are yours, the way they are drawn is not
314
262
 
@@ -344,13 +292,13 @@ is no fourth:
344
292
  | `tone` | Weight | What it is |
345
293
  | --- | --- | --- |
346
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 |
347
- | `current` | `fill` | The one of a set you are on — the sidebar item carrying `aria-current` |
295
+ | `current` | `fill` | The one of a set you are on — the nav item carrying `aria-current` |
348
296
  | `quiet` | `light` | Furniture: a marker in a metadata row, not a control and not a state |
349
297
 
350
298
  ```tsx
351
- <SidebarItem href="/cursos" active icon={<Icon as={GraduationCap} tone="current" />}>
299
+ <NavItem href="/cursos" active icon={<Icon as={GraduationCap} tone="current" />}>
352
300
  cursos
353
- </SidebarItem>
301
+ </NavItem>
354
302
  ```
355
303
 
356
304
  `current` is the one that earns the axis. An active item already paints itself
@@ -377,7 +325,7 @@ a Server Component throws. It ships no `"use client"` to stop you, so the failur
377
325
  arrives at render rather than at build. The `/ssr` entry is the same icons
378
326
  without the context read, and `Icon` works with either.
379
327
 
380
- See `docs/decisions.md` § 29 and § 35.
328
+ See `decisions/0.7.md` § 29 and § 35.
381
329
 
382
330
  ### `Stat`'s delta says direction, not judgement
383
331
 
@@ -394,7 +342,7 @@ errores» point the same way and mean opposite things, so whether a number is go
394
342
  news is `tone`'s job and yours: `neutral` for a datum, `alert` when the number IS
395
343
  the problem, `achievement` when it is the reward. `alert` and `achievement` paint
396
344
  the same sand on purpose — the API is the meaning, the colour is the
397
- implementation. See `docs/decisions.md` § 28.
345
+ implementation. See `decisions/0.7.md` § 28.
398
346
 
399
347
  `delta.value` arrives already formatted, like `value`: the library imposes no
400
348
  locale and computes no percentage. `spark` is a `ReactNode` and the library ships
@@ -404,7 +352,7 @@ no sparkline — pass your own, exactly like `icon`.
404
352
  and biolume goes on the icon badge and the sparkline instead: three accents in
405
353
  one card and the figure stops being the loudest thing in it. `alert` and
406
354
  `achievement` DO paint the number sand, which is how «this number is not just a
407
- number» is said. See `docs/decisions.md` § 31.
355
+ number» is said. See `decisions/0.7.md` § 31.
408
356
 
409
357
  **`icon` is a badge in the corner opposite the title**, in a circle tinted at
410
358
  10 % of the tone. You pass the glyph; the circle, the tint and the size are the
@@ -432,6 +380,102 @@ Do not reach for `page` inside a table because the face is «nicer»: an admin
432
380
  screen with a dozen empty regions gets a dozen mascots, which is what made every
433
381
  consuming project write its own empty state instead of using this one.
434
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
+
435
479
  ### The social icons come from `./social`
436
480
 
437
481
  ```tsx
@@ -446,9 +490,16 @@ import { social } from '@eduardoalvarez/arrecife';
446
490
  <social.GitHub />
447
491
  ```
448
492
 
449
- All nine: `GitHub`, `LinkedIn`, `X`, `Instagram`, `Discord`, `YouTube`, `Rss`,
450
- `Email`, `Newsletter`. `Newsletter` is the bell: a way to follow, like `Rss`,
451
- named for what it means.
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.
452
503
 
453
504
  **In a Server Component the subpath is mandatory, not preferred.** The root
454
505
  carries `"use client"`, and a client reference crosses the boundary per EXPORT —
@@ -460,6 +511,24 @@ client JS. Use `social` only when mapping a list of names onto icons.
460
511
  The root keeps the group because one of them is called `X`, and loose at the root
461
512
  it collides. In the subpath, alias it: `import { X as XIcon }`.
462
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.
531
+
463
532
  The internal glyphs — `Close`, `ChevronDown`, `Sun` — are **not exported** and
464
533
  are not going to be: they are the primitives' minimum set. A component that needs
465
534
  an icon receives it as a prop (`Stat` has `icon`, each `SocialLink` in `Footer`
@@ -498,7 +567,7 @@ They carry a prefix because `xs, sm, md, lg, xl` are the names of Tailwind's
498
567
  `--container-*` scale, and a `--spacing-md` of our own was swallowing `max-w-md`
499
568
  across the whole project with nothing warning about it. `max-w-*`, `w-*` and
500
569
  `h-*` belong to Tailwind and are used as they are. Migration guide from 0.2.0:
501
- <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>.
502
571
 
503
572
  ## System rules the consuming code must not break
504
573
 
@@ -511,10 +580,16 @@ compiles and looks wrong, or that fails the project's accessibility audit.
511
580
  3. **`Button variant="destructive"` is for the irreversible only.** Never for
512
581
  «cancel» on a form, and not inside an `AlertDialog` — there the confirm button
513
582
  stays `primary`, because the title, the focus on cancel and the no-click-outside
514
- already carry the weight. See `docs/decisions.md` § 21.
583
+ already carry the weight. See `decisions/0.6.md` § 21.
515
584
  4. **`secondary` is never filled.** It is border and text.
516
585
  5. **No entrance animations.** Modals, menus, tooltips and toasts appear where
517
- they will stay. The only exception is the `Button loading` spinner.
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.
518
593
  6. **Semantics and scale are independent.** An `h2` that has to look small is
519
594
  `<Text as="h2" variant="h3">`, never an `h3` that lies about the hierarchy.
520
595
  7. **`textMuted` never goes over `surfaceRaised`**: it gives 4.07 in dark. Over a
@@ -534,7 +609,7 @@ compiles and looks wrong, or that fails the project's accessibility audit.
534
609
  hole inside a table page or a dashboard widget, and it carries no face — the
535
610
  type does not accept one. `page`, the default, is the one that IS the screen,
536
611
  and there `expression` stays mandatory. A dozen mascots on one admin screen is
537
- not the humour contract. See `docs/decisions.md` § 27.
612
+ not the humour contract. See `decisions/0.7.md` § 27.
538
613
  12. **The fin is not a free parameter**: `foam` on a dark background, `color` on a
539
614
  light one. The components already choose it from the background.
540
615
 
@@ -833,7 +908,7 @@ Source: `src/primitives/date-field.tsx`
833
908
 
834
909
  A date field on the native control, not on a calendar of our own.
835
910
 
836
- - Extends: `Omit<ComponentPropsWithoutRef<'input'>, 'type'>`
911
+ - Extends: `Omit<ComponentProps<'input'>, 'type'>`
837
912
 
838
913
  | prop | type | req. | default | what it does |
839
914
  | --- | --- | --- | --- | --- |
@@ -922,7 +997,9 @@ No entrance animation: the menu appears, it does not unfold.
922
997
 
923
998
  Source: `src/primitives/input.tsx`
924
999
 
925
- - Extends: `ComponentPropsWithoutRef<'input'>`
1000
+ `ComponentProps` and not `ComponentPropsWithoutRef`, and the difference is a bug and not a preference.
1001
+
1002
+ - Extends: `ComponentProps<'input'>`
926
1003
 
927
1004
  | prop | type | req. | default | what it does |
928
1005
  | --- | --- | --- | --- | --- |
@@ -934,7 +1011,7 @@ Source: `src/primitives/label.tsx`
934
1011
 
935
1012
  The `label` scale: 13px, which is the system's absolute minimum on screen.
936
1013
 
937
- - Extends: `ComponentPropsWithoutRef<typeof LabelPrimitive.Root>`
1014
+ - Extends: `ComponentProps<typeof LabelPrimitive.Root>`
938
1015
  - No own props: it passes through those of the element or primitive it wraps.
939
1016
 
940
1017
  ### Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext, PaginationEllipsis
@@ -1118,7 +1195,7 @@ The knob changes position, but is not animated while doing so: the position IS t
1118
1195
  Source: `src/primitives/table.tsx`
1119
1196
 
1120
1197
  **Table**
1121
- The container scrolls horizontally: the page never does.
1198
+ The table, and the surface it sits on. The two are one piece.
1122
1199
 
1123
1200
  - No own props: it passes through those of the element or primitive it wraps.
1124
1201
 
@@ -1141,6 +1218,8 @@ The container scrolls horizontally: the page never does.
1141
1218
  - No own props: it passes through those of the element or primitive it wraps.
1142
1219
 
1143
1220
  **TableCaption**
1221
+ The caption, at the bottom and INSIDE the surface.
1222
+
1144
1223
  - No own props: it passes through those of the element or primitive it wraps.
1145
1224
 
1146
1225
  ### Tabs, TabsList, TabsTrigger, TabsContent
@@ -1164,7 +1243,9 @@ Source: `src/primitives/tabs.tsx`
1164
1243
 
1165
1244
  Source: `src/primitives/textarea.tsx`
1166
1245
 
1167
- - Extends: `ComponentPropsWithoutRef<'textarea'>`
1246
+ `ComponentProps` carries `ref`, which React 19 passes as a prop. See `InputProps`.
1247
+
1248
+ - Extends: `ComponentProps<'textarea'>`
1168
1249
 
1169
1250
  | prop | type | req. | default | what it does |
1170
1251
  | --- | --- | --- | --- | --- |
@@ -1215,7 +1296,7 @@ Source: `src/primitives/typography.tsx`
1215
1296
 
1216
1297
  ## Components
1217
1298
 
1218
- Imported from `@eduardoalvarez/arrecife`. 25 exports.
1299
+ Imported from `@eduardoalvarez/arrecife`. 21 exports.
1219
1300
 
1220
1301
  ### ArticleCard
1221
1302
 
@@ -1223,7 +1304,7 @@ Source: `src/components/article-card/index.tsx`
1223
1304
 
1224
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.
1225
1306
 
1226
- - Extends: `Omit<CardShellProps, 'children' \| 'title'>`
1307
+ - Extends: `Omit<CardShellProps, "children" \| "title">`
1227
1308
 
1228
1309
  | prop | type | req. | default | what it does |
1229
1310
  | --- | --- | --- | --- | --- |
@@ -1355,26 +1436,25 @@ Source: `src/components/event-calendar/index.tsx`
1355
1436
  | `onUpdateEvent` | `(event: CalendarEvent) => void` | | | |
1356
1437
  | `selected` | `Date` | | | Selected day, if the project controls it. Without it, it starts on today. |
1357
1438
 
1358
- ### Footer, FooterLink
1439
+ ### Footer
1359
1440
 
1360
1441
  Source: `src/components/footer/index.tsx`
1361
1442
 
1362
- **Footer**
1363
- - 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; } )`
1364
1444
 
1365
1445
  | prop | type | req. | default | what it does |
1366
1446
  | --- | --- | --- | --- | --- |
1447
+ | `action` | `ReactNode` | | | An action under the row of icons — «Reportar un problema». Usually a tertiary button. |
1367
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
+ | `domain` | `string` | | | The domain the signature prints, defaulting to the identity's own. |
1452
+ | `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`. |
1453
+ | `signatureHref` | `string` | | | Makes the domain inside the signature a link, keeping the `$`, the path and the prompt's mark as text. |
1368
1454
  | `social` | `readonly SocialLink[]` | | | |
1455
+ | `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. |
1369
1456
  | `year` | `number` | | `new Date().getFullYear()` | The signature's year. |
1370
1457
 
1371
- **FooterLink**
1372
- - Extends: `ComponentPropsWithoutRef<'a'>`
1373
-
1374
- | prop | type | req. | default | what it does |
1375
- | --- | --- | --- | --- | --- |
1376
- | `asChild` | `boolean \| undefined` | | `false` | |
1377
-
1378
1458
  ### Hero
1379
1459
 
1380
1460
  Source: `src/components/hero/index.tsx`
@@ -1494,46 +1574,6 @@ How much you have read. It is NOT `Progress` under another name.
1494
1574
  | `target` | `RefObject<HTMLElement \| null>` | | | The element being measured. Without it, the whole document. |
1495
1575
  | `tone` | `"accent" \| "warm"` | | `accent` | Sand instead of biolume, to match course progress. |
1496
1576
 
1497
- ### SidebarItem, SidebarGroup, SidebarNav
1498
-
1499
- Source: `src/components/sidebar-nav/index.tsx`
1500
-
1501
- **SidebarItem**
1502
- The blog admin's sidebar.
1503
-
1504
- - Extends: `ComponentPropsWithoutRef<'a'>`
1505
-
1506
- | prop | type | req. | default | what it does |
1507
- | --- | --- | --- | --- | --- |
1508
- | `active` | `boolean \| undefined` | | `false` | |
1509
- | `asChild` | `boolean \| undefined` | | `false` | |
1510
- | `badge` | `ReactNode` | | | Counter on the right: pending drafts, unused media. |
1511
- | `icon` | `ReactNode` | | | The section's glyph, on the left. It REPLACES the `▸` rather than joining it, and it inherits `currentColor`, so it follows the item's state without being tinted separately. |
1512
-
1513
- **SidebarGroup**
1514
- A labelled block of items — «Contenido», «Alumnos», «Ventas».
1515
-
1516
- - Extends: `Omit<ComponentPropsWithoutRef<'li'>, 'title'>`
1517
-
1518
- | prop | type | req. | default | what it does |
1519
- | --- | --- | --- | --- | --- |
1520
- | `label` | `ReactNode` | yes | | The block's name. Sentence case, not a section title. |
1521
-
1522
- **SidebarNav**
1523
- - Extends: `ComponentPropsWithoutRef<'nav'>`
1524
-
1525
- | prop | type | req. | default | what it does |
1526
- | --- | --- | --- | --- | --- |
1527
- | `branch` | `ReactNode` | | | |
1528
- | `brand` | `ReactNode` | | | The row at the top: isotype and wordmark, `cursos · admin`. It is a slot and not a `logo`/`name` pair because every panel spells its own name differently, and the part that IS the system — the rhythm, the hairline under it — is here. |
1529
- | `collapsed` | `boolean \| undefined` | | `false` | Turns the sidebar into a rail: icons only, and the widths become the library's — `w-sidebar` and `w-sidebar-rail`. It is CONTROLLED and there is no uncontrolled mode, because this state is almost always persisted in a cookie or in `localStorage`, and an internal state would fight the one the project already keeps. |
1530
- | `collapseLabel` | `string` | | `Plegar el panel` | The toggle's accessible name, in the two directions. |
1531
- | `expandLabel` | `string` | | `Desplegar el panel` | |
1532
- | `mark` | `ReactNode` | | | What `brand` becomes in the rail. Usually the isotype with no wordmark. |
1533
- | `onCollapsedChange` | `(collapsed: boolean) => void` | | | Called with what the state should become. With it, the toggle appears; with `collapsed` alone the sidebar is a rail with no way out of it, which is a legitimate layout and not an accident. |
1534
- | `user` | `ReactNode` | | | Who is signed in, at the bottom above the version. A slot, because an avatar needs a session and a sign-out route and the library takes no project infrastructure — the same reason `Nav`'s user menu goes in `actions`. |
1535
- | `version` | `ReactNode` | | | Version and branch, at the bottom. |
1536
-
1537
1577
  ### Stat
1538
1578
 
1539
1579
  Source: `src/components/stat/index.tsx`
@@ -1550,7 +1590,7 @@ A large metric: the number in the `stat` scale and its name underneath.
1550
1590
  | `label` | `ReactNode` | yes | | What is being counted. It goes in mono small caps. |
1551
1591
  | `progress` | `number` | | | With `progress`, the metric reads as progress and adds the bar. |
1552
1592
  | `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`. |
1553
- | `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.md` § 28. |
1593
+ | `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. |
1554
1594
  | `value` | `ReactNode` | yes | | The number, already formatted. The library imposes no locale. |
1555
1595
 
1556
1596
  ### TalkCard
@@ -1658,9 +1698,9 @@ Tiburoncín's head, with an expression.
1658
1698
 
1659
1699
  ## Social icons
1660
1700
 
1661
- Imported from `@eduardoalvarez/arrecife/social` · or grouped as `social` from the root. 9 exports.
1701
+ Imported from `@eduardoalvarez/arrecife/social` · or grouped as `social` from the root. 10 exports.
1662
1702
 
1663
- ### GitHub, LinkedIn, X, Instagram, Discord, YouTube, Rss, Email, Newsletter
1703
+ ### GitHub, LinkedIn, X, Instagram, Discord, YouTube, Rss, Email, Newsletter, Website
1664
1704
 
1665
1705
  Source: `src/social/index.tsx`
1666
1706
 
@@ -1693,6 +1733,11 @@ The newsletter. It plays the same role as `Rss` — a way to follow, not a socia
1693
1733
 
1694
1734
  - No own props: it passes through those of the element or primitive it wraps.
1695
1735
 
1736
+ **Website**
1737
+ «My other site»: the personal domain in a footer full of social networks.
1738
+
1739
+ - No own props: it passes through those of the element or primitive it wraps.
1740
+
1696
1741
  ## Icons
1697
1742
 
1698
1743
  Imported from `@eduardoalvarez/arrecife/icons` · requires `@phosphor-icons/react`. 1 exports.
@@ -1754,9 +1799,9 @@ The layer that ties the controls to a form with validation and messages.
1754
1799
 
1755
1800
  ## Charts
1756
1801
 
1757
- Imported from `@eduardoalvarez/arrecife/chart` · requires `recharts`. 5 exports.
1802
+ Imported from `@eduardoalvarez/arrecife/chart` · requires `recharts`. 8 exports.
1758
1803
 
1759
- ### ChartContainer, ChartTooltip, ChartLegend, ChartTooltipContent, ChartLegendContent
1804
+ ### ChartContainer, ChartTooltip, ChartLegend, ChartTooltipContent, ChartLegendContent, AreaChart, BarChart, LineChart
1760
1805
 
1761
1806
  Source: `src/chart/index.tsx`
1762
1807
 
@@ -1803,12 +1848,91 @@ The legend, with the tooltip's same square swatch and the `label` scale.
1803
1848
  | `className` | `string` | | | |
1804
1849
  | `payload` | `readonly ChartPayloadItem[]` | | | |
1805
1850
 
1851
+ **AreaChart**
1852
+ A series over time, with the fill fading out underneath it.
1853
+
1854
+ - Extends: `SeriesChartProps`
1855
+
1856
+ | prop | type | req. | default | what it does |
1857
+ | --- | --- | --- | --- | --- |
1858
+ | `data` | `readonly ChartDatum[]` | yes | | |
1859
+ | `formatter` | `(value: unknown) => ReactNode` | | | Formats the value in the tooltip. The library imposes no locale. |
1860
+ | `height` | `number` | | | Height in pixels. Recharts needs a concrete one to measure itself. |
1861
+ | `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. |
1862
+ | `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. |
1863
+ | `series` | `readonly ChartSeries[]` | yes | | |
1864
+ | `stacked` | `boolean \| undefined` | | `false` | Adds the series up instead of overlaying them. |
1865
+ | `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
1866
+ | `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
1867
+ | `xTickFormatter` | `(value: unknown) => string` | | | Formats the TICK on the category axis. Returns a string, because an axis tick is an SVG `<text>` and not a place a node can go. |
1868
+ | `yTickFormatter` | `(value: unknown) => string` | | | Formats the tick on the VALUE axis — the currency symbol, the thousands separator, the percent sign. |
1869
+
1870
+ **BarChart**
1871
+ Bars, upright or lying down.
1872
+
1873
+ - Extends: `SeriesChartProps`
1874
+
1875
+ | prop | type | req. | default | what it does |
1876
+ | --- | --- | --- | --- | --- |
1877
+ | `data` | `readonly ChartDatum[]` | yes | | |
1878
+ | `formatter` | `(value: unknown) => ReactNode` | | | Formats the value in the tooltip. The library imposes no locale. |
1879
+ | `height` | `number` | | | Height in pixels. Recharts needs a concrete one to measure itself. |
1880
+ | `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. |
1881
+ | `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. |
1882
+ | `orientation` | `"horizontal" \| "vertical"` | | `vertical` | `vertical` grows the bars upwards, which is the default. `horizontal` is a ranking. |
1883
+ | `series` | `readonly ChartSeries[]` | yes | | |
1884
+ | `stacked` | `boolean \| undefined` | | `false` | Stacks the series instead of putting them side by side. |
1885
+ | `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
1886
+ | `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
1887
+ | `xTickFormatter` | `(value: unknown) => string` | | | Formats the TICK on the category axis. Returns a string, because an axis tick is an SVG `<text>` and not a place a node can go. |
1888
+ | `yTickFormatter` | `(value: unknown) => string` | | | Formats the tick on the VALUE axis — the currency symbol, the thousands separator, the percent sign. |
1889
+
1890
+ **LineChart**
1891
+ Lines, for comparing series against each other.
1892
+
1893
+ - Extends: `SeriesChartProps`
1894
+
1895
+ | prop | type | req. | default | what it does |
1896
+ | --- | --- | --- | --- | --- |
1897
+ | `data` | `readonly ChartDatum[]` | yes | | |
1898
+ | `formatter` | `(value: unknown) => ReactNode` | | | Formats the value in the tooltip. The library imposes no locale. |
1899
+ | `height` | `number` | | | Height in pixels. Recharts needs a concrete one to measure itself. |
1900
+ | `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. |
1901
+ | `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. |
1902
+ | `series` | `readonly ChartSeries[]` | yes | | |
1903
+ | `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
1904
+ | `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
1905
+ | `xTickFormatter` | `(value: unknown) => string` | | | Formats the TICK on the category axis. Returns a string, because an axis tick is an SVG `<text>` and not a place a node can go. |
1906
+ | `yTickFormatter` | `(value: unknown) => string` | | | Formats the tick on the VALUE axis — the currency symbol, the thousands separator, the percent sign. |
1907
+
1806
1908
  ## Exports that are not components
1807
1909
 
1808
1910
  The root re-exports everything from `./tokens` and `./brand` for convenience.
1809
1911
  Each one appears exactly once, under the most specific subpath that publishes
1810
1912
  it: if the code does not mount React, that subpath is the one to import.
1811
1913
 
1914
+ ### `@eduardoalvarez/arrecife/social/data`
1915
+
1916
+ | export | type | what it is |
1917
+ | --- | --- | --- |
1918
+ | `discordGlyph` | `SocialGlyph` | Discord's mark. Brand, so it is a solid silhouette. |
1919
+ | `emailGlyph` | `SocialGlyph` | The envelope. Functional, so it is a 1.6 stroke. |
1920
+ | `gitHubGlyph` | `SocialGlyph` | GitHub's mark. Brand, so it is a solid silhouette. |
1921
+ | `instagramGlyph` | `SocialGlyph` | Instagram's mark. Brand, so it is a solid silhouette. |
1922
+ | `linkedInGlyph` | `SocialGlyph` | LinkedIn's mark. Brand, so it is a solid silhouette. |
1923
+ | `newsletterGlyph` | `SocialGlyph` | |
1924
+ | `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. |
1925
+ | `SOCIAL_STROKE_WIDTH` | `1.6` | The stroke width of a functional glyph, from the document. |
1926
+ | `SOCIAL_VIEW_BOX` | `"0 0 24 24"` | The grid every glyph is drawn on. |
1927
+ | `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`. |
1928
+ | `socialNames` | `readonly ("Discord" \| "Email" \| "GitHub" \| "Instagram" \| "LinkedIn" \| "Newsletter" \| "Rss" \| "Website" \| "X" \| "YouTube")[]` | The ten names, in the order the catalogue declares them. |
1929
+ | `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. |
1930
+ | `websiteGlyph` | `SocialGlyph` | «My other site», and the reason it is here rather than borrowed. |
1931
+ | `xGlyph` | `SocialGlyph` | X's mark. Brand, so it is a solid silhouette. |
1932
+ | `youTubeGlyph` | `SocialGlyph` | YouTube's mark. Brand, so it is a solid silhouette. |
1933
+
1934
+ Types (3): `SocialGlyph`, `SocialGlyphShape`, `SocialName`.
1935
+
1812
1936
  ### `@eduardoalvarez/arrecife/variants`
1813
1937
 
1814
1938
  | export | type | what it is |
@@ -1909,7 +2033,7 @@ Types (1): `ShikiTheme`.
1909
2033
  | `SERIES_COLORS` | `string[]` | All four, in order, to hand to a `Pie` with `Cell` in one go. |
1910
2034
  | `seriesColor` | `(index: number): string` | The color of series `index`, as a custom property. |
1911
2035
 
1912
- Types (4): `ChartContainerProps`, `ChartLegendContentProps`, `ChartPayloadItem`, `ChartTooltipContentProps`.
2036
+ Types (10): `AreaChartProps`, `BarChartProps`, `ChartContainerProps`, `ChartDatum`, `ChartLegendContentProps`, `ChartPayloadItem`, `ChartSeries`, `ChartTooltipContentProps`, `LineChartProps`, `SeriesChartProps`.
1913
2037
 
1914
2038
  ### `@eduardoalvarez/arrecife/form`
1915
2039
 
@@ -1939,7 +2063,7 @@ Types (6): `ArticleData`, `BaseData`, `CourseData`, `DefaultData`, `SatoriNode`,
1939
2063
  | `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. |
1940
2064
  | `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. |
1941
2065
 
1942
- Types (62): `AccordionProps`, `AccordionTriggerProps`, `AlertProps`, `ArticleCardProps`, `AudioPlayerMode`, `AudioPlayerProps`, `AuthorCardProps`, `AvatarProps`, `AvatarUploadProps`, `BadgeProps`, `BlockquoteProps`, `BreadcrumbProps`, `ButtonProps`, `CalendarEvent`, `CalendarProps`, `CategoryBadgeProps`, `CheckboxProps`, `CodeBlockProps`, `CodeProps`, `CourseCardProps`, `Crumb`, `DateFieldProps`, `EmptyStateProps`, `EventCalendarProps`, `FooterLinkProps`, `FooterProps`, `HeroProps`, `InputProps`, `LabelProps`, `LinkRowProps`, `MetricBadgeProps`, `NavItemProps`, `NavProps`, `NewsletterFormProps`, `NewsletterState`, `PageHeaderProps`, `PaginationLinkProps`, `PopoverContentProps`, `ProgressProps`, `RadioGroupItemProps`, `RadioGroupProps`, `ScrollingProgressBarProps`, `SeparatorProps`, `SheetContentProps`, `SidebarGroupProps`, `SidebarItemProps`, `SidebarNavProps`, `SkeletonProps`, `SocialLink`, `StatDelta`, `StatProps`, `SwitchProps`, `TableOfContentsProps`, `TabsProps`, `TalkCardProps`, `TextProps`, `TextareaProps`, `ThemeToggleProps`, `ToastOptions`, `ToastVariant`, `ToasterProps`, `TocEntry`.
2066
+ 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`.
1943
2067
 
1944
2068
  # Where to look if this is not enough
1945
2069
 
@@ -1947,8 +2071,8 @@ Types (62): `AccordionProps`, `AccordionTriggerProps`, `AlertProps`, `ArticleCar
1947
2071
  generated from the types.
1948
2072
  - The repo's `README.md`: the reasoning behind each decision, the contrast
1949
2073
  correction table and the release cycle.
1950
- - `docs/design-system.md` and `docs/brand-manual.md`: the identity documents,
2074
+ - `architecture/design-system.md` and `architecture/brand-manual.md`: the identity documents,
1951
2075
  greppable.
1952
- - `docs/decisions.md`: the points where the code and the document did not say the
2076
+ - `decisions/`: the points where the code and the document did not say the
1953
2077
  same thing, each with its resolution.
1954
2078
  - `AGENTS.md`: for working inside the library's repo.