@usefidel/design-system 0.20.0 → 0.22.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/dist/admin.css CHANGED
@@ -32,6 +32,7 @@
32
32
  --color-success: #059669;
33
33
  --color-success-bg: #f0fdf4;
34
34
  --color-success-text: #15803d;
35
+ --color-success-border: #bbf7d0;
35
36
  --color-warning: #ca8a04;
36
37
  --color-warning-bg: #fffbeb;
37
38
  --color-warning-text: #92400e;
@@ -56,6 +57,17 @@
56
57
  --color-error-pressed: #7f1d1d;
57
58
  --color-error-border-hover: #fca5a5;
58
59
  --color-error-bg-pressed: #fee2e2;
60
+ --color-white-alpha-6: rgba(255, 255, 255, 0.06);
61
+ --color-white-alpha-8: rgba(255, 255, 255, 0.08);
62
+ --color-white-alpha-10: rgba(255, 255, 255, 0.1);
63
+ --color-white-alpha-12: rgba(255, 255, 255, 0.12);
64
+ --color-white-alpha-35: rgba(255, 255, 255, 0.35);
65
+ --color-white-alpha-55: rgba(255, 255, 255, 0.55);
66
+ --color-white-alpha-60: rgba(255, 255, 255, 0.6);
67
+ --color-white-alpha-92: rgba(255, 255, 255, 0.92);
68
+ --color-black-alpha-4: rgba(0, 0, 0, 0.04);
69
+ --color-black-alpha-8: rgba(0, 0, 0, 0.08);
70
+ --color-black-alpha-60: rgba(0, 0, 0, 0.6);
59
71
  --font-display: 'Rethink Sans', system-ui, -apple-system, sans-serif;
60
72
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
61
73
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
@@ -130,9 +142,12 @@
130
142
  --shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.06), 0 16px 40px rgba(0, 0, 0, 0.1);
131
143
  --shadow-pill: 0 1px 2px rgba(15, 23, 42, 0.08);
132
144
  --shadow-cta: 0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.06);
145
+ --shadow-popover: 0 1px 2px rgba(15, 23, 42, 0.08), 0 8px 24px rgba(15, 23, 42, 0.14);
146
+ --shadow-focus-error: 0 0 0 3px rgba(220, 38, 38, 0.15);
133
147
  --font-weight-regular: 400;
134
148
  --font-weight-medium: 500;
135
149
  --font-weight-semibold: 600;
136
150
  --font-weight-bold: 700;
137
151
  --font-weight-extrabold: 800;
152
+ --gradient-brand-warm: linear-gradient(160deg, #fbfbfb 34%, #f29c6f 90%);
138
153
  }
@@ -32,6 +32,7 @@
32
32
  --color-success: #059669;
33
33
  --color-success-bg: #f0fdf4;
34
34
  --color-success-text: #15803d;
35
+ --color-success-border: #bbf7d0;
35
36
  --color-warning: #ca8a04;
36
37
  --color-warning-bg: #fffbeb;
37
38
  --color-warning-text: #92400e;
@@ -56,6 +57,17 @@
56
57
  --color-error-pressed: #7f1d1d;
57
58
  --color-error-border-hover: #fca5a5;
58
59
  --color-error-bg-pressed: #fee2e2;
60
+ --color-white-alpha-6: rgba(255, 255, 255, 0.06);
61
+ --color-white-alpha-8: rgba(255, 255, 255, 0.08);
62
+ --color-white-alpha-10: rgba(255, 255, 255, 0.1);
63
+ --color-white-alpha-12: rgba(255, 255, 255, 0.12);
64
+ --color-white-alpha-35: rgba(255, 255, 255, 0.35);
65
+ --color-white-alpha-55: rgba(255, 255, 255, 0.55);
66
+ --color-white-alpha-60: rgba(255, 255, 255, 0.6);
67
+ --color-white-alpha-92: rgba(255, 255, 255, 0.92);
68
+ --color-black-alpha-4: rgba(0, 0, 0, 0.04);
69
+ --color-black-alpha-8: rgba(0, 0, 0, 0.08);
70
+ --color-black-alpha-60: rgba(0, 0, 0, 0.6);
59
71
  --font-display: 'Rethink Sans', system-ui, -apple-system, sans-serif;
60
72
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
61
73
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
@@ -130,9 +142,12 @@
130
142
  --shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.06), 0 16px 40px rgba(0, 0, 0, 0.1);
131
143
  --shadow-pill: 0 1px 2px rgba(15, 23, 42, 0.08);
132
144
  --shadow-cta: 0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.06);
145
+ --shadow-popover: 0 1px 2px rgba(15, 23, 42, 0.08), 0 8px 24px rgba(15, 23, 42, 0.14);
146
+ --shadow-focus-error: 0 0 0 3px rgba(220, 38, 38, 0.15);
133
147
  --font-weight-regular: 400;
134
148
  --font-weight-medium: 500;
135
149
  --font-weight-semibold: 600;
136
150
  --font-weight-bold: 700;
137
151
  --font-weight-extrabold: 800;
152
+ --gradient-brand-warm: linear-gradient(160deg, #fbfbfb 34%, #f29c6f 90%);
138
153
  }
@@ -10,6 +10,6 @@
10
10
  "webapp.css"
11
11
  ],
12
12
  "storybookUrl": null,
13
- "packageVersion": "0.20.0",
14
- "resolvedSha": "03e0eb5580241d65f5ba3e517571a81ccb6f792d"
13
+ "packageVersion": "0.22.0",
14
+ "resolvedSha": "6456c3022db3b5a3641365c386dec120fa3485b5"
15
15
  }
package/dist/index.cjs CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  Pagination: () => Pagination,
42
42
  PricingCard: () => PricingCard,
43
43
  Radio: () => Radio,
44
+ RadioCard: () => RadioCard,
44
45
  SearchInput: () => SearchInput,
45
46
  SectionHeader: () => SectionHeader,
46
47
  SegmentedControl: () => SegmentedControl,
@@ -1463,9 +1464,41 @@ var Radio = (0, import_react13.forwardRef)(function Radio2({ label, description,
1463
1464
  ] });
1464
1465
  });
1465
1466
 
1466
- // src/components/Accordion/Accordion.tsx
1467
+ // src/components/RadioCard/RadioCard.tsx
1467
1468
  var import_react14 = require("react");
1468
1469
  var import_jsx_runtime27 = require("react/jsx-runtime");
1470
+ var RadioCard = (0, import_react14.forwardRef)(function RadioCard2({ label, description, icon, meta, className, id, disabled, ...rest }, ref) {
1471
+ const generatedId = (0, import_react14.useId)();
1472
+ const inputId = id ?? generatedId;
1473
+ const descriptionId = description != null ? `${inputId}-description` : void 0;
1474
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: ["fds-radio-card", className].filter(Boolean).join(" "), "data-disabled": disabled ? "" : void 0, children: [
1475
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1476
+ "input",
1477
+ {
1478
+ ...rest,
1479
+ id: inputId,
1480
+ ref,
1481
+ type: "radio",
1482
+ disabled,
1483
+ "aria-describedby": descriptionId,
1484
+ className: "fds-radio-card__input"
1485
+ }
1486
+ ),
1487
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { htmlFor: inputId, className: "fds-radio-card__body", children: [
1488
+ icon != null && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "fds-radio-card__icon", "aria-hidden": "true", children: icon }),
1489
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "fds-radio-card__text", children: [
1490
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "fds-radio-card__label", children: label }),
1491
+ description != null && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { id: descriptionId, className: "fds-radio-card__description", children: description }),
1492
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "fds-radio-card__meta", children: meta })
1493
+ ] }),
1494
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "fds-radio-card__circle", "aria-hidden": "true" })
1495
+ ] })
1496
+ ] });
1497
+ });
1498
+
1499
+ // src/components/Accordion/Accordion.tsx
1500
+ var import_react15 = require("react");
1501
+ var import_jsx_runtime28 = require("react/jsx-runtime");
1469
1502
  function Accordion({
1470
1503
  summary,
1471
1504
  actions,
@@ -1476,23 +1509,23 @@ function Accordion({
1476
1509
  className,
1477
1510
  ...rest
1478
1511
  }) {
1479
- const [openState, setOpenState] = (0, import_react14.useState)(defaultOpen);
1512
+ const [openState, setOpenState] = (0, import_react15.useState)(defaultOpen);
1480
1513
  const open = openProp ?? openState;
1481
- const bodyId = (0, import_react14.useId)();
1514
+ const bodyId = (0, import_react15.useId)();
1482
1515
  const toggle = () => {
1483
1516
  const next = !open;
1484
1517
  if (openProp === void 0) setOpenState(next);
1485
1518
  onOpenChange?.(next);
1486
1519
  };
1487
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
1520
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1488
1521
  "div",
1489
1522
  {
1490
1523
  className: ["fds-accordion", className].filter(Boolean).join(" "),
1491
1524
  "data-open": open ? "" : void 0,
1492
1525
  ...rest,
1493
1526
  children: [
1494
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "fds-accordion__header", children: [
1495
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1527
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "fds-accordion__header", children: [
1528
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1496
1529
  "button",
1497
1530
  {
1498
1531
  type: "button",
@@ -1503,17 +1536,17 @@ function Accordion({
1503
1536
  children: summary
1504
1537
  }
1505
1538
  ),
1506
- actions != null && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "fds-accordion__actions", children: actions }),
1507
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "fds-accordion__chevron", "aria-hidden": "true", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { d: "M6 9l6 6 6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
1539
+ actions != null && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "fds-accordion__actions", children: actions }),
1540
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "fds-accordion__chevron", "aria-hidden": "true", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { d: "M6 9l6 6 6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
1508
1541
  ] }),
1509
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { id: bodyId, className: "fds-accordion__body", hidden: !open, children })
1542
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { id: bodyId, className: "fds-accordion__body", hidden: !open, children })
1510
1543
  ]
