@sproutsocial/seeds-react-narrative-kit 0.1.0 → 0.3.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 (60) hide show
  1. package/.turbo/turbo-build.log +11 -11
  2. package/CHANGELOG.md +28 -0
  3. package/dist/esm/index.js +324 -2
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/eyebrow-token.css +37 -0
  6. package/dist/index.d.mts +304 -1
  7. package/dist/index.d.ts +304 -1
  8. package/dist/index.js +333 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/metric-highlight.css +168 -0
  11. package/dist/narrative-container.css +1 -1
  12. package/dist/narrative-divider.css +27 -0
  13. package/dist/narrative-headline.css +132 -0
  14. package/dist/narrative-summary.css +126 -0
  15. package/dist/pull-quote.css +89 -0
  16. package/package.json +13 -3
  17. package/src/EyebrowToken/EyebrowToken.stories.tsx +25 -0
  18. package/src/EyebrowToken/EyebrowToken.tsx +25 -0
  19. package/src/EyebrowToken/EyebrowTokenTypes.ts +7 -0
  20. package/src/EyebrowToken/__tests__/EyebrowToken.test.tsx +35 -0
  21. package/src/EyebrowToken/index.ts +2 -0
  22. package/src/MetricHighlight/MetricHighlight.stories.tsx +110 -0
  23. package/src/MetricHighlight/MetricHighlight.tsx +116 -0
  24. package/src/MetricHighlight/MetricHighlightTypes.ts +58 -0
  25. package/src/MetricHighlight/__tests__/MetricHighlight.test.tsx +116 -0
  26. package/src/MetricHighlight/index.ts +5 -0
  27. package/src/NarrativeContainer/NarrativeContainer.stories.tsx +3 -3
  28. package/src/NarrativeContainer/NarrativeContainer.tsx +1 -23
  29. package/src/NarrativeDivider/NarrativeDivider.stories.tsx +33 -0
  30. package/src/NarrativeDivider/NarrativeDivider.tsx +30 -0
  31. package/src/NarrativeDivider/NarrativeDividerTypes.ts +4 -0
  32. package/src/NarrativeDivider/__tests__/NarrativeDivider.test.tsx +35 -0
  33. package/src/NarrativeDivider/index.ts +2 -0
  34. package/src/NarrativeHeadline/NarrativeHeadline.stories.tsx +68 -0
  35. package/src/NarrativeHeadline/NarrativeHeadline.tsx +45 -0
  36. package/src/NarrativeHeadline/NarrativeHeadlineHighlight.tsx +31 -0
  37. package/src/NarrativeHeadline/NarrativeHeadlineRoll.tsx +103 -0
  38. package/src/NarrativeHeadline/NarrativeHeadlineTypes.ts +63 -0
  39. package/src/NarrativeHeadline/__tests__/NarrativeHeadline.test.tsx +133 -0
  40. package/src/NarrativeHeadline/index.ts +10 -0
  41. package/src/NarrativeSummary/NarrativeSummary.stories.tsx +79 -0
  42. package/src/NarrativeSummary/NarrativeSummary.tsx +98 -0
  43. package/src/NarrativeSummary/NarrativeSummaryTypes.ts +59 -0
  44. package/src/NarrativeSummary/__tests__/NarrativeSummary.test.tsx +99 -0
  45. package/src/NarrativeSummary/index.ts +5 -0
  46. package/src/Playground/Playground.stories.tsx +163 -0
  47. package/src/PullQuote/PullQuote.stories.tsx +45 -0
  48. package/src/PullQuote/PullQuote.tsx +42 -0
  49. package/src/PullQuote/PullQuoteTypes.ts +18 -0
  50. package/src/PullQuote/__tests__/PullQuote.test.tsx +48 -0
  51. package/src/PullQuote/index.ts +2 -0
  52. package/src/_internal/cn.ts +22 -0
  53. package/src/eyebrow-token.css +37 -0
  54. package/src/index.ts +31 -0
  55. package/src/metric-highlight.css +168 -0
  56. package/src/narrative-container.css +1 -1
  57. package/src/narrative-divider.css +27 -0
  58. package/src/narrative-headline.css +132 -0
  59. package/src/narrative-summary.css +126 -0
  60. package/src/pull-quote.css +89 -0
package/dist/index.js CHANGED
@@ -30,13 +30,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- NarrativeContainer: () => NarrativeContainer_default
33
+ EyebrowToken: () => EyebrowToken_default,
34
+ MetricHighlight: () => MetricHighlight_default,
35
+ NarrativeContainer: () => NarrativeContainer_default,
36
+ NarrativeDivider: () => NarrativeDivider_default,
37
+ NarrativeHeadline: () => NarrativeHeadline_default,
38
+ NarrativeHeadlineHighlight: () => NarrativeHeadlineHighlight_default,
39
+ NarrativeHeadlineRoll: () => NarrativeHeadlineRoll_default,
40
+ NarrativeSummary: () => NarrativeSummary_default,
41
+ PullQuote: () => PullQuote_default
34
42
  });
35
43
  module.exports = __toCommonJS(index_exports);
36
44
 
37
45
  // src/NarrativeContainer/NarrativeContainer.tsx
38
46
  var React = __toESM(require("react"));
