@charcuterie/ui 3.10.0 → 3.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/README.md +1 -0
- package/dist/Card/Card.d.ts +12 -1
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +14 -2
- package/dist/Card/Card.js.map +1 -1
- package/dist/Card/cardAccentEdge.d.ts +101 -0
- package/dist/Card/cardAccentEdge.d.ts.map +1 -0
- package/dist/Card/cardAccentEdge.js +92 -0
- package/dist/Card/cardAccentEdge.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/Card/Card.mdx +21 -0
- package/src/Card/Card.stories.tsx +91 -0
- package/src/Card/Card.test.tsx +92 -1
- package/src/Card/Card.tsx +34 -0
- package/src/Card/cardAccentEdge.test.ts +105 -0
- package/src/Card/cardAccentEdge.ts +135 -0
- package/src/index.ts +1 -0
package/README.md
CHANGED
|
@@ -146,6 +146,7 @@ an hour of confusion.
|
|
|
146
146
|
| Type | `text-sm`/`text-md`/`text-lg`, which are **ours**: `theme.css` bridges `--text-*` onto the density-scaled `--font-size-*` |
|
|
147
147
|
| Motion | `styles.css`, at `--duration-loop-*`, switched off under `prefers-reduced-motion` |
|
|
148
148
|
| Scrollbar | `styles.css` — add `charcuterie-scrollbar` to any scrolling element for a token-tinted bar (rounded thumb on Chromium/Safari; thin standard match on Firefox) that flips with `[data-scheme]` |
|
|
149
|
+
| Accent edge | `Card/cardAccentEdge.ts` — `<Card accentEdge={{ categorical }} \| {{ color }}>` draws a bar down the leading edge from a pseudo-element that **inherits the card's radius**. A border cannot follow a corner, which is why three apps had a square bar on a round card |
|
|
149
150
|
| State | `@charcuterie/logic` — `useUniqueId` for label wiring, `useStatus` for `MediaTile`'s three image states |
|
|
150
151
|
|
|
151
152
|
**Class names are never interpolated.** `` `bg-intent-${intent}-solid` `` generates nothing
|
package/dist/Card/Card.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import type { ElevationStep, SurfaceRole } from "@charcuterie/tokens";
|
|
2
2
|
import type { ComponentPropsWithRef, ReactNode } from "react";
|
|
3
|
+
import type { CardAccentEdge } from "./cardAccentEdge.ts";
|
|
3
4
|
export type CardSurface = Extract<SurfaceRole, "base" | "raised" | "sunken">;
|
|
4
5
|
export type CardPadding = "lg" | "md" | "none" | "sm";
|
|
5
6
|
export type CardProps = ComponentPropsWithRef<"section"> & {
|
|
7
|
+
/**
|
|
8
|
+
* A coloured bar down the leading edge, following the card's own
|
|
9
|
+
* corners.
|
|
10
|
+
*
|
|
11
|
+
* `{ categorical: 3 }` for a colour a user picked; `{ color }`
|
|
12
|
+
* for one an app computed — a hue hashed from a repo's name, say,
|
|
13
|
+
* where ten indices are not enough. See `cardAccentEdge.ts` for
|
|
14
|
+
* why it is a pseudo-element and not a border.
|
|
15
|
+
*/
|
|
16
|
+
accentEdge?: CardAccentEdge;
|
|
6
17
|
/** Buttons or a badge, laid out beside the heading. */
|
|
7
18
|
actions?: ReactNode;
|
|
8
19
|
elevation?: ElevationStep;
|
|
@@ -40,5 +51,5 @@ export declare const ELEVATION_CLASS: Record<ElevationStep, string>;
|
|
|
40
51
|
* because a card wrapping a poster grid genuinely has none, which is
|
|
41
52
|
* a layout fact rather than a density one.
|
|
42
53
|
*/
|
|
43
|
-
export declare const Card: ({ actions, children, className, elevation, footer, heading, headingLevel, padding, surface, ...sectionProps }: CardProps) => ReactNode;
|
|
54
|
+
export declare const Card: ({ accentEdge, actions, children, className, elevation, footer, heading, headingLevel, padding, style, surface, ...sectionProps }: CardProps) => ReactNode;
|
|
44
55
|
//# sourceMappingURL=Card.d.ts.map
|
package/dist/Card/Card.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/Card/Card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EACV,qBAAqB,EACrB,SAAS,EACV,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/Card/Card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EACV,qBAAqB,EACrB,SAAS,EACV,MAAM,OAAO,CAAA;AAGd,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAMzD,MAAM,MAAM,WAAW,GAAG,OAAO,CAC/B,WAAW,EACX,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAC7B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;AAErD,MAAM,MAAM,SAAS,GAAG,qBAAqB,CAAC,SAAS,CAAC,GAAG;IACzD;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,cAAc,CAAA;IAC3B,uDAAuD;IACvD,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACxB,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,OAAO,CAAC,EAAE,WAAW,CAAA;CACtB,CAAA;AAQD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAClC,aAAa,EACb,MAAM,CAMP,CAAA;AASD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,IAAI,GAAI,kIAalB,SAAS,KAAG,SAmEd,CAAA"}
|
package/dist/Card/Card.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useUniqueId } from "@charcuterie/logic";
|
|
3
3
|
import { toClassName } from "../toClassName.js";
|
|
4
|
+
import { getAccentEdgeClassName, getAccentEdgeStyle, } from "./cardAccentEdge.js";
|
|
4
5
|
const SURFACE_CLASS = {
|
|
5
6
|
base: "bg-surface-base",
|
|
6
7
|
raised: "bg-surface-raised",
|
|
@@ -45,8 +46,17 @@ const PADDING_CLASS = {
|
|
|
45
46
|
* because a card wrapping a poster grid genuinely has none, which is
|
|
46
47
|
* a layout fact rather than a density one.
|
|
47
48
|
*/
|
|
48
|
-
export const Card = ({ actions, children, className, elevation = "low", footer, heading, headingLevel = 2, padding = "md", surface = "raised", ...sectionProps }) => {
|
|
49
|
+
export const Card = ({ accentEdge, actions, children, className, elevation = "low", footer, heading, headingLevel = 2, padding = "md", style, surface = "raised", ...sectionProps }) => {
|
|
49
50
|
const headingId = useUniqueId();
|
|
51
|
+
// The caller's own `style` wins. An accent colour is one custom
|
|
52
|
+
// property, and silently dropping whatever else the call site set
|
|
53
|
+
// would be a worse trade than letting it override this one.
|
|
54
|
+
const accentEdgeStyle = accentEdge == null
|
|
55
|
+
? undefined
|
|
56
|
+
: getAccentEdgeStyle(accentEdge);
|
|
57
|
+
const mergedStyle = accentEdgeStyle == null
|
|
58
|
+
? style
|
|
59
|
+
: { ...accentEdgeStyle, ...style };
|
|
50
60
|
const Heading = `h${headingLevel}`;
|
|
51
61
|
return (_jsxs("section", { ...sectionProps, "aria-labelledby": heading ? headingId : undefined, className: toClassName(
|
|
52
62
|
// `@container` here, not on a wrapper, is what lets the
|
|
@@ -54,6 +64,8 @@ export const Card = ({ actions, children, className, elevation = "low", footer,
|
|
|
54
64
|
// a card in a sidebar and the same card full-bleed are the
|
|
55
65
|
// case a media query cannot tell apart, and the fleet's
|
|
56
66
|
// poster grids get it wrong at intermediate widths today.
|
|
57
|
-
"@container flex flex-col gap-3 rounded-lg border border-border-subtle text-content-primary", SURFACE_CLASS[surface], ELEVATION_CLASS[elevation], PADDING_CLASS[padding],
|
|
67
|
+
"@container flex flex-col gap-3 rounded-lg border border-border-subtle text-content-primary", SURFACE_CLASS[surface], ELEVATION_CLASS[elevation], PADDING_CLASS[padding], accentEdge == null
|
|
68
|
+
? undefined
|
|
69
|
+
: getAccentEdgeClassName(accentEdge), className), style: mergedStyle, children: [heading || actions ? (_jsxs("header", { className: "flex flex-col gap-2 cq-sm:flex-row cq-sm:items-start cq-sm:justify-between", children: [heading ? (_jsx(Heading, { className: "font-semibold text-md leading-tight", id: headingId, children: heading })) : null, actions ? (_jsx("div", { className: "flex shrink-0 items-center gap-1", children: actions })) : null] })) : null, children, footer ? (_jsx("footer", { className: "border-t border-border-subtle pt-3 text-content-secondary text-sm", children: footer })) : null] }));
|
|
58
70
|
};
|
|
59
71
|
//# sourceMappingURL=Card.js.map
|
package/dist/Card/Card.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/Card/Card.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAUhD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/Card/Card.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAUhD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EACL,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AA8B5B,MAAM,aAAa,GAAgC;IACjD,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,mBAAmB;IAC3B,MAAM,EAAE,mBAAmB;CAC5B,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAGxB;IACF,IAAI,EAAE,aAAa;IACnB,GAAG,EAAE,YAAY;IACjB,MAAM,EAAE,eAAe;IACvB,IAAI,EAAE,aAAa;CACpB,CAAA;AAED,MAAM,aAAa,GAAgC;IACjD,IAAI,EAAE,KAAK;IACX,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,KAAK;CACV,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EACnB,UAAU,EACV,OAAO,EACP,QAAQ,EACR,SAAS,EACT,SAAS,GAAG,KAAK,EACjB,MAAM,EACN,OAAO,EACP,YAAY,GAAG,CAAC,EAChB,OAAO,GAAG,IAAI,EACd,KAAK,EACL,OAAO,GAAG,QAAQ,EAClB,GAAG,YAAY,EACL,EAAa,EAAE;IACzB,MAAM,SAAS,GAAG,WAAW,EAAE,CAAA;IAE/B,gEAAgE;IAChE,kEAAkE;IAClE,4DAA4D;IAC5D,MAAM,eAAe,GACnB,UAAU,IAAI,IAAI;QAChB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAA;IAEpC,MAAM,WAAW,GACf,eAAe,IAAI,IAAI;QACrB,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,EAAE,GAAG,eAAe,EAAE,GAAG,KAAK,EAAE,CAAA;IAEtC,MAAM,OAAO,GAAG,IAAI,YAAY,EAAW,CAAA;IAE3C,OAAO,CACL,sBACM,YAAY,qBACC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAChD,SAAS,EAAE,WAAW;QACpB,wDAAwD;QACxD,2DAA2D;QAC3D,2DAA2D;QAC3D,wDAAwD;QACxD,0DAA0D;QAC1D,4FAA4F,EAC5F,aAAa,CAAC,OAAO,CAAC,EACtB,eAAe,CAAC,SAAS,CAAC,EAC1B,aAAa,CAAC,OAAO,CAAC,EACtB,UAAU,IAAI,IAAI;YAChB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,sBAAsB,CAAC,UAAU,CAAC,EACtC,SAAS,CACV,EACD,KAAK,EAAE,WAAW,aAEjB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CACpB,kBAAQ,SAAS,EAAC,4EAA4E,aAC3F,OAAO,CAAC,CAAC,CAAC,CACT,KAAC,OAAO,IACN,SAAS,EAAC,qCAAqC,EAC/C,EAAE,EAAE,SAAS,YAEZ,OAAO,GACA,CACX,CAAC,CAAC,CAAC,IAAI,EAEP,OAAO,CAAC,CAAC,CAAC,CACT,cAAK,SAAS,EAAC,kCAAkC,YAC9C,OAAO,GACJ,CACP,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAC,CAAC,CAAC,IAAI,EAEP,QAAQ,EAER,MAAM,CAAC,CAAC,CAAC,CACR,iBAAQ,SAAS,EAAC,mEAAmE,YAClF,MAAM,GACA,CACV,CAAC,CAAC,CAAC,IAAI,IACA,CACX,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A coloured bar down a card's leading edge — and the reason it is
|
|
3
|
+
* a pseudo-element rather than a border.
|
|
4
|
+
*
|
|
5
|
+
* Three apps had grown this shape independently and all three drew
|
|
6
|
+
* it as a straight border beside a rounded box, so the bar ran past
|
|
7
|
+
* the curve and stopped square while the card it belonged to was
|
|
8
|
+
* round. Folio put `border-inline-start` on a WRAPPER around the
|
|
9
|
+
* card; mail-sifter puts `borderInlineStartWidth: 4` on a
|
|
10
|
+
* `rounded-xl` anchor; spoolbuddy writes `rounded-lg border-l-3`.
|
|
11
|
+
* A border is painted on the border box, so none of them can follow
|
|
12
|
+
* a corner — the notch is not a bug in any one app, it is what that
|
|
13
|
+
* technique does.
|
|
14
|
+
*
|
|
15
|
+
* A pseudo-element overlays the card and takes
|
|
16
|
+
* `border-radius: inherit`, so the bar follows whatever radius the
|
|
17
|
+
* card already has and nobody states a radius twice.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ **The shadow goes on the pseudo-element, never on the card.**
|
|
20
|
+
* `Card` carries `shadow-low` from the elevation scale, and an app
|
|
21
|
+
* stylesheet is unlayered while Tailwind's utilities sit in
|
|
22
|
+
* `@layer utilities` — so a `box-shadow` written at the call site
|
|
23
|
+
* outranks the utility and takes the card's elevation away with it.
|
|
24
|
+
* That is not hypothetical; it is the version of this fix that was
|
|
25
|
+
* written first.
|
|
26
|
+
*
|
|
27
|
+
* ⚠️ **Not a 3px-wide pseudo-element with a rounded leading edge.**
|
|
28
|
+
* A `border-radius` of `0.5rem` on a 3px-wide box is clamped by the
|
|
29
|
+
* browser to fit, so it caps the bar instead of following the
|
|
30
|
+
* card's curve.
|
|
31
|
+
*
|
|
32
|
+
* ⚠️ **`box-shadow` has no logical form**, so the offset is
|
|
33
|
+
* physical and the `rtl:` variant is what carries the bar to the
|
|
34
|
+
* other side. A single `inset 3px` would put it on the left of an
|
|
35
|
+
* Arabic page, which is the trailing edge there.
|
|
36
|
+
*/
|
|
37
|
+
import type { CategoricalIndex } from "@charcuterie/tokens";
|
|
38
|
+
/**
|
|
39
|
+
* Which colour the bar takes.
|
|
40
|
+
*
|
|
41
|
+
* Two arms, because the fleet has two answers and neither is wrong.
|
|
42
|
+
* Docket picks a **categorical index** — a colour a user chose for
|
|
43
|
+
* a project, from the ten-wide contrast-audited family. Folio and
|
|
44
|
+
* mail-sifter derive a **hue from a name hash**, so a repo added
|
|
45
|
+
* tomorrow already has a colour and nobody maintains a palette;
|
|
46
|
+
* that is 360 answers, not ten, and it cannot be an index.
|
|
47
|
+
*
|
|
48
|
+
* `intent` is deliberately absent. An intent is a claim the design
|
|
49
|
+
* system makes — `danger` says what happens if you press the thing
|
|
50
|
+
* — and no card in this fleet wants its edge to make one. When one
|
|
51
|
+
* does, that is a third arm and a decision record, not a guess
|
|
52
|
+
* made here.
|
|
53
|
+
*/
|
|
54
|
+
export type CardAccentEdge = {
|
|
55
|
+
categorical: CategoricalIndex;
|
|
56
|
+
color?: never;
|
|
57
|
+
} | {
|
|
58
|
+
categorical?: never;
|
|
59
|
+
color: string;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The custom property an explicit colour is threaded through.
|
|
63
|
+
*
|
|
64
|
+
* A property rather than an inline `box-shadow`, because the shadow
|
|
65
|
+
* string has to stay a COMPLETE literal in the source for Tailwind
|
|
66
|
+
* to generate it at all. One literal reading one variable covers
|
|
67
|
+
* every colour an app can compute; interpolating the colour into
|
|
68
|
+
* the class name would generate nothing, paint nothing, and report
|
|
69
|
+
* nothing.
|
|
70
|
+
*/
|
|
71
|
+
export declare const ACCENT_EDGE_COLOR_PROPERTY = "--charcuterie-accent-edge";
|
|
72
|
+
/**
|
|
73
|
+
* The overlay itself. Colour arrives separately.
|
|
74
|
+
*
|
|
75
|
+
* `pointer-events: none` is load-bearing rather than tidy: this box
|
|
76
|
+
* covers the whole card, including every link and button in it.
|
|
77
|
+
*/
|
|
78
|
+
export declare const ACCENT_EDGE_BASE_CLASS = "relative before:pointer-events-none before:absolute before:inset-0 before:rounded-[inherit] before:content-['']";
|
|
79
|
+
/**
|
|
80
|
+
* Ten indices, written out in full, for the reason
|
|
81
|
+
* `categoricalStyles.ts` opens with: Tailwind scans source text for
|
|
82
|
+
* COMPLETE class strings, so a template literal generates nothing
|
|
83
|
+
* at all and the bar renders invisible with no error and no failing
|
|
84
|
+
* test. `tailwindCandidates.test.ts` compiles every literal in this
|
|
85
|
+
* package through the real Tailwind, which is the something that
|
|
86
|
+
* checks.
|
|
87
|
+
*/
|
|
88
|
+
export declare const ACCENT_EDGE_CATEGORICAL_CLASS: Record<CategoricalIndex, string>;
|
|
89
|
+
/** The same bar, reading the caller's own colour. */
|
|
90
|
+
export declare const ACCENT_EDGE_COLOR_CLASS = "before:shadow-[inset_3px_0_0_var(--charcuterie-accent-edge)] rtl:before:shadow-[inset_-3px_0_0_var(--charcuterie-accent-edge)]";
|
|
91
|
+
export declare const getAccentEdgeClassName: (accentEdge: CardAccentEdge) => string;
|
|
92
|
+
/**
|
|
93
|
+
* The inline style an explicit colour needs, and nothing when the
|
|
94
|
+
* colour came from an index.
|
|
95
|
+
*
|
|
96
|
+
* Returns `undefined` rather than `{}` so a card with a categorical
|
|
97
|
+
* edge and no `style` of its own renders no `style` attribute at
|
|
98
|
+
* all.
|
|
99
|
+
*/
|
|
100
|
+
export declare const getAccentEdgeStyle: (accentEdge: CardAccentEdge) => Record<string, string> | undefined;
|
|
101
|
+
//# sourceMappingURL=cardAccentEdge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cardAccentEdge.d.ts","sourceRoot":"","sources":["../../src/Card/cardAccentEdge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,WAAW,EAAE,gBAAgB,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAChD;IAAE,WAAW,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1C;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,8BACV,CAAA;AAE7B;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,oHACgF,CAAA;AAEnH;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAChD,gBAAgB,EAChB,MAAM,CAYP,CAAA;AAED,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,mIAC8F,CAAA;AAElI,eAAO,MAAM,sBAAsB,GACjC,YAAY,cAAc,KACzB,MAOC,CAAA;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAC7B,YAAY,cAAc,KACzB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAG4B,CAAA"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A coloured bar down a card's leading edge — and the reason it is
|
|
3
|
+
* a pseudo-element rather than a border.
|
|
4
|
+
*
|
|
5
|
+
* Three apps had grown this shape independently and all three drew
|
|
6
|
+
* it as a straight border beside a rounded box, so the bar ran past
|
|
7
|
+
* the curve and stopped square while the card it belonged to was
|
|
8
|
+
* round. Folio put `border-inline-start` on a WRAPPER around the
|
|
9
|
+
* card; mail-sifter puts `borderInlineStartWidth: 4` on a
|
|
10
|
+
* `rounded-xl` anchor; spoolbuddy writes `rounded-lg border-l-3`.
|
|
11
|
+
* A border is painted on the border box, so none of them can follow
|
|
12
|
+
* a corner — the notch is not a bug in any one app, it is what that
|
|
13
|
+
* technique does.
|
|
14
|
+
*
|
|
15
|
+
* A pseudo-element overlays the card and takes
|
|
16
|
+
* `border-radius: inherit`, so the bar follows whatever radius the
|
|
17
|
+
* card already has and nobody states a radius twice.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ **The shadow goes on the pseudo-element, never on the card.**
|
|
20
|
+
* `Card` carries `shadow-low` from the elevation scale, and an app
|
|
21
|
+
* stylesheet is unlayered while Tailwind's utilities sit in
|
|
22
|
+
* `@layer utilities` — so a `box-shadow` written at the call site
|
|
23
|
+
* outranks the utility and takes the card's elevation away with it.
|
|
24
|
+
* That is not hypothetical; it is the version of this fix that was
|
|
25
|
+
* written first.
|
|
26
|
+
*
|
|
27
|
+
* ⚠️ **Not a 3px-wide pseudo-element with a rounded leading edge.**
|
|
28
|
+
* A `border-radius` of `0.5rem` on a 3px-wide box is clamped by the
|
|
29
|
+
* browser to fit, so it caps the bar instead of following the
|
|
30
|
+
* card's curve.
|
|
31
|
+
*
|
|
32
|
+
* ⚠️ **`box-shadow` has no logical form**, so the offset is
|
|
33
|
+
* physical and the `rtl:` variant is what carries the bar to the
|
|
34
|
+
* other side. A single `inset 3px` would put it on the left of an
|
|
35
|
+
* Arabic page, which is the trailing edge there.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* The custom property an explicit colour is threaded through.
|
|
39
|
+
*
|
|
40
|
+
* A property rather than an inline `box-shadow`, because the shadow
|
|
41
|
+
* string has to stay a COMPLETE literal in the source for Tailwind
|
|
42
|
+
* to generate it at all. One literal reading one variable covers
|
|
43
|
+
* every colour an app can compute; interpolating the colour into
|
|
44
|
+
* the class name would generate nothing, paint nothing, and report
|
|
45
|
+
* nothing.
|
|
46
|
+
*/
|
|
47
|
+
export const ACCENT_EDGE_COLOR_PROPERTY = "--charcuterie-accent-edge";
|
|
48
|
+
/**
|
|
49
|
+
* The overlay itself. Colour arrives separately.
|
|
50
|
+
*
|
|
51
|
+
* `pointer-events: none` is load-bearing rather than tidy: this box
|
|
52
|
+
* covers the whole card, including every link and button in it.
|
|
53
|
+
*/
|
|
54
|
+
export const ACCENT_EDGE_BASE_CLASS = "relative before:pointer-events-none before:absolute before:inset-0 before:rounded-[inherit] before:content-['']";
|
|
55
|
+
/**
|
|
56
|
+
* Ten indices, written out in full, for the reason
|
|
57
|
+
* `categoricalStyles.ts` opens with: Tailwind scans source text for
|
|
58
|
+
* COMPLETE class strings, so a template literal generates nothing
|
|
59
|
+
* at all and the bar renders invisible with no error and no failing
|
|
60
|
+
* test. `tailwindCandidates.test.ts` compiles every literal in this
|
|
61
|
+
* package through the real Tailwind, which is the something that
|
|
62
|
+
* checks.
|
|
63
|
+
*/
|
|
64
|
+
export const ACCENT_EDGE_CATEGORICAL_CLASS = {
|
|
65
|
+
1: "before:shadow-[inset_3px_0_0_var(--color-categorical-1-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-1-solid)]",
|
|
66
|
+
2: "before:shadow-[inset_3px_0_0_var(--color-categorical-2-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-2-solid)]",
|
|
67
|
+
3: "before:shadow-[inset_3px_0_0_var(--color-categorical-3-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-3-solid)]",
|
|
68
|
+
4: "before:shadow-[inset_3px_0_0_var(--color-categorical-4-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-4-solid)]",
|
|
69
|
+
5: "before:shadow-[inset_3px_0_0_var(--color-categorical-5-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-5-solid)]",
|
|
70
|
+
6: "before:shadow-[inset_3px_0_0_var(--color-categorical-6-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-6-solid)]",
|
|
71
|
+
7: "before:shadow-[inset_3px_0_0_var(--color-categorical-7-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-7-solid)]",
|
|
72
|
+
8: "before:shadow-[inset_3px_0_0_var(--color-categorical-8-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-8-solid)]",
|
|
73
|
+
9: "before:shadow-[inset_3px_0_0_var(--color-categorical-9-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-9-solid)]",
|
|
74
|
+
10: "before:shadow-[inset_3px_0_0_var(--color-categorical-10-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-10-solid)]",
|
|
75
|
+
};
|
|
76
|
+
/** The same bar, reading the caller's own colour. */
|
|
77
|
+
export const ACCENT_EDGE_COLOR_CLASS = "before:shadow-[inset_3px_0_0_var(--charcuterie-accent-edge)] rtl:before:shadow-[inset_-3px_0_0_var(--charcuterie-accent-edge)]";
|
|
78
|
+
export const getAccentEdgeClassName = (accentEdge) => `${ACCENT_EDGE_BASE_CLASS} ${accentEdge.categorical == null
|
|
79
|
+
? ACCENT_EDGE_COLOR_CLASS
|
|
80
|
+
: ACCENT_EDGE_CATEGORICAL_CLASS[accentEdge.categorical]}`;
|
|
81
|
+
/**
|
|
82
|
+
* The inline style an explicit colour needs, and nothing when the
|
|
83
|
+
* colour came from an index.
|
|
84
|
+
*
|
|
85
|
+
* Returns `undefined` rather than `{}` so a card with a categorical
|
|
86
|
+
* edge and no `style` of its own renders no `style` attribute at
|
|
87
|
+
* all.
|
|
88
|
+
*/
|
|
89
|
+
export const getAccentEdgeStyle = (accentEdge) => accentEdge.color == null
|
|
90
|
+
? undefined
|
|
91
|
+
: { [ACCENT_EDGE_COLOR_PROPERTY]: accentEdge.color };
|
|
92
|
+
//# sourceMappingURL=cardAccentEdge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cardAccentEdge.js","sourceRoot":"","sources":["../../src/Card/cardAccentEdge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAwBH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,0BAA0B,GACrC,2BAA2B,CAAA;AAE7B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GACjC,iHAAiH,CAAA;AAEnH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAGtC;IACF,CAAC,EAAE,oIAAoI;IACvI,CAAC,EAAE,oIAAoI;IACvI,CAAC,EAAE,oIAAoI;IACvI,CAAC,EAAE,oIAAoI;IACvI,CAAC,EAAE,oIAAoI;IACvI,CAAC,EAAE,oIAAoI;IACvI,CAAC,EAAE,oIAAoI;IACvI,CAAC,EAAE,oIAAoI;IACvI,CAAC,EAAE,oIAAoI;IACvI,EAAE,EAAE,sIAAsI;CAC3I,CAAA;AAED,qDAAqD;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAClC,gIAAgI,CAAA;AAElI,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,UAA0B,EAClB,EAAE,CACV,GAAG,sBAAsB,IACvB,UAAU,CAAC,WAAW,IAAI,IAAI;IAC5B,CAAC,CAAC,uBAAuB;IACzB,CAAC,CAAC,6BAA6B,CAC3B,UAAU,CAAC,WAAW,CAE9B,EAAE,CAAA;AAEJ;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,UAA0B,EACU,EAAE,CACtC,UAAU,CAAC,KAAK,IAAI,IAAI;IACtB,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,EAAE,CAAC,0BAA0B,CAAC,EAAE,UAAU,CAAC,KAAK,EAAE,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -57,6 +57,7 @@ export type { ButtonLinkProps } from "./ButtonLink/ButtonLink.tsx";
|
|
|
57
57
|
export { ButtonLink } from "./ButtonLink/ButtonLink.tsx";
|
|
58
58
|
export type { CardPadding, CardProps, CardSurface, } from "./Card/Card.tsx";
|
|
59
59
|
export { Card } from "./Card/Card.tsx";
|
|
60
|
+
export type { CardAccentEdge } from "./Card/cardAccentEdge.ts";
|
|
60
61
|
export type { CheckboxProps } from "./Checkbox/Checkbox.tsx";
|
|
61
62
|
export { Checkbox } from "./Checkbox/Checkbox.tsx";
|
|
62
63
|
export type { ColorSchemeSwitcherProps } from "./ColorSchemeSwitcher/ColorSchemeSwitcher.tsx";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAOH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA2B,CAAA;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAiC,CAAA;AAE9D,OAAO,EACL,aAAa,EACb,wBAAwB,EACxB,0BAA0B,EAC1B,iCAAiC,EACjC,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,iCAAiC,CAAA;AAKxC,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,sCAAsC,CAAA;AAK7C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAGzC,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAK3D,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AASzC,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,cAAc,GACf,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAqB,CAAA;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA6B,CAAA;AAMxD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/Card/Card.mdx
CHANGED
|
@@ -51,3 +51,24 @@ The header stacks below `--cq-sm` and sits on one row above it, and the containe
|
|
|
51
51
|
cannot tell apart, and it is where the fleet's poster grids look wrong today.
|
|
52
52
|
|
|
53
53
|
<Canvas of={CardStories.Responsive} />
|
|
54
|
+
|
|
55
|
+
## The accent edge follows the corner
|
|
56
|
+
|
|
57
|
+
`accentEdge` draws a coloured bar down the leading edge. `{ categorical: 3 }` is a colour a
|
|
58
|
+
user picked, from the ten-wide contrast-audited family; `{ color }` is one the app computed,
|
|
59
|
+
for the case where ten indices are not enough — Folio hashes a repo's name so a repo added
|
|
60
|
+
tomorrow already has a hue and nobody maintains a palette.
|
|
61
|
+
|
|
62
|
+
> **It is a pseudo-element, not a border, and that is the whole point.** Three apps grew this
|
|
63
|
+
> shape independently and all three drew a straight border beside a rounded box, so the bar
|
|
64
|
+
> ran past the curve and stopped square while the card was round. A border is painted on the
|
|
65
|
+
> border box; it cannot follow a corner. The overlay here takes `border-radius: inherit`, so
|
|
66
|
+
> the bar reads the radius off whatever card it is on and nobody states one twice.
|
|
67
|
+
|
|
68
|
+
Two shapes this deliberately is not. **Not `box-shadow: inset` on the card itself** — `Card`
|
|
69
|
+
carries `shadow-low` from the elevation scale, and a `box-shadow` at the call site outranks
|
|
70
|
+
that utility and takes the elevation with it. **Not a 3px-wide pseudo-element with a rounded
|
|
71
|
+
leading edge** — a `0.5rem` radius on a 3px box is clamped to fit, so it caps the bar instead
|
|
72
|
+
of following the curve.
|
|
73
|
+
|
|
74
|
+
<Canvas of={CardStories.AccentEdge} />
|
|
@@ -13,12 +13,18 @@ import { IconButton } from "../IconButton/IconButton.tsx"
|
|
|
13
13
|
import { SettingsIcon } from "../icons.storyHelpers.tsx"
|
|
14
14
|
import { ProgressBar } from "../ProgressBar/ProgressBar.tsx"
|
|
15
15
|
import { Card, ELEVATION_CLASS } from "./Card.tsx"
|
|
16
|
+
import { ACCENT_EDGE_CATEGORICAL_CLASS } from "./cardAccentEdge.ts"
|
|
16
17
|
|
|
17
18
|
const meta = {
|
|
18
19
|
title: "Components/Layout/Card",
|
|
19
20
|
component: Card,
|
|
20
21
|
parameters: { layout: "padded" },
|
|
21
22
|
argTypes: {
|
|
23
|
+
// An object union, so an object control is the right one — but
|
|
24
|
+
// it is stated rather than inferred, because docgen's fallback
|
|
25
|
+
// for a type it cannot read is also an object control and the
|
|
26
|
+
// two are indistinguishable in the panel.
|
|
27
|
+
accentEdge: { control: "object" },
|
|
22
28
|
elevation: toStoryChoice(
|
|
23
29
|
Object.keys(
|
|
24
30
|
ELEVATION_CLASS,
|
|
@@ -205,3 +211,88 @@ export const Interactive: Story = {
|
|
|
205
211
|
</div>
|
|
206
212
|
),
|
|
207
213
|
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* The leading edge, and the two answers the fleet has for what
|
|
217
|
+
* colour it is.
|
|
218
|
+
*
|
|
219
|
+
* A **categorical index** is a colour a user picked — Docket's
|
|
220
|
+
* project colours come from this ten-wide family, and every pair in
|
|
221
|
+
* it is contrast-audited. An explicit **colour** is one the app
|
|
222
|
+
* computed: Folio hashes a repo's name so a repo added tomorrow
|
|
223
|
+
* already has a hue and nobody maintains a palette, which is 360
|
|
224
|
+
* answers rather than ten.
|
|
225
|
+
*
|
|
226
|
+
* Both bars follow the card's own corner, because the treatment
|
|
227
|
+
* inherits its radius instead of naming one. Every app that grew
|
|
228
|
+
* this shape by hand drew it as a straight border beside a rounded
|
|
229
|
+
* box, and a border cannot follow a curve.
|
|
230
|
+
*/
|
|
231
|
+
export const AccentEdge: Story = {
|
|
232
|
+
args: { children: "Content" },
|
|
233
|
+
render: () => (
|
|
234
|
+
<StorySection title="A categorical index, and an app's own colour. Both take the card's radius.">
|
|
235
|
+
<StoryGrid columns={3}>
|
|
236
|
+
{(
|
|
237
|
+
Object.keys(
|
|
238
|
+
ACCENT_EDGE_CATEGORICAL_CLASS,
|
|
239
|
+
) as unknown as (keyof typeof ACCENT_EDGE_CATEGORICAL_CLASS)[]
|
|
240
|
+
).map((index) => (
|
|
241
|
+
<StoryCell
|
|
242
|
+
align="stretch"
|
|
243
|
+
key={index}
|
|
244
|
+
label={`categorical ${index}`}
|
|
245
|
+
>
|
|
246
|
+
<Card
|
|
247
|
+
accentEdge={{
|
|
248
|
+
categorical: Number(index) as 1,
|
|
249
|
+
}}
|
|
250
|
+
heading={`Project ${index}`}
|
|
251
|
+
>
|
|
252
|
+
<p className="text-content-secondary text-sm">
|
|
253
|
+
A colour the user picked.
|
|
254
|
+
</p>
|
|
255
|
+
</Card>
|
|
256
|
+
</StoryCell>
|
|
257
|
+
))}
|
|
258
|
+
|
|
259
|
+
<StoryCell align="stretch" label="a hashed hue">
|
|
260
|
+
<Card
|
|
261
|
+
accentEdge={{ color: "hsl(287 55% 52%)" }}
|
|
262
|
+
heading="home-assistant"
|
|
263
|
+
>
|
|
264
|
+
<p className="text-content-secondary text-sm">
|
|
265
|
+
A hue hashed from the name, not an index.
|
|
266
|
+
</p>
|
|
267
|
+
</Card>
|
|
268
|
+
</StoryCell>
|
|
269
|
+
|
|
270
|
+
<StoryCell
|
|
271
|
+
align="stretch"
|
|
272
|
+
label="a rounder card, same rule"
|
|
273
|
+
>
|
|
274
|
+
<Card
|
|
275
|
+
accentEdge={{ color: "hsl(24 55% 52%)" }}
|
|
276
|
+
className="rounded-3xl"
|
|
277
|
+
heading="A wider radius"
|
|
278
|
+
>
|
|
279
|
+
<p className="text-content-secondary text-sm">
|
|
280
|
+
The bar reads the radius off the card rather
|
|
281
|
+
than naming one, so an override still lines
|
|
282
|
+
up.
|
|
283
|
+
</p>
|
|
284
|
+
</Card>
|
|
285
|
+
</StoryCell>
|
|
286
|
+
|
|
287
|
+
<StoryCell align="stretch" label="a link inside it">
|
|
288
|
+
<Card
|
|
289
|
+
accentEdge={{ categorical: 4 }}
|
|
290
|
+
heading="Still clickable"
|
|
291
|
+
>
|
|
292
|
+
<Button size="sm">Open</Button>
|
|
293
|
+
</Card>
|
|
294
|
+
</StoryCell>
|
|
295
|
+
</StoryGrid>
|
|
296
|
+
</StorySection>
|
|
297
|
+
),
|
|
298
|
+
}
|
package/src/Card/Card.test.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import { mountStory } from "../mountStory.testHelpers.ts"
|
|
|
6
6
|
import { expectAgentDrivable } from "../testing/index.ts"
|
|
7
7
|
import * as stories from "./Card.stories.tsx"
|
|
8
8
|
|
|
9
|
-
const { AllStates, Default, Interactive } =
|
|
9
|
+
const { AccentEdge, AllStates, Default, Interactive } =
|
|
10
10
|
composeStories(stories)
|
|
11
11
|
|
|
12
12
|
test("a heading turns the card into a named landmark", async () => {
|
|
@@ -54,3 +54,94 @@ test("region scoping disambiguates two identical buttons", async () => {
|
|
|
54
54
|
}),
|
|
55
55
|
).toHaveAttribute("aria-valuenow", "40")
|
|
56
56
|
})
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The bar overlays the entire card, links and buttons included, so
|
|
60
|
+
* `pointer-events: none` on it is the difference between a card you
|
|
61
|
+
* can use and one that swallows every click. Driven, not asserted
|
|
62
|
+
* off a class name — the class is what the fix looks like, and this
|
|
63
|
+
* is what it is for.
|
|
64
|
+
*/
|
|
65
|
+
test("the accent edge does not swallow a click", async () => {
|
|
66
|
+
const { canvas } = await mountStory(AccentEdge)
|
|
67
|
+
|
|
68
|
+
const open = expectAgentDrivable(canvas, {
|
|
69
|
+
name: "Open",
|
|
70
|
+
role: "button",
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
let isClicked = false
|
|
74
|
+
|
|
75
|
+
open.addEventListener("click", () => {
|
|
76
|
+
isClicked = true
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
open.click()
|
|
80
|
+
|
|
81
|
+
await expect(isClicked).toBe(true)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
const readRadius = (card: Element, isBar: boolean) =>
|
|
85
|
+
globalThis.getComputedStyle(
|
|
86
|
+
card,
|
|
87
|
+
isBar ? "::before" : undefined,
|
|
88
|
+
).borderTopLeftRadius
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The radius is INHERITED rather than restated, which is what lets
|
|
92
|
+
* one treatment sit on `rounded-lg`, on `rounded-3xl`, and on
|
|
93
|
+
* whatever an app overrides it to. Computed styles, because a class
|
|
94
|
+
* name is the thing that can be right while the paint is wrong.
|
|
95
|
+
*/
|
|
96
|
+
test("the bar takes the card's own radius, whatever it is", async () => {
|
|
97
|
+
const { canvas } = await mountStory(AccentEdge)
|
|
98
|
+
|
|
99
|
+
const wider = expectAgentDrivable(canvas, {
|
|
100
|
+
name: "A wider radius",
|
|
101
|
+
role: "region",
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const stock = expectAgentDrivable(canvas, {
|
|
105
|
+
name: "Project 1",
|
|
106
|
+
role: "region",
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
await expect(readRadius(wider, true)).toBe(
|
|
110
|
+
readRadius(wider, false),
|
|
111
|
+
)
|
|
112
|
+
await expect(readRadius(stock, true)).toBe(
|
|
113
|
+
readRadius(stock, false),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
// And the two cards genuinely differ, or the assertions above
|
|
117
|
+
// would pass on a component that hardcoded one radius.
|
|
118
|
+
await expect(readRadius(wider, false)).not.toBe(
|
|
119
|
+
readRadius(stock, false),
|
|
120
|
+
)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* `Card` carries `shadow-low`. The accent edge is a second shadow,
|
|
125
|
+
* and the first version of this fix wrote it onto the card itself —
|
|
126
|
+
* where an unlayered rule outranks the utility and the elevation
|
|
127
|
+
* silently goes away.
|
|
128
|
+
*/
|
|
129
|
+
test("the accent edge leaves the card's elevation alone", async () => {
|
|
130
|
+
const { canvas } = await mountStory(AccentEdge)
|
|
131
|
+
|
|
132
|
+
const card = expectAgentDrivable(canvas, {
|
|
133
|
+
name: "Project 1",
|
|
134
|
+
role: "region",
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
const cardShadow =
|
|
138
|
+
globalThis.getComputedStyle(card).boxShadow
|
|
139
|
+
const barShadow = globalThis.getComputedStyle(
|
|
140
|
+
card,
|
|
141
|
+
"::before",
|
|
142
|
+
).boxShadow
|
|
143
|
+
|
|
144
|
+
await expect(cardShadow).not.toBe("none")
|
|
145
|
+
await expect(cardShadow).not.toContain("inset")
|
|
146
|
+
await expect(barShadow).toContain("inset")
|
|
147
|
+
})
|
package/src/Card/Card.tsx
CHANGED
|
@@ -9,6 +9,11 @@ import type {
|
|
|
9
9
|
} from "react"
|
|
10
10
|
|
|
11
11
|
import { toClassName } from "../toClassName.ts"
|
|
12
|
+
import type { CardAccentEdge } from "./cardAccentEdge.ts"
|
|
13
|
+
import {
|
|
14
|
+
getAccentEdgeClassName,
|
|
15
|
+
getAccentEdgeStyle,
|
|
16
|
+
} from "./cardAccentEdge.ts"
|
|
12
17
|
|
|
13
18
|
export type CardSurface = Extract<
|
|
14
19
|
SurfaceRole,
|
|
@@ -18,6 +23,16 @@ export type CardSurface = Extract<
|
|
|
18
23
|
export type CardPadding = "lg" | "md" | "none" | "sm"
|
|
19
24
|
|
|
20
25
|
export type CardProps = ComponentPropsWithRef<"section"> & {
|
|
26
|
+
/**
|
|
27
|
+
* A coloured bar down the leading edge, following the card's own
|
|
28
|
+
* corners.
|
|
29
|
+
*
|
|
30
|
+
* `{ categorical: 3 }` for a colour a user picked; `{ color }`
|
|
31
|
+
* for one an app computed — a hue hashed from a repo's name, say,
|
|
32
|
+
* where ten indices are not enough. See `cardAccentEdge.ts` for
|
|
33
|
+
* why it is a pseudo-element and not a border.
|
|
34
|
+
*/
|
|
35
|
+
accentEdge?: CardAccentEdge
|
|
21
36
|
/** Buttons or a badge, laid out beside the heading. */
|
|
22
37
|
actions?: ReactNode
|
|
23
38
|
elevation?: ElevationStep
|
|
@@ -79,6 +94,7 @@ const PADDING_CLASS: Record<CardPadding, string> = {
|
|
|
79
94
|
* a layout fact rather than a density one.
|
|
80
95
|
*/
|
|
81
96
|
export const Card = ({
|
|
97
|
+
accentEdge,
|
|
82
98
|
actions,
|
|
83
99
|
children,
|
|
84
100
|
className,
|
|
@@ -87,11 +103,25 @@ export const Card = ({
|
|
|
87
103
|
heading,
|
|
88
104
|
headingLevel = 2,
|
|
89
105
|
padding = "md",
|
|
106
|
+
style,
|
|
90
107
|
surface = "raised",
|
|
91
108
|
...sectionProps
|
|
92
109
|
}: CardProps): ReactNode => {
|
|
93
110
|
const headingId = useUniqueId()
|
|
94
111
|
|
|
112
|
+
// The caller's own `style` wins. An accent colour is one custom
|
|
113
|
+
// property, and silently dropping whatever else the call site set
|
|
114
|
+
// would be a worse trade than letting it override this one.
|
|
115
|
+
const accentEdgeStyle =
|
|
116
|
+
accentEdge == null
|
|
117
|
+
? undefined
|
|
118
|
+
: getAccentEdgeStyle(accentEdge)
|
|
119
|
+
|
|
120
|
+
const mergedStyle =
|
|
121
|
+
accentEdgeStyle == null
|
|
122
|
+
? style
|
|
123
|
+
: { ...accentEdgeStyle, ...style }
|
|
124
|
+
|
|
95
125
|
const Heading = `h${headingLevel}` as const
|
|
96
126
|
|
|
97
127
|
return (
|
|
@@ -108,8 +138,12 @@ export const Card = ({
|
|
|
108
138
|
SURFACE_CLASS[surface],
|
|
109
139
|
ELEVATION_CLASS[elevation],
|
|
110
140
|
PADDING_CLASS[padding],
|
|
141
|
+
accentEdge == null
|
|
142
|
+
? undefined
|
|
143
|
+
: getAccentEdgeClassName(accentEdge),
|
|
111
144
|
className,
|
|
112
145
|
)}
|
|
146
|
+
style={mergedStyle}
|
|
113
147
|
>
|
|
114
148
|
{heading || actions ? (
|
|
115
149
|
<header className="flex flex-col gap-2 cq-sm:flex-row cq-sm:items-start cq-sm:justify-between">
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ACCENT_EDGE_BASE_CLASS,
|
|
5
|
+
ACCENT_EDGE_CATEGORICAL_CLASS,
|
|
6
|
+
ACCENT_EDGE_COLOR_CLASS,
|
|
7
|
+
ACCENT_EDGE_COLOR_PROPERTY,
|
|
8
|
+
getAccentEdgeClassName,
|
|
9
|
+
getAccentEdgeStyle,
|
|
10
|
+
} from "./cardAccentEdge.ts"
|
|
11
|
+
|
|
12
|
+
describe("getAccentEdgeClassName", () => {
|
|
13
|
+
test("reads a categorical index off the ten-wide family", () => {
|
|
14
|
+
const className = getAccentEdgeClassName({
|
|
15
|
+
categorical: 3,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
expect(className).toContain(ACCENT_EDGE_BASE_CLASS)
|
|
19
|
+
expect(className).toContain(
|
|
20
|
+
ACCENT_EDGE_CATEGORICAL_CLASS[3],
|
|
21
|
+
)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test("threads an app's own colour through one literal", () => {
|
|
25
|
+
const className = getAccentEdgeClassName({
|
|
26
|
+
color: "hsl(210 55% 52%)",
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
expect(className).toContain(ACCENT_EDGE_BASE_CLASS)
|
|
30
|
+
expect(className).toContain(ACCENT_EDGE_COLOR_CLASS)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The bar overlays the whole card, links and buttons included, so
|
|
35
|
+
* this is the difference between a card you can click and one you
|
|
36
|
+
* cannot.
|
|
37
|
+
*/
|
|
38
|
+
test("never eats a pointer", () => {
|
|
39
|
+
expect(
|
|
40
|
+
getAccentEdgeClassName({ categorical: 1 }),
|
|
41
|
+
).toContain("before:pointer-events-none")
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The card already has a radius; the bar must not restate it.
|
|
46
|
+
* `inherit` is what makes one component work on `rounded-lg`,
|
|
47
|
+
* `rounded-xl` and whatever an app overrides it to.
|
|
48
|
+
*/
|
|
49
|
+
test("takes the card's own radius rather than naming one", () => {
|
|
50
|
+
expect(
|
|
51
|
+
getAccentEdgeClassName({ categorical: 1 }),
|
|
52
|
+
).toContain("before:rounded-[inherit]")
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* `box-shadow` has no logical form. Without the `rtl:` twin the
|
|
57
|
+
* bar sits on the left of an Arabic page, which is the trailing
|
|
58
|
+
* edge there.
|
|
59
|
+
*/
|
|
60
|
+
test("carries the bar to the other side under rtl", () => {
|
|
61
|
+
for (const className of [
|
|
62
|
+
...Object.values(ACCENT_EDGE_CATEGORICAL_CLASS),
|
|
63
|
+
ACCENT_EDGE_COLOR_CLASS,
|
|
64
|
+
]) {
|
|
65
|
+
expect(className).toContain("rtl:before:shadow-")
|
|
66
|
+
expect(className).toContain("inset_-3px")
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Tailwind scans source text for COMPLETE class strings, so an
|
|
72
|
+
* interpolated index generates nothing, paints nothing and
|
|
73
|
+
* reports nothing. This is the cheap half of that guarantee;
|
|
74
|
+
* `tailwindCandidates.test.ts` is the half that compiles them.
|
|
75
|
+
*/
|
|
76
|
+
test("names every categorical index in full", () => {
|
|
77
|
+
for (const [index, className] of Object.entries(
|
|
78
|
+
ACCENT_EDGE_CATEGORICAL_CLASS,
|
|
79
|
+
)) {
|
|
80
|
+
expect(className).toContain(
|
|
81
|
+
`var(--color-categorical-${index}-solid)`,
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
describe("getAccentEdgeStyle", () => {
|
|
88
|
+
test("writes one custom property for an app's own colour", () => {
|
|
89
|
+
expect(
|
|
90
|
+
getAccentEdgeStyle({ color: "hsl(210 55% 52%)" }),
|
|
91
|
+
).toStrictEqual({
|
|
92
|
+
[ACCENT_EDGE_COLOR_PROPERTY]: "hsl(210 55% 52%)",
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* `undefined`, not `{}`, so a categorical card renders no `style`
|
|
98
|
+
* attribute at all.
|
|
99
|
+
*/
|
|
100
|
+
test("writes nothing when the colour came from an index", () => {
|
|
101
|
+
expect(
|
|
102
|
+
getAccentEdgeStyle({ categorical: 7 }),
|
|
103
|
+
).toBeUndefined()
|
|
104
|
+
})
|
|
105
|
+
})
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A coloured bar down a card's leading edge — and the reason it is
|
|
3
|
+
* a pseudo-element rather than a border.
|
|
4
|
+
*
|
|
5
|
+
* Three apps had grown this shape independently and all three drew
|
|
6
|
+
* it as a straight border beside a rounded box, so the bar ran past
|
|
7
|
+
* the curve and stopped square while the card it belonged to was
|
|
8
|
+
* round. Folio put `border-inline-start` on a WRAPPER around the
|
|
9
|
+
* card; mail-sifter puts `borderInlineStartWidth: 4` on a
|
|
10
|
+
* `rounded-xl` anchor; spoolbuddy writes `rounded-lg border-l-3`.
|
|
11
|
+
* A border is painted on the border box, so none of them can follow
|
|
12
|
+
* a corner — the notch is not a bug in any one app, it is what that
|
|
13
|
+
* technique does.
|
|
14
|
+
*
|
|
15
|
+
* A pseudo-element overlays the card and takes
|
|
16
|
+
* `border-radius: inherit`, so the bar follows whatever radius the
|
|
17
|
+
* card already has and nobody states a radius twice.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ **The shadow goes on the pseudo-element, never on the card.**
|
|
20
|
+
* `Card` carries `shadow-low` from the elevation scale, and an app
|
|
21
|
+
* stylesheet is unlayered while Tailwind's utilities sit in
|
|
22
|
+
* `@layer utilities` — so a `box-shadow` written at the call site
|
|
23
|
+
* outranks the utility and takes the card's elevation away with it.
|
|
24
|
+
* That is not hypothetical; it is the version of this fix that was
|
|
25
|
+
* written first.
|
|
26
|
+
*
|
|
27
|
+
* ⚠️ **Not a 3px-wide pseudo-element with a rounded leading edge.**
|
|
28
|
+
* A `border-radius` of `0.5rem` on a 3px-wide box is clamped by the
|
|
29
|
+
* browser to fit, so it caps the bar instead of following the
|
|
30
|
+
* card's curve.
|
|
31
|
+
*
|
|
32
|
+
* ⚠️ **`box-shadow` has no logical form**, so the offset is
|
|
33
|
+
* physical and the `rtl:` variant is what carries the bar to the
|
|
34
|
+
* other side. A single `inset 3px` would put it on the left of an
|
|
35
|
+
* Arabic page, which is the trailing edge there.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import type { CategoricalIndex } from "@charcuterie/tokens"
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Which colour the bar takes.
|
|
42
|
+
*
|
|
43
|
+
* Two arms, because the fleet has two answers and neither is wrong.
|
|
44
|
+
* Docket picks a **categorical index** — a colour a user chose for
|
|
45
|
+
* a project, from the ten-wide contrast-audited family. Folio and
|
|
46
|
+
* mail-sifter derive a **hue from a name hash**, so a repo added
|
|
47
|
+
* tomorrow already has a colour and nobody maintains a palette;
|
|
48
|
+
* that is 360 answers, not ten, and it cannot be an index.
|
|
49
|
+
*
|
|
50
|
+
* `intent` is deliberately absent. An intent is a claim the design
|
|
51
|
+
* system makes — `danger` says what happens if you press the thing
|
|
52
|
+
* — and no card in this fleet wants its edge to make one. When one
|
|
53
|
+
* does, that is a third arm and a decision record, not a guess
|
|
54
|
+
* made here.
|
|
55
|
+
*/
|
|
56
|
+
export type CardAccentEdge =
|
|
57
|
+
| { categorical: CategoricalIndex; color?: never }
|
|
58
|
+
| { categorical?: never; color: string }
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The custom property an explicit colour is threaded through.
|
|
62
|
+
*
|
|
63
|
+
* A property rather than an inline `box-shadow`, because the shadow
|
|
64
|
+
* string has to stay a COMPLETE literal in the source for Tailwind
|
|
65
|
+
* to generate it at all. One literal reading one variable covers
|
|
66
|
+
* every colour an app can compute; interpolating the colour into
|
|
67
|
+
* the class name would generate nothing, paint nothing, and report
|
|
68
|
+
* nothing.
|
|
69
|
+
*/
|
|
70
|
+
export const ACCENT_EDGE_COLOR_PROPERTY =
|
|
71
|
+
"--charcuterie-accent-edge"
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The overlay itself. Colour arrives separately.
|
|
75
|
+
*
|
|
76
|
+
* `pointer-events: none` is load-bearing rather than tidy: this box
|
|
77
|
+
* covers the whole card, including every link and button in it.
|
|
78
|
+
*/
|
|
79
|
+
export const ACCENT_EDGE_BASE_CLASS =
|
|
80
|
+
"relative before:pointer-events-none before:absolute before:inset-0 before:rounded-[inherit] before:content-['']"
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Ten indices, written out in full, for the reason
|
|
84
|
+
* `categoricalStyles.ts` opens with: Tailwind scans source text for
|
|
85
|
+
* COMPLETE class strings, so a template literal generates nothing
|
|
86
|
+
* at all and the bar renders invisible with no error and no failing
|
|
87
|
+
* test. `tailwindCandidates.test.ts` compiles every literal in this
|
|
88
|
+
* package through the real Tailwind, which is the something that
|
|
89
|
+
* checks.
|
|
90
|
+
*/
|
|
91
|
+
export const ACCENT_EDGE_CATEGORICAL_CLASS: Record<
|
|
92
|
+
CategoricalIndex,
|
|
93
|
+
string
|
|
94
|
+
> = {
|
|
95
|
+
1: "before:shadow-[inset_3px_0_0_var(--color-categorical-1-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-1-solid)]",
|
|
96
|
+
2: "before:shadow-[inset_3px_0_0_var(--color-categorical-2-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-2-solid)]",
|
|
97
|
+
3: "before:shadow-[inset_3px_0_0_var(--color-categorical-3-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-3-solid)]",
|
|
98
|
+
4: "before:shadow-[inset_3px_0_0_var(--color-categorical-4-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-4-solid)]",
|
|
99
|
+
5: "before:shadow-[inset_3px_0_0_var(--color-categorical-5-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-5-solid)]",
|
|
100
|
+
6: "before:shadow-[inset_3px_0_0_var(--color-categorical-6-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-6-solid)]",
|
|
101
|
+
7: "before:shadow-[inset_3px_0_0_var(--color-categorical-7-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-7-solid)]",
|
|
102
|
+
8: "before:shadow-[inset_3px_0_0_var(--color-categorical-8-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-8-solid)]",
|
|
103
|
+
9: "before:shadow-[inset_3px_0_0_var(--color-categorical-9-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-9-solid)]",
|
|
104
|
+
10: "before:shadow-[inset_3px_0_0_var(--color-categorical-10-solid)] rtl:before:shadow-[inset_-3px_0_0_var(--color-categorical-10-solid)]",
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** The same bar, reading the caller's own colour. */
|
|
108
|
+
export const ACCENT_EDGE_COLOR_CLASS =
|
|
109
|
+
"before:shadow-[inset_3px_0_0_var(--charcuterie-accent-edge)] rtl:before:shadow-[inset_-3px_0_0_var(--charcuterie-accent-edge)]"
|
|
110
|
+
|
|
111
|
+
export const getAccentEdgeClassName = (
|
|
112
|
+
accentEdge: CardAccentEdge,
|
|
113
|
+
): string =>
|
|
114
|
+
`${ACCENT_EDGE_BASE_CLASS} ${
|
|
115
|
+
accentEdge.categorical == null
|
|
116
|
+
? ACCENT_EDGE_COLOR_CLASS
|
|
117
|
+
: ACCENT_EDGE_CATEGORICAL_CLASS[
|
|
118
|
+
accentEdge.categorical
|
|
119
|
+
]
|
|
120
|
+
}`
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The inline style an explicit colour needs, and nothing when the
|
|
124
|
+
* colour came from an index.
|
|
125
|
+
*
|
|
126
|
+
* Returns `undefined` rather than `{}` so a card with a categorical
|
|
127
|
+
* edge and no `style` of its own renders no `style` attribute at
|
|
128
|
+
* all.
|
|
129
|
+
*/
|
|
130
|
+
export const getAccentEdgeStyle = (
|
|
131
|
+
accentEdge: CardAccentEdge,
|
|
132
|
+
): Record<string, string> | undefined =>
|
|
133
|
+
accentEdge.color == null
|
|
134
|
+
? undefined
|
|
135
|
+
: { [ACCENT_EDGE_COLOR_PROPERTY]: accentEdge.color }
|
package/src/index.ts
CHANGED
|
@@ -98,6 +98,7 @@ export type {
|
|
|
98
98
|
CardSurface,
|
|
99
99
|
} from "./Card/Card.tsx"
|
|
100
100
|
export { Card } from "./Card/Card.tsx"
|
|
101
|
+
export type { CardAccentEdge } from "./Card/cardAccentEdge.ts"
|
|
101
102
|
export type { CheckboxProps } from "./Checkbox/Checkbox.tsx"
|
|
102
103
|
export { Checkbox } from "./Checkbox/Checkbox.tsx"
|
|
103
104
|
export type { ColorSchemeSwitcherProps } from "./ColorSchemeSwitcher/ColorSchemeSwitcher.tsx"
|