1511
1544
  }
1512
1545
  );
1513
1546
  }
1514
1547
 
1515
1548
  // src/components/StepList/StepList.tsx
1516
- var import_jsx_runtime28 = require("react/jsx-runtime");
1549
+ var import_jsx_runtime29 = require("react/jsx-runtime");
1517
1550
  var STATUS_TEXT = {
1518
1551
  done: "Done",
1519
1552
  active: "In progress",
@@ -1523,32 +1556,32 @@ var STATUS_TEXT = {
1523
1556
  function StepIcon({ status }) {
1524
1557
  const common = { viewBox: "0 0 24 24", width: 18, height: 18, fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
1525
1558
  if (status === "done") {
1526
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("svg", { ...common, children: [
1527
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
1528
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { d: "M8 12.5l2.5 2.5 5-5.5" })
1559
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("svg", { ...common, children: [
1560
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
1561
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { d: "M8 12.5l2.5 2.5 5-5.5" })
1529
1562
  ] });
1530
1563
  }
1531
1564
  if (status === "active") {
1532
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { ...common, className: "fds-steps__spinner", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { d: "M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1" }) });
1565
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { ...common, className: "fds-steps__spinner", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { d: "M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1" }) });
1533
1566
  }
1534
1567
  if (status === "failed") {
1535
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("svg", { ...common, children: [
1536
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
1537
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { d: "M12 7.5v5.5M12 16.5v.01" })
1568
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("svg", { ...common, children: [
1569
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
1570
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { d: "M12 7.5v5.5M12 16.5v.01" })
1538
1571
  ] });
1539
1572
  }
1540
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { ...common, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("circle", { cx: "12", cy: "12", r: "9" }) });
1573
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { ...common, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("circle", { cx: "12", cy: "12", r: "9" }) });
1541
1574
  }
1542
1575
  function StepList({ steps, className, ...rest }) {
1543
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("ol", { className: ["fds-steps", className].filter(Boolean).join(" "), ...rest, children: steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1576
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("ol", { className: ["fds-steps", className].filter(Boolean).join(" "), ...rest, children: steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1544
1577
  "li",
1545
1578
  {
1546
1579
  className: `fds-steps__step fds-steps__step--${step.status}`,
1547
1580
  "aria-current": step.status === "active" ? "step" : void 0,
1548
1581
  children: [
1549
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "fds-steps__icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(StepIcon, { status: step.status }) }),
1550
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "fds-steps__label", children: step.label }),
1551
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "fds-steps__sr", children: [
1582
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "fds-steps__icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(StepIcon, { status: step.status }) }),
1583
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "fds-steps__label", children: step.label }),
1584
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "fds-steps__sr", children: [
1552
1585
  ", ",
1553
1586
  STATUS_TEXT[step.status]
1554
1587
  ] })
@@ -1559,10 +1592,10 @@ function StepList({ steps, className, ...rest }) {
1559
1592
  }
1560
1593
 
1561
1594
  // src/components/Input/Input.tsx
1562
- var import_react15 = require("react");
1563
- var import_jsx_runtime29 = require("react/jsx-runtime");
1564
- var Input = (0, import_react15.forwardRef)(function Input2({ label, hint, error, leadingIcon, trailing, id, className, containerClassName, readOnly, disabled, ...rest }, ref) {
1565
- const genId = (0, import_react15.useId)();
1595
+ var import_react16 = require("react");
1596
+ var import_jsx_runtime30 = require("react/jsx-runtime");
1597
+ var Input = (0, import_react16.forwardRef)(function Input2({ label, hint, error, leadingIcon, trailing, id, className, containerClassName, readOnly, disabled, ...rest }, ref) {
1598
+ const genId = (0, import_react16.useId)();
1566
1599
  const inputId = id ?? genId;
1567
1600
  const msgId = `${genId}-msg`;
1568
1601
  const message = error ?? hint;
@@ -1571,11 +1604,11 @@ var Input = (0, import_react15.forwardRef)(function Input2({ label, hint, error,
1571
1604
  error ? "fds-input__box--error" : "",
1572
1605
  readOnly || disabled ? "fds-input__box--locked" : ""
1573
1606
  ].filter(Boolean).join(" ");
1574
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: ["fds-input", containerClassName].filter(Boolean).join(" "), children: [
1575
- label != null && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("label", { htmlFor: inputId, className: "fds-input__label", children: label }),
1576
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: boxClasses, children: [
1577
- leadingIcon != null && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "fds-input__icon", "aria-hidden": "true", children: leadingIcon }),
1578
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
1607
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: ["fds-input", containerClassName].filter(Boolean).join(" "), children: [
1608
+ label != null && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { htmlFor: inputId, className: "fds-input__label", children: label }),
1609
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: boxClasses, children: [
1610
+ leadingIcon != null && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "fds-input__icon", "aria-hidden": "true", children: leadingIcon }),
1611
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1579
1612
  "input",
1580
1613
  {
1581
1614
  ref,
@@ -1588,14 +1621,14 @@ var Input = (0, import_react15.forwardRef)(function Input2({ label, hint, error,
1588
1621
  ...rest
1589
1622
  }
1590
1623
  ),
1591
- trailing != null && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "fds-input__trailing", children: trailing })
1624
+ trailing != null && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "fds-input__trailing", children: trailing })
1592
1625
  ] }),
1593
- message != null && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { id: msgId, className: error ? "fds-input__error" : "fds-input__hint", children: message })
1626
+ message != null && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { id: msgId, className: error ? "fds-input__error" : "fds-input__hint", children: message })
1594
1627
  ] });
1595
1628
  });
1596
1629
 
1597
1630
  // src/components/IconButton/IconButton.tsx
1598
- var import_jsx_runtime30 = require("react/jsx-runtime");
1631
+ var import_jsx_runtime31 = require("react/jsx-runtime");
1599
1632
  function IconButton({
1600
1633
  icon,
1601
1634
  variant = "outlined",
@@ -1605,20 +1638,20 @@ function IconButton({
1605
1638
  ...rest
1606
1639
  }) {
1607
1640
  const classes = ["fds-icon-button", `fds-icon-button--${variant}`, `fds-icon-button--${size}`, className].filter(Boolean).join(" ");
1608
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type, className: classes, ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "fds-icon-button__icon", "aria-hidden": "true", children: icon }) });
1641
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type, className: classes, ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "fds-icon-button__icon", "aria-hidden": "true", children: icon }) });
1609
1642
  }
1610
1643
 
1611
1644
  // src/components/Menu/Menu.tsx
