@cloudgrid-io/ui 0.18.1 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/blocks/compare-table.d.ts.map +1 -1
  2. package/dist/blocks/compare-table.js +10 -8
  3. package/dist/blocks/compare-table.js.map +1 -1
  4. package/dist/blocks/drop-zone.js +2 -2
  5. package/dist/blocks/drop-zone.js.map +1 -1
  6. package/dist/blocks/entity-card.d.ts +190 -13
  7. package/dist/blocks/entity-card.d.ts.map +1 -1
  8. package/dist/blocks/entity-card.js +223 -52
  9. package/dist/blocks/entity-card.js.map +1 -1
  10. package/dist/blocks/eyebrow.d.ts +43 -0
  11. package/dist/blocks/eyebrow.d.ts.map +1 -0
  12. package/dist/blocks/eyebrow.js +53 -0
  13. package/dist/blocks/eyebrow.js.map +1 -0
  14. package/dist/blocks/feature-cells.d.ts +12 -7
  15. package/dist/blocks/feature-cells.d.ts.map +1 -1
  16. package/dist/blocks/feature-cells.js +11 -11
  17. package/dist/blocks/feature-cells.js.map +1 -1
  18. package/dist/blocks/icons.d.ts +68 -10
  19. package/dist/blocks/icons.d.ts.map +1 -1
  20. package/dist/blocks/icons.js +68 -10
  21. package/dist/blocks/icons.js.map +1 -1
  22. package/dist/blocks/onboarding-question.js +2 -2
  23. package/dist/blocks/onboarding-question.js.map +1 -1
  24. package/dist/blocks/page-heading.d.ts +5 -0
  25. package/dist/blocks/page-heading.d.ts.map +1 -1
  26. package/dist/blocks/page-heading.js +7 -1
  27. package/dist/blocks/page-heading.js.map +1 -1
  28. package/dist/blocks/phosphor-marks.d.ts +99 -22
  29. package/dist/blocks/phosphor-marks.d.ts.map +1 -1
  30. package/dist/blocks/phosphor-marks.js +155 -25
  31. package/dist/blocks/phosphor-marks.js.map +1 -1
  32. package/dist/blocks/pricing-tier-cards.d.ts +6 -3
  33. package/dist/blocks/pricing-tier-cards.d.ts.map +1 -1
  34. package/dist/blocks/pricing-tier-cards.js +2 -2
  35. package/dist/blocks/pricing-tier-cards.js.map +1 -1
  36. package/dist/blocks/token-specimen.d.ts +59 -0
  37. package/dist/blocks/token-specimen.d.ts.map +1 -0
  38. package/dist/blocks/token-specimen.js +61 -0
  39. package/dist/blocks/token-specimen.js.map +1 -0
  40. package/dist/index.d.ts +2 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +2 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/ui/accordion.d.ts.map +1 -1
  45. package/dist/ui/accordion.js +2 -2
  46. package/dist/ui/accordion.js.map +1 -1
  47. package/dist/ui/badge.d.ts +1 -1
  48. package/dist/ui/button.d.ts +1 -1
  49. package/dist/ui/checkbox.d.ts.map +1 -1
  50. package/dist/ui/checkbox.js +2 -2
  51. package/dist/ui/checkbox.js.map +1 -1
  52. package/dist/ui/code-block.js +1 -1
  53. package/dist/ui/code-block.js.map +1 -1
  54. package/dist/ui/combobox.js +3 -3
  55. package/dist/ui/combobox.js.map +1 -1
  56. package/dist/ui/dialog.d.ts.map +1 -1
  57. package/dist/ui/dialog.js +2 -2
  58. package/dist/ui/dialog.js.map +1 -1
  59. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  60. package/dist/ui/dropdown-menu.js +1 -1
  61. package/dist/ui/dropdown-menu.js.map +1 -1
  62. package/dist/ui/number-field.js +1 -1
  63. package/dist/ui/number-field.js.map +1 -1
  64. package/dist/ui/select.d.ts.map +1 -1
  65. package/dist/ui/select.js +1 -1
  66. package/dist/ui/select.js.map +1 -1
  67. package/dist/ui/sonner.js +5 -5
  68. package/dist/ui/sonner.js.map +1 -1
  69. package/package.json +1 -2
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Card } from "../ui/card.js";
3
3
  import { EntityIdentity } from "./entity-identity.js";
4
- import { KindAgentIcon, KindAppIcon, KindInspirationIcon, OpenLiveIcon, SettingsIcon, } from "./icons.js";
4
+ import { EntityDashboardIcon, KindAgentIcon, KindAppIcon, KindInspirationIcon, OpenLiveIcon, } from "./icons.js";
5
5
  import { cn } from "../lib/cloudgrid-cn.js";
