@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.
- package/CHANGELOG.md +51 -0
- package/README.md +115 -41
- package/dist/brand/index.cjs +2 -2
- package/dist/brand/index.js +3 -3
- package/dist/chart/index.cjs +155 -2
- package/dist/chart/index.d.cts +136 -4
- package/dist/chart/index.d.ts +136 -4
- package/dist/chart/index.js +155 -5
- package/dist/{chunk-TA7TLWW4.js → chunk-5A5GH2PF.js} +1 -1
- package/dist/{chunk-727HCBD4.js → chunk-6IGD5REB.js} +1 -1
- package/dist/{chunk-2WPWEIMD.js → chunk-FAAGZG7A.js} +1 -1
- package/dist/{chunk-OMKSESQB.js → chunk-FGFNK72B.js} +3 -3
- package/dist/chunk-HOADZ6GS.js +72 -0
- package/dist/chunk-LXRGQKMG.js +145 -0
- package/dist/{chunk-JN3IS5OS.js → chunk-MPZBF2TZ.js} +2 -2
- package/dist/{chunk-WGNIRIN7.js → chunk-TRPBID2W.js} +1 -1
- package/dist/{chunk-E6KFUSKB.js → chunk-XXDATT3A.js} +1 -1
- package/dist/doctor.mjs +95 -13
- 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 +2 -2
- package/dist/icons/index.d.cts +2 -2
- package/dist/icons/index.d.ts +2 -2
- package/dist/icons/index.js +2 -2
- package/dist/{index-DlAO2JZs.d.cts → index-BbRplw_B.d.cts} +15 -4
- package/dist/{index-DlAO2JZs.d.ts → index-BbRplw_B.d.ts} +15 -4
- package/dist/index.cjs +264 -264
- package/dist/index.d.cts +212 -126
- package/dist/index.d.ts +212 -126
- package/dist/index.js +153 -236
- 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.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 +124 -38
- package/dist/social/index.d.cts +1 -1
- package/dist/social/index.d.ts +1 -1
- package/dist/social/index.js +2 -1
- package/dist/tokens/index.cjs +3 -3
- package/dist/tokens/index.d.cts +5 -5
- package/dist/tokens/index.d.ts +5 -5
- package/dist/tokens/index.js +2 -2
- package/dist/tokens/theme.css +46 -19
- package/dist/variants/index.cjs +1 -1
- package/dist/variants/index.d.cts +2 -2
- package/dist/variants/index.d.ts +2 -2
- package/dist/variants/index.js +1 -1
- package/llms.txt +264 -140
- package/package.json +6 -1
- 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
|
|
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
|
|
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
|
|
150
|
-
matters in a Server Component: `./tokens`, `./theme`, `./variants`, `./
|
|
151
|
-
`./shiki` stay on the server. Neither does `./social`, which is a third
|
|
152
|
-
renders React — it is
|
|
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 `
|
|
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
|
|
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
|
-
<
|
|
299
|
+
<NavItem href="/cursos" active icon={<Icon as={GraduationCap} tone="current" />}>
|
|
352
300
|
cursos
|
|
353
|
-
</
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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
|
|
450
|
-
`Email`, `Newsletter`. `Newsletter` is the bell: a way to follow, like
|
|
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 `
|
|
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.
|
|
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 `
|
|
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<
|
|
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
|
-
|
|
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: `
|
|
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
|
|
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
|
-
|
|
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`.
|
|
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,
|
|
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
|
|
1439
|
+
### Footer
|
|
1359
1440
|
|
|
1360
1441
|
Source: `src/components/footer/index.tsx`
|
|
1361
1442
|
|
|
1362
|
-
|
|
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.
|
|
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`.
|
|
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 (
|
|
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 (
|
|
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
|
-
- `
|
|
2074
|
+
- `architecture/design-system.md` and `architecture/brand-manual.md`: the identity documents,
|
|
1951
2075
|
greppable.
|
|
1952
|
-
- `
|
|
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.
|