@eduardoalvarez/arrecife 0.9.0 → 0.11.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 +58 -0
- package/README.md +111 -70
- package/dist/brand/index.cjs +9 -3
- package/dist/brand/index.d.cts +45 -6
- package/dist/brand/index.d.ts +45 -6
- package/dist/brand/index.js +2 -3
- package/dist/chart/index.cjs +26 -4
- package/dist/chart/index.d.cts +19 -3
- package/dist/chart/index.d.ts +19 -3
- package/dist/chart/index.js +26 -5
- package/dist/{chunk-MPZBF2TZ.js → chunk-RKGKO2TW.js} +11 -5
- package/dist/chunk-ZSCSKCTY.js +26 -0
- package/dist/form/index.js +0 -1
- package/dist/icons/index.d.cts +19 -10
- package/dist/icons/index.d.ts +19 -10
- package/dist/icons/index.js +2 -27
- package/dist/index.cjs +277 -401
- package/dist/index.d.cts +114 -13
- package/dist/index.d.ts +114 -13
- package/dist/index.js +211 -203
- package/dist/og/index.js +0 -1
- package/dist/shiki/index.js +0 -1
- package/dist/theme/index.js +0 -1
- package/dist/tokens/index.js +0 -1
- package/dist/tokens/theme.css +21 -1
- package/dist/variants/index.js +0 -1
- package/llms.txt +99 -138
- package/package.json +18 -30
- package/dist/chunk-HOADZ6GS.js +0 -72
- package/dist/chunk-LXRGQKMG.js +0 -145
- package/dist/chunk-MLKGABMK.js +0 -7
- package/dist/index-BbRplw_B.d.cts +0 -58
- package/dist/index-BbRplw_B.d.ts +0 -58
- package/dist/social/data.cjs +0 -161
- package/dist/social/data.d.cts +0 -161
- package/dist/social/data.d.ts +0 -161
- package/dist/social/data.js +0 -2
- package/dist/social/index.cjs +0 -153
- package/dist/social/index.d.cts +0 -2
- package/dist/social/index.d.ts +0 -2
- package/dist/social/index.js +0 -3
package/dist/og/index.js
CHANGED
package/dist/shiki/index.js
CHANGED
package/dist/theme/index.js
CHANGED
package/dist/tokens/index.js
CHANGED
package/dist/tokens/theme.css
CHANGED
|
@@ -379,7 +379,22 @@
|
|
|
379
379
|
focus-ring-warm exists for the ONE control the ring cannot be biolume on:
|
|
380
380
|
the conversion button is the system's only sand fill, and a biolume ring
|
|
381
381
|
around it puts both of the brand's accents in the same three pixels. It sets
|
|
382
|
-
only the color, so the width and the offset stay in one place.
|
|
382
|
+
only the color, so the width and the offset stay in one place.
|
|
383
|
+
|
|
384
|
+
focus-ring-inset flips the OFFSET, and only the offset, for the same reason
|
|
385
|
+
and by the same rule: an element that is focusable but sits inside a clipped
|
|
386
|
+
container cannot wear a ring drawn 3px outside itself, because the container
|
|
387
|
+
paints it away. CodeBlock is the case — its root carries overflow-hidden so
|
|
388
|
+
its rounded corners hold, and its pre scrolls, so the pre has to be focusable.
|
|
389
|
+
With the outward ring, three of its four sides were clipped and what was left
|
|
390
|
+
read as a stray line under the header: a focus indicator that is present in
|
|
391
|
+
the CSS and invisible on screen, which is WCAG 2.4.7 failing while looking
|
|
392
|
+
fixed.
|
|
393
|
+
|
|
394
|
+
It is -3px and not 0: at 0 the ring sits exactly on the border box and reads
|
|
395
|
+
as a change of border rather than as a ring. The padding it eats into is
|
|
396
|
+
p-step-md, so it never touches the text. Reach for it ONLY when a clipping
|
|
397
|
+
ancestor is the reason — not because the outward ring looks too loud. */
|
|
383
398
|
@utility focus-ring {
|
|
384
399
|
&:focus-visible {
|
|
385
400
|
outline: 2px solid var(--color-accent);
|
|
@@ -391,6 +406,11 @@
|
|
|
391
406
|
outline-color: var(--color-warm);
|
|
392
407
|
}
|
|
393
408
|
}
|
|
409
|
+
@utility focus-ring-inset {
|
|
410
|
+
&:focus-visible {
|
|
411
|
+
outline-offset: -3px;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
394
414
|
|
|
395
415
|
/* The system's only transition, as a utility. States are communicated with
|
|
396
416
|
border and color, not with movement: this class cannot animate anything else. */
|
package/dist/variants/index.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
export { CARD, CARD_HOVER, CARD_SURFACE, alert as alertVariants, avatar as avatarVariants, badge as badgeVariants, button as buttonVariants, category as categoryBadgeVariants, metric as metricBadgeVariants } from '../chunk-XXDATT3A.js';
|
|
2
2
|
export { text as textVariants } from '../chunk-ODBFN44D.js';
|
|
3
|
-
import '../chunk-MLKGABMK.js';
|
package/llms.txt
CHANGED
|
@@ -34,6 +34,7 @@ Requirements, and they are not optional:
|
|
|
34
34
|
| | |
|
|
35
35
|
| --- | --- |
|
|
36
36
|
| React | `^19.0.0` and `react-dom` `^19.0.0`, as peer dependencies |
|
|
37
|
+
| Phosphor | `@phosphor-icons/react` `^2.1.0`, as a peer dependency. **Required since 0.10.0**: every icon the library draws comes from it |
|
|
37
38
|
| Tailwind | v4. **There is no v3 preset**: the output is `@theme`, which v3 does not understand |
|
|
38
39
|
| Node | `>=22.18.0` for the subpaths that run at build time (`./og`, `./tokens`) |
|
|
39
40
|
|
|
@@ -41,8 +42,15 @@ Radix, `clsx`, `tailwind-merge`, `class-variance-authority`, `date-fns` and
|
|
|
41
42
|
`react-day-picker` come as dependencies of the library. You do not need to
|
|
42
43
|
install or declare them.
|
|
43
44
|
|
|
44
|
-
**It ships no icon
|
|
45
|
-
|
|
45
|
+
**It ships no icon INVENTORY, and it does ship the drawing.** Until 0.10.0 the
|
|
46
|
+
components carried a hand-drawn set of their own; they now draw every glyph from
|
|
47
|
+
`@phosphor-icons/react` through `Icon`, which fixes the size at 1em and takes the
|
|
48
|
+
weight from `tone`. Which icons your project uses is still your project's
|
|
49
|
+
decision — what stopped being the project's is the line they are drawn with.
|
|
50
|
+
|
|
51
|
+
That is why Phosphor is a required peer dependency rather than an optional one:
|
|
52
|
+
the `Alert`, the `Select` and the `Button` you import already draw with it,
|
|
53
|
+
whether or not you draw an icon yourself.
|
|
46
54
|
|
|
47
55
|
## Tailwind configuration
|
|
48
56
|
|
|
@@ -116,8 +124,7 @@ that only whoever uses them installs.
|
|
|
116
124
|
| `@eduardoalvarez/arrecife/og` | **no** | — | The Open Graph templates for Satori |
|
|
117
125
|
| `@eduardoalvarez/arrecife/shiki` | **no** | — | The syntax highlighting theme |
|
|
118
126
|
| `@eduardoalvarez/arrecife/brand` | yes | — | Logo, isotype and mascot as components |
|
|
119
|
-
| `@eduardoalvarez/arrecife/
|
|
120
|
-
| `@eduardoalvarez/arrecife/social/data` | **no** | — | The same ten as shapes, plus `socialSvg`. For a template that mounts no React |
|
|
127
|
+
| `@eduardoalvarez/arrecife/icons` | yes, on the server only | `@phosphor-icons/react` | `Icon`, the wrapper that fixes size and weight. No `"use client"` |
|
|
121
128
|
| `@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 |
|
|
122
129
|
| `@eduardoalvarez/arrecife/form` | yes | `react-hook-form` | The form layer: labels, errors and `aria-*` |
|
|
123
130
|
| `@eduardoalvarez/arrecife/chart` | yes | `recharts` | The chart chassis, the series palette and the three chart types |
|
|
@@ -148,12 +155,12 @@ before 0.6.0 and it pulled 272 KB of client chunk in for components that never
|
|
|
148
155
|
needed it.
|
|
149
156
|
|
|
150
157
|
The six portable subpaths do NOT carry the directive, and that is the half that
|
|
151
|
-
matters in a Server Component: `./tokens`, `./theme`, `./variants`,
|
|
152
|
-
`./og` and `./shiki` stay on the server. Neither does `./
|
|
153
|
-
case: it renders React — it is
|
|
154
|
-
holds no state and nothing about it needs a client boundary. It is
|
|
155
|
-
|
|
156
|
-
below says
|
|
158
|
+
matters in a Server Component: `./tokens`, `./theme`, `./variants`,
|
|
159
|
+
`./og` and `./shiki` stay on the server. Neither does `./icons`, which is a third
|
|
160
|
+
case: it renders React — it is one `<svg>` — so it can never be portable, but it
|
|
161
|
+
holds no state and nothing about it needs a client boundary. It is how you put an
|
|
162
|
+
icon in a Server Component, and § «The social icons are yours, and they come from
|
|
163
|
+
Phosphor» below says which Phosphor entry to pair it with there. If all you need are classes — for a `<div>`, an
|
|
157
164
|
`<a>` or an Astro island you do not want to hydrate — import them from
|
|
158
165
|
`./variants` and nothing crosses to the client:
|
|
159
166
|
|
|
@@ -373,8 +380,9 @@ component's.
|
|
|
373
380
|
<EmptyState variant="inline" expression="waiting" title="…" />
|
|
374
381
|
```
|
|
375
382
|
|
|
376
|
-
`inline` takes an optional `icon` — a `ReactNode` the project passes
|
|
377
|
-
|
|
383
|
+
`inline` takes an optional `icon` — a `ReactNode` the project passes, normally
|
|
384
|
+
`<Icon as={…} />` from `./icons`, which is already 1em and `currentColor`. The
|
|
385
|
+
library ships no icon inventory: which glyph goes there is your decision.
|
|
378
386
|
|
|
379
387
|
Do not reach for `page` inside a table because the face is «nicer»: an admin
|
|
380
388
|
screen with a dozen empty regions gets a dozen mascots, which is what made every
|
|
@@ -383,7 +391,10 @@ consuming project write its own empty state instead of using this one.
|
|
|
383
391
|
### The two shapes of `Footer`
|
|
384
392
|
|
|
385
393
|
```tsx
|
|
386
|
-
// The default. Stacked rows, signature level with the first one
|
|
394
|
+
// The default. Stacked rows, signature level with the first one — and stacked
|
|
395
|
+
// and CENTRED below `sm`, which is what a phone gets.
|
|
396
|
+
// SOCIAL is the project's own array: `{ label, href, icon }`, the icon drawn
|
|
397
|
+
// with `<Icon as={GithubLogo} tone="current" />`.
|
|
387
398
|
<Footer brand={<Logo />} social={SOCIAL} />
|
|
388
399
|
|
|
389
400
|
// `full`. Brand and description on the left, link columns on the right,
|
|
@@ -469,6 +480,13 @@ re-exported, because they are unchanged and wrapping them buys nothing.
|
|
|
469
480
|
down for a ranking. Recharts calls that same thing `layout="vertical"` — if you
|
|
470
481
|
are porting code, the value flips.
|
|
471
482
|
|
|
483
|
+
**A percentage passes `valueMax={100}`.** Without it the value axis ends at the
|
|
484
|
+
largest datum, and on a horizontal ranking — whose value axis is hidden — a
|
|
485
|
+
course watched to 40 % draws as a full bar when it is the highest on the list.
|
|
486
|
+
The bottom is always zero, and it is a floor rather than a clip: a datum above
|
|
487
|
+
`valueMax` widens the axis instead of running off the edge. It is on all three
|
|
488
|
+
types. See `decisions/0.11.md` § 58.
|
|
489
|
+
|
|
472
490
|
`stacked` on `AreaChart` and `BarChart` adds the series up. Without it areas
|
|
473
491
|
overlap, which is honest and rarely what you want with more than one series: to
|
|
474
492
|
COMPARE rather than add up, the type is `LineChart`.
|
|
@@ -476,63 +494,50 @@ COMPARE rather than add up, the type is `LineChart`.
|
|
|
476
494
|
Anything that is not a series over a category axis has no type and is not missing
|
|
477
495
|
one. A doughnut is `ChartContainer` plus Recharts' `Pie` with `SERIES_COLORS`.
|
|
478
496
|
|
|
479
|
-
### The social icons come from
|
|
497
|
+
### The social icons are yours, and they come from Phosphor
|
|
498
|
+
|
|
499
|
+
Until 0.10.0 the library shipped ten of them at `./social` — `GitHub`,
|
|
500
|
+
`LinkedIn`, `X`, `Instagram`, `Discord`, `YouTube`, `Rss`, `Email`,
|
|
501
|
+
`Newsletter`, `Website` — drawn by hand. That subpath is gone. Phosphor has all
|
|
502
|
+
ten and the migration is one import per call site:
|
|
480
503
|
|
|
481
504
|
```tsx
|
|
482
|
-
// ❌
|
|
483
|
-
import { GitHub } from '@eduardoalvarez/arrecife';
|
|
505
|
+
// ❌ removed in 0.10.0
|
|
506
|
+
import { GitHub, LinkedIn, Website } from '@eduardoalvarez/arrecife/social';
|
|
484
507
|
|
|
485
|
-
// ✅
|
|
486
|
-
import {
|
|
508
|
+
// ✅
|
|
509
|
+
import { GithubLogo, LinkedinLogo, Globe } from '@phosphor-icons/react';
|
|
510
|
+
import { Icon } from '@eduardoalvarez/arrecife/icons';
|
|
487
511
|
|
|
488
|
-
|
|
489
|
-
import { social } from '@eduardoalvarez/arrecife';
|
|
490
|
-
<social.GitHub />
|
|
512
|
+
<Icon as={GithubLogo} tone="current" />
|
|
491
513
|
```
|
|
492
514
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
`
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
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
|
-
|
|
532
|
-
The internal glyphs — `Close`, `ChevronDown`, `Sun` — are **not exported** and
|
|
533
|
-
are not going to be: they are the primitives' minimum set. A component that needs
|
|
534
|
-
an icon receives it as a prop (`Stat` has `icon`, each `SocialLink` in `Footer`
|
|
535
|
-
has its own). Do not ask for them to be published: pass your own.
|
|
515
|
+
| Removed | Phosphor | `tone` |
|
|
516
|
+
| --- | --- | --- |
|
|
517
|
+
| `GitHub` | `GithubLogo` | `current` |
|
|
518
|
+
| `LinkedIn` | `LinkedinLogo` | `current` |
|
|
519
|
+
| `X` | `XLogo` | `current` |
|
|
520
|
+
| `Instagram` | `InstagramLogo` | `current` |
|
|
521
|
+
| `Discord` | `DiscordLogo` | `current` |
|
|
522
|
+
| `YouTube` | `YoutubeLogo` | `current` |
|
|
523
|
+
| `Rss` | `Rss` | `action` |
|
|
524
|
+
| `Email` | `Envelope` | `action` |
|
|
525
|
+
| `Newsletter` | `BellSimple` | `action` |
|
|
526
|
+
| `Website` | `Globe` | `action` |
|
|
527
|
+
|
|
528
|
+
The `tone` column IS the old drawing rule, written on the axis `Icon` already
|
|
529
|
+
has. Six are brands and go SOLID, which is `tone="current"` — Phosphor's `fill`.
|
|
530
|
+
Four are functional and keep the default `action`, which is the system's line. A
|
|
531
|
+
row that mixes the two pens is the normal case, not a defect: a brand is somebody
|
|
532
|
+
else's silhouette and cannot be outlined, and a symbol has no owner to be
|
|
533
|
+
faithful to.
|
|
534
|
+
|
|
535
|
+
**In a Server Component import `Icon` from `./icons` and the glyph from
|
|
536
|
+
`@phosphor-icons/react/ssr`.** The root of this library carries `"use client"`;
|
|
537
|
+
`./icons` deliberately does not, so an icon renders on the server and ships no
|
|
538
|
+
client JS. Phosphor's default build reads `IconContext` through `useContext`,
|
|
539
|
+
which throws in a Server Component — the `/ssr` entry is the same icons without
|
|
540
|
+
that read.
|
|
536
541
|
|
|
537
542
|
## Tokens
|
|
538
543
|
|
|
@@ -592,6 +597,10 @@ compiles and looks wrong, or that fails the project's accessibility audit.
|
|
|
592
597
|
the only member of the second criterion § 23 opened for it.
|
|
593
598
|
6. **Semantics and scale are independent.** An `h2` that has to look small is
|
|
594
599
|
`<Text as="h2" variant="h3">`, never an `h3` that lies about the hierarchy.
|
|
600
|
+
`PageHeader` makes the same split: `as` is the level and `titleVariant` the
|
|
601
|
+
scale. An admin panel's title is `<PageHeader title="Ventas"
|
|
602
|
+
titleVariant="h3" />` — still the page's only `h1`, at 25px instead of 44. See
|
|
603
|
+
`decisions/0.11.md` § 57.
|
|
595
604
|
7. **`textMuted` never goes over `surfaceRaised`**: it gives 4.07 in dark. Over a
|
|
596
605
|
raised surface — menus, active tabs — the token is `textSecondary`.
|
|
597
606
|
8. **A background tinted with a semantic color carries text from a text token**,
|
|
@@ -612,6 +621,11 @@ compiles and looks wrong, or that fails the project's accessibility audit.
|
|
|
612
621
|
not the humour contract. See `decisions/0.7.md` § 27.
|
|
613
622
|
12. **The fin is not a free parameter**: `foam` on a dark background, `color` on a
|
|
614
623
|
light one. The components already choose it from the background.
|
|
624
|
+
**On a site that switches theme, pass `background="auto"`** to `Isotype` or
|
|
625
|
+
`Logo`: both fins are rendered and the `light:` variant shows the one that
|
|
626
|
+
reads, so no call site has to know the theme. A surface that keeps one mode
|
|
627
|
+
whatever the page does — a dark panel on a light page — is a fixed
|
|
628
|
+
background, and it still says `dark`. See `decisions/0.11.md` § 60.
|
|
615
629
|
|
|
616
630
|
## What the library does NOT do, on purpose
|
|
617
631
|
|
|
@@ -627,6 +641,12 @@ These are the confusions people run into most often when consuming it.
|
|
|
627
641
|
provider.
|
|
628
642
|
- **It ships no router.** The components with links accept `asChild` to wrap the
|
|
629
643
|
framework's `Link`.
|
|
644
|
+
- **It does not know your prices, ratings or images.** `CourseCard` takes
|
|
645
|
+
`media` — the cover, bleeding to the edges, with `alt=""` because the title
|
|
646
|
+
already names the card — and `footer`, the closing row where a project puts the
|
|
647
|
+
rating and the price. Both are nodes the project draws; the card keeps the
|
|
648
|
+
title, its hover and the sand progress bar. The title does not go over the
|
|
649
|
+
cover. See `decisions/0.11.md` § 59.
|
|
630
650
|
- **It ships no `data-testid`.** A composed part your test suite has to reach is
|
|
631
651
|
reached with a slot: `ArticleCard`'s `tagAsChild`, `Breadcrumb`'s and
|
|
632
652
|
`TableOfContents`'s `linkAsChild`. They hand you the element and its
|
|
@@ -771,7 +791,7 @@ Source: `src/primitives/alert.tsx`
|
|
|
771
791
|
| prop | type | req. | default | what it does |
|
|
772
792
|
| --- | --- | --- | --- | --- |
|
|
773
793
|
| `emphasis` | `"subtle" \| "strong"` | | | |
|
|
774
|
-
| `icon` | `ReactNode` | | | Replaces the variant's
|
|
794
|
+
| `icon` | `ReactNode` | | | Replaces the variant's glyph. Never an emoji: if you need something else, it is `<Icon as={…} />` from `@eduardoalvarez/arrecife/icons`. |
|
|
775
795
|
| `title` | `ReactNode` | | | |
|
|
776
796
|
| `variant` | `"accent" \| "success" \| "warning" \| "error"` | | | |
|
|
777
797
|
|
|
@@ -1391,11 +1411,15 @@ Source: `src/components/code-block/index.tsx`
|
|
|
1391
1411
|
|
|
1392
1412
|
Source: `src/components/course-card/index.tsx`
|
|
1393
1413
|
|
|
1394
|
-
|
|
1414
|
+
The course, as a card that links to it.
|
|
1415
|
+
|
|
1416
|
+
- Extends: `Omit<CardShellProps, 'children' \| 'title' \| 'media'>`
|
|
1395
1417
|
|
|
1396
1418
|
| prop | type | req. | default | what it does |
|
|
1397
1419
|
| --- | --- | --- | --- | --- |
|
|
1398
1420
|
| `asChild` | `boolean \| undefined` | | | Renders the child instead of an `<a>`. It is how Next's or Astro's `Link` plugs in without the library depending on any router. |
|
|
1421
|
+
| `footer` | `ReactNode` | | | The closing row, under `meta`: the rating, the price, whatever the project sells the course with. It sits at the bottom of the card, so the rows of a grid line up whatever the length of each summary. |
|
|
1422
|
+
| `media` | `ReactNode` | | | The cover, at the top and bleeding to the card's edges, with `alt=""`: the whole card is one link and `title` already names it. |
|
|
1399
1423
|
| `meta` | `readonly ReactNode[]` | | | Level, duration, number of lessons: whatever the project wants to list. |
|
|
1400
1424
|
| `progress` | `number` | | | Percentage completed. It only makes sense for someone already enrolled; when passed, the bar goes in sand, which is the color of course progress. |
|
|
1401
1425
|
| `status` | `ReactNode` | | | Status label: «próximamente», «gratis», «nuevo». |
|
|
@@ -1559,6 +1583,7 @@ One header at two scales, not two components.
|
|
|
1559
1583
|
| `eyebrow` | `ReactNode` | | | Mono, small caps, in accent. It is the section the page belongs to. |
|
|
1560
1584
|
| `size` | `"display" \| "page"` | | `page` | |
|
|
1561
1585
|
| `title` | `ReactNode` | yes | | |
|
|
1586
|
+
| `titleVariant` | `"display" \| "h1" \| "h2" \| "h3"` | | | The headline's scale, when the screen needs a different one from what `size` gives — `display` for `display`, `h1` for `page`. |
|
|
1562
1587
|
|
|
1563
1588
|
### ScrollingProgressBar
|
|
1564
1589
|
|
|
@@ -1647,12 +1672,14 @@ Imported from `@eduardoalvarez/arrecife` or `@eduardoalvarez/arrecife/brand`. 4
|
|
|
1647
1672
|
|
|
1648
1673
|
Source: `src/brand/isotype.tsx`
|
|
1649
1674
|
|
|
1675
|
+
The fin, in the variant its background asks for.
|
|
1676
|
+
|
|
1650
1677
|
- Extends: `Omit<ComponentPropsWithoutRef<'img'>, 'src' \| 'alt'>`
|
|
1651
1678
|
|
|
1652
1679
|
| prop | type | req. | default | what it does |
|
|
1653
1680
|
| --- | --- | --- | --- | --- |
|
|
1654
1681
|
| `alt` | `string` | | | Alt text. Empty when the isotype accompanies text that already names it. |
|
|
1655
|
-
| `background` | `"dark" \| "light"` | | `dark` | Which background it sits on. Deciding is mandatory even though it has a default: the fin's body is nearly black, so the two-blue variant disappears over abyss.
|
|
1682
|
+
| `background` | `"dark" \| "light" \| "auto"` | | `dark` | Which background it sits on, or `auto` on a site that switches theme: both fins are rendered and CSS shows the one that reads. Deciding is mandatory even though it has a default: the fin's body is nearly black, so the two-blue variant disappears over abyss. |
|
|
1656
1683
|
| `basePath` | `string` | | `ASSETS_PATH` | |
|
|
1657
1684
|
|
|
1658
1685
|
### Logo
|
|
@@ -1665,7 +1692,7 @@ The wordmark comes from `naming.wordmark`, not from a hand-written string, and i
|
|
|
1665
1692
|
|
|
1666
1693
|
| prop | type | req. | default | what it does |
|
|
1667
1694
|
| --- | --- | --- | --- | --- |
|
|
1668
|
-
| `background` | `"dark" \| "light"` | | `dark` |
|
|
1695
|
+
| `background` | `"dark" \| "light" \| "auto"` | | `dark` | The background the logo sits on, handed to its fin. `auto` follows the theme — see `Isotype`. The wordmark needs no help: it is `textPrimary`, which already follows the mode. |
|
|
1669
1696
|
| `basePath` | `string` | | `ASSETS_PATH` | |
|
|
1670
1697
|
| `isotypeOnly` | `boolean \| undefined` | | `false` | Hides the wordmark and leaves only the fin, for very narrow bars. |
|
|
1671
1698
|
| `withTagline` | `boolean \| undefined` | | `false` | Adds the tagline under the wordmark, separated from the fin by a divider. |
|
|
@@ -1696,48 +1723,6 @@ Tiburoncín's head, with an expression.
|
|
|
1696
1723
|
| `basePath` | `string` | | `ASSETS_PATH` | |
|
|
1697
1724
|
| `expression` | `"annoyed" \| "confused" \| "hearts" \| "laughing" \| "shades" \| "waiting" \| "wink"` | yes | | |
|
|
1698
1725
|
|
|
1699
|
-
## Social icons
|
|
1700
|
-
|
|
1701
|
-
Imported from `@eduardoalvarez/arrecife/social` · or grouped as `social` from the root. 10 exports.
|
|
1702
|
-
|
|
1703
|
-
### GitHub, LinkedIn, X, Instagram, Discord, YouTube, Rss, Email, Newsletter, Website
|
|
1704
|
-
|
|
1705
|
-
Source: `src/social/index.tsx`
|
|
1706
|
-
|
|
1707
|
-
**GitHub**
|
|
1708
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
1709
|
-
|
|
1710
|
-
**LinkedIn**
|
|
1711
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
1712
|
-
|
|
1713
|
-
**X**
|
|
1714
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
1715
|
-
|
|
1716
|
-
**Instagram**
|
|
1717
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
1718
|
-
|
|
1719
|
-
**Discord**
|
|
1720
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
1721
|
-
|
|
1722
|
-
**YouTube**
|
|
1723
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
1724
|
-
|
|
1725
|
-
**Rss**
|
|
1726
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
1727
|
-
|
|
1728
|
-
**Email**
|
|
1729
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
1730
|
-
|
|
1731
|
-
**Newsletter**
|
|
1732
|
-
The newsletter. It plays the same role as `Rss` — a way to follow, not a social network — which is why it belongs in this catalogue and does not open the door to an icon library.
|
|
1733
|
-
|
|
1734
|
-
- No own props: it passes through those of the element or primitive it wraps.
|
|
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
|
-
|
|
1741
1726
|
## Icons
|
|
1742
1727
|
|
|
1743
1728
|
Imported from `@eduardoalvarez/arrecife/icons` · requires `@phosphor-icons/react`. 1 exports.
|
|
@@ -1863,6 +1848,7 @@ A series over time, with the fill fading out underneath it.
|
|
|
1863
1848
|
| `series` | `readonly ChartSeries[]` | yes | | |
|
|
1864
1849
|
| `stacked` | `boolean \| undefined` | | `false` | Adds the series up instead of overlaying them. |
|
|
1865
1850
|
| `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
|
|
1851
|
+
| `valueMax` | `number` | | | The top of the value axis, when the scale has one that the data does not reach — 100 for a percentage. |
|
|
1866
1852
|
| `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
|
|
1867
1853
|
| `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
1854
|
| `yTickFormatter` | `(value: unknown) => string` | | | Formats the tick on the VALUE axis — the currency symbol, the thousands separator, the percent sign. |
|
|
@@ -1883,6 +1869,7 @@ Bars, upright or lying down.
|
|
|
1883
1869
|
| `series` | `readonly ChartSeries[]` | yes | | |
|
|
1884
1870
|
| `stacked` | `boolean \| undefined` | | `false` | Stacks the series instead of putting them side by side. |
|
|
1885
1871
|
| `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
|
|
1872
|
+
| `valueMax` | `number` | | | The top of the value axis, when the scale has one that the data does not reach — 100 for a percentage. |
|
|
1886
1873
|
| `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
|
|
1887
1874
|
| `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
1875
|
| `yTickFormatter` | `(value: unknown) => string` | | | Formats the tick on the VALUE axis — the currency symbol, the thousands separator, the percent sign. |
|
|
@@ -1901,6 +1888,7 @@ Lines, for comparing series against each other.
|
|
|
1901
1888
|
| `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
1889
|
| `series` | `readonly ChartSeries[]` | yes | | |
|
|
1903
1890
|
| `summary` | `ReactNode` | | | What the chart says, in words. It goes in a visually hidden `figcaption`. |
|
|
1891
|
+
| `valueMax` | `number` | | | The top of the value axis, when the scale has one that the data does not reach — 100 for a percentage. |
|
|
1904
1892
|
| `xKey` | `string` | yes | | The key on the category axis: the day, the month, the course. |
|
|
1905
1893
|
| `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
1894
|
| `yTickFormatter` | `(value: unknown) => string` | | | Formats the tick on the VALUE axis — the currency symbol, the thousands separator, the percent sign. |
|
|
@@ -1911,28 +1899,6 @@ The root re-exports everything from `./tokens` and `./brand` for convenience.
|
|
|
1911
1899
|
Each one appears exactly once, under the most specific subpath that publishes
|
|
1912
1900
|
it: if the code does not mount React, that subpath is the one to import.
|
|
1913
1901
|
|
|
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
|
-
|
|
1936
1902
|
### `@eduardoalvarez/arrecife/variants`
|
|
1937
1903
|
|
|
1938
1904
|
| export | type | what it is |
|
|
@@ -1974,10 +1940,6 @@ Types (3): `SocialGlyph`, `SocialGlyphShape`, `SocialName`.
|
|
|
1974
1940
|
|
|
1975
1941
|
Types (13): `BrandToken`, `ColorMode`, `ColorToken`, `ControlToken`, `FontToken`, `GradientToken`, `RadiusToken`, `SeriesToken`, `SizeToken`, `SpacingToken`, `SyntaxToken`, `Tokens`, `TypeScaleToken`.
|
|
1976
1942
|
|
|
1977
|
-
### `@eduardoalvarez/arrecife/social`
|
|
1978
|
-
|
|
1979
|
-
Types (1): `SocialIconProps`.
|
|
1980
|
-
|
|
1981
1943
|
### `@eduardoalvarez/arrecife/theme`
|
|
1982
1944
|
|
|
1983
1945
|
| export | type | what it is |
|
|
@@ -2007,7 +1969,7 @@ Types (2): `Theme`, `ThemeOptions`.
|
|
|
2007
1969
|
| `poseList` | `readonly ("desk" \| "laptop-coffee" \| "peek" \| "surf")[]` | |
|
|
2008
1970
|
| `poses` | `{ readonly desk: "pose-desk.png"; readonly 'laptop-coffee': "pose-laptop-coffee.png"; readonly peek: "pose-peek.png"; readonly surf: "pose-surf.png"; }` | Full-body poses. |
|
|
2009
1971
|
|
|
2010
|
-
Types (
|
|
1972
|
+
Types (9): `Background`, `Face`, `Fin`, `IsotypeBackground`, `IsotypeProps`, `LogoProps`, `MascotFaceProps`, `MascotProps`, `Pose`.
|
|
2011
1973
|
|
|
2012
1974
|
### `@eduardoalvarez/arrecife/icons`
|
|
2013
1975
|
|
|
@@ -2059,7 +2021,6 @@ Types (6): `ArticleData`, `BaseData`, `CourseData`, `DefaultData`, `SatoriNode`,
|
|
|
2059
2021
|
| export | type | what it is |
|
|
2060
2022
|
| --- | --- | --- |
|
|
2061
2023
|
| `cn` | `(...inputs: ClassValue[]): string` | |
|
|
2062
|
-
| `social` | `typeof import("src/social/index")` | |
|
|
2063
2024
|
| `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. |
|
|
2064
2025
|
| `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. |
|
|
2065
2026
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eduardoalvarez/arrecife",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "The component library of Eduardo Álvarez’s visual identity",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Eduardo Esteban Álvarez Castañeda <soy@eduardoalvarez.dev>",
|
|
@@ -49,16 +49,6 @@
|
|
|
49
49
|
"import": "./dist/brand/index.js",
|
|
50
50
|
"require": "./dist/brand/index.cjs"
|
|
51
51
|
},
|
|
52
|
-
"./social": {
|
|
53
|
-
"types": "./dist/social/index.d.ts",
|
|
54
|
-
"import": "./dist/social/index.js",
|
|
55
|
-
"require": "./dist/social/index.cjs"
|
|
56
|
-
},
|
|
57
|
-
"./social/data": {
|
|
58
|
-
"types": "./dist/social/data.d.ts",
|
|
59
|
-
"import": "./dist/social/data.js",
|
|
60
|
-
"require": "./dist/social/data.cjs"
|
|
61
|
-
},
|
|
62
52
|
"./icons": {
|
|
63
53
|
"types": "./dist/icons/index.d.ts",
|
|
64
54
|
"import": "./dist/icons/index.js",
|
|
@@ -126,9 +116,6 @@
|
|
|
126
116
|
"recharts": "^3.0.0"
|
|
127
117
|
},
|
|
128
118
|
"peerDependenciesMeta": {
|
|
129
|
-
"@phosphor-icons/react": {
|
|
130
|
-
"optional": true
|
|
131
|
-
},
|
|
132
119
|
"react-hook-form": {
|
|
133
120
|
"optional": true
|
|
134
121
|
},
|
|
@@ -139,32 +126,33 @@
|
|
|
139
126
|
"devDependencies": {
|
|
140
127
|
"@eslint/js": "^10.0.1",
|
|
141
128
|
"@phosphor-icons/react": "^2.1.10",
|
|
142
|
-
"@storybook/addon-a11y": "^10.
|
|
143
|
-
"@storybook/addon-docs": "^10.
|
|
144
|
-
"@storybook/addon-themes": "^10.
|
|
145
|
-
"@storybook/addon-vitest": "^10.
|
|
146
|
-
"@storybook/react-vite": "^10.
|
|
129
|
+
"@storybook/addon-a11y": "^10.6.0",
|
|
130
|
+
"@storybook/addon-docs": "^10.6.0",
|
|
131
|
+
"@storybook/addon-themes": "^10.6.0",
|
|
132
|
+
"@storybook/addon-vitest": "^10.6.0",
|
|
133
|
+
"@storybook/react-vite": "^10.6.0",
|
|
147
134
|
"@tailwindcss/vite": "^4.3.3",
|
|
148
135
|
"@types/react": "^19.2.0",
|
|
149
|
-
"@types/react-dom": "^19.2.
|
|
150
|
-
"@vitest/browser": "^
|
|
151
|
-
"@vitest/browser-playwright": "^
|
|
152
|
-
"eslint": "^10.
|
|
136
|
+
"@types/react-dom": "^19.2.7",
|
|
137
|
+
"@vitest/browser": "^5.0.0",
|
|
138
|
+
"@vitest/browser-playwright": "^5.0.0",
|
|
139
|
+
"eslint": "^10.10.0",
|
|
153
140
|
"eslint-plugin-react-hooks": "^7.0.0",
|
|
154
|
-
"globals": "^17.
|
|
155
|
-
"playwright": "^1.
|
|
141
|
+
"globals": "^17.12.0",
|
|
142
|
+
"playwright": "^1.63.0",
|
|
156
143
|
"react": "^19.2.0",
|
|
157
144
|
"react-dom": "^19.2.0",
|
|
158
145
|
"react-hook-form": "^7.87.0",
|
|
159
146
|
"recharts": "^3.10.1",
|
|
160
|
-
"storybook": "^10.
|
|
161
|
-
"storybook-addon-pseudo-states": "^10.
|
|
147
|
+
"storybook": "^10.6.0",
|
|
148
|
+
"storybook-addon-pseudo-states": "^10.6.0",
|
|
162
149
|
"tailwindcss": "^4.3.3",
|
|
163
150
|
"tsup": "^8.5.1",
|
|
164
|
-
"typescript": "^
|
|
165
|
-
"typescript-eslint": "^8.
|
|
151
|
+
"typescript": "^6.0.3",
|
|
152
|
+
"typescript-eslint": "^8.69.0",
|
|
166
153
|
"vite": "^8.2.2",
|
|
167
|
-
"vitest": "^
|
|
154
|
+
"vitest": "^5.0.0",
|
|
155
|
+
"eslint-plugin-storybook": "10.6.0"
|
|
168
156
|
},
|
|
169
157
|
"packageManager": "pnpm@11.20.0",
|
|
170
158
|
"engines": {
|
package/dist/chunk-HOADZ6GS.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { gitHubGlyph, linkedInGlyph, xGlyph, instagramGlyph, discordGlyph, youTubeGlyph, rssGlyph, emailGlyph, newsletterGlyph, websiteGlyph, SOCIAL_STROKE_WIDTH, SOCIAL_VIEW_BOX } from './chunk-LXRGQKMG.js';
|
|
2
|
-
import { __export } from './chunk-MLKGABMK.js';
|
|
3
|
-
import { jsx } from 'react/jsx-runtime';
|
|
4
|
-
|
|
5
|
-
// src/social/index.tsx
|
|
6
|
-
var social_exports = {};
|
|
7
|
-
__export(social_exports, {
|
|
8
|
-
Discord: () => Discord,
|
|
9
|
-
Email: () => Email,
|
|
10
|
-
GitHub: () => GitHub,
|
|
11
|
-
Instagram: () => Instagram,
|
|
12
|
-
LinkedIn: () => LinkedIn,
|
|
13
|
-
Newsletter: () => Newsletter,
|
|
14
|
-
Rss: () => Rss,
|
|
15
|
-
Website: () => Website,
|
|
16
|
-
X: () => X,
|
|
17
|
-
YouTube: () => YouTube
|
|
18
|
-
});
|
|
19
|
-
var SOLID = { fill: "currentColor", stroke: "none" };
|
|
20
|
-
function drawShape(shape, index) {
|
|
21
|
-
if (shape.tag === "path") {
|
|
22
|
-
return /* @__PURE__ */ jsx("path", { d: shape.d, ...shape.solid ? SOLID : {} }, index);
|
|
23
|
-
}
|
|
24
|
-
if (shape.tag === "circle") {
|
|
25
|
-
return /* @__PURE__ */ jsx("circle", { cx: shape.cx, cy: shape.cy, r: shape.r, ...shape.solid ? SOLID : {} }, index);
|
|
26
|
-
}
|
|
27
|
-
return /* @__PURE__ */ jsx(
|
|
28
|
-
"rect",
|
|
29
|
-
{
|
|
30
|
-
x: shape.x,
|
|
31
|
-
y: shape.y,
|
|
32
|
-
width: shape.width,
|
|
33
|
-
height: shape.height,
|
|
34
|
-
rx: shape.rx
|
|
35
|
-
},
|
|
36
|
-
index
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
function Glyph({ glyph, ...props }) {
|
|
40
|
-
const brand = glyph.kind === "brand";
|
|
41
|
-
return /* @__PURE__ */ jsx(
|
|
42
|
-
"svg",
|
|
43
|
-
{
|
|
44
|
-
viewBox: SOCIAL_VIEW_BOX,
|
|
45
|
-
width: "1em",
|
|
46
|
-
height: "1em",
|
|
47
|
-
fill: brand ? "currentColor" : "none",
|
|
48
|
-
...brand ? {} : {
|
|
49
|
-
stroke: "currentColor",
|
|
50
|
-
strokeWidth: SOCIAL_STROKE_WIDTH,
|
|
51
|
-
strokeLinecap: "round",
|
|
52
|
-
strokeLinejoin: "round"
|
|
53
|
-
},
|
|
54
|
-
"aria-hidden": "true",
|
|
55
|
-
focusable: "false",
|
|
56
|
-
...props,
|
|
57
|
-
children: glyph.shapes.map(drawShape)
|
|
58
|
-
}
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
var GitHub = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: gitHubGlyph, ...props });
|
|
62
|
-
var LinkedIn = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: linkedInGlyph, ...props });
|
|
63
|
-
var X = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: xGlyph, ...props });
|
|
64
|
-
var Instagram = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: instagramGlyph, ...props });
|
|
65
|
-
var Discord = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: discordGlyph, ...props });
|
|
66
|
-
var YouTube = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: youTubeGlyph, ...props });
|
|
67
|
-
var Rss = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: rssGlyph, ...props });
|
|
68
|
-
var Email = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: emailGlyph, ...props });
|
|
69
|
-
var Newsletter = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: newsletterGlyph, ...props });
|
|
70
|
-
var Website = (props) => /* @__PURE__ */ jsx(Glyph, { glyph: websiteGlyph, ...props });
|
|
71
|
-
|
|
72
|
-
export { Discord, Email, GitHub, Instagram, LinkedIn, Newsletter, Rss, Website, X, YouTube, social_exports };
|