6
6
  /**
7
7
  * What an entity IS. Three kinds, and they are the product's, not this file's:
@@ -34,6 +34,75 @@ export const ENTITY_KIND_LABEL = {
34
34
  inspiration: "Inspiration",
35
35
  app: "App",
36
36
  };
37
+ /**
38
+ * The sizes, in the order they get smaller. Read from the console census
39
+ * (2026-09-08) rather than invented: `default` is the 360px track, `compact`
40
+ * covers the 260 and 280 ones, `row` is the list surfaces, the rails and the
41
+ * sidebar.
42
+ *
43
+ * The array is the source and the type is derived from it, the same arrangement
44
+ * `ENTITY_KIND_ORDER` uses: a size added here is immediately missing from
45
+ * `SIZE_STYLE` and typecheck says so.
46
+ */
47
+ export const ENTITY_CARD_SIZE_ORDER = ["default", "compact", "row"];
48
+ /**
49
+ * WHAT EACH SIZE CHANGES, in one table.
50
+ *
51
+ * Every entry is a type or spacing utility, never a colour: a size is a
52
+ * measurement, and a card that changed hue when it got smaller would be a
53
+ * second design rather than the same one at another scale. That is also what
54
+ * keeps the literals gate honest here — there is nothing in this table a token
55
+ * does not already own.
56
+ *
57
+ * It is a table rather than a run of ternaries at the call sites because the
58
+ * whole point of the axis is that the sizes stay comparable. Three ternaries in
59
+ * three places is how one of them silently stops matching the other two.
60
+ *
61
+ * `row` builds its own composition below, so its `stats`, `reveal` and
62
+ * `revealTitle` entries are empty: a row has no stat rule and no reveal panel.
63
+ * They are present rather than omitted so the record stays total and a fourth
64
+ * size cannot be half-added.
65
+ */
66
+ const SIZE_STYLE = {
67
+ default: {
68
+ cardSpacing: "",
69
+ body: "gap-3",
70
+ title: "text-body-sm",
71
+ description: "text-body-sm",
72
+ stats: "gap-4 pt-3",
73
+ reveal: "gap-1.5 p-3",
74
+ revealTitle: "text-body-sm",
75
+ },
76
+ compact: {
77
+ cardSpacing: "[--card-spacing:--spacing(3)]",
78
+ body: "gap-2",
79
+ title: "text-caption",
80
+ description: "text-caption",
81
+ stats: "gap-3 pt-2",
82
+ reveal: "gap-1 p-2",
83
+ revealTitle: "text-caption",
84
+ },
85
+ row: {
86
+ cardSpacing: "[--card-spacing:--spacing(3)]",
87
+ body: "gap-0.5",
88
+ title: "text-body-sm",
89
+ description: "text-caption",
90
+ stats: "",
91
+ reveal: "",
92
+ revealTitle: "",
93
+ },
94
+ };
95
+ /**
96
+ * The row thumbnail's width. Fixed rather than a fraction, so every row in a
97
+ * list starts its text at the same x — which is what makes a list of these
98
+ * scannable, and what a percentage width would lose the moment the column
99
+ * resized.
100
+ *
101
+ * 128px against the 1200/630 ratio is a 67px picture, so a row is a little over
102
+ * 90px tall with its padding. A 28px kind badge would cover a fifth of that
103
+ * thumbnail, which is why the row uses the small one.
104
+ */
105
+ const ROW_THUMBNAIL = "w-32";
37
106
  /**
38
107
  * Make a caller's URL safe to sit inside a CSS `url("…")` string — and nothing
39
108
  * more than that.
@@ -95,16 +164,159 @@ function EntityKindBadge({ kind, size = "md", className, ...props }) {
95
164
  border: "1px solid color-mix(in srgb, var(--cg-ink) 12%, transparent)",
96
165
  }, ...props, children: [_jsx(Icon, { className: size === "md" ? "size-4" : "size-3.5" }), _jsx("span", { className: "sr-only", children: ENTITY_KIND_LABEL[kind] })] }));
97
166
  }
98
- function EntityCard({ title, slug, description, titleLines = 2, descriptionLines = 1, status, stats, seed, previewUrl, kind, reveal = false, settingsHref, creator, href, ariaLabel, meta, footer, className, children, ...props }) {
167
+ function EntityCard({ title, slug, description, size = "default", titleLines = 2, descriptionLines = 1, status, headerActions, stats, seed, previewUrl, kind, reveal = false, dashboardHref, settingsHref, creator, href, ariaLabel, meta, footer, className, children, ...props }) {
168
+ const sized = SIZE_STYLE[size];
99
169
  // The reveal owns the preview and spends the `href`, so it only exists when
100
170
  // both are there. Asked for without a `seed` it would be a panel over nothing;
101
171
  // asked for without an `href` its Open action would be an anchor with no
102
172
  // target, which renders as a link, is not focusable, and does nothing when
103
173
  // clicked. Silently off in both cases rather than half-built.
104
- const revealed = reveal && Boolean(seed) && Boolean(href);
174
+ //
175
+ // A `row` never reveals, whatever the caller passed. Not a limitation: the row
176
+ // already shows everything the panel carries, so there is nothing to reveal —
177
+ // see the size note at the top. Its two actions are rendered at the end of the
178
+ // row and appear on hover, which is the half of the behaviour that survives.
179
+ const revealed = reveal && Boolean(seed) && Boolean(href) && size !== "row";
180
+ // One target, two prop names, for one minor. `settingsHref` is the old name
181
+ // (#182 renamed the action to Dashboard, because the console page it opens is
182
+ // a dashboard and not a settings screen), and it is resolved here rather than
183
+ // at the render site so there is exactly one place the alias exists and one
184
+ // place to delete when it goes. `??`, not `||`: an empty string is a caller
185
+ // saying "no target", and coalescing it to the deprecated name would resurrect
186
+ // a link the caller had switched off.
187
+ const dashboardTarget = dashboardHref ?? settingsHref;
188
+ // Compact keeps the stat ROW and shows one stat in it, rather than dropping
189
+ // the row. The row is a hairline plus a number, and a listing where some cards
190
+ // carry it and some do not has two card heights in one grid. Which stat
191
+ // survives is the caller's order, not a rule here: a card that reordered its
192
+ // caller's stats would be deciding which one matters.
193
+ const shownStats = stats && size === "compact" ? stats.slice(0, 1) : stats;
194
+ // One line on compact and on row, whatever the caller asked for. See the note
195
+ // on the prop: this is a height rule, not a preference.
196
+ const clampDescription = size === "default" && descriptionLines === 2 ? "line-clamp-2" : "truncate";
197
+ /**
198
+ * THE TWO ACTIONS. One pair, written once, used by the reveal panel and by the
199
+ * row alike — because #182's premise is that every entity card offers the same
200
+ * two doors, and two copies of a pair is how one of them quietly grows a third.
201
+ *
202
+ * Both halves of the hit model travel with them, and both are load-bearing:
203
+ *
204
+ * Open carries `after:absolute after:inset-0`, which stretches it over its
205
+ * nearest POSITIONED ancestor. That is the reveal panel on a media card (the
206
+ * panel is `absolute`) and the card itself on a row (which declares `relative`
207
+ * for exactly this). Either way a click anywhere on the card opens the entity,
208
+ * including on a phone where nothing ever hovers. The anchor itself must not
209
+ * be positioned or the stretched layer would size to the pill.
210
+ *
211
+ * Dashboard is `relative`, which lifts it above that stretched layer — and
212
+ * because it is lifted it must not be live while it is invisible.
213
+ * `opacity-0` is a paint state, not a pointer state, so at rest the pill was
214
+ * a region of the card that went somewhere different from every pixel around
215
+ * it, with nothing to see (#171). `pointer-events-none` until hover or
216
+ * focus-within, and Open's overlay untouched, is the whole fix.
217
+ */
218
+ const actionPair = (_jsxs(_Fragment, { children: [_jsxs("a", { href: href, "data-slot": "entity-card-open", className: "inline-flex items-center gap-1 rounded-pill border border-hairline px-2 py-1 text-caption no-underline after:absolute after:inset-0 after:content-[''] focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", children: [_jsx(OpenLiveIcon, { className: "size-3.5" }), "Open"] }), dashboardTarget ? (_jsxs("a", { href: dashboardTarget, "data-slot": "entity-card-dashboard", className: "pointer-events-none relative inline-flex items-center gap-1 rounded-pill border border-hairline px-2 py-1 text-caption no-underline group-hover/card:pointer-events-auto group-focus-within/card:pointer-events-auto focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", children: [_jsx(EntityDashboardIcon, { className: "size-3.5" }), "Dashboard"] })) : null] }));
105
219
  const body = children ??