1612
- var import_react16 = require("react");
1613
- var import_jsx_runtime31 = require("react/jsx-runtime");
1645
+ var import_react17 = require("react");
1646
+ var import_jsx_runtime32 = require("react/jsx-runtime");
1614
1647
  function Menu({ trigger, items, align = "end", className }) {
1615
- const listId = (0, import_react16.useId)();
1616
- const rootRef = (0, import_react16.useRef)(null);
1617
- const listRef = (0, import_react16.useRef)(null);
1618
- const [open, setOpen] = (0, import_react16.useState)(false);
1619
- const [active, setActive] = (0, import_react16.useState)(0);
1648
+ const listId = (0, import_react17.useId)();
1649
+ const rootRef = (0, import_react17.useRef)(null);
1650
+ const listRef = (0, import_react17.useRef)(null);
1651
+ const [open, setOpen] = (0, import_react17.useState)(false);
1652
+ const [active, setActive] = (0, import_react17.useState)(0);
1620
1653
  const enabled = items.map((it, i) => it.disabled ? -1 : i).filter((i) => i >= 0);
1621
- (0, import_react16.useEffect)(() => {
1654
+ (0, import_react17.useEffect)(() => {
1622
1655
  if (!open) return;
1623
1656
  const onDown = (e) => {
1624
1657
  if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
@@ -1672,7 +1705,7 @@ function Menu({ trigger, items, align = "end", className }) {
1672
1705
  } else if (e.key === "Tab") setOpen(false);
1673
1706
  };
1674
1707
  const own = trigger.props;
1675
- const wired = (0, import_react16.cloneElement)(trigger, {
1708
+ const wired = (0, import_react17.cloneElement)(trigger, {
1676
1709
  "aria-haspopup": "menu",
1677
1710
  "aria-expanded": open,
1678
1711
  "aria-controls": open ? listId : void 0,
@@ -1692,9 +1725,9 @@ function Menu({ trigger, items, align = "end", className }) {
1692
1725
  }
1693
1726
  }
1694
1727
  });
1695
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { ref: rootRef, className: ["fds-menu", className].filter(Boolean).join(" "), children: [
1728
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { ref: rootRef, className: ["fds-menu", className].filter(Boolean).join(" "), children: [
1696
1729
  wired,
1697
- open && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
1730
+ open && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1698
1731
  "div",
1699
1732
  {
1700
1733
  ref: listRef,
@@ -1704,7 +1737,7 @@ function Menu({ trigger, items, align = "end", className }) {
1704
1737
  className: `fds-menu__list fds-menu__list--${align}`,
1705
1738
  "aria-activedescendant": `${listId}-item-${active}`,
1706
1739
  onKeyDown: onListKeyDown,
1707
- children: items.map((it, i) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
1740
+ children: items.map((it, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
1708
1741
  "div",
1709
1742
  {
1710
1743
  id: `${listId}-item-${i}`,
@@ -1720,7 +1753,7 @@ function Menu({ trigger, items, align = "end", className }) {
1720
1753
  onMouseDown: (e) => e.preventDefault(),
1721
1754
  onClick: () => choose(i),
1722
1755
  children: [
1723
- it.icon != null && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "fds-menu__icon", "aria-hidden": "true", children: it.icon }),
1756
+ it.icon != null && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "fds-menu__icon", "aria-hidden": "true", children: it.icon }),
1724
1757
  it.label
1725
1758
  ]
1726
1759
  },
@@ -1732,10 +1765,10 @@ function Menu({ trigger, items, align = "end", className }) {
1732
1765
  }
1733
1766
 
1734
1767
  // src/components/Table/Table.tsx
1735
- var import_jsx_runtime32 = require("react/jsx-runtime");
1768
+ var import_jsx_runtime33 = require("react/jsx-runtime");
1736
1769
  function Table({ columns, rows, rowKey, empty, className, "aria-label": ariaLabel, ...rest }) {
1737
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: ["fds-table", className].filter(Boolean).join(" "), ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("table", { className: "fds-table__table", "aria-label": ariaLabel, children: [
1738
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("tr", { children: columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1770
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: ["fds-table", className].filter(Boolean).join(" "), ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("table", { className: "fds-table__table", "aria-label": ariaLabel, children: [
1771
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("tr", { children: columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
1739
1772
  "th",
1740
1773
  {
1741
1774
  scope: "col",
@@ -1745,17 +1778,17 @@ function Table({ columns, rows, rowKey, empty, className, "aria-label": ariaLabe
1745
1778
  },
1746
1779
  c.key
1747
1780
  )) }) }),
1748
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("tbody", { children: [
1749
- rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("tr", { children: columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { className: c.align === "end" ? "fds-table__cell--end" : void 0, children: c.cell(row) }, c.key)) }, rowKey(row))),
1750
- rows.length === 0 && empty != null && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { colSpan: columns.length, className: "fds-table__empty", children: empty }) })
1781
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("tbody", { children: [
1782
+ rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("tr", { children: columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("td", { className: c.align === "end" ? "fds-table__cell--end" : void 0, children: c.cell(row) }, c.key)) }, rowKey(row))),
1783
+ rows.length === 0 && empty != null && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("td", { colSpan: columns.length, className: "fds-table__empty", children: empty }) })
1751
1784
  ] })
1752
1785
  ] }) });
1753
1786
  }
1754
1787
 
1755
1788
  // src/components/PricingCard/PricingCard.tsx
1756
- var import_jsx_runtime33 = require("react/jsx-runtime");
1789
+ var import_jsx_runtime34 = require("react/jsx-runtime");
1757
1790
  function CheckIcon3() {
1758
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("svg", { viewBox: "0 0 16 16", width: "12", height: "12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: "M3.5 8.5l3 3 6-7", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) });
1791
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("svg", { viewBox: "0 0 16 16", width: "12", height: "12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { d: "M3.5 8.5l3 3 6-7", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) });
1759
1792
  }
1760
1793
  function PricingCard({
1761
1794
  eyebrow,
@@ -1773,25 +1806,25 @@ function PricingCard({
1773
1806
  ...rest
1774
1807
  }) {
1775
1808
  const classes = ["fds-pricing-card", highlighted ? "fds-pricing-card--highlighted" : "", className].filter(Boolean).join(" ");
1776
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("article", { className: classes, ...rest, children: [
1777
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "fds-pricing-card__top", children: [
1778
- eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "fds-pricing-card__eyebrow", children: eyebrow }),
1779
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("h3", { className: "fds-pricing-card__title", children: [
1809
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("article", { className: classes, ...rest, children: [
1810
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "fds-pricing-card__top", children: [
1811
+ eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "fds-pricing-card__eyebrow", children: eyebrow }),
1812
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("h3", { className: "fds-pricing-card__title", children: [
1780
1813
  title,
1781
1814
  badge
1782
1815
  ] }),
1783
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("p", { className: "fds-pricing-card__price", children: [
1784
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "fds-pricing-card__amount", children: price }),
1785
- period != null && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "fds-pricing-card__period", children: period })
1816
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { className: "fds-pricing-card__price", children: [
1817
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "fds-pricing-card__amount", children: price }),
1818
+ period != null && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "fds-pricing-card__period", children: period })
1786
1819
  ] }),
1787
- description != null && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "fds-pricing-card__description", children: description }),
1788
- action != null && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "fds-pricing-card__action", children: action })
1820
+ description != null && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "fds-pricing-card__description", children: description }),
1821
+ action != null && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "fds-pricing-card__action", children: action })
1789
1822
  ] }),
1790
- features.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "fds-pricing-card__features", children: [
1791
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "fds-pricing-card__featuresTitle", children: featuresTitle }),
1792
- featuresIntro != null && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "fds-pricing-card__intro", children: featuresIntro }),
1793
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("ul", { className: "fds-pricing-card__list", children: features.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("li", { className: "fds-pricing-card__feature", children: [
1794
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "fds-pricing-card__check", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CheckIcon3, {}) }),
1823
+ features.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "fds-pricing-card__features", children: [
1824
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "fds-pricing-card__featuresTitle", children: featuresTitle }),
1825
+ featuresIntro != null && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "fds-pricing-card__intro", children: featuresIntro }),
1826
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("ul", { className: "fds-pricing-card__list", children: features.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("li", { className: "fds-pricing-card__feature", children: [
1827
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "fds-pricing-card__check", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CheckIcon3, {}) }),
1795
1828
  f
1796
1829
  ] }, i)) })
1797
1830
  ] })
@@ -1820,6 +1853,7 @@ function PricingCard({
1820
1853
  Pagination,
1821
1854
  PricingCard,
1822
1855
  Radio,
1856
+ RadioCard,
1823
1857
  SearchInput,
1824
1858
  SectionHeader,
1825
1859
  SegmentedControl,
package/dist/index.css CHANGED
@@ -2532,6 +2532,120 @@
2532
2532
  }
2533
2533
  }
2534
2534
 