39
- var import_jsx_runtime = require("react/jsx-runtime");
47
+
48
+ // src/_internal/cn.ts
40
49
  function cn(...inputs) {
41
50
  const classes = [];
42
51
  for (const input of inputs) {
@@ -53,6 +62,9 @@ function cn(...inputs) {
53
62
  }
54
63
  return classes.join(" ");
55
64
  }
65
+
66
+ // src/NarrativeContainer/NarrativeContainer.tsx
67
+ var import_jsx_runtime = require("react/jsx-runtime");
56
68
  var NarrativeContainer = React.forwardRef(({ children, accent = true, className, ...props }, ref) => {
57
69
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
58
70
  "div",
@@ -70,8 +82,326 @@ var NarrativeContainer = React.forwardRef(({ children, accent = true, className,
70
82
  });
71
83
  NarrativeContainer.displayName = "NarrativeContainer";
72
84
  var NarrativeContainer_default = NarrativeContainer;
85
+
86
+ // src/NarrativeHeadline/NarrativeHeadline.tsx
87
+ var React2 = __toESM(require("react"));
88
+ var import_jsx_runtime2 = require("react/jsx-runtime");
89
+ var NarrativeHeadline = React2.forwardRef(
90
+ ({ children, headingLevel = 2, size = "default", className, ...props }, ref) => {
91
+ const Heading = `h${headingLevel}`;
92
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
93
+ Heading,
94
+ {
95
+ ref,
96
+ className: cn(
97
+ "seeds-narrative-headline",
98
+ { "seeds-narrative-headline-small": size === "small" },
99
+ className
100
+ ),
101
+ ...props,
102
+ children
103
+ }
104
+ );
105
+ }
106
+ );
107
+ NarrativeHeadline.displayName = "NarrativeHeadline";
108
+ var NarrativeHeadline_default = NarrativeHeadline;
109
+
110
+ // src/NarrativeHeadline/NarrativeHeadlineHighlight.tsx
111
+ var React3 = __toESM(require("react"));
112
+ var import_jsx_runtime3 = require("react/jsx-runtime");
113
+ var NarrativeHeadlineHighlight = React3.forwardRef(({ children, className, ...props }, ref) => {
114
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
115
+ "span",
116
+ {
117
+ ref,
118
+ className: cn("seeds-narrative-headline-highlight", className),
119
+ ...props,
120
+ children
121
+ }
122
+ );
123
+ });
124
+ NarrativeHeadlineHighlight.displayName = "NarrativeHeadlineHighlight";
125
+ var NarrativeHeadlineHighlight_default = NarrativeHeadlineHighlight;
126
+
127
+ // src/NarrativeHeadline/NarrativeHeadlineRoll.tsx
128
+ var React4 = __toESM(require("react"));
129
+ var import_jsx_runtime4 = require("react/jsx-runtime");
130
+ var NarrativeHeadlineRoll = React4.forwardRef(
131
+ ({
132
+ words,
133
+ intervalMs = 2200,
134
+ transitionMs = 500,
135
+ direction = "up",
136
+ gradient = true,
137
+ className,
138
+ style,
139
+ ...rest
140
+ }, ref) => {
141
+ const [i, setI] = React4.useState(0);
142
+ React4.useEffect(() => {
143
+ if (words.length <= 1) return;
144
+ const reduced = typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
145
+ if (reduced) return;
146
+ const t = setInterval(
147
+ () => setI((j) => (j + 1) % words.length),
148
+ intervalMs
149
+ );
150
+ return () => clearInterval(t);
151
+ }, [intervalMs, words.length]);
152
+ const merged = {
153
+ ...style,
154
+ // Consumed by the transition timing in narrative-headline.css.
155
+ ["--seeds-narrative-headline-roll-ms"]: `${transitionMs}ms`
156
+ };
157
+ const prev = words.length ? (i - 1 + words.length) % words.length : 0;
158
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
159
+ "span",
160
+ {
161
+ ref,
162
+ className: cn(
163
+ "seeds-narrative-headline-roll",
164
+ { "seeds-narrative-headline-roll-down": direction === "down" },
165
+ { "seeds-narrative-headline-roll-gradient": gradient },
166
+ className
167
+ ),
168
+ style: merged,
169
+ ...rest,
170
+ children: [
171
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
172
+ "span",
173
+ {
174
+ className: "seeds-narrative-headline-roll-sizer",
175
+ "aria-hidden": "true",
176
+ children: words[i]
177
+ }
178
+ ),
179
+ words.map((w, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
180
+ "span",
181
+ {
182
+ className: cn("seeds-narrative-headline-roll-word", {
183
+ "seeds-narrative-headline-roll-word-active": idx === i,
184
+ "seeds-narrative-headline-roll-word-past": idx === prev && i !== prev
185
+ }),
186
+ "aria-hidden": idx === i ? void 0 : "true",
187
+ children: w
188
+ },
189
+ idx
190
+ ))
191
+ ]
192
+ }
193
+ );
194
+ }
195
+ );
196
+ NarrativeHeadlineRoll.displayName = "NarrativeHeadlineRoll";
197
+ var NarrativeHeadlineRoll_default = NarrativeHeadlineRoll;
198
+
199
+ // src/PullQuote/PullQuote.tsx
200
+ var React5 = __toESM(require("react"));
201
+ var import_jsx_runtime5 = require("react/jsx-runtime");
202
+ var PullQuote = React5.forwardRef(
203
+ ({ quote, attribution, appearance = "subtle", className, ...props }, ref) => {
204
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
205
+ "figure",
206
+ {
207
+ ref,
208
+ className: cn(
209
+ "seeds-pull-quote",
210
+ { "seeds-pull-quote-vivid": appearance === "vivid" },
211
+ className
212
+ ),
213
+ ...props,
214
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "seeds-pull-quote-bar", children: [
215
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("blockquote", { className: "seeds-pull-quote-text", children: quote }),
216
+ attribution != null && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("figcaption", { className: "seeds-pull-quote-attribution", children: attribution })
217
+ ] })
218
+ }
219
+ );
220
+ }
221
+ );
222
+ PullQuote.displayName = "PullQuote";
223
+ var PullQuote_default = PullQuote;
224
+
225
+ // src/EyebrowToken/EyebrowToken.tsx
226
+ var React6 = __toESM(require("react"));
227
+ var import_jsx_runtime6 = require("react/jsx-runtime");
228
+ var EyebrowToken = React6.forwardRef(
229
+ ({ children, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { ref, className: cn("seeds-eyebrow-token", className), ...props, children })
230
+ );
231
+ EyebrowToken.displayName = "EyebrowToken";
232
+ var EyebrowToken_default = EyebrowToken;
233
+
234
+ // src/NarrativeDivider/NarrativeDivider.tsx
235
+ var React7 = __toESM(require("react"));
236
+ var import_jsx_runtime7 = require("react/jsx-runtime");
237
+ var NarrativeDivider = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
238
+ "hr",
239
+ {
240
+ ref,
241
+ className: cn("seeds-narrative-divider", className),
242
+ ...props
243
+ }
244
+ ));
245
+ NarrativeDivider.displayName = "NarrativeDivider";
246
+ var NarrativeDivider_default = NarrativeDivider;
247
+
248
+ // src/MetricHighlight/MetricHighlight.tsx
249
+ var React8 = __toESM(require("react"));
250
+ var import_jsx_runtime8 = require("react/jsx-runtime");
251
+ var TrendArrow = ({ direction }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
252
+ "svg",
253
+ {
254
+ className: "seeds-metric-highlight-trend-arrow",
255
+ viewBox: "0 0 16 16",
256
+ "aria-hidden": true,
257
+ focusable: false,
258
+ children: direction === "up" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
259
+ "path",
260
+ {
261
+ d: "M4.5 11.5 11.5 4.5M11.5 4.5H5.5M11.5 4.5V10.5",
262
+ fill: "none",
263
+ strokeLinecap: "round",
264
+ strokeLinejoin: "round"
265
+ }
266
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
267
+ "path",
268
+ {
269
+ d: "M4.5 4.5 11.5 11.5M11.5 11.5H5.5M11.5 11.5V5.5",
270
+ fill: "none",
271
+ strokeLinecap: "round",
272
+ strokeLinejoin: "round"
273
+ }
274
+ )
275
+ }
276
+ );
277
+ var TrendBadge = ({
278
+ direction = "up",
279
+ value,
280
+ ...rest
281
+ }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
282
+ "span",
283
+ {
284
+ className: cn("seeds-metric-highlight-trend", {
285
+ "seeds-metric-highlight-trend-down": direction === "down"
286
+ }),
287
+ ...rest,
288
+ children: [
289
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TrendArrow, { direction }),
290
+ value != null && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "seeds-metric-highlight-trend-value", children: value })
291
+ ]
292
+ }
293
+ );
294
+ var MetricHighlight = React8.forwardRef(
295
+ ({
296
+ label,
297
+ value,
298
+ trend,
299
+ sparkline,
300
+ appearance = "horizontal",
301
+ size = "default",
302
+ container = true,
303
+ className,
304
+ ...props
305
+ }, ref) => {
306
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
307
+ "div",
308
+ {
309
+ ref,
310
+ className: cn(
311
+ "seeds-metric-highlight",
312
+ {
313
+ "seeds-metric-highlight-vertical": appearance === "vertical",
314
+ "seeds-metric-highlight-small": size === "small",
315
+ "seeds-metric-highlight-bare": !container
316
+ },
317
+ className
318
+ ),
319
+ ...props,
320
+ children: [
321
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "seeds-metric-highlight-metric", children: [
322
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "seeds-metric-highlight-label", children: label }),
323
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "seeds-metric-highlight-value-row", children: [
324
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "seeds-metric-highlight-value", children: value }),
325
+ trend != null && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TrendBadge, { ...trend })
326
+ ] })
327
+ ] }),
328
+ sparkline != null && // Layout-only slot (bounded dimensions per horizontal/vertical/small)
329
+ // for a consumer-supplied chart. It controls its own look; the slot
330
+ // only sizes and centers it.
331
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "seeds-metric-highlight-chart", children: sparkline })
332
+ ]
333
+ }
334
+ );
335
+ }
336
+ );
337
+ MetricHighlight.displayName = "MetricHighlight";
338
+ var MetricHighlight_default = MetricHighlight;
339
+
340
+ // src/NarrativeSummary/NarrativeSummary.tsx
341
+ var React9 = __toESM(require("react"));
342
+ var import_jsx_runtime9 = require("react/jsx-runtime");
343
+ var NarrativeSummary = React9.forwardRef(
344
+ ({
345
+ eyebrow,
346
+ headline,
347
+ headingLevel = 2,
348
+ action,
349
+ summary,
350
+ summaryLabel = "Summary",
351
+ keyThemes,
352
+ keyThemesLabel = "Key themes",
353
+ layout = "three-column",
354
+ className,
355
+ ...props
356
+ }, ref) => {
357
+ const hasKeyThemes = keyThemes != null && keyThemes.length > 0;
358
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
359
+ "div",
360
+ {
361
+ ref,
362
+ className: cn("seeds-narrative-summary", className),
363
+ ...props,
364
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
365
+ "div",
366
+ {
367
+ className: cn("seeds-narrative-summary-grid", {
368
+ "seeds-narrative-summary-two-column": layout === "two-column"
369
+ }),
370
+ children: [
371
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "seeds-narrative-summary-lead", children: [
372
+ eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EyebrowToken_default, { children: eyebrow }),
373
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "seeds-narrative-summary-headline", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(NarrativeHeadline_default, { size: "small", headingLevel, children: headline }) }),
374
+ action != null && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "seeds-narrative-summary-action", children: action })
375
+ ] }),
376
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "seeds-narrative-summary-content", children: [
377
+ summary != null && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("section", { className: "seeds-narrative-summary-section", children: [
378
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "seeds-narrative-summary-label", children: summaryLabel }),
379
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "seeds-narrative-summary-text", children: summary })
380
+ ] }),
381
+ hasKeyThemes && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("section", { className: "seeds-narrative-summary-section", children: [
382
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "seeds-narrative-summary-label", children: keyThemesLabel }),
383
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { className: "seeds-narrative-summary-list", children: keyThemes.map((theme, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { children: theme }, i)) })
384
+ ] })
385
+ ] })
386
+ ]
387
+ }
388
+ )
389
+ }
390
+ );
391
+ }
392
+ );
393
+ NarrativeSummary.displayName = "NarrativeSummary";
394
+ var NarrativeSummary_default = NarrativeSummary;
73
395
  // Annotate the CommonJS export names for ESM import in node:
74
396
  0 && (module.exports = {
75
- NarrativeContainer
397
+ EyebrowToken,
398
+ MetricHighlight,
399
+ NarrativeContainer,
400
+ NarrativeDivider,
401
+ NarrativeHeadline,
402
+ NarrativeHeadlineHighlight,
403
+ NarrativeHeadlineRoll,
404
+ NarrativeSummary,
405
+ PullQuote
76
406
  });
77
407
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/NarrativeContainer/NarrativeContainer.tsx"],"sourcesContent":["/* Narrative Kit — composable narrative primitives.\n * Each primitive adds a single line below. No default export — this is a kit. */\nexport {\n NarrativeContainer,\n type TypeNarrativeContainerProps,\n} from \"./NarrativeContainer\";\n\nexport type { TypeNarrativeTone } from \"./_internal/types\";\n","import * as React from \"react\";\nimport type { TypeNarrativeContainerProps } from \"./NarrativeContainerTypes\";\n\n/** Merge class names, supporting `{ \"class\": boolean }` toggles. */\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\n/**\n * NarrativeContainer — the foundational surface that narrative primitives are\n * composed inside. A padded, rounded, elevated card with a content slot and an\n * optional decorative gradient accent that wraps the top-left corner.\n *\n * Styled via `narrative-container.css` (Seeds CSS custom properties). Consumers\n * import the classes through `@sproutsocial/racine/css/components`. Surface\n * overrides are done with standard `className` / `style`.\n */\nconst NarrativeContainer = React.forwardRef<\n HTMLDivElement,\n TypeNarrativeContainerProps\n>(({ children, accent = true, className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"seeds-narrative-container\",\n { \"seeds-narrative-container-accent\": accent },\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n});\n\nNarrativeContainer.displayName = \"NarrativeContainer\";\n\nexport default NarrativeContainer;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;AAwCnB;AApCJ,SAAS,MACJ,QACK;AACR,QAAM,UAAoB,CAAC;AAE3B,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAO;AAEZ,QAAI,OAAO,UAAU,UAAU;AAC7B,cAAQ,KAAK,KAAK;AAAA,IACpB,WAAW,OAAO,UAAU,UAAU;AACpC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,YAAI,OAAO;AACT,kBAAQ,KAAK,GAAG;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ,KAAK,GAAG;AACzB;AAWA,IAAM,qBAA2B,iBAG/B,CAAC,EAAE,UAAU,SAAS,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,EAAE,oCAAoC,OAAO;AAAA,QAC7C;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ,CAAC;AAED,mBAAmB,cAAc;AAEjC,IAAO,6BAAQ;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/NarrativeContainer/NarrativeContainer.tsx","../src/_internal/cn.ts","../src/NarrativeHeadline/NarrativeHeadline.tsx","../src/NarrativeHeadline/NarrativeHeadlineHighlight.tsx","../src/NarrativeHeadline/NarrativeHeadlineRoll.tsx","../src/PullQuote/PullQuote.tsx","../src/EyebrowToken/EyebrowToken.tsx","../src/NarrativeDivider/NarrativeDivider.tsx","../src/MetricHighlight/MetricHighlight.tsx","../src/NarrativeSummary/NarrativeSummary.tsx"],"sourcesContent":["/* Narrative Kit — composable narrative primitives.\n * Each primitive adds a single line below. No default export — this is a kit. */\nexport {\n NarrativeContainer,\n type TypeNarrativeContainerProps,\n} from \"./NarrativeContainer\";\n\nexport {\n NarrativeHeadline,\n NarrativeHeadlineHighlight,\n NarrativeHeadlineRoll,\n type TypeNarrativeHeadlineProps,\n type TypeNarrativeHeadlineLevel,\n type TypeNarrativeHeadlineHighlightProps,\n type TypeNarrativeHeadlineRollProps,\n} from \"./NarrativeHeadline\";\n\nexport { PullQuote, type TypePullQuoteProps } from \"./PullQuote\";\n\nexport { EyebrowToken, type TypeEyebrowTokenProps } from \"./EyebrowToken\";\n\nexport {\n NarrativeDivider,\n type TypeNarrativeDividerProps,\n} from \"./NarrativeDivider\";\n\nexport {\n MetricHighlight,\n type TypeMetricHighlightProps,\n type TypeMetricHighlightTrend,\n} from \"./MetricHighlight\";\n\nexport {\n NarrativeSummary,\n type TypeNarrativeSummaryProps,\n type TypeNarrativeSummaryLayout,\n} from \"./NarrativeSummary\";\n\nexport type { TypeNarrativeTone } from \"./_internal/types\";\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport type { TypeNarrativeContainerProps } from \"./NarrativeContainerTypes\";\n\n/**\n * NarrativeContainer — the foundational surface that narrative primitives are\n * composed inside. A padded, rounded, elevated card with a content slot and an\n * optional decorative gradient accent that wraps the top-left corner.\n *\n * Styled via `narrative-container.css` (Seeds CSS custom properties). Consumers\n * import the classes through `@sproutsocial/racine/css/components`. Surface\n * overrides are done with standard `className` / `style`.\n */\nconst NarrativeContainer = React.forwardRef<\n HTMLDivElement,\n TypeNarrativeContainerProps\n>(({ children, accent = true, className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"seeds-narrative-container\",\n { \"seeds-narrative-container-accent\": accent },\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n});\n\nNarrativeContainer.displayName = \"NarrativeContainer\";\n\nexport default NarrativeContainer;\n","/** Merge class names, supporting `{ \"class\": boolean }` toggles. */\nexport function cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport type { TypeNarrativeHeadlineProps } from \"./NarrativeHeadlineTypes\";\n\n/**\n * NarrativeHeadline — the titling primitive for a narrative block. A single\n * heading element, nothing more: supporting copy and tags/tokens belong to\n * sibling primitives that compose alongside it, not baked into the title.\n *\n * Wrap part of the headline in `<NarrativeHeadlineHighlight>` for a static\n * gradient accent, or `<NarrativeHeadlineRoll>` for the rolling \"roll\" variant.\n *\n * Styled via `narrative-headline.css` (Seeds CSS custom properties). Consumers\n * import the classes through `@sproutsocial/racine/css/components`. Overrides\n * are done with standard `className` / `style`.\n */\nconst NarrativeHeadline = React.forwardRef<\n HTMLHeadingElement,\n TypeNarrativeHeadlineProps\n>(\n (\n { children, headingLevel = 2, size = \"default\", className, ...props },\n ref\n ) => {\n const Heading = `h${headingLevel}` as const;\n\n return (\n <Heading\n ref={ref}\n className={cn(\n \"seeds-narrative-headline\",\n { \"seeds-narrative-headline-small\": size === \"small\" },\n className\n )}\n {...props}\n >\n {children}\n </Heading>\n );\n }\n);\n\nNarrativeHeadline.displayName = \"NarrativeHeadline\";\n\nexport default NarrativeHeadline;\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport type { TypeNarrativeHeadlineHighlightProps } from \"./NarrativeHeadlineTypes\";\n\n/**\n * NarrativeHeadlineHighlight — paints a span of headline text with the AI\n * brand gradient (the \"highlighted word\" treatment). Drop it inline inside a\n * `<NarrativeHeadline>`:\n *\n * <NarrativeHeadline>\n * Headline with a <NarrativeHeadlineHighlight>highlighted</NarrativeHeadlineHighlight> word\n * </NarrativeHeadline>\n */\nconst NarrativeHeadlineHighlight = React.forwardRef<\n HTMLSpanElement,\n TypeNarrativeHeadlineHighlightProps\n>(({ children, className, ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(\"seeds-narrative-headline-highlight\", className)}\n {...props}\n >\n {children}\n </span>\n );\n});\n\nNarrativeHeadlineHighlight.displayName = \"NarrativeHeadlineHighlight\";\n\nexport default NarrativeHeadlineHighlight;\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport type { TypeNarrativeHeadlineRollProps } from \"./NarrativeHeadlineTypes\";\n\n/**\n * NarrativeHeadlineRoll — the \"roll\" variant: a vertical word roll for the\n * highlighted slot of a headline. The active word slides into view while the\n * previous one rolls out (no typing). Inspired by the performative-ui WordRoll.\n *\n * <NarrativeHeadline>\n * Built for{\" \"}\n * <NarrativeHeadlineRoll words={[\"marketers\", \"agencies\", \"teams\"]} />\n * </NarrativeHeadline>\n *\n * The container width follows the active word so it sits naturally inline.\n * Gradient-painted by default; honors `prefers-reduced-motion` by holding the\n * first word static.\n */\nconst NarrativeHeadlineRoll = React.forwardRef<\n HTMLSpanElement,\n TypeNarrativeHeadlineRollProps\n>(\n (\n {\n words,\n intervalMs = 2200,\n transitionMs = 500,\n direction = \"up\",\n gradient = true,\n className,\n style,\n ...rest\n },\n ref\n ) => {\n const [i, setI] = React.useState(0);\n\n React.useEffect(() => {\n if (words.length <= 1) return;\n\n // Respect reduced-motion: hold the first word, skip the cycle entirely.\n const reduced =\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n if (reduced) return;\n\n const t = setInterval(\n () => setI((j) => (j + 1) % words.length),\n intervalMs\n );\n return () => clearInterval(t);\n }, [intervalMs, words.length]);\n\n const merged: React.CSSProperties = {\n ...style,\n // Consumed by the transition timing in narrative-headline.css.\n [\"--seeds-narrative-headline-roll-ms\" as string]: `${transitionMs}ms`,\n };\n\n const prev = words.length ? (i - 1 + words.length) % words.length : 0;\n\n return (\n <span\n ref={ref}\n className={cn(\n \"seeds-narrative-headline-roll\",\n { \"seeds-narrative-headline-roll-down\": direction === \"down\" },\n { \"seeds-narrative-headline-roll-gradient\": gradient },\n className\n )}\n style={merged}\n {...rest}\n >\n {/* Sizer keeps the container width matched to the active word — without\n it the absolutely-positioned words would collapse the box. */}\n <span\n className=\"seeds-narrative-headline-roll-sizer\"\n aria-hidden=\"true\"\n >\n {words[i]}\n </span>\n {words.map((w, idx) => (\n <span\n key={idx}\n className={cn(\"seeds-narrative-headline-roll-word\", {\n \"seeds-narrative-headline-roll-word-active\": idx === i,\n \"seeds-narrative-headline-roll-word-past\":\n idx === prev && i !== prev,\n })}\n aria-hidden={idx === i ? undefined : \"true\"}\n >\n {w}\n </span>\n ))}\n </span>\n );\n }\n);\n\nNarrativeHeadlineRoll.displayName = \"NarrativeHeadlineRoll\";\n\nexport default NarrativeHeadlineRoll;\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport type { TypePullQuoteProps } from \"./PullQuoteTypes\";\n\n/**\n * PullQuote — a narrative primitive that spotlights a quotation on an AI\n * gradient surface. The quote sits behind an accented vertical bar with an\n * optional attribution row (author name, avatar, network).\n *\n * Rendered as semantic `<figure>` / `<blockquote>` / `<figcaption>` markup.\n * Styled via `pull-quote.css` (Seeds CSS custom properties); consumers import\n * the classes through `@sproutsocial/racine/css/components`. Surface overrides\n * are done with standard `className` / `style`.\n */\nconst PullQuote = React.forwardRef<HTMLElement, TypePullQuoteProps>(\n ({ quote, attribution, appearance = \"subtle\", className, ...props }, ref) => {\n return (\n <figure\n ref={ref}\n className={cn(\n \"seeds-pull-quote\",\n { \"seeds-pull-quote-vivid\": appearance === \"vivid\" },\n className\n )}\n {...props}\n >\n <div className=\"seeds-pull-quote-bar\">\n <blockquote className=\"seeds-pull-quote-text\">{quote}</blockquote>\n {attribution != null && (\n <figcaption className=\"seeds-pull-quote-attribution\">\n {attribution}\n </figcaption>\n )}\n </div>\n </figure>\n );\n }\n);\n\nPullQuote.displayName = \"PullQuote\";\n\nexport default PullQuote;\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport type { TypeEyebrowTokenProps } from \"./EyebrowTokenTypes\";\n\n/**\n * EyebrowToken — a small gray pill that sits above a headline to carry a short\n * bit of context: a date (e.g. \"May 31, 2026\"), category, or kicker.\n *\n * A faithful match of the Figma \"Token / Non Clickable / Default\" design — a\n * solid `#dee1e1` fill with a matching border, 6px radius, and small body text.\n * Styled via `eyebrow-token.css` (Seeds CSS custom properties); consumers import\n * the classes through `@sproutsocial/racine/css/components`. Overrides come via\n * standard `className` / `style`.\n */\nconst EyebrowToken = React.forwardRef<HTMLSpanElement, TypeEyebrowTokenProps>(\n ({ children, className, ...props }, ref) => (\n <span ref={ref} className={cn(\"seeds-eyebrow-token\", className)} {...props}>\n {children}\n </span>\n )\n);\n\nEyebrowToken.displayName = \"EyebrowToken\";\n\nexport default EyebrowToken;\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport type { TypeNarrativeDividerProps } from \"./NarrativeDividerTypes\";\n\n/**\n * NarrativeDivider — a full-width, 1px horizontal rule that separates sections\n * within a narrative brief (e.g. a row of metrics from the headline/summary\n * block below it).\n *\n * Renders a semantic <hr> stripped of its user-agent margins and borders, then\n * draws a single 1px line with the container-border-base token (#dee1e1, which\n * also tracks dark mode). Styled via narrative-divider.css (Seeds CSS custom\n * properties); consumers import the classes through\n * @sproutsocial/racine/css/components. Overrides come via standard className /\n * style.\n */\nconst NarrativeDivider = React.forwardRef<\n HTMLHRElement,\n TypeNarrativeDividerProps\n>(({ className, ...props }, ref) => (\n <hr\n ref={ref}\n className={cn(\"seeds-narrative-divider\", className)}\n {...props}\n />\n));\n\nNarrativeDivider.displayName = \"NarrativeDivider\";\n\nexport default NarrativeDivider;\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport type {\n TypeMetricHighlightProps,\n TypeMetricHighlightTrend,\n} from \"./MetricHighlightTypes\";\n\n/** Directional arrow glyph for the trend badge (decorative; `aria-hidden`). */\nconst TrendArrow = ({ direction }: { direction: \"up\" | \"down\" }) => (\n <svg\n className=\"seeds-metric-highlight-trend-arrow\"\n viewBox=\"0 0 16 16\"\n aria-hidden\n focusable={false}\n >\n {direction === \"up\" ? (\n <path\n d=\"M4.5 11.5 11.5 4.5M11.5 4.5H5.5M11.5 4.5V10.5\"\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n ) : (\n <path\n d=\"M4.5 4.5 11.5 11.5M11.5 11.5H5.5M11.5 11.5V5.5\"\n fill=\"none\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n </svg>\n);\n\nconst TrendBadge = ({\n direction = \"up\",\n value,\n ...rest\n}: TypeMetricHighlightTrend) => (\n <span\n className={cn(\"seeds-metric-highlight-trend\", {\n \"seeds-metric-highlight-trend-down\": direction === \"down\",\n })}\n {...rest}\n >\n <TrendArrow direction={direction} />\n {value != null && (\n <span className=\"seeds-metric-highlight-trend-value\">{value}</span>\n )}\n </span>\n);\n\n/**\n * MetricHighlight — a narrative primitive that spotlights a single metric: a\n * label, a large monospace value, an optional trend badge (a directional arrow\n * plus an optional number such as \"240%\"), and an optional chart supplied via\n * the `sparkline` slot (e.g. a `<SparklineChart />` from\n * `@sproutsocial/seeds-react-data-viz/sparkline`).\n *\n * Styled via `metric-highlight.css` (Seeds CSS custom properties); consumers\n * import the classes through `@sproutsocial/racine/css/components`. Layout flexes\n * across `appearance` (horizontal/vertical) and `size` (default/small); surface\n * overrides are done with standard `className` / `style`.\n */\nconst MetricHighlight = React.forwardRef<\n HTMLDivElement,\n TypeMetricHighlightProps\n>(\n (\n {\n label,\n value,\n trend,\n sparkline,\n appearance = \"horizontal\",\n size = \"default\",\n container = true,\n className,\n ...props\n },\n ref\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"seeds-metric-highlight\",\n {\n \"seeds-metric-highlight-vertical\": appearance === \"vertical\",\n \"seeds-metric-highlight-small\": size === \"small\",\n \"seeds-metric-highlight-bare\": !container,\n },\n className\n )}\n {...props}\n >\n <div className=\"seeds-metric-highlight-metric\">\n <p className=\"seeds-metric-highlight-label\">{label}</p>\n <div className=\"seeds-metric-highlight-value-row\">\n <p className=\"seeds-metric-highlight-value\">{value}</p>\n {trend != null && <TrendBadge {...trend} />}\n </div>\n </div>\n {sparkline != null && (\n // Layout-only slot (bounded dimensions per horizontal/vertical/small)\n // for a consumer-supplied chart. It controls its own look; the slot\n // only sizes and centers it.\n <div className=\"seeds-metric-highlight-chart\">{sparkline}</div>\n )}\n </div>\n );\n }\n);\n\nMetricHighlight.displayName = \"MetricHighlight\";\n\nexport default MetricHighlight;\n","import * as React from \"react\";\nimport { cn } from \"../_internal/cn\";\nimport EyebrowToken from \"../EyebrowToken/EyebrowToken\";\nimport NarrativeHeadline from \"../NarrativeHeadline/NarrativeHeadline\";\nimport type { TypeNarrativeSummaryProps } from \"./NarrativeSummaryTypes\";\n\n/**\n * NarrativeSummary — a composed narrative block that pairs a lead column\n * (eyebrow + headline + optional action) with a Summary section and a Key\n * themes list.\n *\n * Renders inner content only — it carries no surface, shadow, or accent of its\n * own. Drop it into a `NarrativeContainer` (see the stories / playground).\n *\n * Layout is CSS Grid driven by container queries, so the columns collapse based\n * on the width the component is actually given, not the viewport:\n * - `\"three-column\"` → lead | Summary | Key themes.\n * - `\"two-column\"` → a 1/3 | 2/3 split with Summary and Key themes stacked in\n * the wider column.\n *\n * Styled via `narrative-summary.css` (Seeds CSS custom properties); consumers\n * import the classes through `@sproutsocial/racine/css/components`. Overrides\n * come via standard `className` / `style`.\n */\nconst NarrativeSummary = React.forwardRef<\n HTMLDivElement,\n TypeNarrativeSummaryProps\n>(\n (\n {\n eyebrow,\n headline,\n headingLevel = 2,\n action,\n summary,\n summaryLabel = \"Summary\",\n keyThemes,\n keyThemesLabel = \"Key themes\",\n layout = \"three-column\",\n className,\n ...props\n },\n ref\n ) => {\n const hasKeyThemes = keyThemes != null && keyThemes.length > 0;\n\n return (\n <div\n ref={ref}\n className={cn(\"seeds-narrative-summary\", className)}\n {...props}\n >\n <div\n className={cn(\"seeds-narrative-summary-grid\", {\n \"seeds-narrative-summary-two-column\": layout === \"two-column\",\n })}\n >\n <div className=\"seeds-narrative-summary-lead\">\n {eyebrow != null && <EyebrowToken>{eyebrow}</EyebrowToken>}\n <div className=\"seeds-narrative-summary-headline\">\n <NarrativeHeadline size=\"small\" headingLevel={headingLevel}>\n {headline}\n </NarrativeHeadline>\n </div>\n {action != null && (\n <div className=\"seeds-narrative-summary-action\">{action}</div>\n )}\n </div>\n\n <div className=\"seeds-narrative-summary-content\">\n {summary != null && (\n <section className=\"seeds-narrative-summary-section\">\n <p className=\"seeds-narrative-summary-label\">{summaryLabel}</p>\n <p className=\"seeds-narrative-summary-text\">{summary}</p>\n </section>\n )}\n {hasKeyThemes && (\n <section className=\"seeds-narrative-summary-section\">\n <p className=\"seeds-narrative-summary-label\">\n {keyThemesLabel}\n </p>\n <ul className=\"seeds-narrative-summary-list\">\n {keyThemes.map((theme, i) => (\n <li key={i}>{theme}</li>\n ))}\n </ul>\n </section>\n )}\n </div>\n </div>\n </div>\n );\n }\n);\n\nNarrativeSummary.displayName = \"NarrativeSummary\";\n\nexport default NarrativeSummary;\n"],"mappings":"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","names":["React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime"]}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Seeds MetricHighlight component classes.
3
+ * Use these instead of writing out individual Tailwind utility classes.
4
+ *
5
+ * Requires @sproutsocial/seeds-react-theme/dist/theme-all.css imported for
6
+ * CSS variable definitions and dark mode support.
7
+ *
8
+ * Usage:
9
+ * <div class="seeds-metric-highlight">…</div> // horizontal, default
10
+ * <div class="seeds-metric-highlight seeds-metric-highlight-vertical">…</div>
11
+ * <div class="seeds-metric-highlight seeds-metric-highlight-small">…</div>
12
+ * <div class="seeds-metric-highlight seeds-metric-highlight-bare">…</div> // no surface
13
+ */
14
+
15
+ @layer components {
16
+
17
+ .seeds-metric-highlight {
18
+ box-sizing: border-box;
19
+ display: flex;
20
+ align-items: flex-start;
21
+ gap: var(--space-350); /* 12px */
22
+ border-radius: var(--radius-800); /* 12px */
23
+ font-family: var(--font-family);
24
+ /* Container (default): a padded gray app surface (matches the design's
25
+ #f3f4f4 box). `-bare` strips it. */
26
+ padding: var(--space-400) var(--space-450); /* 16px / 24px */
27
+ background-color: var(--color-app-bg-base);
28
+ }
29
+
30
+ .seeds-metric-highlight-bare {
31
+ padding: 0;
32
+ background-color: transparent;
33
+ }
34
+
35
+ .seeds-metric-highlight-vertical {
36
+ flex-direction: column;
37
+ }
38
+
39
+ /* The metric block: label + value/trend. Grows to fill the row in horizontal. */
40
+ .seeds-metric-highlight-metric {
41
+ box-sizing: border-box;
42
+ display: flex;
43
+ flex-direction: column;
44
+ align-items: flex-start;
45
+ gap: var(--space-200); /* 4px */
46
+ flex: 1 0 0;
47
+ min-width: 0;
48
+ }
49
+
50
+ .seeds-metric-highlight-vertical .seeds-metric-highlight-metric {
51
+ width: 100%;
52
+ flex: 0 0 auto;
53
+ }
54
+
55
+ /* Small: label and value collapse onto a single centered row. */
56
+ .seeds-metric-highlight-small .seeds-metric-highlight-metric {
57
+ flex-direction: row;
58
+ align-items: center;
59
+ gap: var(--space-300); /* 8px */
60
+ }
61
+
62
+ .seeds-metric-highlight-label {
63
+ margin: 0;
64
+ font-size: var(--font-size-300); /* 16px */
65
+ line-height: var(--line-height-400); /* ~28px */
66
+ font-weight: var(--font-weight-normal);
67
+ color: var(--color-text-body);
68
+ overflow-wrap: break-word;
69
+ }
70
+
71
+ /* In small, the label takes the slack so the value/trend align to the end. */
72
+ .seeds-metric-highlight-small .seeds-metric-highlight-label {
73
+ flex: 1 0 0;
74
+ min-width: 0;
75
+ }
76
+
77
+ .seeds-metric-highlight-value-row {
78
+ display: flex;
79
+ align-items: center;
80
+ gap: var(--space-300); /* 8px */
81
+ }
82
+
83
+ .seeds-metric-highlight-small .seeds-metric-highlight-value-row {
84
+ justify-content: flex-end;
85
+ }
86
+
87
+ .seeds-metric-highlight-value {
88
+ margin: 0;
89
+ /* No mono token exists yet; fall back to a system monospace stack. Mirrors the
90
+ font/font-mono treatment in the design. */
91
+ font-family: var(--font-family-mono, ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace);
92
+ font-size: var(--font-size-700); /* 32px */
93
+ line-height: var(--line-height-700); /* 40px */
94
+ font-weight: var(--font-weight-bold);
95
+ color: var(--color-text-headline);
96
+ white-space: nowrap;
97
+ }
98
+
99
+ .seeds-metric-highlight-small .seeds-metric-highlight-value {
100
+ font-size: var(--font-size-600); /* 24px */
101
+ line-height: var(--line-height-600); /* 32px */
102
+ }
103
+
104
+ /* Trend badge — a rounded pill. Up is the positive (green) treatment; down
105
+ swaps to the negative (red) treatment. Color flows to the arrow + value via
106
+ currentColor. */
107
+ .seeds-metric-highlight-trend {
108
+ display: inline-flex;
109
+ align-items: center;
110
+ gap: var(--space-200); /* 4px */
111
+ padding: var(--space-100) var(--space-300); /* 2px / 8px */
112
+ border-radius: 999px;
113
+ font-size: var(--font-size-200); /* 13px */
114
+ line-height: var(--line-height-200);
115
+ font-weight: var(--font-weight-bold);
116
+ white-space: nowrap;
117
+ background-color: var(--color-container-bg-decorative-green);
118
+ color: var(--color-text-decorative-green);
119
+ }
120
+
121
+ .seeds-metric-highlight-trend-down {
122
+ background-color: var(--color-container-bg-decorative-red);
123
+ color: var(--color-text-decorative-red);
124
+ }
125
+
126
+ .seeds-metric-highlight-trend-arrow {
127
+ flex: 0 0 auto;
128
+ width: 1em;
129
+ height: 1em;
130
+ stroke: currentColor;
131
+ stroke-width: 1.5;
132
+ }
133
+
134
+ /* Slot for an injected chart (e.g. a data-viz SparklineChart). Layout only — no
135
+ stroke/background styling, so the injected chart controls its own look. Heights
136
+ are explicit (never percentage/stretch) so a Highcharts chart always measures a
137
+ concrete container instead of falling back to its 400px default. */
138
+ .seeds-metric-highlight-chart {
139
+ box-sizing: border-box;
140
+ flex: 0 0 auto;
141
+ align-self: center;
142
+ /* Center the injected chart as a flex item — an inline/inline-block child
143
+ (e.g. the data-viz SparklineChart) otherwise sits on the text baseline with
144
+ descender space below it, reading as vertically off-center in the slot. */
145
+ display: flex;
146
+ align-items: center;
147
+ }
148
+
149
+ .seeds-metric-highlight:not(.seeds-metric-highlight-vertical) .seeds-metric-highlight-chart {
150
+ width: 104px;
151
+ height: 48px;
152
+ }
153
+
154
+ .seeds-metric-highlight-small:not(.seeds-metric-highlight-vertical) .seeds-metric-highlight-chart {
155
+ width: 88px;
156
+ height: 40px;
157
+ }
158
+
159
+ .seeds-metric-highlight-vertical .seeds-metric-highlight-chart {
160
+ width: 100%;
161
+ height: 96px;
162
+ }
163
+
164
+ .seeds-metric-highlight-vertical.seeds-metric-highlight-small .seeds-metric-highlight-chart {
165
+ height: 56px;
166
+ }
167
+
168
+ }
@@ -17,7 +17,7 @@
17
17
  box-sizing: border-box;
18
18
  display: flex;
19
19
  flex-direction: column;
20
- align-items: flex-start;
20
+ align-items: stretch;
21
21
  padding: var(--space-500);
22
22
  border-radius: var(--radius-800);
23
23
  box-shadow: var(--shadow-low);
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Seeds NarrativeDivider component classes.
3
+ * Use these instead of writing out individual Tailwind utility classes.
4
+ *
5
+ * Requires @sproutsocial/seeds-react-theme/dist/theme-all.css imported for
6
+ * CSS variable definitions and dark mode support.
7
+ *
8
+ * Usage:
9
+ * <hr class="seeds-narrative-divider" />
10
+ */
11
+
12
+ @layer components {
13
+
14
+ /* A full-width, 1px horizontal rule. The <hr> ships with user-agent margins
15
+ and a beveled border, so reset those and draw the line with a single
16
+ border-top using the container-border-base token (#dee1e1), which also
17
+ tracks dark mode. */
18
+ .seeds-narrative-divider {
19
+ box-sizing: border-box;
20
+ width: 100%;
21
+ height: 0;
22
+ margin: 0;
23
+ border: 0;
24
+ border-top: 1px solid var(--color-container-border-base); /* #dee1e1 */
25
+ }
26
+
27
+ }