@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/index.d.cts
CHANGED
|
@@ -26,9 +26,8 @@ import * as ToastPrimitive from '@radix-ui/react-toast';
|
|
|
26
26
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
27
27
|
import { F as Face, P as Pose } from './catalog-D13txprv.cjs';
|
|
28
28
|
export { A as ASSETS_PATH, B as Background, a as Fin, f as faceList, b as faceUsage, c as faces, d as fins, p as poseList, e as poses } from './catalog-D13txprv.cjs';
|
|
29
|
-
export { Isotype, IsotypeProps, Logo, LogoProps, Mascot, MascotFace, MascotFaceProps, MascotProps } from './brand/index.cjs';
|
|
29
|
+
export { Isotype, IsotypeBackground, IsotypeProps, Logo, LogoProps, Mascot, MascotFace, MascotFaceProps, MascotProps } from './brand/index.cjs';
|
|
30
30
|
import { ClassValue } from 'clsx';
|
|
31
|
-
export { i as social } from './index-BbRplw_B.cjs';
|
|
32
31
|
import '@radix-ui/react-label';
|
|
33
32
|
|
|
34
33
|
/**
|
|
@@ -81,8 +80,8 @@ declare function AccordionContent({ className, children, ...props }: ComponentPr
|
|
|
81
80
|
type AlertProps = Omit<ComponentPropsWithoutRef<'div'>, 'title'> & VariantProps<typeof alert> & {
|
|
82
81
|
title?: ReactNode;
|
|
83
82
|
/**
|
|
84
|
-
* Replaces the variant's
|
|
85
|
-
*
|
|
83
|
+
* Replaces the variant's glyph. Never an emoji: if you need something else,
|
|
84
|
+
* it is `<Icon as={…} />` from `@eduardoalvarez/arrecife/icons`.
|
|
86
85
|
*/
|
|
87
86
|
icon?: ReactNode;
|
|
88
87
|
};
|
|
@@ -545,6 +544,40 @@ type TextareaProps = ComponentProps<'textarea'> & {
|
|
|
545
544
|
declare function Textarea({ className, invalid, ...props }: TextareaProps): react.JSX.Element;
|
|
546
545
|
|
|
547
546
|
declare const ToastAction: react.ForwardRefExoticComponent<ToastPrimitive.ToastActionProps & react.RefAttributes<HTMLButtonElement>>;
|
|
547
|
+
/**
|
|
548
|
+
* THE TONE IS A SURFACE, NOT A LINE, and that is what 0.10.0 changed.
|
|
549
|
+
*
|
|
550
|
+
* It used to be `bg-surface` for all three and the whole difference between a
|
|
551
|
+
* confirmation and a failure was `border-success/40` against `border-error/40`:
|
|
552
|
+
* two hairlines at 40 % opacity, on a box that floats over whatever page it
|
|
553
|
+
* happens to land on, with no mark on it and the text in `textSecondary`. At the
|
|
554
|
+
* size a toast actually appears at, that is not a colour — it is two greys.
|
|
555
|
+
*
|
|
556
|
+
* What it is now is the recipe `Alert` already carries and had already argued:
|
|
557
|
+
* the semantic colour SOLID on the border and at 10 % as a tint, which is
|
|
558
|
+
* `emphasis="strong"` in `variants/alert.ts`. That variant exists for the alert
|
|
559
|
+
* that has to read UNDER a form field, and a toast has the same problem from the
|
|
560
|
+
* other side — it reads over content it did not choose, so the subtle 8 %/22 %
|
|
561
|
+
* recipe is not enough on its own.
|
|
562
|
+
*
|
|
563
|
+
* THE TINT RIDES ON A GRADIENT and not on `background-color`, which is the one
|
|
564
|
+
* odd line here. A toast has to be OPAQUE: it floats, and `bg-success/10` alone
|
|
565
|
+
* would let the article underneath show through it. `bg-surface` paints the
|
|
566
|
+
* opaque ground and the flat `linear-gradient` paints the tint on top of it, in
|
|
567
|
+
* one element, without a wrapper or a `::before` that would need its own
|
|
568
|
+
* stacking context. The two `from-`/`to-` stops are the same colour on purpose:
|
|
569
|
+
* it is a fill, not a gradient.
|
|
570
|
+
*
|
|
571
|
+
* MEASURED over the resulting surface, dark then light, worst case of the two:
|
|
572
|
+
*
|
|
573
|
+
* text-text-primary over the success tint 14.9 14.6
|
|
574
|
+
* text-text-secondary over the success tint 8.4 7.1
|
|
575
|
+
* the border against the tint 4.2 3.6 (3:1 graphical)
|
|
576
|
+
*
|
|
577
|
+
* The body stays `textSecondary` and the title `textPrimary`, which is the same
|
|
578
|
+
* split `Alert` uses and for the same reason: a semantic colour is not a text
|
|
579
|
+
* colour over its own tint.
|
|
580
|
+
*/
|
|
548
581
|
declare const toast$1: (props?: ({
|
|
549
582
|
variant?: "error" | "neutral" | "success" | null | undefined;
|
|
550
583
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
@@ -734,15 +767,19 @@ declare function AuthorCard({ name, role, src, bio, action, className, ...props
|
|
|
734
767
|
* the same. What changed is the skin and the two dependencies a package cannot
|
|
735
768
|
* have:
|
|
736
769
|
*
|
|
737
|
-
* - the portfolio's `Icon` → the
|
|
738
|
-
* the
|
|
770
|
+
* - the portfolio's `Icon` → the library's own `Icon` over Phosphor. The eight
|
|
771
|
+
* paths this file used to carry verbatim from the portfolio are gone with
|
|
772
|
+
* `lib/glyphs.tsx`; `Play`, `Pause`, `SpeakerHigh` and `SpeakerSlash` are the
|
|
773
|
+
* same symbols in Phosphor's hand, and the ±15s skips are `ArrowCounterClockwise`
|
|
774
|
+
* and `ArrowClockwise`. See `docs/decisions/0.10.md` § 51.
|
|
739
775
|
* - analytics' `trackEvent` → the `onFirstPlay` prop, which the consumer wires
|
|
740
776
|
* to whatever they use. It still fires exactly once per load.
|
|
741
777
|
*
|
|
742
778
|
* And three things the system does not allow:
|
|
743
779
|
*
|
|
744
|
-
* - The waveform no longer animates `scaleY`.
|
|
745
|
-
*
|
|
780
|
+
* - The waveform no longer animates `scaleY`. Since 0.10.0 it is not even drawn
|
|
781
|
+
* here: it is Phosphor's `Waveform`, which is the same five bars. It still
|
|
782
|
+
* tells playback from pause by opacity, and it does not move.
|
|
746
783
|
* - The floating player appears and disappears instead of sliding.
|
|
747
784
|
* - The progress bar no longer interpolates its width.
|
|
748
785
|
*
|
|
@@ -832,7 +869,13 @@ type CodeBlockProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
|
|
|
832
869
|
};
|
|
833
870
|
declare function CodeBlock({ children, language, copyText, className, ...props }: CodeBlockProps): react.JSX.Element;
|
|
834
871
|
|
|
835
|
-
|
|
872
|
+
/**
|
|
873
|
+
* `media` is left out of the shell's props because `<a>` already has an
|
|
874
|
+
* attribute by that name — a media query for the linked resource, a string —
|
|
875
|
+
* and intersected with the slot it would make the slot accept only strings.
|
|
876
|
+
* No browser acts on it and no project was passing it.
|
|
877
|
+
*/
|
|
878
|
+
type CourseCardProps = Omit<CardShellProps, 'children' | 'title' | 'media'> & {
|
|
836
879
|
title: ReactNode;
|
|
837
880
|
summary?: ReactNode;
|
|
838
881
|
/** Level, duration, number of lessons: whatever the project wants to list. */
|
|
@@ -844,8 +887,42 @@ type CourseCardProps = Omit<CardShellProps, 'children' | 'title'> & {
|
|
|
844
887
|
* when passed, the bar goes in sand, which is the color of course progress.
|
|
845
888
|
*/
|
|
846
889
|
progress?: number | undefined;
|
|
890
|
+
/**
|
|
891
|
+
* The cover, at the top and bleeding to the card's edges, with `alt=""`: the
|
|
892
|
+
* whole card is one link and `title` already names it.
|
|
893
|
+
*
|
|
894
|
+
* The project owns the element — an `<img>`, a framework's `Image`, a
|
|
895
|
+
* generated cover — and its ratio; the card clips it to its own corners. An
|
|
896
|
+
* `alt` that repeats the title makes a screen reader say the course twice
|
|
897
|
+
* before anything else.
|
|
898
|
+
*/
|
|
899
|
+
media?: ReactNode;
|
|
900
|
+
/**
|
|
901
|
+
* The closing row, under `meta`: the rating, the price, whatever the project
|
|
902
|
+
* sells the course with. It sits at the bottom of the card, so the rows of a
|
|
903
|
+
* grid line up whatever the length of each summary.
|
|
904
|
+
*/
|
|
905
|
+
footer?: ReactNode;
|
|
847
906
|
};
|
|
848
|
-
|
|
907
|
+
/**
|
|
908
|
+
* The course, as a card that links to it.
|
|
909
|
+
*
|
|
910
|
+
* `media` and `footer` are slots rather than props for a cover URL, a rating
|
|
911
|
+
* and a price, because none of those three is the identity's. The price comes
|
|
912
|
+
* formatted in a currency the library does not know, the rating is drawn by a
|
|
913
|
+
* component the project already has, and the cover is an image pipeline. What
|
|
914
|
+
* IS the identity's stays here: the title's scale and its hover, the sand bar,
|
|
915
|
+
* the status badge. See `docs/decisions/0.11.md` § 59.
|
|
916
|
+
*
|
|
917
|
+
* The title does NOT go over the cover. It stays in the body at `h3`, with the
|
|
918
|
+
* hover every other card has. Text on a photograph needs a scrim, and a scrim's
|
|
919
|
+
* contrast depends on the photograph: it cannot be measured once and recorded,
|
|
920
|
+
* which is the only way contrast is decided in this system.
|
|
921
|
+
*
|
|
922
|
+
* And the cover does not move on hover. Rule 6 is the border and nothing else:
|
|
923
|
+
* no zoom, no scale, no displacement.
|
|
924
|
+
*/
|
|
925
|
+
declare function CourseCard({ title, summary, meta, status, progress, media, footer, className, ...props }: CourseCardProps): react.JSX.Element;
|
|
849
926
|
|
|
850
927
|
/**
|
|
851
928
|
* The mascot's most important rule, finally as code.
|
|
@@ -982,8 +1059,10 @@ type SocialLink = {
|
|
|
982
1059
|
label: string;
|
|
983
1060
|
href: string;
|
|
984
1061
|
/**
|
|
985
|
-
* The glyph, at 19px.
|
|
986
|
-
*
|
|
1062
|
+
* The glyph, at 19px. It is the PROJECT's — the library ships no catalogue of
|
|
1063
|
+
* social marks since 0.10.0 — and the drawing rule it should follow is the
|
|
1064
|
+
* system's: a brand is SOLID, so `<Icon as={GithubLogo} tone="current" />`,
|
|
1065
|
+
* and a functional mark keeps the default `action`. Never an emoji.
|
|
987
1066
|
*/
|
|
988
1067
|
icon: ReactNode;
|
|
989
1068
|
};
|
|
@@ -1353,6 +1432,15 @@ declare function NewsletterForm({ title, description, state, onSubmitEmail, succ
|
|
|
1353
1432
|
*
|
|
1354
1433
|
* `display` for covers, `page` for section headers.
|
|
1355
1434
|
*
|
|
1435
|
+
* The size picks the title's scale by default, and `titleVariant` lets the
|
|
1436
|
+
* screen pick another one. The default is the document's — «h1 44/700» on the
|
|
1437
|
+
* six interior pages of the reading site — and it is right there. It is not
|
|
1438
|
+
* right in the two admin apps: `blog-content-manager` titles its twelve screens
|
|
1439
|
+
* at 24px, and `cursos` titles 29 of its 32 at `h3` — every one in the panel —
|
|
1440
|
+
* and the other three, the public catalog pages, at `h2`. Both are rungs the
|
|
1441
|
+
* scale already has, and a third `size` could only have named one of them. See
|
|
1442
|
+
* `docs/decisions/0.11.md` § 57.
|
|
1443
|
+
*
|
|
1356
1444
|
* It takes no mascot face, at either scale: faces go in empty states,
|
|
1357
1445
|
* confirmations, errors, course progress and celebration.
|
|
1358
1446
|
*
|
|
@@ -1377,8 +1465,21 @@ type PageHeaderProps = Omit<ComponentPropsWithoutRef<'header'>, 'title'> & Varia
|
|
|
1377
1465
|
action?: ReactNode | undefined;
|
|
1378
1466
|
/** The headline's level. `h1` unless the page already has one. */
|
|
1379
1467
|
as?: 'h1' | 'h2' | undefined;
|
|
1468
|
+
/**
|
|
1469
|
+
* The headline's scale, when the screen needs a different one from what
|
|
1470
|
+
* `size` gives — `display` for `display`, `h1` for `page`.
|
|
1471
|
+
*
|
|
1472
|
+
* It is the same split `Text` makes: `as` is the level, this is how big it
|
|
1473
|
+
* looks. A panel's `<h1>` at `h3` is still the page's only `h1`. The padding
|
|
1474
|
+
* stays with `size`, so a header inside a layout that already spaces its
|
|
1475
|
+
* content passes `className="py-0"`.
|
|
1476
|
+
*
|
|
1477
|
+
* Only the four headline scales, all in the display family. `stat` is for
|
|
1478
|
+
* numbers and `body` is not a headline.
|
|
1479
|
+
*/
|
|
1480
|
+
titleVariant?: 'display' | 'h1' | 'h2' | 'h3' | undefined;
|
|
1380
1481
|
};
|
|
1381
|
-
declare function PageHeader({ title, eyebrow, description, action, size, as, className, ...props }: PageHeaderProps): react.JSX.Element;
|
|
1482
|
+
declare function PageHeader({ title, eyebrow, description, action, size, as, titleVariant, className, ...props }: PageHeaderProps): react.JSX.Element;
|
|
1382
1483
|
|
|
1383
1484
|
/**
|
|
1384
1485
|
* How much you have read. It is NOT `Progress` under another name.
|
package/dist/index.d.ts
CHANGED
|
@@ -26,9 +26,8 @@ import * as ToastPrimitive from '@radix-ui/react-toast';
|
|
|
26
26
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
27
27
|
import { F as Face, P as Pose } from './catalog-D13txprv.js';
|
|
28
28
|
export { A as ASSETS_PATH, B as Background, a as Fin, f as faceList, b as faceUsage, c as faces, d as fins, p as poseList, e as poses } from './catalog-D13txprv.js';
|
|
29
|
-
export { Isotype, IsotypeProps, Logo, LogoProps, Mascot, MascotFace, MascotFaceProps, MascotProps } from './brand/index.js';
|
|
29
|
+
export { Isotype, IsotypeBackground, IsotypeProps, Logo, LogoProps, Mascot, MascotFace, MascotFaceProps, MascotProps } from './brand/index.js';
|
|
30
30
|
import { ClassValue } from 'clsx';
|
|
31
|
-
export { i as social } from './index-BbRplw_B.js';
|
|
32
31
|
import '@radix-ui/react-label';
|
|
33
32
|
|
|
34
33
|
/**
|
|
@@ -81,8 +80,8 @@ declare function AccordionContent({ className, children, ...props }: ComponentPr
|
|
|
81
80
|
type AlertProps = Omit<ComponentPropsWithoutRef<'div'>, 'title'> & VariantProps<typeof alert> & {
|
|
82
81
|
title?: ReactNode;
|
|
83
82
|
/**
|
|
84
|
-
* Replaces the variant's
|
|
85
|
-
*
|
|
83
|
+
* Replaces the variant's glyph. Never an emoji: if you need something else,
|
|
84
|
+
* it is `<Icon as={…} />` from `@eduardoalvarez/arrecife/icons`.
|
|
86
85
|
*/
|
|
87
86
|
icon?: ReactNode;
|
|
88
87
|
};
|
|
@@ -545,6 +544,40 @@ type TextareaProps = ComponentProps<'textarea'> & {
|
|
|
545
544
|
declare function Textarea({ className, invalid, ...props }: TextareaProps): react.JSX.Element;
|
|
546
545
|
|
|
547
546
|
declare const ToastAction: react.ForwardRefExoticComponent<ToastPrimitive.ToastActionProps & react.RefAttributes<HTMLButtonElement>>;
|
|
547
|
+
/**
|
|
548
|
+
* THE TONE IS A SURFACE, NOT A LINE, and that is what 0.10.0 changed.
|
|
549
|
+
*
|
|
550
|
+
* It used to be `bg-surface` for all three and the whole difference between a
|
|
551
|
+
* confirmation and a failure was `border-success/40` against `border-error/40`:
|
|
552
|
+
* two hairlines at 40 % opacity, on a box that floats over whatever page it
|
|
553
|
+
* happens to land on, with no mark on it and the text in `textSecondary`. At the
|
|
554
|
+
* size a toast actually appears at, that is not a colour — it is two greys.
|
|
555
|
+
*
|
|
556
|
+
* What it is now is the recipe `Alert` already carries and had already argued:
|
|
557
|
+
* the semantic colour SOLID on the border and at 10 % as a tint, which is
|
|
558
|
+
* `emphasis="strong"` in `variants/alert.ts`. That variant exists for the alert
|
|
559
|
+
* that has to read UNDER a form field, and a toast has the same problem from the
|
|
560
|
+
* other side — it reads over content it did not choose, so the subtle 8 %/22 %
|
|
561
|
+
* recipe is not enough on its own.
|
|
562
|
+
*
|
|
563
|
+
* THE TINT RIDES ON A GRADIENT and not on `background-color`, which is the one
|
|
564
|
+
* odd line here. A toast has to be OPAQUE: it floats, and `bg-success/10` alone
|
|
565
|
+
* would let the article underneath show through it. `bg-surface` paints the
|
|
566
|
+
* opaque ground and the flat `linear-gradient` paints the tint on top of it, in
|
|
567
|
+
* one element, without a wrapper or a `::before` that would need its own
|
|
568
|
+
* stacking context. The two `from-`/`to-` stops are the same colour on purpose:
|
|
569
|
+
* it is a fill, not a gradient.
|
|
570
|
+
*
|
|
571
|
+
* MEASURED over the resulting surface, dark then light, worst case of the two:
|
|
572
|
+
*
|
|
573
|
+
* text-text-primary over the success tint 14.9 14.6
|
|
574
|
+
* text-text-secondary over the success tint 8.4 7.1
|
|
575
|
+
* the border against the tint 4.2 3.6 (3:1 graphical)
|
|
576
|
+
*
|
|
577
|
+
* The body stays `textSecondary` and the title `textPrimary`, which is the same
|
|
578
|
+
* split `Alert` uses and for the same reason: a semantic colour is not a text
|
|
579
|
+
* colour over its own tint.
|
|
580
|
+
*/
|
|
548
581
|
declare const toast$1: (props?: ({
|
|
549
582
|
variant?: "error" | "neutral" | "success" | null | undefined;
|
|
550
583
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
@@ -734,15 +767,19 @@ declare function AuthorCard({ name, role, src, bio, action, className, ...props
|
|
|
734
767
|
* the same. What changed is the skin and the two dependencies a package cannot
|
|
735
768
|
* have:
|
|
736
769
|
*
|
|
737
|
-
* - the portfolio's `Icon` → the
|
|
738
|
-
* the
|
|
770
|
+
* - the portfolio's `Icon` → the library's own `Icon` over Phosphor. The eight
|
|
771
|
+
* paths this file used to carry verbatim from the portfolio are gone with
|
|
772
|
+
* `lib/glyphs.tsx`; `Play`, `Pause`, `SpeakerHigh` and `SpeakerSlash` are the
|
|
773
|
+
* same symbols in Phosphor's hand, and the ±15s skips are `ArrowCounterClockwise`
|
|
774
|
+
* and `ArrowClockwise`. See `docs/decisions/0.10.md` § 51.
|
|
739
775
|
* - analytics' `trackEvent` → the `onFirstPlay` prop, which the consumer wires
|
|
740
776
|
* to whatever they use. It still fires exactly once per load.
|
|
741
777
|
*
|
|
742
778
|
* And three things the system does not allow:
|
|
743
779
|
*
|
|
744
|
-
* - The waveform no longer animates `scaleY`.
|
|
745
|
-
*
|
|
780
|
+
* - The waveform no longer animates `scaleY`. Since 0.10.0 it is not even drawn
|
|
781
|
+
* here: it is Phosphor's `Waveform`, which is the same five bars. It still
|
|
782
|
+
* tells playback from pause by opacity, and it does not move.
|
|
746
783
|
* - The floating player appears and disappears instead of sliding.
|
|
747
784
|
* - The progress bar no longer interpolates its width.
|
|
748
785
|
*
|
|
@@ -832,7 +869,13 @@ type CodeBlockProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
|
|
|
832
869
|
};
|
|
833
870
|
declare function CodeBlock({ children, language, copyText, className, ...props }: CodeBlockProps): react.JSX.Element;
|
|
834
871
|
|
|
835
|
-
|
|
872
|
+
/**
|
|
873
|
+
* `media` is left out of the shell's props because `<a>` already has an
|
|
874
|
+
* attribute by that name — a media query for the linked resource, a string —
|
|
875
|
+
* and intersected with the slot it would make the slot accept only strings.
|
|
876
|
+
* No browser acts on it and no project was passing it.
|
|
877
|
+
*/
|
|
878
|
+
type CourseCardProps = Omit<CardShellProps, 'children' | 'title' | 'media'> & {
|
|
836
879
|
title: ReactNode;
|
|
837
880
|
summary?: ReactNode;
|
|
838
881
|
/** Level, duration, number of lessons: whatever the project wants to list. */
|
|
@@ -844,8 +887,42 @@ type CourseCardProps = Omit<CardShellProps, 'children' | 'title'> & {
|
|
|
844
887
|
* when passed, the bar goes in sand, which is the color of course progress.
|
|
845
888
|
*/
|
|
846
889
|
progress?: number | undefined;
|
|
890
|
+
/**
|
|
891
|
+
* The cover, at the top and bleeding to the card's edges, with `alt=""`: the
|
|
892
|
+
* whole card is one link and `title` already names it.
|
|
893
|
+
*
|
|
894
|
+
* The project owns the element — an `<img>`, a framework's `Image`, a
|
|
895
|
+
* generated cover — and its ratio; the card clips it to its own corners. An
|
|
896
|
+
* `alt` that repeats the title makes a screen reader say the course twice
|
|
897
|
+
* before anything else.
|
|
898
|
+
*/
|
|
899
|
+
media?: ReactNode;
|
|
900
|
+
/**
|
|
901
|
+
* The closing row, under `meta`: the rating, the price, whatever the project
|
|
902
|
+
* sells the course with. It sits at the bottom of the card, so the rows of a
|
|
903
|
+
* grid line up whatever the length of each summary.
|
|
904
|
+
*/
|
|
905
|
+
footer?: ReactNode;
|
|
847
906
|
};
|
|
848
|
-
|
|
907
|
+
/**
|
|
908
|
+
* The course, as a card that links to it.
|
|
909
|
+
*
|
|
910
|
+
* `media` and `footer` are slots rather than props for a cover URL, a rating
|
|
911
|
+
* and a price, because none of those three is the identity's. The price comes
|
|
912
|
+
* formatted in a currency the library does not know, the rating is drawn by a
|
|
913
|
+
* component the project already has, and the cover is an image pipeline. What
|
|
914
|
+
* IS the identity's stays here: the title's scale and its hover, the sand bar,
|
|
915
|
+
* the status badge. See `docs/decisions/0.11.md` § 59.
|
|
916
|
+
*
|
|
917
|
+
* The title does NOT go over the cover. It stays in the body at `h3`, with the
|
|
918
|
+
* hover every other card has. Text on a photograph needs a scrim, and a scrim's
|
|
919
|
+
* contrast depends on the photograph: it cannot be measured once and recorded,
|
|
920
|
+
* which is the only way contrast is decided in this system.
|
|
921
|
+
*
|
|
922
|
+
* And the cover does not move on hover. Rule 6 is the border and nothing else:
|
|
923
|
+
* no zoom, no scale, no displacement.
|
|
924
|
+
*/
|
|
925
|
+
declare function CourseCard({ title, summary, meta, status, progress, media, footer, className, ...props }: CourseCardProps): react.JSX.Element;
|
|
849
926
|
|
|
850
927
|
/**
|
|
851
928
|
* The mascot's most important rule, finally as code.
|
|
@@ -982,8 +1059,10 @@ type SocialLink = {
|
|
|
982
1059
|
label: string;
|
|
983
1060
|
href: string;
|
|
984
1061
|
/**
|
|
985
|
-
* The glyph, at 19px.
|
|
986
|
-
*
|
|
1062
|
+
* The glyph, at 19px. It is the PROJECT's — the library ships no catalogue of
|
|
1063
|
+
* social marks since 0.10.0 — and the drawing rule it should follow is the
|
|
1064
|
+
* system's: a brand is SOLID, so `<Icon as={GithubLogo} tone="current" />`,
|
|
1065
|
+
* and a functional mark keeps the default `action`. Never an emoji.
|
|
987
1066
|
*/
|
|
988
1067
|
icon: ReactNode;
|
|
989
1068
|
};
|
|
@@ -1353,6 +1432,15 @@ declare function NewsletterForm({ title, description, state, onSubmitEmail, succ
|
|
|
1353
1432
|
*
|
|
1354
1433
|
* `display` for covers, `page` for section headers.
|
|
1355
1434
|
*
|
|
1435
|
+
* The size picks the title's scale by default, and `titleVariant` lets the
|
|
1436
|
+
* screen pick another one. The default is the document's — «h1 44/700» on the
|
|
1437
|
+
* six interior pages of the reading site — and it is right there. It is not
|
|
1438
|
+
* right in the two admin apps: `blog-content-manager` titles its twelve screens
|
|
1439
|
+
* at 24px, and `cursos` titles 29 of its 32 at `h3` — every one in the panel —
|
|
1440
|
+
* and the other three, the public catalog pages, at `h2`. Both are rungs the
|
|
1441
|
+
* scale already has, and a third `size` could only have named one of them. See
|
|
1442
|
+
* `docs/decisions/0.11.md` § 57.
|
|
1443
|
+
*
|
|
1356
1444
|
* It takes no mascot face, at either scale: faces go in empty states,
|
|
1357
1445
|
* confirmations, errors, course progress and celebration.
|
|
1358
1446
|
*
|
|
@@ -1377,8 +1465,21 @@ type PageHeaderProps = Omit<ComponentPropsWithoutRef<'header'>, 'title'> & Varia
|
|
|
1377
1465
|
action?: ReactNode | undefined;
|
|
1378
1466
|
/** The headline's level. `h1` unless the page already has one. */
|
|
1379
1467
|
as?: 'h1' | 'h2' | undefined;
|
|
1468
|
+
/**
|
|
1469
|
+
* The headline's scale, when the screen needs a different one from what
|
|
1470
|
+
* `size` gives — `display` for `display`, `h1` for `page`.
|
|
1471
|
+
*
|
|
1472
|
+
* It is the same split `Text` makes: `as` is the level, this is how big it
|
|
1473
|
+
* looks. A panel's `<h1>` at `h3` is still the page's only `h1`. The padding
|
|
1474
|
+
* stays with `size`, so a header inside a layout that already spaces its
|
|
1475
|
+
* content passes `className="py-0"`.
|
|
1476
|
+
*
|
|
1477
|
+
* Only the four headline scales, all in the display family. `stat` is for
|
|
1478
|
+
* numbers and `body` is not a headline.
|
|
1479
|
+
*/
|
|
1480
|
+
titleVariant?: 'display' | 'h1' | 'h2' | 'h3' | undefined;
|
|
1380
1481
|
};
|
|
1381
|
-
declare function PageHeader({ title, eyebrow, description, action, size, as, className, ...props }: PageHeaderProps): react.JSX.Element;
|
|
1482
|
+
declare function PageHeader({ title, eyebrow, description, action, size, as, titleVariant, className, ...props }: PageHeaderProps): react.JSX.Element;
|
|
1382
1483
|
|
|
1383
1484
|
/**
|
|
1384
1485
|
* How much you have read. It is NOT `Progress` under another name.
|