106
- (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("span", { dir: "auto", "data-slot": "entity-card-title", title: title, className: cn("block text-body-sm font-medium break-words text-ink", titleLines === 1 ? "truncate" : "line-clamp-2"), children: [kind && !seed ? (_jsx(EntityKindBadge, { kind: kind, size: "sm", className: "mr-1.5 align-[-0.2em]" })) : null, title] }), slug ? (_jsx("span", { dir: "auto", "data-slot": "entity-card-slug", title: slug, className: "mt-0.5 block truncate font-mono text-caption text-faint", children: slug })) : null] }), status ? _jsx("div", { className: "shrink-0", children: status }) : null] }), description ? (_jsx("p", { dir: "auto", "data-slot": "entity-card-description", title: description, className: cn("m-0 text-body-sm text-body", descriptionLines === 1 ? "truncate" : "line-clamp-2"), children: description })) : null, meta, _jsx("div", { "aria-hidden": "true", className: "grow" }), stats && stats.length > 0 ? (_jsx("div", { "data-slot": "entity-card-stats", className: "flex flex-wrap items-center gap-4 border-t border-hairline pt-3 text-caption text-body", children: stats.map((stat) => (_jsxs("span", { className: "inline-flex items-center gap-1.5", children: [stat.icon ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex [&>svg]:size-4", children: stat.icon })) : null, stat.value, _jsx("span", { className: "sr-only", children: stat.label })] }, stat.label))) })) : null, footer] }));
107
- const card = (_jsxs(Card, { "data-slot": "entity-card",
220
+ (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("span", { dir: "auto", "data-slot": "entity-card-title", title: title, className: cn("block font-medium break-words text-ink", sized.title, titleLines === 1 ? "truncate" : "line-clamp-2"), children: [kind && !seed ? (_jsx(EntityKindBadge, { kind: kind, size: "sm", className: "mr-1.5 align-[-0.2em]" })) : null, title] }), slug ? (_jsx("span", { dir: "auto", "data-slot": "entity-card-slug", title: slug, className: "mt-0.5 block truncate font-mono text-caption text-faint", children: slug })) : null] }), status ? _jsx("div", { className: "shrink-0", children: status }) : null, headerActions ? (_jsx("div", { "data-slot": "entity-card-actions",
221
+ // items-center against the title's first line, and -mt-1 to pull an
222
+ // icon button's own padding back so the glyph optically lines up
223
+ // with the title rather than sitting a couple of pixels low.
224
+ className: "-mt-1 flex shrink-0 items-center gap-1", children: headerActions })) : null] }), description ? (_jsx("p", { dir: "auto", "data-slot": "entity-card-description", title: description, className: cn("m-0 text-body", sized.description, clampDescription), children: description })) : null, meta, _jsx("div", { "aria-hidden": "true", className: "grow" }), shownStats && shownStats.length > 0 ? (_jsx("div", { "data-slot": "entity-card-stats", className: cn("flex flex-wrap items-center border-t border-hairline text-caption text-body", sized.stats), children: shownStats.map((stat) => (_jsxs("span", { className: "inline-flex items-center gap-1.5", children: [stat.icon ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex [&>svg]:size-4", children: stat.icon })) : null, stat.value, _jsx("span", { className: "sr-only", children: stat.label })] }, stat.label))) })) : null, footer] }));
225
+ /**
226
+ * The preview region, shared by all three sizes.
227
+ *
228
+ * A function rather than a second copy, because the two things that differ
229
+ * between the stacked sizes and the row are its shape and whether a panel goes
230
+ * over it. Everything that is easy to get wrong — the capture painting over
231
+ * the identity rather than instead of it, the badge sitting after the panel so
232
+ * the scrim does not smudge it, the badge not eating a click meant for the
233
+ * link — is written once and is the same picture in every size.
234
+ */
235
+ const previewRegion = (shape, badgeSize, panel) => seed ? (_jsxs("div", { "data-slot": "entity-card-preview", className: cn("relative shrink-0", shape), children: [_jsx(EntityIdentity, { seed: seed, name: title }), previewUrl ? (_jsx("div", { "data-slot": "entity-card-capture", "aria-hidden": "true", className: "absolute inset-0 bg-cover bg-center",
236
+ // A background image, not an <img>: a URL that 404s paints nothing
237
+ // and the identity tile below shows through, with no state and no
238
+ // client boundary. The URL goes out exactly as the caller wrote it —
239
+ // `cssUrlString` escapes only the quote and backslash that would
240
+ // break out of url("..."), and never re-encodes an already-encoded
241
+ // URL (ui#178).
242
+ style: { backgroundImage: `url("${cssUrlString(previewUrl)}")` } })) : null, panel, kind ? (_jsx(EntityKindBadge, { kind: kind, size: badgeSize, className: cn("pointer-events-none absolute", badgeSize === "md" ? "top-2 right-2" : "top-1 right-1") })) : null] })) : null;
243
+ /**
244
+ * The reveal panel, which belongs to the stacked sizes only.
245
+ *
246
+ * Extracted to a variable rather than left inline because `previewRegion`
247
+ * above is now shared with the row, and the row deliberately has no panel to
248
+ * pass it. The alternative — a boolean the region branches on — would put the
249
+ * decision in two places instead of one.
250
+ */
251
+ const revealPanel = revealed ? (_jsxs("div", { "data-slot": "entity-card-reveal", "data-cg-surface": "ink", className: cn("absolute inset-0 flex flex-col justify-end bg-scrim-strong text-ink",
252
+ // The only thing compact changes about this panel is its
253
+ // measurements. Same scrim, same ink surface, same two
254
+ // foregrounds — a panel that got smaller AND paler would be
255
+ // trading contrast for space, which is the one thing the
256
+ // guardrail exists to stop.
257
+ sized.reveal,
258
+ // opacity-0, not hidden: the panel is in the tab order at all
259
+ // times, so tabbing into Open is what reveals it, and a touch
260
+ // user with no hover still has a live tap target.
261
+ "opacity-0 transition-opacity duration-[var(--cg-duration)] ease-out", "group-hover/card:opacity-100 group-focus-within/card:opacity-100",
262
+ // Reduced motion removes the FADE, not the panel. Someone who
263
+ // has asked for less movement still needs the actions.
264
+ "motion-reduce:transition-none"), children: [_jsx("span", { "data-slot": "entity-card-reveal-title", dir: "auto", className: cn("truncate font-medium", sized.revealTitle), children: title }), description ? (_jsx("p", { "data-slot": "entity-card-reveal-description", dir: "auto",
265
+ // text-body, never text-faint. The secondary measures 6.18:1
266
+ // on this scrim and the guardrail holds it there; the muted
267
+ // rung measures 4.06:1, under AA, and is deliberately outside
268
+ // that assertion because it is documented as non-essential
269
+ // text. So there is no muted tier available on this panel.
270
+ className: "m-0 truncate text-caption text-body", children: description })) : null, creator || status ? (_jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [creator ? (_jsxs("span", { "data-slot": "entity-card-reveal-creator", className: "flex min-w-0 items-center gap-1.5 text-caption text-body", children: [creator.avatar ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex size-4 shrink-0 overflow-hidden rounded-pill [&>*]:size-full", children: creator.avatar })) : null, _jsx("span", { className: "truncate", children: creator.name })] })) : (_jsx("span", {})), status ? _jsx("span", { className: "shrink-0", children: status }) : null] })) : null, _jsx("div", { className: "flex items-center gap-2 pt-0.5", children: actionPair })] })) : null;
271
+ /**
272
+ * THE ROW. The same card, running across instead of down.
273
+ *
274
+ * Its own return rather than a set of conditionals threaded through the
275
+ * stacked one, because almost nothing about the arrangement survives the
276
+ * rotation: the preview is beside the text rather than above it, the title,
277
+ * the description and the creator are one column of single lines, and the
278
+ * state, the header's controls and the two actions form a cluster at the end.
279
+ * Threading that through would leave a body that reads as neither shape.
280
+ *
281
+ * What IS shared is shared for real: `previewRegion` paints the same picture,
282
+ * `actionPair` is the same two anchors, and `SIZE_STYLE.row` is a column of
283
+ * the same table. Nothing about a row is a second implementation of something
284
+ * the media card already does.
285
+ *
286
+ * ## The hit model, which is the media card's with one thing moved
287
+ *
288
+ * `relative` on the card is load-bearing: it is what Open's stretched
289
+ * `::after` sizes to, so a click anywhere on the row opens the entity, exactly
290
+ * as a click anywhere on a thumbnail does. That also means a row is never
291
+ * wrapped in a whole-card anchor — the actions are anchors, and an anchor
292
+ * inside an anchor is invalid HTML that browsers repair by closing the outer
293
+ * one.
294
+ *
295
+ * `headerActions` is the thing that moves. On a media card it sits in the body
296
+ * and nothing is stretched over it. Here it sits inside Open's hit area, so it
297
+ * carries `relative z-10` to stay above it. That is safe in a way the same
298
+ * treatment on the panel's Dashboard was not (#171): these controls are
299
+ * VISIBLE at rest, so a tap landing on the save toggle rather than on the row
300
+ * is what a reader can see is going to happen. The invisible-at-rest rule
301
+ * still binds the two actions, which is why Dashboard keeps its
302
+ * `pointer-events-none`.
303
+ *
304
+ * `stats` and `footer` are not rendered here — see the size note at the top.
305
+ */
306
+ if (size === "row") {
307
+ return (_jsxs(Card, { "data-slot": "entity-card", "data-entity-size": "row", className: cn("relative flex-row items-center gap-3 p-(--card-spacing)", sized.cardSpacing, className), ...props, children: [previewRegion(
308
+ // A left thumbnail, so it rounds on all four corners rather than
309
+ // sharing the card's top edge, and it carries a full hairline rather
310
+ // than the media card's single bottom rule.
311
+ cn("overflow-hidden rounded-lg border border-hairline", ROW_THUMBNAIL), "sm", null), _jsx("div", { className: cn("flex w-0 min-w-0 flex-1 flex-col", sized.body), children: children ?? (_jsxs(_Fragment, { children: [_jsxs("span", { dir: "auto", "data-slot": "entity-card-title", title: title, className: cn("block truncate font-medium text-ink", sized.title), children: [kind && !seed ? (_jsx(EntityKindBadge, { kind: kind, size: "sm", className: "mr-1.5 align-[-0.2em]" })) : null, title] }), slug ? (_jsx("span", { dir: "auto", "data-slot": "entity-card-slug", title: slug, className: "block truncate font-mono text-caption text-faint", children: slug })) : null, description ? (_jsx("p", { dir: "auto", "data-slot": "entity-card-description", title: description, className: cn("m-0 truncate text-body", sized.description), children: description })) : null, creator || meta ? (_jsxs("div", { className: "flex min-w-0 items-center gap-2 text-caption text-body", children: [creator ? (_jsxs("span", { "data-slot": "entity-card-creator", className: "flex min-w-0 items-center gap-1.5", children: [creator.avatar ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex size-4 shrink-0 overflow-hidden rounded-pill [&>*]:size-full", children: creator.avatar })) : null, _jsx("span", { className: "truncate", children: creator.name })] })) : null, meta] })) : null] })) }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [status ? _jsx("span", { className: "shrink-0", children: status }) : null, headerActions ? (_jsx("div", { "data-slot": "entity-card-actions", className: "relative z-10 flex shrink-0 items-center gap-1", children: headerActions })) : null, href ? (_jsx("div", { "data-slot": "entity-card-row-actions", className: cn("flex shrink-0 items-center gap-2",
312
+ // The row's whole hover behaviour, and all of it: the
313
+ // information is already on screen, so what arrives is the two
314
+ // actions and nothing else.
315
+ "opacity-0 transition-opacity duration-[var(--cg-duration)] ease-out", "group-hover/card:opacity-100 group-focus-within/card:opacity-100",
316
+ // Reduced motion removes the FADE, not the actions.
317
+ "motion-reduce:transition-none"), children: actionPair })) : null] })] }));
318
+ }
319
+ const card = (_jsxs(Card, { "data-slot": "entity-card", "data-entity-size": size,
108
320
  // gap-0 py-0: `Card` pads itself for a header/content/footer stack, and
109
321
  // this card's preview is full bleed to the top edge. The padding moves
110
322
  // inside, onto the body, so the preview can touch the corners.
@@ -118,53 +330,12 @@ function EntityCard({ title, slug, description, titleLines = 2, descriptionLines
118
330
  // anchor. As a direct grid item it must NOT be h-full: a grid area has a
119
331
  // definite height, so height:100% pins the card to the tallest card in the
120
332
  // row even when the grid was told `items-start`.
121
- className: cn("gap-0 py-0", href && !revealed && "h-full", className), ...props, children: [seed ? (_jsxs("div", { "data-slot": "entity-card-preview",
122
- // rounded-t-xl is the same --cg-radius-xl the card rounds to, and
123
- // overflow-hidden is what keeps the reveal panel inside it. The card
124
- // already clips; stating it here means the panel can never paint a
125
- // corner the card does not have.
126
- className: "relative shrink-0 overflow-hidden rounded-t-xl border-b border-hairline", children: [_jsx(EntityIdentity, { seed: seed, name: title }), previewUrl ? (_jsx("div", { "data-slot": "entity-card-capture", "aria-hidden": "true", className: "absolute inset-0 bg-cover bg-center",
127
- // A background image, not an <img>: a URL that 404s paints
128
- // nothing and the identity tile below shows through, with no
129
- // state and no client boundary. The URL goes out exactly as the
130
- // caller wrote it — `cssUrlString` escapes only the quote and
131
- // backslash that would break out of url("..."), and never
132
- // re-encodes an already-encoded URL (ui#178).
133
- style: { backgroundImage: `url("${cssUrlString(previewUrl)}")` } })) : null, revealed ? (_jsxs("div", { "data-slot": "entity-card-reveal", "data-cg-surface": "ink", className: cn("absolute inset-0 flex flex-col justify-end gap-1.5 bg-scrim-strong p-3 text-ink",
134
- // opacity-0, not hidden: the panel is in the tab order at all
135
- // times, so tabbing into Open is what reveals it, and a touch
136
- // user with no hover still has a live tap target.
137
- "opacity-0 transition-opacity duration-[var(--cg-duration)] ease-out", "group-hover/card:opacity-100 group-focus-within/card:opacity-100",
138
- // Reduced motion removes the FADE, not the panel. Someone who
139
- // has asked for less movement still needs the actions.
140
- "motion-reduce:transition-none"), children: [_jsx("span", { "data-slot": "entity-card-reveal-title", dir: "auto", className: "truncate text-body-sm font-medium", children: title }), description ? (_jsx("p", { "data-slot": "entity-card-reveal-description", dir: "auto",
141
- // text-body, never text-faint. The secondary measures 6.18:1
142
- // on this scrim and the guardrail holds it there; the muted
143
- // rung measures 4.06:1, under AA, and is deliberately outside
144
- // that assertion because it is documented as non-essential
145
- // text. So there is no muted tier available on this panel.
146
- className: "m-0 truncate text-caption text-body", children: description })) : null, creator || status ? (_jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [creator ? (_jsxs("span", { "data-slot": "entity-card-reveal-creator", className: "flex min-w-0 items-center gap-1.5 text-caption text-body", children: [creator.avatar ? (_jsx("span", { "aria-hidden": "true", className: "inline-flex size-4 shrink-0 overflow-hidden rounded-pill [&>*]:size-full", children: creator.avatar })) : null, _jsx("span", { className: "truncate", children: creator.name })] })) : (_jsx("span", {})), status ? _jsx("span", { className: "shrink-0", children: status }) : null] })) : null, _jsxs("div", { className: "flex items-center gap-2 pt-0.5", children: [_jsxs("a", { href: href, "data-slot": "entity-card-open",
147
- // after:inset-0 makes this link the whole panel, so a click
148
- // anywhere on the thumbnail opens the entity. The anchor
149
- // itself must NOT be positioned or the stretched layer sizes
150
- // to the anchor instead of to the panel — the panel is already
151
- // absolute, so it is the containing block. Settings comes
152
- // later in the DOM and IS positioned, so it stacks above the
153
- // stretched layer rather than under it.
154
- className: "inline-flex items-center gap-1 rounded-pill border border-hairline px-2 py-1 text-caption no-underline after:absolute after:inset-0 after:content-[''] focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", children: [_jsx(OpenLiveIcon, { className: "size-3.5" }), "Open"] }), settingsHref ? (_jsxs("a", { href: settingsHref, "data-slot": "entity-card-settings",
155
- // relative, and that is load-bearing: it lifts this link
156
- // above Open's stretched ::after, which otherwise covers the
157
- // whole panel and would swallow every click meant for here.
158
- //
159
- // And because it is lifted, it must not be live while the
160
- // panel is invisible: opacity-0 is a paint state, so at rest
161
- // this pill was a region of the thumbnail that went to
162
- // Settings on a tap instead of opening the entity (#171).
163
- // pointer-events-none until the panel is actually revealed —
164
- // the same reasoning the kind mark carries. Open keeps its
165
- // stretched hit area at all times, so the touch fallback is
166
- // untouched.
167
- className: "pointer-events-none relative inline-flex items-center gap-1 rounded-pill border border-hairline px-2 py-1 text-caption no-underline group-hover/card:pointer-events-auto group-focus-within/card:pointer-events-auto focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", children: [_jsx(SettingsIcon, { className: "size-3.5" }), "Settings"] })) : null] })] })) : null, kind ? (_jsx(EntityKindBadge, { kind: kind, className: "pointer-events-none absolute top-2 right-2" })) : null] })) : null, _jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-3 p-(--card-spacing)", children: body })] }));
333
+ className: cn("gap-0 py-0", sized.cardSpacing, href && !revealed && "h-full", className), ...props, children: [previewRegion(
334
+ // rounded-t-xl is the same --cg-radius-xl the card rounds to, and
335
+ // overflow-hidden is what keeps the reveal panel inside it. The card
336
+ // already clips; stating it here means the panel can never paint a
337
+ // corner the card does not have.
338
+ "overflow-hidden rounded-t-xl border-b border-hairline", "md", revealPanel), _jsx("div", { className: cn("flex min-h-0 flex-1 flex-col p-(--card-spacing)", sized.body), children: body })] }));
168
339
  // A revealed card is never wrapped: the panel's Open action is already an
169
340
  // anchor, and an anchor inside an anchor is invalid HTML that browsers repair
170
341
  // by closing the outer one.
@@ -1 +1 @@
1
- {"version":3,"file":"entity-card.js","sourceRoot":"","sources":["../../src/blocks/entity-card.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entity-card.js","sourceRoot":"","sources":["../../src/blocks/entity-card.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The small label that sits above something and names the part of the page it
3
+ * belongs to. A section label, a specimen caption, the word over a lockup.
4
+ *
5
+ * ## Why it exists as its own thing (#176)
6
+ *
7
+ * The recipe was already in this library — `text-label font-medium text-faint`,
8
+ * written inline inside `PageHeading` and reachable only by rendering a whole
9
+ * page lockup. So a surface that wanted the label and not the display heading
10
+ * had two options, and both are wrong in the same way: hand-build the three
11
+ * classes, or borrow the nearest primitive that is not this one.
12
+ *
13
+ * The console's styleguide did the second. Its section labels render as
14
+ * `Badge variant="outline"`, which is a pill — the right colour, the wrong
15
+ * shape, and a reference page for a design system teaching its reader that
16
+ * building your own furniture is normal. That is what cloudgrid-console#654
17
+ * filed and what this answers.
18
+ *
19
+ * `PageHeading` renders this rather than repeating the classes, so there is one
20
+ * definition of what an eyebrow looks like and retuning it is one edit here.
21
+ *
22
+ * ## What it is not
23
+ *
24
+ * Not a heading. It is a `<p>`, and it takes no `level`: an eyebrow is a label
25
+ * for the thing under it, so promoting it to `<h2>` would put a second entry in
26
+ * the document outline for one section and announce the label instead of the
27
+ * title. When the eyebrow and a heading belong together, put both in a
28
+ * `PageHeading`, which stacks them and keeps the heading the heading.
29
+ *
30
+ * Not uppercase. `--cg-label-size` carries its own weight and leading through
31
+ * `text-label`, and the brand's uppercase treatment belongs to the display face
32
+ * — the heading — rather than to the small print above it. A caller who wants
33
+ * caps has `className`.
34
+ *
35
+ * ## Type
36
+ *
37
+ * `text-label` rather than `text-caption`, deliberately: the label step exists
38
+ * on the brand ramp with its own weight companion (`--cg-label-weight`), and a
39
+ * caption is body copy set small. They render close and mean different things.
40
+ */
41
+ declare function Eyebrow({ className, ...props }: React.ComponentProps<"p">): import("react").JSX.Element;
42
+ export { Eyebrow };
43
+ //# sourceMappingURL=eyebrow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eyebrow.d.ts","sourceRoot":"","sources":["../../src/blocks/eyebrow.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,iBAAS,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,+BAalE;AAED,OAAO,EAAE,OAAO,EAAE,CAAA"}
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/cloudgrid-cn.js";
3
+ /**
4
+ * The small label that sits above something and names the part of the page it
5
+ * belongs to. A section label, a specimen caption, the word over a lockup.
6
+ *
7
+ * ## Why it exists as its own thing (#176)
8
+ *
9
+ * The recipe was already in this library — `text-label font-medium text-faint`,
10
+ * written inline inside `PageHeading` and reachable only by rendering a whole
11
+ * page lockup. So a surface that wanted the label and not the display heading
12
+ * had two options, and both are wrong in the same way: hand-build the three
13
+ * classes, or borrow the nearest primitive that is not this one.
14
+ *
15
+ * The console's styleguide did the second. Its section labels render as
16
+ * `Badge variant="outline"`, which is a pill — the right colour, the wrong
17
+ * shape, and a reference page for a design system teaching its reader that
18
+ * building your own furniture is normal. That is what cloudgrid-console#654
19
+ * filed and what this answers.
20
+ *
21
+ * `PageHeading` renders this rather than repeating the classes, so there is one
22
+ * definition of what an eyebrow looks like and retuning it is one edit here.
23
+ *
24
+ * ## What it is not
25
+ *
26
+ * Not a heading. It is a `<p>`, and it takes no `level`: an eyebrow is a label
27
+ * for the thing under it, so promoting it to `<h2>` would put a second entry in
28
+ * the document outline for one section and announce the label instead of the
29
+ * title. When the eyebrow and a heading belong together, put both in a
30
+ * `PageHeading`, which stacks them and keeps the heading the heading.
31
+ *
32
+ * Not uppercase. `--cg-label-size` carries its own weight and leading through
33
+ * `text-label`, and the brand's uppercase treatment belongs to the display face
34
+ * — the heading — rather than to the small print above it. A caller who wants
35
+ * caps has `className`.
36
+ *
37
+ * ## Type
38
+ *
39
+ * `text-label` rather than `text-caption`, deliberately: the label step exists
40
+ * on the brand ramp with its own weight companion (`--cg-label-weight`), and a
41
+ * caption is body copy set small. They render close and mean different things.
42
+ */
43
+ function Eyebrow({ className, ...props }) {
44
+ return (_jsx("p", { "data-slot": "eyebrow",
45
+ // m-0 because a consumer without Tailwind's preflight — a prose block, an
46
+ // Astro page with its own base sheet — inherits a paragraph margin and the
47
+ // label drifts away from the thing it labels. This library's own pages are
48
+ // preflighted, so the margin is invisible here and only ever wrong
49
+ // downstream, which is the failure worth carrying three characters for.
50
+ className: cn("m-0 text-label font-medium text-faint", className), ...props }));
51
+ }
52
+ export { Eyebrow };
53
+ //# sourceMappingURL=eyebrow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eyebrow.js","sourceRoot":"","sources":["../../src/blocks/eyebrow.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,SAAS,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA6B;IACjE,OAAO,CACL,yBACY,SAAS;QACnB,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,mEAAmE;QACnE,wEAAwE;QACxE,SAAS,EAAE,EAAE,CAAC,uCAAuC,EAAE,SAAS,CAAC,KAC7D,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,CAAA"}
@@ -7,16 +7,21 @@
7
7
  * structure, because the copy reads as a sequence of commitments rather than a
8
8
  * feature race.
9
9
  *
10
- * ## Icons are lucide here, not Phosphor
10
+ * ## The glyphs are Phosphor, through the library's own names
11
11
  *
12
12
  * v0 inlined ten Phosphor SVGs as raw strings, because Astro can import SVG via
13
13
  * Vite's `?raw` and React bundlers cannot, and rendered them with
14
- * `dangerouslySetInnerHTML`. Two reasons not to carry that over: this registry
15
- * declares `iconLibrary: lucide` and already depends on `lucide-react`, so
16
- * Phosphor strings would put a second icon vocabulary in the library; and
17
- * `dangerouslySetInnerHTML` for decoration is a sharp tool used for nothing. The
18
- * lucide equivalents are close in weight and monoline, which is the system's rule
19
- * for icons.
14
+ * `dangerouslySetInnerHTML`. This renders the same family, without either
15
+ * problem: `scripts/generate-phosphor-marks.mjs` reads the path data out of
16
+ * `@phosphor-icons/core` and inlines it as components, and this file names roles
17
+ * `AiIcon`, `MemoryIcon`, `ScheduleIcon` rather than glyphs, so a repick is
18
+ * one slug in the generator and no edit here (#167).
19
+ *
20
+ * The interim between the two was lucide, chosen when this registry declared
21
+ * `iconLibrary: lucide`. It no longer does: Phosphor is the only icon library,
22
+ * every equivalent was an approximation of a mark the designer had already
23
+ * picked, and `dangerouslySetInnerHTML` for decoration remains a sharp tool used
24
+ * for nothing.
20
25
  *
21
26
  * ## The matcher, and its escape hatch
22
27
  *
@@ -1 +1 @@
1
- {"version":3,"file":"feature-cells.d.ts","sourceRoot":"","sources":["../../src/blocks/feature-cells.tsx"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,KAAK,gBAAgB,GAAG;IACtB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,mDAAmD;IACnD,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACnD,CAAA;AA+BD,iBAAS,YAAY,CAAC,EACpB,KAAK,EACL,OAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,GAAG;IAC3C,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACzB,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;CAC7B,+BA4DA;AAED,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EAAE,gBAAgB,EAAE,CAAA"}
1
+ {"version":3,"file":"feature-cells.d.ts","sourceRoot":"","sources":["../../src/blocks/feature-cells.tsx"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,KAAK,gBAAgB,GAAG;IACtB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,mDAAmD;IACnD,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACnD,CAAA;AA+BD,iBAAS,YAAY,CAAC,EACpB,KAAK,EACL,OAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,GAAG;IAC3C,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACzB,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;CAC7B,+BA4DA;AAED,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EAAE,gBAAgB,EAAE,CAAA"}
@@ -1,22 +1,22 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Brain, Clock, Database, Globe, HardDrive, KeyRound, Plug, Sparkles, Users, Zap, } from "lucide-react";
2
+ import { AiIcon, DatabaseIcon, FastIcon, MemoryIcon, PeopleIcon, PlugIcon, ScheduleIcon, SecretIcon, StorageIcon, WebIcon, } from "./icons.js";
3
3
  import { cn } from "../lib/cloudgrid-cn.js";
4
4
  const MATCHERS = [
5
- [/\bai\b|model|gateway/i, Sparkles],
6
- [/database|postgres/i, Database],
7
- [/storage|files?\b/i, HardDrive],
8
- [/memory|brain/i, Brain],
9
- [/live|url|domain/i, Globe],
10
- [/key|sign-?in|auth|secret/i, KeyRound],
11
- [/cron|schedule|clock/i, Clock],
12
- [/found|shared|picked|player|people/i, Users],
13
- [/cache|fast|instant/i, Zap],
5
+ [/\bai\b|model|gateway/i, AiIcon],
6
+ [/database|postgres/i, DatabaseIcon],
7
+ [/storage|files?\b/i, StorageIcon],
8
+ [/memory|brain/i, MemoryIcon],
9
+ [/live|url|domain/i, WebIcon],
10
+ [/key|sign-?in|auth|secret/i, SecretIcon],
11
+ [/cron|schedule|clock/i, ScheduleIcon],
12
+ [/found|shared|picked|player|people/i, PeopleIcon],
13
+ [/cache|fast|instant/i, FastIcon],
14
14
  ];
15
15
  function glyphFor(item) {
16
16
  if (item.icon)
17
17
  return item.icon;
18
18
  const text = `${item.q} ${item.a}`;
19
- return MATCHERS.find(([re]) => re.test(text))?.[1] ?? Plug;
19
+ return MATCHERS.find(([re]) => re.test(text))?.[1] ?? PlugIcon;
20
20
  }
21
21
  /**
22
22
  * The three-tint cycle. Tints are mixed against the page surface rather than
@@ -1 +1 @@
1
- {"version":3,"file":"feature-cells.js","sourceRoot":"","sources":["../../src/blocks/feature-cells.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature-cells.js","sourceRoot":"","sources":["../../src/blocks/feature-cells.tsx"],"names":[],"mappings":"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"}