2535
+ /* src/components/RadioCard/radio-card.css */
2536
+ .fds-radio-card {
2537
+ position: relative;
2538
+ display: flex;
2539
+ min-width: 0;
2540
+ }
2541
+ .fds-radio-card__input {
2542
+ position: absolute;
2543
+ inset: 0;
2544
+ width: 100%;
2545
+ height: 100%;
2546
+ margin: 0;
2547
+ opacity: 0;
2548
+ cursor: pointer;
2549
+ z-index: 1;
2550
+ }
2551
+ .fds-radio-card__input:disabled {
2552
+ cursor: not-allowed;
2553
+ }
2554
+ .fds-radio-card__body {
2555
+ box-sizing: border-box;
2556
+ flex: 1;
2557
+ display: flex;
2558
+ align-items: flex-start;
2559
+ gap: var(--spacing-3, 12px);
2560
+ padding: var(--spacing-4, 16px);
2561
+ border: 1px solid var(--color-border, #e5e5e5);
2562
+ border-radius: var(--radius-xl, 12px);
2563
+ background: var(--color-bg, #ffffff);
2564
+ cursor: pointer;
2565
+ transition: border-color var(--duration-quick, 150ms) ease, box-shadow var(--duration-quick, 150ms) ease;
2566
+ }
2567
+ .fds-radio-card__input:hover:not(:disabled):not(:checked) ~ .fds-radio-card__body {
2568
+ border-color: var(--color-border-strong, #d4d4d4);
2569
+ }
2570
+ .fds-radio-card__input:checked ~ .fds-radio-card__body {
2571
+ border-color: var(--color-text, #171717);
2572
+ box-shadow: 0 0 0 1px var(--color-text, #171717);
2573
+ }
2574
+ .fds-radio-card__input:focus-visible ~ .fds-radio-card__body {
2575
+ outline: 2px solid var(--color-focus, #ea580c);
2576
+ outline-offset: 2px;
2577
+ }
2578
+ .fds-radio-card__icon {
2579
+ flex-shrink: 0;
2580
+ display: inline-flex;
2581
+ align-items: center;
2582
+ justify-content: center;
2583
+ width: 36px;
2584
+ height: 36px;
2585
+ border-radius: var(--radius-lg, 8px);
2586
+ background: var(--color-surface, #f5f5f5);
2587
+ color: var(--color-text, #171717);
2588
+ }
2589
+ .fds-radio-card__text {
2590
+ flex: 1;
2591
+ min-width: 0;
2592
+ display: flex;
2593
+ flex-direction: column;
2594
+ gap: 2px;
2595
+ }
2596
+ .fds-radio-card__label {
2597
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
2598
+ font-size: var(--font-size-text-sm, 14px);
2599
+ line-height: var(--line-height-text-sm, 22px);
2600
+ font-weight: var(--font-weight-semibold, 600);
2601
+ color: var(--color-text, #171717);
2602
+ }
2603
+ .fds-radio-card__description {
2604
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
2605
+ font-size: var(--font-size-text-compact, 13px);
2606
+ line-height: var(--line-height-text-compact, 20px);
2607
+ color: var(--color-text-secondary, #525252);
2608
+ }
2609
+ .fds-radio-card__meta {
2610
+ margin-top: var(--spacing-1, 4px);
2611
+ font-family: var(--font-body, "Rethink Sans", system-ui, sans-serif);
2612
+ font-size: var(--font-size-text-xs, 12px);
2613
+ line-height: var(--line-height-text-xs, 18px);
2614
+ color: var(--color-text-secondary, #525252);
2615
+ }
2616
+ .fds-radio-card__circle {
2617
+ box-sizing: border-box;
2618
+ flex-shrink: 0;
2619
+ width: 16px;
2620
+ height: 16px;
2621
+ margin-top: 3px;
2622
+ border: 1px solid var(--color-border-strong, #d4d4d4);
2623
+ border-radius: var(--radius-full, 9999px);
2624
+ background: var(--color-bg, #ffffff);
2625
+ transition: border-color var(--duration-quick, 150ms) ease, border-width var(--duration-quick, 150ms) ease;
2626
+ }
2627
+ .fds-radio-card__input:checked ~ .fds-radio-card__body .fds-radio-card__circle {
2628
+ border: 5px solid var(--color-text, #171717);
2629
+ }
2630
+ .fds-radio-card[data-disabled] .fds-radio-card__body {
2631
+ cursor: not-allowed;
2632
+ background: var(--color-surface-subtle, #fafafa);
2633
+ }
2634
+ .fds-radio-card[data-disabled] .fds-radio-card__label,
2635
+ .fds-radio-card[data-disabled] .fds-radio-card__description,
2636
+ .fds-radio-card[data-disabled] .fds-radio-card__meta {
2637
+ color: var(--color-text-muted, #a3a3a3);
2638
+ }
2639
+ .fds-radio-card[data-disabled] .fds-radio-card__circle {
2640
+ opacity: 0.5;
2641
+ }
2642
+ @media (prefers-reduced-motion: reduce) {
2643
+ .fds-radio-card__body,
2644
+ .fds-radio-card__circle {
2645
+ transition: none;
2646
+ }
2647
+ }
2648
+
2535
2649
  /* src/components/Accordion/accordion.css */
2536
2650
  .fds-accordion {
2537
2651
  box-sizing: border-box;
@@ -3025,7 +3139,7 @@
3025
3139
  }
3026
3140
  .fds-pricing-card__feature {
3027
3141
  display: flex;
3028
- align-items: center;
3142
+ align-items: flex-start;
3029
3143
  gap: var(--spacing-3, 12px);
3030
3144
  font-size: var(--font-size-text-sm, 14px);
3031
3145
  line-height: var(--line-height-text-sm, 22px);
package/dist/index.d.cts CHANGED
@@ -696,6 +696,25 @@ interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'
696
696
  */
697
697
  declare const Radio: react.ForwardRefExoticComponent<RadioProps & react.RefAttributes<HTMLInputElement>>;
698
698
 
699
+ interface RadioCardProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
700
+ /** Card title. */
701
+ label: ReactNode;
702
+ /** One or two lines under the title saying what the choice does. */
703
+ description?: ReactNode;
704
+ /** Small picture left of the text, usually an 18px icon. */
705
+ icon?: ReactNode;
706
+ /** Extra line under the description, e.g. a status or requirement. */
707
+ meta?: ReactNode;
708
+ }
709
+ /**
710
+ * Fidel design-system RadioCard: one choice of several, shown as a card with
711
+ * an icon, title and description. A native radio underneath, so cards that
712
+ * share a `name` move with the arrow keys and submit like any radio. Wrap the
713
+ * set in a `role="radiogroup"` element (or a fieldset) with a label; lay the
714
+ * cards out with the parent's grid or flex.
715
+ */
716
+ declare const RadioCard: react.ForwardRefExoticComponent<RadioCardProps & react.RefAttributes<HTMLInputElement>>;
717
+
699
718
  interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
700
719
  /** Header content, always visible. Clicking it opens and closes the body. */
701
720
  summary: ReactNode;
@@ -859,4 +878,4 @@ interface PricingCardProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
859
878
  */
860
879
  declare function PricingCard({ eyebrow, title, badge, price, period, description, action, featuresTitle, featuresIntro, features, highlighted, className, ...rest }: PricingCardProps): react.JSX.Element;
861
880
 
862
- export { Accordion, type AccordionProps, AppNav, type AppNavProps, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type Breakpoint, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, type ButtonSize, type ButtonVariant, Callout, type CalloutProps, type CalloutTone, Card, type CardPadding, type CardProps, type CardTone, Checkbox, type CheckboxProps, type DiffElement, type DiffPropertyLine, DiffPropertyList, type DiffPropertyListProps, DiffSection, type DiffSectionProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant, Input, type InputProps, Menu, type MenuItem, type MenuProps, MismatchCard, type MismatchCardProps, type MismatchProperty, Modal, type ModalProps, type ModalSize, type ModalTone, MultiSelect, type MultiSelectOption, type MultiSelectProps, Pagination, type PaginationProps, PricingCard, type PricingCardProps, Radio, type RadioProps, SearchInput, type SearchInputProps, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlProps, type SegmentedOption, Select, type SelectOption, type SelectProps, SettingsSection, type SettingsSectionProps, Skeleton, SkeletonGroup, type SkeletonGroupProps, type SkeletonProps, type SkeletonShape, Split, type SplitProps, StackedCardsIllustration, Stat, type StatProps, type Step, StepList, type StepListProps, type StepStatus, TabNav, type TabNavProps, Table, type TableColumn, type TableProps, Tag, type TagProps, Toggle, type ToggleProps, type ToggleSize, type Tone, breakpoints };
881
+ export { Accordion, type AccordionProps, AppNav, type AppNavProps, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type Breakpoint, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, type ButtonSize, type ButtonVariant, Callout, type CalloutProps, type CalloutTone, Card, type CardPadding, type CardProps, type CardTone, Checkbox, type CheckboxProps, type DiffElement, type DiffPropertyLine, DiffPropertyList, type DiffPropertyListProps, DiffSection, type DiffSectionProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant, Input, type InputProps, Menu, type MenuItem, type MenuProps, MismatchCard, type MismatchCardProps, type MismatchProperty, Modal, type ModalProps, type ModalSize, type ModalTone, MultiSelect, type MultiSelectOption, type MultiSelectProps, Pagination, type PaginationProps, PricingCard, type PricingCardProps, Radio, RadioCard, type RadioCardProps, type RadioProps, SearchInput, type SearchInputProps, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlProps, type SegmentedOption, Select, type SelectOption, type SelectProps, SettingsSection, type SettingsSectionProps, Skeleton, SkeletonGroup, type SkeletonGroupProps, type SkeletonProps, type SkeletonShape, Split, type SplitProps, StackedCardsIllustration, Stat, type StatProps, type Step, StepList, type StepListProps, type StepStatus, TabNav, type TabNavProps, Table, type TableColumn, type TableProps, Tag, type TagProps, Toggle, type ToggleProps, type ToggleSize, type Tone, breakpoints };
package/dist/index.d.ts CHANGED
@@ -696,6 +696,25 @@ interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'
696
696
  */
697
697
  declare const Radio: react.ForwardRefExoticComponent<RadioProps & react.RefAttributes<HTMLInputElement>>;
698
698
 
699
+ interface RadioCardProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
700
+ /** Card title. */
701
+ label: ReactNode;
702
+ /** One or two lines under the title saying what the choice does. */
703
+ description?: ReactNode;
704
+ /** Small picture left of the text, usually an 18px icon. */
705
+ icon?: ReactNode;
706
+ /** Extra line under the description, e.g. a status or requirement. */
707
+ meta?: ReactNode;
708
+ }
709
+ /**
710
+ * Fidel design-system RadioCard: one choice of several, shown as a card with
711
+ * an icon, title and description. A native radio underneath, so cards that
712
+ * share a `name` move with the arrow keys and submit like any radio. Wrap the
713
+ * set in a `role="radiogroup"` element (or a fieldset) with a label; lay the
714
+ * cards out with the parent's grid or flex.
715
+ */
716
+ declare const RadioCard: react.ForwardRefExoticComponent<RadioCardProps & react.RefAttributes<HTMLInputElement>>;
717
+
699
718
  interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
700
719
  /** Header content, always visible. Clicking it opens and closes the body. */
701
720
  summary: ReactNode;
@@ -859,4 +878,4 @@ interface PricingCardProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
859
878
  */
860
879
  declare function PricingCard({ eyebrow, title, badge, price, period, description, action, featuresTitle, featuresIntro, features, highlighted, className, ...rest }: PricingCardProps): react.JSX.Element;
861
880
 
862
- export { Accordion, type AccordionProps, AppNav, type AppNavProps, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type Breakpoint, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, type ButtonSize, type ButtonVariant, Callout, type CalloutProps, type CalloutTone, Card, type CardPadding, type CardProps, type CardTone, Checkbox, type CheckboxProps, type DiffElement, type DiffPropertyLine, DiffPropertyList, type DiffPropertyListProps, DiffSection, type DiffSectionProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant, Input, type InputProps, Menu, type MenuItem, type MenuProps, MismatchCard, type MismatchCardProps, type MismatchProperty, Modal, type ModalProps, type ModalSize, type ModalTone, MultiSelect, type MultiSelectOption, type MultiSelectProps, Pagination, type PaginationProps, PricingCard, type PricingCardProps, Radio, type RadioProps, SearchInput, type SearchInputProps, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlProps, type SegmentedOption, Select, type SelectOption, type SelectProps, SettingsSection, type SettingsSectionProps, Skeleton, SkeletonGroup, type SkeletonGroupProps, type SkeletonProps, type SkeletonShape, Split, type SplitProps, StackedCardsIllustration, Stat, type StatProps, type Step, StepList, type StepListProps, type StepStatus, TabNav, type TabNavProps, Table, type TableColumn, type TableProps, Tag, type TagProps, Toggle, type ToggleProps, type ToggleSize, type Tone, breakpoints };
881
+ export { Accordion, type AccordionProps, AppNav, type AppNavProps, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type Breakpoint, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, type ButtonSize, type ButtonVariant, Callout, type CalloutProps, type CalloutTone, Card, type CardPadding, type CardProps, type CardTone, Checkbox, type CheckboxProps, type DiffElement, type DiffPropertyLine, DiffPropertyList, type DiffPropertyListProps, DiffSection, type DiffSectionProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant, Input, type InputProps, Menu, type MenuItem, type MenuProps, MismatchCard, type MismatchCardProps, type MismatchProperty, Modal, type ModalProps, type ModalSize, type ModalTone, MultiSelect, type MultiSelectOption, type MultiSelectProps, Pagination, type PaginationProps, PricingCard, type PricingCardProps, Radio, RadioCard, type RadioCardProps, type RadioProps, SearchInput, type SearchInputProps, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlProps, type SegmentedOption, Select, type SelectOption, type SelectProps, SettingsSection, type SettingsSectionProps, Skeleton, SkeletonGroup, type SkeletonGroupProps, type SkeletonProps, type SkeletonShape, Split, type SplitProps, StackedCardsIllustration, Stat, type StatProps, type Step, StepList, type StepListProps, type StepStatus, TabNav, type TabNavProps, Table, type TableColumn, type TableProps, Tag, type TagProps, Toggle, type ToggleProps, type ToggleSize, type Tone, breakpoints };
package/dist/index.js CHANGED
@@ -1415,9 +1415,41 @@ var Radio = forwardRef5(function Radio2({ label, description, className, id, dis
1415
1415
  ] });
1416
1416
  });
1417
1417
 
1418
- // src/components/Accordion/Accordion.tsx
1419
- import { useId as useId9, useState as useState7 } from "react";
1418
+ // src/components/RadioCard/RadioCard.tsx
1419
+ import { forwardRef as forwardRef6, useId as useId9 } from "react";
1420
1420
  import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
1421
+ var RadioCard = forwardRef6(function RadioCard2({ label, description, icon, meta, className, id, disabled, ...rest }, ref) {
1422
+ const generatedId = useId9();
1423
+ const inputId = id ?? generatedId;
1424
+ const descriptionId = description != null ? `${inputId}-description` : void 0;
1425
+ return /* @__PURE__ */ jsxs23("div", { className: ["fds-radio-card", className].filter(Boolean).join(" "), "data-disabled": disabled ? "" : void 0, children: [
1426
+ /* @__PURE__ */ jsx27(
1427
+ "input",
1428
+ {
1429
+ ...rest,
1430
+ id: inputId,
1431
+ ref,
1432
+ type: "radio",
1433
+ disabled,
1434
+ "aria-describedby": descriptionId,
1435
+ className: "fds-radio-card__input"
1436
+ }
1437
+ ),
1438
+ /* @__PURE__ */ jsxs23("label", { htmlFor: inputId, className: "fds-radio-card__body", children: [
1439
+ icon != null && /* @__PURE__ */ jsx27("span", { className: "fds-radio-card__icon", "aria-hidden": "true", children: icon }),
1440
+ /* @__PURE__ */ jsxs23("span", { className: "fds-radio-card__text", children: [
1441
+ /* @__PURE__ */ jsx27("span", { className: "fds-radio-card__label", children: label }),
1442
+ description != null && /* @__PURE__ */ jsx27("span", { id: descriptionId, className: "fds-radio-card__description", children: description }),
1443
+ meta != null && /* @__PURE__ */ jsx27("span", { className: "fds-radio-card__meta", children: meta })
1444
+ ] }),
1445
+ /* @__PURE__ */ jsx27("span", { className: "fds-radio-card__circle", "aria-hidden": "true" })
1446
+ ] })
1447
+ ] });
1448
+ });
1449
+
1450
+ // src/components/Accordion/Accordion.tsx
1451
+ import { useId as useId10, useState as useState7 } from "react";
1452
+ import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
1421
1453
  function Accordion({
1422
1454
  summary,
1423
1455
  actions,
@@ -1430,21 +1462,21 @@ function Accordion({
1430
1462
  }) {
1431
1463
  const [openState, setOpenState] = useState7(defaultOpen);
1432
1464
  const open = openProp ?? openState;
1433
- const bodyId = useId9();
1465
+ const bodyId = useId10();
1434
1466
  const toggle = () => {
1435
1467
  const next = !open;
1436
1468
  if (openProp === void 0) setOpenState(next);
1437
1469
  onOpenChange?.(next);
1438
1470
  };
1439
- return /* @__PURE__ */ jsxs23(
1471
+ return /* @__PURE__ */ jsxs24(
1440
1472
  "div",
1441
1473
  {
1442
1474
  className: ["fds-accordion", className].filter(Boolean).join(" "),
1443
1475
  "data-open": open ? "" : void 0,
1444
1476
  ...rest,
1445
1477
  children: [
1446
- /* @__PURE__ */ jsxs23("div", { className: "fds-accordion__header", children: [
1447
- /* @__PURE__ */ jsx27(
1478
+ /* @__PURE__ */ jsxs24("div", { className: "fds-accordion__header", children: [
1479
+ /* @__PURE__ */ jsx28(
1448
1480
  "button",
1449
1481
  {
1450
1482
  type: "button",
@@ -1455,17 +1487,17 @@ function Accordion({
1455
1487
  children: summary
1456
1488
  }
1457
1489
  ),
1458
- actions != null && /* @__PURE__ */ jsx27("div", { className: "fds-accordion__actions", children: actions }),
1459
- /* @__PURE__ */ jsx27("span", { className: "fds-accordion__chevron", "aria-hidden": "true", onClick: toggle, children: /* @__PURE__ */ jsx27("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ jsx27("path", { d: "M6 9l6 6 6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
1490
+ actions != null && /* @__PURE__ */ jsx28("div", { className: "fds-accordion__actions", children: actions }),
1491
+ /* @__PURE__ */ jsx28("span", { className: "fds-accordion__chevron", "aria-hidden": "true", onClick: toggle, children: /* @__PURE__ */ jsx28("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", children: /* @__PURE__ */ jsx28("path", { d: "M6 9l6 6 6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
1460
1492
  ] }),
1461
- /* @__PURE__ */ jsx27("div", { id: bodyId, className: "fds-accordion__body", hidden: !open, children })
1493
+ /* @__PURE__ */ jsx28("div", { id: bodyId, className: "fds-accordion__body", hidden: !open, children })
1462
1494
  ]
1463
1495
  }
1464
1496
  );
1465
1497
  }
1466
1498
 
1467
1499
  // src/components/StepList/StepList.tsx
1468
- import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
1500
+ import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
1469
1501
  var STATUS_TEXT = {
1470
1502
  done: "Done",
1471
1503
  active: "In progress",
@@ -1475,32 +1507,32 @@ var STATUS_TEXT = {
1475
1507
  function StepIcon({ status }) {
1476
1508
  const common = { viewBox: "0 0 24 24", width: 18, height: 18, fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
1477
1509
  if (status === "done") {
1478
- return /* @__PURE__ */ jsxs24("svg", { ...common, children: [
1479
- /* @__PURE__ */ jsx28("circle", { cx: "12", cy: "12", r: "9" }),
1480
- /* @__PURE__ */ jsx28("path", { d: "M8 12.5l2.5 2.5 5-5.5" })
1510
+ return /* @__PURE__ */ jsxs25("svg", { ...common, children: [
1511
+ /* @__PURE__ */ jsx29("circle", { cx: "12", cy: "12", r: "9" }),
1512
+ /* @__PURE__ */ jsx29("path", { d: "M8 12.5l2.5 2.5 5-5.5" })
1481
1513
  ] });
1482
1514
  }
1483
1515
  if (status === "active") {
1484
- return /* @__PURE__ */ jsx28("svg", { ...common, className: "fds-steps__spinner", children: /* @__PURE__ */ jsx28("path", { d: "M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1" }) });
1516
+ return /* @__PURE__ */ jsx29("svg", { ...common, className: "fds-steps__spinner", children: /* @__PURE__ */ jsx29("path", { d: "M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1" }) });
1485
1517
  }
1486
1518
  if (status === "failed") {
1487
- return /* @__PURE__ */ jsxs24("svg", { ...common, children: [
1488
- /* @__PURE__ */ jsx28("circle", { cx: "12", cy: "12", r: "9" }),
1489
- /* @__PURE__ */ jsx28("path", { d: "M12 7.5v5.5M12 16.5v.01" })
1519
+ return /* @__PURE__ */ jsxs25("svg", { ...common, children: [
1520
+ /* @__PURE__ */ jsx29("circle", { cx: "12", cy: "12", r: "9" }),
1521
+ /* @__PURE__ */ jsx29("path", { d: "M12 7.5v5.5M12 16.5v.01" })
1490
1522
  ] });
1491
1523
  }
1492
- return /* @__PURE__ */ jsx28("svg", { ...common, children: /* @__PURE__ */ jsx28("circle", { cx: "12", cy: "12", r: "9" }) });
1524
+ return /* @__PURE__ */ jsx29("svg", { ...common, children: /* @__PURE__ */ jsx29("circle", { cx: "12", cy: "12", r: "9" }) });
1493
1525
  }
1494
1526
  function StepList({ steps, className, ...rest }) {
1495
- return /* @__PURE__ */ jsx28("ol", { className: ["fds-steps", className].filter(Boolean).join(" "), ...rest, children: steps.map((step) => /* @__PURE__ */ jsxs24(
1527
+ return /* @__PURE__ */ jsx29("ol", { className: ["fds-steps", className].filter(Boolean).join(" "), ...rest, children: steps.map((step) => /* @__PURE__ */ jsxs25(
1496
1528
  "li",
1497
1529
  {
1498
1530
  className: `fds-steps__step fds-steps__step--${step.status}`,
1499
1531
  "aria-current": step.status === "active" ? "step" : void 0,
1500
1532
  children: [
1501
- /* @__PURE__ */ jsx28("span", { className: "fds-steps__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx28(StepIcon, { status: step.status }) }),
1502
- /* @__PURE__ */ jsx28("span", { className: "fds-steps__label", children: step.label }),
1503
- /* @__PURE__ */ jsxs24("span", { className: "fds-steps__sr", children: [
1533
+ /* @__PURE__ */ jsx29("span", { className: "fds-steps__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx29(StepIcon, { status: step.status }) }),
1534
+ /* @__PURE__ */ jsx29("span", { className: "fds-steps__label", children: step.label }),
1535
+ /* @__PURE__ */ jsxs25("span", { className: "fds-steps__sr", children: [
1504
1536
  ", ",
1505
1537
  STATUS_TEXT[step.status]
1506
1538
  ] })
@@ -1511,10 +1543,10 @@ function StepList({ steps, className, ...rest }) {
1511
1543
  }
1512
1544
 
1513
1545
  // src/components/Input/Input.tsx
1514
- import { forwardRef as forwardRef6, useId as useId10 } from "react";
1515
- import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
1516
- var Input = forwardRef6(function Input2({ label, hint, error, leadingIcon, trailing, id, className, containerClassName, readOnly, disabled, ...rest }, ref) {
1517
- const genId = useId10();
1546
+ import { forwardRef as forwardRef7, useId as useId11 } from "react";
1547
+ import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
1548
+ var Input = forwardRef7(function Input2({ label, hint, error, leadingIcon, trailing, id, className, containerClassName, readOnly, disabled, ...rest }, ref) {
1549
+ const genId = useId11();
1518
1550
  const inputId = id ?? genId;
1519
1551
  const msgId = `${genId}-msg`;
1520
1552
  const message = error ?? hint;
@@ -1523,11 +1555,11 @@ var Input = forwardRef6(function Input2({ label, hint, error, leadingIcon, trail
1523
1555
  error ? "fds-input__box--error" : "",
1524
1556
  readOnly || disabled ? "fds-input__box--locked" : ""
1525
1557
  ].filter(Boolean).join(" ");
1526
- return /* @__PURE__ */ jsxs25("div", { className: ["fds-input", containerClassName].filter(Boolean).join(" "), children: [
1527
- label != null && /* @__PURE__ */ jsx29("label", { htmlFor: inputId, className: "fds-input__label", children: label }),
1528
- /* @__PURE__ */ jsxs25("div", { className: boxClasses, children: [
1529
- leadingIcon != null && /* @__PURE__ */ jsx29("span", { className: "fds-input__icon", "aria-hidden": "true", children: leadingIcon }),
1530
- /* @__PURE__ */ jsx29(
1558
+ return /* @__PURE__ */ jsxs26("div", { className: ["fds-input", containerClassName].filter(Boolean).join(" "), children: [
1559
+ label != null && /* @__PURE__ */ jsx30("label", { htmlFor: inputId, className: "fds-input__label", children: label }),
1560
+ /* @__PURE__ */ jsxs26("div", { className: boxClasses, children: [
1561
+ leadingIcon != null && /* @__PURE__ */ jsx30("span", { className: "fds-input__icon", "aria-hidden": "true", children: leadingIcon }),
1562
+ /* @__PURE__ */ jsx30(
1531
1563
  "input",
1532
1564
  {
1533
1565
  ref,
@@ -1540,14 +1572,14 @@ var Input = forwardRef6(function Input2({ label, hint, error, leadingIcon, trail
1540
1572
  ...rest
1541
1573
  }
1542
1574
  ),
1543
- trailing != null && /* @__PURE__ */ jsx29("span", { className: "fds-input__trailing", children: trailing })
1575
+ trailing != null && /* @__PURE__ */ jsx30("span", { className: "fds-input__trailing", children: trailing })
1544
1576
  ] }),
1545
- message != null && /* @__PURE__ */ jsx29("p", { id: msgId, className: error ? "fds-input__error" : "fds-input__hint", children: message })
1577
+ message != null && /* @__PURE__ */ jsx30("p", { id: msgId, className: error ? "fds-input__error" : "fds-input__hint", children: message })
1546
1578
  ] });
1547
1579
  });
1548
1580
 
1549
1581
  // src/components/IconButton/IconButton.tsx
1550
- import { jsx as jsx30 } from "react/jsx-runtime";
1582
+ import { jsx as jsx31 } from "react/jsx-runtime";
1551
1583
  function IconButton({
1552
1584
  icon,
1553
1585
  variant = "outlined",
@@ -1557,20 +1589,20 @@ function IconButton({
1557
1589
  ...rest
1558
1590
  }) {
1559
1591
  const classes = ["fds-icon-button", `fds-icon-button--${variant}`, `fds-icon-button--${size}`, className].filter(Boolean).join(" ");
1560
- return /* @__PURE__ */ jsx30("button", { type, className: classes, ...rest, children: /* @__PURE__ */ jsx30("span", { className: "fds-icon-button__icon", "aria-hidden": "true", children: icon }) });
1592
+ return /* @__PURE__ */ jsx31("button", { type, className: classes, ...rest, children: /* @__PURE__ */ jsx31("span", { className: "fds-icon-button__icon", "aria-hidden": "true", children: icon }) });
1561
1593
  }
1562
1594
 
1563
1595
  // src/components/Menu/Menu.tsx
1564
1596
  import {
1565
1597
  cloneElement,
1566
1598
  useEffect as useEffect6,
1567
- useId as useId11,
1599
+ useId as useId12,
1568
1600
  useRef as useRef7,
1569
1601
  useState as useState8
1570
1602
  } from "react";
1571
- import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
1603
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
1572
1604
  function Menu({ trigger, items, align = "end", className }) {
1573
- const listId = useId11();
1605
+ const listId = useId12();
1574
1606
  const rootRef = useRef7(null);
1575
1607
  const listRef = useRef7(null);
1576
1608
  const [open, setOpen] = useState8(false);
@@ -1650,9 +1682,9 @@ function Menu({ trigger, items, align = "end", className }) {
1650
1682
  }
1651
1683
  }
1652
1684
  });
1653
- return /* @__PURE__ */ jsxs26("div", { ref: rootRef, className: ["fds-menu", className].filter(Boolean).join(" "), children: [
1685
+ return /* @__PURE__ */ jsxs27("div", { ref: rootRef, className: ["fds-menu", className].filter(Boolean).join(" "), children: [
1654
1686
  wired,
1655
- open && /* @__PURE__ */ jsx31(
1687
+ open && /* @__PURE__ */ jsx32(
1656
1688
  "div",
1657
1689
  {
1658
1690
  ref: listRef,
@@ -1662,7 +1694,7 @@ function Menu({ trigger, items, align = "end", className }) {
1662
1694
  className: `fds-menu__list fds-menu__list--${align}`,
1663
1695
  "aria-activedescendant": `${listId}-item-${active}`,
1664
1696
  onKeyDown: onListKeyDown,
1665
- children: items.map((it, i) => /* @__PURE__ */ jsxs26(
1697
+ children: items.map((it, i) => /* @__PURE__ */ jsxs27(
1666
1698
  "div",
1667
1699
  {
1668
1700
  id: `${listId}-item-${i}`,
@@ -1678,7 +1710,7 @@ function Menu({ trigger, items, align = "end", className }) {
1678
1710
  onMouseDown: (e) => e.preventDefault(),
1679
1711
  onClick: () => choose(i),
1680
1712
  children: [
1681
- it.icon != null && /* @__PURE__ */ jsx31("span", { className: "fds-menu__icon", "aria-hidden": "true", children: it.icon }),
1713
+ it.icon != null && /* @__PURE__ */ jsx32("span", { className: "fds-menu__icon", "aria-hidden": "true", children: it.icon }),
1682
1714
  it.label
1683
1715
  ]
1684
1716
  },
@@ -1690,10 +1722,10 @@ function Menu({ trigger, items, align = "end", className }) {
1690
1722
  }
1691
1723
 
1692
1724
  // src/components/Table/Table.tsx
1693
- import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
1725
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
1694
1726
  function Table({ columns, rows, rowKey, empty, className, "aria-label": ariaLabel, ...rest }) {
1695
- return /* @__PURE__ */ jsx32("div", { className: ["fds-table", className].filter(Boolean).join(" "), ...rest, children: /* @__PURE__ */ jsxs27("table", { className: "fds-table__table", "aria-label": ariaLabel, children: [
1696
- /* @__PURE__ */ jsx32("thead", { children: /* @__PURE__ */ jsx32("tr", { children: columns.map((c) => /* @__PURE__ */ jsx32(
1727
+ return /* @__PURE__ */ jsx33("div", { className: ["fds-table", className].filter(Boolean).join(" "), ...rest, children: /* @__PURE__ */ jsxs28("table", { className: "fds-table__table", "aria-label": ariaLabel, children: [
1728
+ /* @__PURE__ */ jsx33("thead", { children: /* @__PURE__ */ jsx33("tr", { children: columns.map((c) => /* @__PURE__ */ jsx33(
1697
1729
  "th",
1698
1730
  {
1699
1731
  scope: "col",
@@ -1703,17 +1735,17 @@ function Table({ columns, rows, rowKey, empty, className, "aria-label": ariaLabe
1703
1735
  },
1704
1736
  c.key
1705
1737
  )) }) }),
1706
- /* @__PURE__ */ jsxs27("tbody", { children: [
1707
- rows.map((row) => /* @__PURE__ */ jsx32("tr", { children: columns.map((c) => /* @__PURE__ */ jsx32("td", { className: c.align === "end" ? "fds-table__cell--end" : void 0, children: c.cell(row) }, c.key)) }, rowKey(row))),
1708
- rows.length === 0 && empty != null && /* @__PURE__ */ jsx32("tr", { children: /* @__PURE__ */ jsx32("td", { colSpan: columns.length, className: "fds-table__empty", children: empty }) })
1738
+ /* @__PURE__ */ jsxs28("tbody", { children: [
1739
+ rows.map((row) => /* @__PURE__ */ jsx33("tr", { children: columns.map((c) => /* @__PURE__ */ jsx33("td", { className: c.align === "end" ? "fds-table__cell--end" : void 0, children: c.cell(row) }, c.key)) }, rowKey(row))),
1740
+ rows.length === 0 && empty != null && /* @__PURE__ */ jsx33("tr", { children: /* @__PURE__ */ jsx33("td", { colSpan: columns.length, className: "fds-table__empty", children: empty }) })
1709
1741
  ] })
1710
1742
  ] }) });
1711
1743
  }
1712
1744
 
1713
1745
  // src/components/PricingCard/PricingCard.tsx
1714
- import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
1746
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
1715
1747
  function CheckIcon3() {
1716
- return /* @__PURE__ */ jsx33("svg", { viewBox: "0 0 16 16", width: "12", height: "12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx33("path", { d: "M3.5 8.5l3 3 6-7", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) });
1748
+ return /* @__PURE__ */ jsx34("svg", { viewBox: "0 0 16 16", width: "12", height: "12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx34("path", { d: "M3.5 8.5l3 3 6-7", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) });
1717
1749
  }
1718
1750
  function PricingCard({
1719
1751
  eyebrow,
@@ -1731,25 +1763,25 @@ function PricingCard({
1731
1763
  ...rest
1732
1764
  }) {
1733
1765
  const classes = ["fds-pricing-card", highlighted ? "fds-pricing-card--highlighted" : "", className].filter(Boolean).join(" ");
1734
- return /* @__PURE__ */ jsxs28("article", { className: classes, ...rest, children: [
1735
- /* @__PURE__ */ jsxs28("div", { className: "fds-pricing-card__top", children: [
1736
- eyebrow != null && /* @__PURE__ */ jsx33("span", { className: "fds-pricing-card__eyebrow", children: eyebrow }),
1737
- /* @__PURE__ */ jsxs28("h3", { className: "fds-pricing-card__title", children: [
1766
+ return /* @__PURE__ */ jsxs29("article", { className: classes, ...rest, children: [
1767
+ /* @__PURE__ */ jsxs29("div", { className: "fds-pricing-card__top", children: [
1768
+ eyebrow != null && /* @__PURE__ */ jsx34("span", { className: "fds-pricing-card__eyebrow", children: eyebrow }),
1769
+ /* @__PURE__ */ jsxs29("h3", { className: "fds-pricing-card__title", children: [
1738
1770
  title,
1739
1771
  badge
1740
1772
  ] }),
1741
- /* @__PURE__ */ jsxs28("p", { className: "fds-pricing-card__price", children: [
1742
- /* @__PURE__ */ jsx33("span", { className: "fds-pricing-card__amount", children: price }),
1743
- period != null && /* @__PURE__ */ jsx33("span", { className: "fds-pricing-card__period", children: period })
1773
+ /* @__PURE__ */ jsxs29("p", { className: "fds-pricing-card__price", children: [
1774
+ /* @__PURE__ */ jsx34("span", { className: "fds-pricing-card__amount", children: price }),
1775
+ period != null && /* @__PURE__ */ jsx34("span", { className: "fds-pricing-card__period", children: period })
1744
1776
  ] }),
1745
- description != null && /* @__PURE__ */ jsx33("p", { className: "fds-pricing-card__description", children: description }),
1746
- action != null && /* @__PURE__ */ jsx33("div", { className: "fds-pricing-card__action", children: action })
1777
+ description != null && /* @__PURE__ */ jsx34("p", { className: "fds-pricing-card__description", children: description }),
1778
+ action != null && /* @__PURE__ */ jsx34("div", { className: "fds-pricing-card__action", children: action })
1747
1779
  ] }),
1748
- features.length > 0 && /* @__PURE__ */ jsxs28("div", { className: "fds-pricing-card__features", children: [
1749
- /* @__PURE__ */ jsx33("p", { className: "fds-pricing-card__featuresTitle", children: featuresTitle }),
1750
- featuresIntro != null && /* @__PURE__ */ jsx33("p", { className: "fds-pricing-card__intro", children: featuresIntro }),
1751
- /* @__PURE__ */ jsx33("ul", { className: "fds-pricing-card__list", children: features.map((f, i) => /* @__PURE__ */ jsxs28("li", { className: "fds-pricing-card__feature", children: [
1752
- /* @__PURE__ */ jsx33("span", { className: "fds-pricing-card__check", children: /* @__PURE__ */ jsx33(CheckIcon3, {}) }),
1780
+ features.length > 0 && /* @__PURE__ */ jsxs29("div", { className: "fds-pricing-card__features", children: [
1781
+ /* @__PURE__ */ jsx34("p", { className: "fds-pricing-card__featuresTitle", children: featuresTitle }),
1782
+ featuresIntro != null && /* @__PURE__ */ jsx34("p", { className: "fds-pricing-card__intro", children: featuresIntro }),
1783
+ /* @__PURE__ */ jsx34("ul", { className: "fds-pricing-card__list", children: features.map((f, i) => /* @__PURE__ */ jsxs29("li", { className: "fds-pricing-card__feature", children: [
1784
+ /* @__PURE__ */ jsx34("span", { className: "fds-pricing-card__check", children: /* @__PURE__ */ jsx34(CheckIcon3, {}) }),
1753
1785
  f
1754
1786
  ] }, i)) })
1755
1787
  ] })
@@ -1777,6 +1809,7 @@ export {
1777
1809
  Pagination,
1778
1810
  PricingCard,
1779
1811
  Radio,
1812
+ RadioCard,
1780
1813
  SearchInput,
1781
1814
  SectionHeader,
1782
1815
  SegmentedControl,
package/dist/landing.css CHANGED
@@ -32,6 +32,7 @@
32
32
  --color-success: #059669;
33
33
  --color-success-bg: #f0fdf4;
34
34
  --color-success-text: #15803d;
35
+ --color-success-border: #bbf7d0;
35
36
  --color-warning: #ca8a04;
36
37
  --color-warning-bg: #fffbeb;
37
38
  --color-warning-text: #92400e;
@@ -56,6 +57,17 @@
56
57
  --color-error-pressed: #7f1d1d;
57
58
  --color-error-border-hover: #fca5a5;
58
59
  --color-error-bg-pressed: #fee2e2;
60
+ --color-white-alpha-6: rgba(255, 255, 255, 0.06);
61
+ --color-white-alpha-8: rgba(255, 255, 255, 0.08);
62
+ --color-white-alpha-10: rgba(255, 255, 255, 0.1);
63
+ --color-white-alpha-12: rgba(255, 255, 255, 0.12);
64
+ --color-white-alpha-35: rgba(255, 255, 255, 0.35);
65
+ --color-white-alpha-55: rgba(255, 255, 255, 0.55);
66
+ --color-white-alpha-60: rgba(255, 255, 255, 0.6);
67
+ --color-white-alpha-92: rgba(255, 255, 255, 0.92);
68
+ --color-black-alpha-4: rgba(0, 0, 0, 0.04);
69
+ --color-black-alpha-8: rgba(0, 0, 0, 0.08);
70
+ --color-black-alpha-60: rgba(0, 0, 0, 0.6);
59
71
  --font-display: 'Rethink Sans', system-ui, -apple-system, sans-serif;
60
72
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
61
73
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
@@ -130,9 +142,12 @@
130
142
  --shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.06), 0 16px 40px rgba(0, 0, 0, 0.1);
131
143
  --shadow-pill: 0 1px 2px rgba(15, 23, 42, 0.08);
132
144
  --shadow-cta: 0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.06);
145
+ --shadow-popover: 0 1px 2px rgba(15, 23, 42, 0.08), 0 8px 24px rgba(15, 23, 42, 0.14);
146
+ --shadow-focus-error: 0 0 0 3px rgba(220, 38, 38, 0.15);
133
147
  --font-weight-regular: 400;
134
148
  --font-weight-medium: 500;
135
149
  --font-weight-semibold: 600;
136
150
  --font-weight-bold: 700;
137
151
  --font-weight-extrabold: 800;
152
+ --gradient-brand-warm: linear-gradient(160deg, #fbfbfb 34%, #f29c6f 90%);
138
153
  }
package/dist/theme.css CHANGED
@@ -34,6 +34,7 @@
34
34
  --color-success: #059669;
35
35
  --color-success-bg: #f0fdf4;
36
36
  --color-success-text: #15803d;
37
+ --color-success-border: #bbf7d0;
37
38
  --color-warning: #ca8a04;
38
39
  --color-warning-bg: #fffbeb;
39
40
  --color-warning-text: #92400e;
@@ -58,6 +59,17 @@
58
59
  --color-error-pressed: #7f1d1d;
59
60
  --color-error-border-hover: #fca5a5;
60
61
  --color-error-bg-pressed: #fee2e2;
62
+ --color-white-alpha-6: rgba(255, 255, 255, 0.06);
63
+ --color-white-alpha-8: rgba(255, 255, 255, 0.08);
64
+ --color-white-alpha-10: rgba(255, 255, 255, 0.1);
65
+ --color-white-alpha-12: rgba(255, 255, 255, 0.12);
66
+ --color-white-alpha-35: rgba(255, 255, 255, 0.35);
67
+ --color-white-alpha-55: rgba(255, 255, 255, 0.55);
68
+ --color-white-alpha-60: rgba(255, 255, 255, 0.6);
69
+ --color-white-alpha-92: rgba(255, 255, 255, 0.92);
70
+ --color-black-alpha-4: rgba(0, 0, 0, 0.04);
71
+ --color-black-alpha-8: rgba(0, 0, 0, 0.08);
72
+ --color-black-alpha-60: rgba(0, 0, 0, 0.6);
61
73
  --font-display: 'Rethink Sans', system-ui, -apple-system, sans-serif;
62
74
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
63
75
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
@@ -132,9 +144,12 @@
132
144
  --shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.06), 0 16px 40px rgba(0, 0, 0, 0.1);
133
145
  --shadow-pill: 0 1px 2px rgba(15, 23, 42, 0.08);
134
146
  --shadow-cta: 0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.06);
147
+ --shadow-popover: 0 1px 2px rgba(15, 23, 42, 0.08), 0 8px 24px rgba(15, 23, 42, 0.14);
148
+ --shadow-focus-error: 0 0 0 3px rgba(220, 38, 38, 0.15);
135
149
  --font-weight-regular: 400;
136
150
  --font-weight-medium: 500;
137
151
  --font-weight-semibold: 600;
138
152
  --font-weight-bold: 700;
139
153
  --font-weight-extrabold: 800;
154
+ --gradient-brand-warm: linear-gradient(160deg, #fbfbfb 34%, #f29c6f 90%);
140
155
  }
package/dist/webapp.css CHANGED
@@ -32,6 +32,7 @@
32
32
  --color-success: #059669;
33
33
  --color-success-bg: #f0fdf4;
34
34
  --color-success-text: #15803d;
35
+ --color-success-border: #bbf7d0;
35
36
  --color-warning: #ca8a04;
36
37
  --color-warning-bg: #fffbeb;
37
38
  --color-warning-text: #92400e;
@@ -56,6 +57,17 @@
56
57
  --color-error-pressed: #7f1d1d;
57
58
  --color-error-border-hover: #fca5a5;
58
59
  --color-error-bg-pressed: #fee2e2;
60
+ --color-white-alpha-6: rgba(255, 255, 255, 0.06);
61
+ --color-white-alpha-8: rgba(255, 255, 255, 0.08);
62
+ --color-white-alpha-10: rgba(255, 255, 255, 0.1);
63
+ --color-white-alpha-12: rgba(255, 255, 255, 0.12);
64
+ --color-white-alpha-35: rgba(255, 255, 255, 0.35);
65
+ --color-white-alpha-55: rgba(255, 255, 255, 0.55);
66
+ --color-white-alpha-60: rgba(255, 255, 255, 0.6);
67
+ --color-white-alpha-92: rgba(255, 255, 255, 0.92);
68
+ --color-black-alpha-4: rgba(0, 0, 0, 0.04);
69
+ --color-black-alpha-8: rgba(0, 0, 0, 0.08);
70
+ --color-black-alpha-60: rgba(0, 0, 0, 0.6);
59
71
  --font-display: 'Rethink Sans', system-ui, -apple-system, sans-serif;
60
72
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
61
73
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
@@ -130,9 +142,12 @@
130
142
  --shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.06), 0 16px 40px rgba(0, 0, 0, 0.1);
131
143
  --shadow-pill: 0 1px 2px rgba(15, 23, 42, 0.08);
132
144
  --shadow-cta: 0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.06);
145
+ --shadow-popover: 0 1px 2px rgba(15, 23, 42, 0.08), 0 8px 24px rgba(15, 23, 42, 0.14);
146
+ --shadow-focus-error: 0 0 0 3px rgba(220, 38, 38, 0.15);
133
147
  --font-weight-regular: 400;
134
148
  --font-weight-medium: 500;
135
149
  --font-weight-semibold: 600;
136
150
  --font-weight-bold: 700;
137
151
  --font-weight-extrabold: 800;
152
+ --gradient-brand-warm: linear-gradient(160deg, #fbfbfb 34%, #f29c6f 90%);
138
153
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usefidel/design-system",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "Fidel brand design tokens + React component library — DTCG token source of truth, generated per-surface CSS + Tailwind-v4 parser-compatibility output, and on-brand React components (Button, MismatchCard, DiffSection).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -200,6 +200,10 @@
200
200
  "$value": "#15803d",
201
201
  "$type": "color"
202
202
  },
203
+ "success-border": {
204
+ "$value": "#bbf7d0",
205
+ "$type": "color"
206
+ },
203
207
  "warning": {
204
208
  "$value": "#ca8a04",
205
209
  "$type": "color"
@@ -295,6 +299,50 @@
295
299
  "error-bg-pressed": {
296
300
  "$value": "#fee2e2",
297
301
  "$type": "color"
302
+ },
303
+ "white-alpha-6": {
304
+ "$value": "rgba(255, 255, 255, 0.06)",
305
+ "$type": "color"
306
+ },
307
+ "white-alpha-8": {
308
+ "$value": "rgba(255, 255, 255, 0.08)",
309
+ "$type": "color"
310
+ },
311
+ "white-alpha-10": {
312
+ "$value": "rgba(255, 255, 255, 0.1)",
313
+ "$type": "color"
314
+ },
315
+ "white-alpha-12": {
316
+ "$value": "rgba(255, 255, 255, 0.12)",
317
+ "$type": "color"
318
+ },
319
+ "white-alpha-35": {
320
+ "$value": "rgba(255, 255, 255, 0.35)",
321
+ "$type": "color"
322
+ },
323
+ "white-alpha-55": {
324
+ "$value": "rgba(255, 255, 255, 0.55)",
325
+ "$type": "color"
326
+ },
327
+ "white-alpha-60": {
328
+ "$value": "rgba(255, 255, 255, 0.6)",
329
+ "$type": "color"
330
+ },
331
+ "white-alpha-92": {
332
+ "$value": "rgba(255, 255, 255, 0.92)",
333
+ "$type": "color"
334
+ },
335
+ "black-alpha-4": {
336
+ "$value": "rgba(0, 0, 0, 0.04)",
337
+ "$type": "color"
338
+ },
339
+ "black-alpha-8": {
340
+ "$value": "rgba(0, 0, 0, 0.08)",
341
+ "$type": "color"
342
+ },
343
+ "black-alpha-60": {
344
+ "$value": "rgba(0, 0, 0, 0.6)",
345
+ "$type": "color"
298
346
  }
299
347
  },
300
348
  "font": {
@@ -633,6 +681,14 @@
633
681
  "cta": {
634
682
  "$value": "0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.06)",
635
683
  "$type": "shadow"
684
+ },
685
+ "popover": {
686
+ "$value": "0 1px 2px rgba(15, 23, 42, 0.08), 0 8px 24px rgba(15, 23, 42, 0.14)",
687
+ "$type": "shadow"
688
+ },
689
+ "focus-error": {
690
+ "$value": "0 0 0 3px rgba(220, 38, 38, 0.15)",
691
+ "$type": "shadow"
636
692
  }
637
693
  },
638
694
  "fontWeight": {
@@ -656,5 +712,11 @@
656
712
  "$value": 800,
657
713
  "$type": "fontWeight"
658
714
  }
715
+ },
716
+ "gradient": {
717
+ "brand-warm": {
718
+ "$value": "linear-gradient(160deg, #fbfbfb 34%, #f29c6f 90%)",
719
+ "$type": "gradient"
720
+ }
659
721
  }
660
722
  }