@fairmint/ui 0.3.4 → 0.3.6

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 (55) hide show
  1. package/dist/_virtual/index3.cjs +5 -3
  2. package/dist/_virtual/index3.cjs.map +1 -1
  3. package/dist/_virtual/index3.js +5 -2
  4. package/dist/_virtual/index3.js.map +1 -1
  5. package/dist/_virtual/index4.cjs +3 -5
  6. package/dist/_virtual/index4.cjs.map +1 -1
  7. package/dist/_virtual/index4.js +2 -5
  8. package/dist/_virtual/index4.js.map +1 -1
  9. package/dist/components/generic/Banner/Banner.cjs +131 -43
  10. package/dist/components/generic/Banner/Banner.cjs.map +1 -1
  11. package/dist/components/generic/Banner/Banner.d.ts +4 -1
  12. package/dist/components/generic/Banner/Banner.d.ts.map +1 -1
  13. package/dist/components/generic/Banner/Banner.js +133 -45
  14. package/dist/components/generic/Banner/Banner.js.map +1 -1
  15. package/dist/components/generic/DataTable/DataTable.cjs +2 -2
  16. package/dist/components/generic/DataTable/DataTable.cjs.map +1 -1
  17. package/dist/components/generic/DataTable/DataTable.d.ts.map +1 -1
  18. package/dist/components/generic/DataTable/DataTable.js +3 -3
  19. package/dist/components/generic/DataTable/DataTable.js.map +1 -1
  20. package/dist/components/generic/StepCard/StepCard.cjs +2 -1
  21. package/dist/components/generic/StepCard/StepCard.cjs.map +1 -1
  22. package/dist/components/generic/StepCard/StepCard.js +2 -1
  23. package/dist/components/generic/StepCard/StepCard.js.map +1 -1
  24. package/dist/components/layout/PageHeader/PageHeader.cjs +2 -1
  25. package/dist/components/layout/PageHeader/PageHeader.cjs.map +1 -1
  26. package/dist/components/layout/PageHeader/PageHeader.d.ts.map +1 -1
  27. package/dist/components/layout/PageHeader/PageHeader.js +2 -1
  28. package/dist/components/layout/PageHeader/PageHeader.js.map +1 -1
  29. package/dist/components/primitives/Table/Table.cjs +4 -2
  30. package/dist/components/primitives/Table/Table.cjs.map +1 -1
  31. package/dist/components/primitives/Table/Table.d.ts +3 -1
  32. package/dist/components/primitives/Table/Table.d.ts.map +1 -1
  33. package/dist/components/primitives/Table/Table.js +4 -2
  34. package/dist/components/primitives/Table/Table.js.map +1 -1
  35. package/dist/fairmint-ui.cjs +2 -0
  36. package/dist/fairmint-ui.cjs.map +1 -1
  37. package/dist/fairmint-ui.js +2 -0
  38. package/dist/fairmint-ui.js.map +1 -1
  39. package/dist/index.d.ts +3 -3
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/node_modules/@mantine/form/esm/hooks/use-form-status/use-form-status.cjs +1 -1
  42. package/dist/node_modules/@mantine/form/esm/hooks/use-form-status/use-form-status.js +1 -1
  43. package/dist/node_modules/prop-types/index.cjs +1 -1
  44. package/dist/node_modules/prop-types/index.js +1 -1
  45. package/dist/theme/index.cjs.map +1 -1
  46. package/dist/theme/index.d.ts +2 -0
  47. package/dist/theme/index.d.ts.map +1 -1
  48. package/dist/theme/index.js.map +1 -1
  49. package/dist/theme/responsiveTypography.cjs +13 -0
  50. package/dist/theme/responsiveTypography.cjs.map +1 -0
  51. package/dist/theme/responsiveTypography.d.ts +40 -0
  52. package/dist/theme/responsiveTypography.d.ts.map +1 -0
  53. package/dist/theme/responsiveTypography.js +13 -0
  54. package/dist/theme/responsiveTypography.js.map +1 -0
  55. package/package.json +1 -1
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- var propTypes = { exports: {} };
4
- exports.__module = propTypes;
2
+ const _commonjsHelpers = require("./_commonjsHelpers.cjs");
3
+ const index = require("../node_modules/fast-deep-equal/index.cjs");
4
+ var fastDeepEqualExports = index.__require();
5
+ const isEqual = /* @__PURE__ */ _commonjsHelpers.getDefaultExportFromCjs(fastDeepEqualExports);
6
+ module.exports = isEqual;
5
7
  //# sourceMappingURL=index3.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index3.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"index3.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -1,5 +1,8 @@
1
- var propTypes = { exports: {} };
1
+ import { getDefaultExportFromCjs } from "./_commonjsHelpers.js";
2
+ import { __require as requireFastDeepEqual } from "../node_modules/fast-deep-equal/index.js";
3
+ var fastDeepEqualExports = requireFastDeepEqual();
4
+ const isEqual = /* @__PURE__ */ getDefaultExportFromCjs(fastDeepEqualExports);
2
5
  export {
3
- propTypes as __module
6
+ isEqual as default
4
7
  };
5
8
  //# sourceMappingURL=index3.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index3.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index3.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
- const _commonjsHelpers = require("./_commonjsHelpers.cjs");
3
- const index = require("../node_modules/fast-deep-equal/index.cjs");
4
- var fastDeepEqualExports = index.__require();
5
- const isEqual = /* @__PURE__ */ _commonjsHelpers.getDefaultExportFromCjs(fastDeepEqualExports);
6
- module.exports = isEqual;
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ var propTypes = { exports: {} };
4
+ exports.__module = propTypes;
7
5
  //# sourceMappingURL=index4.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index4.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
1
+ {"version":3,"file":"index4.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,8 +1,5 @@
1
- import { getDefaultExportFromCjs } from "./_commonjsHelpers.js";
2
- import { __require as requireFastDeepEqual } from "../node_modules/fast-deep-equal/index.js";
3
- var fastDeepEqualExports = requireFastDeepEqual();
4
- const isEqual = /* @__PURE__ */ getDefaultExportFromCjs(fastDeepEqualExports);
1
+ var propTypes = { exports: {} };
5
2
  export {
6
- isEqual as default
3
+ propTypes as __module
7
4
  };
8
5
  //# sourceMappingURL=index4.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index4.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"index4.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -6,8 +6,9 @@ const colors = require("../../../theme/colors.cjs");
6
6
  const Badge = require("../../primitives/Badge/Badge.cjs");
7
7
  const Button = require("../../primitives/Button/Button.cjs");
8
8
  const layout = require("../../primitives/layout.cjs");
9
- const Group = require("../../../node_modules/@mantine/core/esm/components/Group/Group.cjs");
9
+ const spacing = require("../../../theme/spacing.cjs");
10
10
  const ThemeIcon = require("../../../node_modules/@mantine/core/esm/components/ThemeIcon/ThemeIcon.cjs");
11
+ const Group = require("../../../node_modules/@mantine/core/esm/components/Group/Group.cjs");
11
12
  const Text = require("../../../node_modules/@mantine/core/esm/components/Text/Text.cjs");
12
13
  const fontSizes = require("../../../theme/fontSizes.cjs");
13
14
  const TONE_COLORS = {
@@ -79,18 +80,63 @@ const surfaceProps = (tone, presentation) => {
79
80
  }
80
81
  };
81
82
  };
82
- const titleColor = (tone, presentation) => {
83
- if (presentation === "page-level") {
84
- const color = TONE_COLORS[tone];
85
- return `${color}.${tone === "neutral" ? 9 : 8}`;
86
- }
87
- return index.neutralColors[900];
88
- };
89
- const actionVariant = (tone) => {
83
+ const titleColor = () => index.neutralColors[900];
84
+ const actionVariant = (tone, isSecondary) => {
85
+ if (isSecondary) return "outline";
90
86
  if (tone === "brand") return "light";
91
87
  if (tone === "neutral") return "outline";
92
88
  return "filled";
93
89
  };
90
+ const getBannerLayout = ({
91
+ hasActions,
92
+ hasDescription,
93
+ hasIcon,
94
+ hasTitle
95
+ }) => {
96
+ const mobileColumns = hasIcon ? "40px minmax(0, 1fr)" : "minmax(0, 1fr)";
97
+ const desktopContentColumns = hasIcon ? ["40px"] : [];
98
+ if (hasTitle || hasDescription) {
99
+ desktopContentColumns.push("minmax(0, 1fr)");
100
+ }
101
+ if (hasActions) {
102
+ desktopContentColumns.push("auto");
103
+ }
104
+ const mobileRows = [];
105
+ if (hasIcon && hasTitle) mobileRows.push('"icon title"');
106
+ else if (hasIcon) mobileRows.push('"icon icon"');
107
+ else if (hasTitle) mobileRows.push('"title"');
108
+ if (hasDescription) mobileRows.push(hasIcon ? '"description description"' : '"description"');
109
+ if (hasActions) mobileRows.push(hasIcon ? '"actions actions"' : '"actions"');
110
+ const desktopRows = [];
111
+ const actionCell = hasActions ? " actions" : "";
112
+ if (hasIcon && hasTitle && hasDescription) {
113
+ desktopRows.push(`"icon title${actionCell}"`, `"icon description${actionCell}"`);
114
+ } else if (hasIcon && hasTitle) {
115
+ desktopRows.push(`"icon title${actionCell}"`);
116
+ } else if (hasIcon && hasDescription) {
117
+ desktopRows.push(`"icon description${actionCell}"`);
118
+ } else if (hasIcon) {
119
+ desktopRows.push(`"icon${hasActions ? " actions" : ""}"`);
120
+ } else if (hasTitle && hasDescription) {
121
+ desktopRows.push(`"title${actionCell}"`, `"description${actionCell}"`);
122
+ } else if (hasTitle) {
123
+ desktopRows.push(`"title${actionCell}"`);
124
+ } else if (hasDescription) {
125
+ desktopRows.push(`"description${actionCell}"`);
126
+ } else if (hasActions) {
127
+ desktopRows.push('"actions"');
128
+ }
129
+ return {
130
+ gridTemplateAreas: {
131
+ base: mobileRows.join(" "),
132
+ sm: desktopRows.join(" ")
133
+ },
134
+ gridTemplateColumns: {
135
+ base: mobileColumns,
136
+ sm: desktopContentColumns.join(" ") || "auto"
137
+ }
138
+ };
139
+ };
94
140
  const descriptionTextProps = {
95
141
  size: "sm",
96
142
  c: index.neutralColors[500],
@@ -119,6 +165,7 @@ function Banner({
119
165
  className,
120
166
  description,
121
167
  icon,
168
+ actions,
122
169
  presentation = "inline",
123
170
  role,
124
171
  style,
@@ -127,24 +174,17 @@ function Banner({
127
174
  }) {
128
175
  const color = TONE_COLORS[tone];
129
176
  const iconNode = icon === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(DefaultStatusIcon, { tone }) : icon;
177
+ const resolvedActions = actions ?? (action === void 0 ? [] : [action]);
130
178
  const resolvedRole = role ?? (tone === "error" ? "alert" : "status");
131
179
  const resolvedAriaLabel = ariaLabel ?? (typeof title === "string" ? title : void 0);
132
180
  const surface = surfaceProps(tone, presentation);
133
- let actionNode = null;
134
- if (action !== void 0) {
135
- const { label, ...buttonProps } = action;
136
- actionNode = /* @__PURE__ */ jsxRuntime.jsx(
137
- Button.Button,
138
- {
139
- ...buttonProps,
140
- color,
141
- variant: actionVariant(tone),
142
- style: { flex: "0 0 auto", ...buttonProps.style },
143
- children: label
144
- }
145
- );
146
- }
147
- return /* @__PURE__ */ jsxRuntime.jsx(
181
+ const layout$1 = getBannerLayout({
182
+ hasActions: resolvedActions.length > 0,
183
+ hasDescription: description !== void 0,
184
+ hasIcon: iconNode !== null,
185
+ hasTitle: title !== void 0 || badgeLabel !== void 0
186
+ });
187
+ return /* @__PURE__ */ jsxRuntime.jsxs(
148
188
  layout.Box,
149
189
  {
150
190
  "aria-label": resolvedAriaLabel,
@@ -162,7 +202,13 @@ function Banner({
162
202
  ...surface.style,
163
203
  ...style
164
204
  },
165
- children: /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { align: "center", gap: "sm", wrap: "wrap", children: [
205
+ sx: {
206
+ display: "grid",
207
+ columnGap: spacing.spacing.sm,
208
+ rowGap: spacing.spacing.xs,
209
+ ...layout$1
210
+ },
211
+ children: [
166
212
  iconNode !== null && /* @__PURE__ */ jsxRuntime.jsx(
167
213
  ThemeIcon.ThemeIcon,
168
214
  {
@@ -171,28 +217,70 @@ function Banner({
171
217
  radius: "sm",
172
218
  size: 40,
173
219
  variant: "light",
174
- style: { flex: "0 0 auto" },
220
+ style: { gridArea: "icon", alignSelf: "center" },
175
221
  children: iconNode
176
222
  }
177
223
  ),
178
- /* @__PURE__ */ jsxRuntime.jsxs(layout.Stack, { gap: 4, style: { flex: "1 1 240px", minWidth: 0 }, children: [
179
- title !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { align: "center", gap: "xs", wrap: "wrap", children: [
180
- /* @__PURE__ */ jsxRuntime.jsx(
181
- Text.Text,
224
+ (title !== void 0 || badgeLabel !== void 0) && /* @__PURE__ */ jsxRuntime.jsxs(
225
+ Group.Group,
226
+ {
227
+ align: "center",
228
+ gap: "xs",
229
+ wrap: "wrap",
230
+ style: { gridArea: "title", minWidth: 0, overflowWrap: "anywhere" },
231
+ children: [
232
+ title !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
233
+ Text.Text,
234
+ {
235
+ fw: 600,
236
+ size: "md",
237
+ c: titleColor(),
238
+ style: { lineHeight: 1.35, minWidth: 0, overflowWrap: "anywhere" },
239
+ children: title
240
+ }
241
+ ),
242
+ badgeLabel !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { color, size: "sm", variant: "light", children: badgeLabel })
243
+ ]
244
+ }
245
+ ),
246
+ description !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(layout.Box, { style: { gridArea: "description", minWidth: 0, overflowWrap: "anywhere" }, children: /* @__PURE__ */ jsxRuntime.jsx(BannerDescription, { children: description }) }),
247
+ resolvedActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
248
+ layout.Box,
249
+ {
250
+ sx: {
251
+ display: "flex",
252
+ flexDirection: { base: "column", sm: "row" },
253
+ alignItems: "stretch",
254
+ justifyContent: "flex-end",
255
+ gap: spacing.spacing.xs,
256
+ minWidth: 0,
257
+ width: { base: "100%", sm: "max-content" },
258
+ maxWidth: "100%"
259
+ },
260
+ style: { gridArea: "actions", alignSelf: "center", justifySelf: "end" },
261
+ children: resolvedActions.map(({ label, ...buttonProps }, index2) => /* @__PURE__ */ jsxRuntime.jsx(
262
+ Button.Button,
182
263
  {
183
- fw: 600,
184
- size: "md",
185
- c: titleColor(tone, presentation),
186
- style: { lineHeight: 1.35 },
187
- children: title
188
- }
189
- ),
190
- badgeLabel !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { color, size: "sm", variant: "light", children: badgeLabel })
191
- ] }),
192
- description !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(BannerDescription, { children: description })
193
- ] }),
194
- actionNode
195
- ] })
264
+ ...buttonProps,
265
+ color,
266
+ variant: actionVariant(tone, index2 < resolvedActions.length - 1),
267
+ style: {
268
+ ...buttonProps.style,
269
+ boxSizing: "border-box",
270
+ flex: "0 1 auto",
271
+ minHeight: 44,
272
+ maxWidth: "100%",
273
+ overflowWrap: "anywhere",
274
+ whiteSpace: "normal",
275
+ width: "100%"
276
+ },
277
+ children: label
278
+ },
279
+ buttonProps.id ?? (typeof label === "string" ? label : `banner-action-${index2}`)
280
+ ))
281
+ }
282
+ )
283
+ ]
196
284
  }
197
285
  );
198
286
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.cjs","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"sourcesContent":["import type { AriaRole, CSSProperties, ReactNode } from \"react\";\nimport { fontSizes, neutralColors, radii } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text, ThemeIcon } from \"../../primitives/layout\";\n\nexport type BannerTone = \"brand\" | \"neutral\" | \"info\" | \"success\" | \"warning\" | \"error\";\nexport type BannerPresentation = \"inline\" | \"page-level\";\n\nexport interface BannerActionProps extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\"> {\n /** Visible action label. */\n label: ReactNode;\n}\n\nexport interface BannerProps {\n /** Primary message. Omit when the banner is description-only; set `ariaLabel` for accessibility. */\n title?: ReactNode;\n /** Supporting context. Omit for a title-only banner. */\n description?: ReactNode;\n /** Semantic meaning and visual treatment. @default \"brand\" */\n tone?: BannerTone;\n /** Inline content callout or full-width page-edge treatment. @default \"inline\" */\n presentation?: BannerPresentation;\n /** Icon shown in the 40px semantic tile. Pass `null` to hide the tile. */\n icon?: ReactNode | null;\n /** Optional badge label displayed beside the title. */\n badgeLabel?: ReactNode;\n /** Optional standardized CTA. */\n action?: BannerActionProps;\n /** Override the default accessible role. Error defaults to alert; other tones use status. */\n role?: AriaRole;\n /** Accessible label for the banner region. Defaults to the string title when possible. */\n ariaLabel?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst TONE_COLORS = {\n brand: colors.primary,\n neutral: colors.neutral,\n info: colors.info,\n success: colors.success,\n warning: colors.warning,\n error: colors.error,\n} as const;\n\nconst DefaultStatusIcon = ({ tone }: { tone: BannerTone }) => {\n const commonProps = {\n width: 20,\n height: 20,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n \"aria-hidden\": true,\n };\n\n if (tone === \"success\") {\n return (\n <svg {...commonProps}>\n <title>Success</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12 2.25 2.25L15.75 9\" />\n </svg>\n );\n }\n\n if (tone === \"warning\") {\n return (\n <svg {...commonProps}>\n <title>Warning</title>\n <path d=\"M10.3 4.2 2.6 18a2 2 0 0 0 1.75 3h15.3a2 2 0 0 0 1.75-3L13.7 4.2a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n }\n\n if (tone === \"error\") {\n return (\n <svg {...commonProps}>\n <title>Error</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m9 9 6 6\" />\n <path d=\"m15 9-6 6\" />\n </svg>\n );\n }\n\n return (\n <svg {...commonProps}>\n <title>Information</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 11v5\" />\n <path d=\"M12 8h.01\" />\n </svg>\n );\n};\n\nconst surfaceProps = (tone: BannerTone, presentation: BannerPresentation) => {\n const color = TONE_COLORS[tone];\n\n if (presentation === \"page-level\") {\n return {\n bg: `${color}.1`,\n style: {\n borderRadius: 0,\n } satisfies CSSProperties,\n };\n }\n\n // Chip Banner: tinted surface + semantic border (error border = error.2)\n const borderShade = tone === \"brand\" ? 1 : tone === \"neutral\" ? 3 : 2;\n\n return {\n bg: `${color}.0`,\n bd: `1px solid ${color}.${borderShade}`,\n style: {\n borderRadius: radii.lg,\n } satisfies CSSProperties,\n };\n};\n\n/**\n * Inline Chip banners keep light semantic fills across color schemes, so titles\n * stay dark primary text for WCAG AA. Page-level uses a deeper semantic shade.\n */\nconst titleColor = (tone: BannerTone, presentation: BannerPresentation) => {\n if (presentation === \"page-level\") {\n const color = TONE_COLORS[tone];\n return `${color}.${tone === \"neutral\" ? 9 : 8}`;\n }\n return neutralColors[900];\n};\n\nconst actionVariant = (tone: BannerTone): ButtonProps[\"variant\"] => {\n if (tone === \"brand\") return \"light\";\n if (tone === \"neutral\") return \"outline\";\n return \"filled\";\n};\n\nconst descriptionTextProps = {\n size: \"sm\" as const,\n c: neutralColors[500],\n style: { lineHeight: 1.4 },\n};\n\nfunction BannerDescription({ children }: { children: ReactNode }) {\n if (typeof children === \"string\" || typeof children === \"number\") {\n return <Text {...descriptionTextProps}>{children}</Text>;\n }\n\n return (\n <Box\n c={neutralColors[500]}\n style={{\n fontSize: fontSizes.sm,\n lineHeight: 1.4,\n }}\n >\n {children}\n </Box>\n );\n}\n\n/**\n * Persistent contextual guidance with semantic inline and page-level presentations.\n * Position page-level banners in the consuming layout; the component does not use fixed positioning.\n */\nexport function Banner({\n action,\n ariaLabel,\n badgeLabel,\n className,\n description,\n icon,\n presentation = \"inline\",\n role,\n style,\n title,\n tone = \"brand\",\n}: BannerProps) {\n const color = TONE_COLORS[tone];\n const iconNode = icon === undefined ? <DefaultStatusIcon tone={tone} /> : icon;\n const resolvedRole = role ?? (tone === \"error\" ? \"alert\" : \"status\");\n const resolvedAriaLabel = ariaLabel ?? (typeof title === \"string\" ? title : undefined);\n const surface = surfaceProps(tone, presentation);\n let actionNode: ReactNode = null;\n\n if (action !== undefined) {\n const { label, ...buttonProps } = action;\n actionNode = (\n <Button\n {...buttonProps}\n color={color}\n variant={actionVariant(tone)}\n style={{ flex: \"0 0 auto\", ...buttonProps.style }}\n >\n {label}\n </Button>\n );\n }\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n className={className}\n data-presentation={presentation}\n data-tone={tone}\n role={resolvedRole}\n px=\"md\"\n py=\"md\"\n bg={surface.bg}\n bd={\"bd\" in surface ? surface.bd : undefined}\n style={{\n boxSizing: \"border-box\",\n width: \"100%\",\n ...surface.style,\n ...style,\n }}\n >\n <Group align=\"center\" gap=\"sm\" wrap=\"wrap\">\n {iconNode !== null && (\n <ThemeIcon\n aria-hidden\n color={color}\n radius=\"sm\"\n size={40}\n variant=\"light\"\n style={{ flex: \"0 0 auto\" }}\n >\n {iconNode}\n </ThemeIcon>\n )}\n\n <Stack gap={4} style={{ flex: \"1 1 240px\", minWidth: 0 }}>\n {title !== undefined && (\n <Group align=\"center\" gap=\"xs\" wrap=\"wrap\">\n <Text\n fw={600}\n size=\"md\"\n c={titleColor(tone, presentation)}\n style={{ lineHeight: 1.35 }}\n >\n {title}\n </Text>\n {badgeLabel !== undefined && (\n <Badge color={color} size=\"sm\" variant=\"light\">\n {badgeLabel}\n </Badge>\n )}\n </Group>\n )}\n {description !== undefined && <BannerDescription>{description}</BannerDescription>}\n </Stack>\n\n {actionNode}\n </Group>\n </Box>\n );\n}\n"],"names":["colors","jsxs","jsx","radii","neutralColors","Text","Box","fontSizes","Button","Group","ThemeIcon","Stack","Badge"],"mappings":"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"}
1
+ {"version":3,"file":"Banner.cjs","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"sourcesContent":["import type { AriaRole, CSSProperties, ReactNode } from \"react\";\nimport { fontSizes, neutralColors, radii, spacing } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Text, ThemeIcon } from \"../../primitives/layout\";\n\nexport type BannerTone = \"brand\" | \"neutral\" | \"info\" | \"success\" | \"warning\" | \"error\";\nexport type BannerPresentation = \"inline\" | \"page-level\";\n\nexport interface BannerActionProps extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\"> {\n /** Visible action label. */\n label: ReactNode;\n}\n\nexport type BannerActions =\n | readonly [BannerActionProps]\n | readonly [BannerActionProps, BannerActionProps];\n\nexport interface BannerProps {\n /** Primary message. Omit when the banner is description-only; set `ariaLabel` for accessibility. */\n title?: ReactNode;\n /** Supporting context. Omit for a title-only banner. */\n description?: ReactNode;\n /** Semantic meaning and visual treatment. @default \"brand\" */\n tone?: BannerTone;\n /** Inline content callout or full-width page-edge treatment. @default \"inline\" */\n presentation?: BannerPresentation;\n /** Icon shown in the 40px semantic tile. Pass `null` to hide the tile. */\n icon?: ReactNode | null;\n /** Optional badge label displayed beside the title. */\n badgeLabel?: ReactNode;\n /** Optional standardized CTA. */\n action?: BannerActionProps;\n /** Up to two CTAs in visual order: secondary first, primary last. */\n actions?: BannerActions;\n /** Override the default accessible role. Error defaults to alert; other tones use status. */\n role?: AriaRole;\n /** Accessible label for the banner region. Defaults to the string title when possible. */\n ariaLabel?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst TONE_COLORS = {\n brand: colors.primary,\n neutral: colors.neutral,\n info: colors.info,\n success: colors.success,\n warning: colors.warning,\n error: colors.error,\n} as const;\n\nconst DefaultStatusIcon = ({ tone }: { tone: BannerTone }) => {\n const commonProps = {\n width: 20,\n height: 20,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n \"aria-hidden\": true,\n };\n\n if (tone === \"success\") {\n return (\n <svg {...commonProps}>\n <title>Success</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12 2.25 2.25L15.75 9\" />\n </svg>\n );\n }\n\n if (tone === \"warning\") {\n return (\n <svg {...commonProps}>\n <title>Warning</title>\n <path d=\"M10.3 4.2 2.6 18a2 2 0 0 0 1.75 3h15.3a2 2 0 0 0 1.75-3L13.7 4.2a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n }\n\n if (tone === \"error\") {\n return (\n <svg {...commonProps}>\n <title>Error</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m9 9 6 6\" />\n <path d=\"m15 9-6 6\" />\n </svg>\n );\n }\n\n return (\n <svg {...commonProps}>\n <title>Information</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 11v5\" />\n <path d=\"M12 8h.01\" />\n </svg>\n );\n};\n\nconst surfaceProps = (tone: BannerTone, presentation: BannerPresentation) => {\n const color = TONE_COLORS[tone];\n\n if (presentation === \"page-level\") {\n return {\n bg: `${color}.1`,\n style: {\n borderRadius: 0,\n } satisfies CSSProperties,\n };\n }\n\n // Chip Banner: tinted surface + semantic border (error border = error.2)\n const borderShade = tone === \"brand\" ? 1 : tone === \"neutral\" ? 3 : 2;\n\n return {\n bg: `${color}.0`,\n bd: `1px solid ${color}.${borderShade}`,\n style: {\n borderRadius: radii.lg,\n } satisfies CSSProperties,\n };\n};\n\n/** Titles always use dark primary text for WCAG AA contrast, inline or page-level. */\nconst titleColor = () => neutralColors[900];\n\nconst actionVariant = (tone: BannerTone, isSecondary: boolean): ButtonProps[\"variant\"] => {\n if (isSecondary) return \"outline\";\n if (tone === \"brand\") return \"light\";\n if (tone === \"neutral\") return \"outline\";\n return \"filled\";\n};\n\ninterface BannerLayoutOptions {\n hasIcon: boolean;\n hasTitle: boolean;\n hasDescription: boolean;\n hasActions: boolean;\n}\n\nconst getBannerLayout = ({\n hasActions,\n hasDescription,\n hasIcon,\n hasTitle,\n}: BannerLayoutOptions) => {\n const mobileColumns = hasIcon ? \"40px minmax(0, 1fr)\" : \"minmax(0, 1fr)\";\n const desktopContentColumns = hasIcon ? [\"40px\"] : [];\n\n if (hasTitle || hasDescription) {\n desktopContentColumns.push(\"minmax(0, 1fr)\");\n }\n\n if (hasActions) {\n desktopContentColumns.push(\"auto\");\n }\n\n const mobileRows: string[] = [];\n if (hasIcon && hasTitle) mobileRows.push('\"icon title\"');\n else if (hasIcon) mobileRows.push('\"icon icon\"');\n else if (hasTitle) mobileRows.push('\"title\"');\n\n if (hasDescription) mobileRows.push(hasIcon ? '\"description description\"' : '\"description\"');\n if (hasActions) mobileRows.push(hasIcon ? '\"actions actions\"' : '\"actions\"');\n\n const desktopRows: string[] = [];\n const actionCell = hasActions ? \" actions\" : \"\";\n if (hasIcon && hasTitle && hasDescription) {\n desktopRows.push(`\"icon title${actionCell}\"`, `\"icon description${actionCell}\"`);\n } else if (hasIcon && hasTitle) {\n desktopRows.push(`\"icon title${actionCell}\"`);\n } else if (hasIcon && hasDescription) {\n desktopRows.push(`\"icon description${actionCell}\"`);\n } else if (hasIcon) {\n desktopRows.push(`\"icon${hasActions ? \" actions\" : \"\"}\"`);\n } else if (hasTitle && hasDescription) {\n desktopRows.push(`\"title${actionCell}\"`, `\"description${actionCell}\"`);\n } else if (hasTitle) {\n desktopRows.push(`\"title${actionCell}\"`);\n } else if (hasDescription) {\n desktopRows.push(`\"description${actionCell}\"`);\n } else if (hasActions) {\n desktopRows.push('\"actions\"');\n }\n\n return {\n gridTemplateAreas: {\n base: mobileRows.join(\" \"),\n sm: desktopRows.join(\" \"),\n },\n gridTemplateColumns: {\n base: mobileColumns,\n sm: desktopContentColumns.join(\" \") || \"auto\",\n },\n };\n};\n\nconst descriptionTextProps = {\n size: \"sm\" as const,\n c: neutralColors[500],\n style: { lineHeight: 1.4 },\n};\n\nfunction BannerDescription({ children }: { children: ReactNode }) {\n if (typeof children === \"string\" || typeof children === \"number\") {\n return <Text {...descriptionTextProps}>{children}</Text>;\n }\n\n return (\n <Box\n c={neutralColors[500]}\n style={{\n fontSize: fontSizes.sm,\n lineHeight: 1.4,\n }}\n >\n {children}\n </Box>\n );\n}\n\n/**\n * Persistent contextual guidance with semantic inline and page-level presentations.\n * Position page-level banners in the consuming layout; the component does not use fixed positioning.\n */\nexport function Banner({\n action,\n ariaLabel,\n badgeLabel,\n className,\n description,\n icon,\n actions,\n presentation = \"inline\",\n role,\n style,\n title,\n tone = \"brand\",\n}: BannerProps) {\n const color = TONE_COLORS[tone];\n const iconNode = icon === undefined ? <DefaultStatusIcon tone={tone} /> : icon;\n const resolvedActions = actions ?? (action === undefined ? [] : [action]);\n const resolvedRole = role ?? (tone === \"error\" ? \"alert\" : \"status\");\n const resolvedAriaLabel = ariaLabel ?? (typeof title === \"string\" ? title : undefined);\n const surface = surfaceProps(tone, presentation);\n const layout = getBannerLayout({\n hasActions: resolvedActions.length > 0,\n hasDescription: description !== undefined,\n hasIcon: iconNode !== null,\n hasTitle: title !== undefined || badgeLabel !== undefined,\n });\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n className={className}\n data-presentation={presentation}\n data-tone={tone}\n role={resolvedRole}\n px=\"md\"\n py=\"md\"\n bg={surface.bg}\n bd={\"bd\" in surface ? surface.bd : undefined}\n style={{\n boxSizing: \"border-box\",\n width: \"100%\",\n ...surface.style,\n ...style,\n }}\n sx={{\n display: \"grid\",\n columnGap: spacing.sm,\n rowGap: spacing.xs,\n ...layout,\n }}\n >\n {iconNode !== null && (\n <ThemeIcon\n aria-hidden\n color={color}\n radius=\"sm\"\n size={40}\n variant=\"light\"\n style={{ gridArea: \"icon\", alignSelf: \"center\" }}\n >\n {iconNode}\n </ThemeIcon>\n )}\n\n {(title !== undefined || badgeLabel !== undefined) && (\n <Group\n align=\"center\"\n gap=\"xs\"\n wrap=\"wrap\"\n style={{ gridArea: \"title\", minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title !== undefined && (\n <Text\n fw={600}\n size=\"md\"\n c={titleColor()}\n style={{ lineHeight: 1.35, minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n )}\n {badgeLabel !== undefined && (\n <Badge color={color} size=\"sm\" variant=\"light\">\n {badgeLabel}\n </Badge>\n )}\n </Group>\n )}\n\n {description !== undefined && (\n <Box style={{ gridArea: \"description\", minWidth: 0, overflowWrap: \"anywhere\" }}>\n <BannerDescription>{description}</BannerDescription>\n </Box>\n )}\n\n {resolvedActions.length > 0 && (\n <Box\n sx={{\n display: \"flex\",\n flexDirection: { base: \"column\", sm: \"row\" },\n alignItems: \"stretch\",\n justifyContent: \"flex-end\",\n gap: spacing.xs,\n minWidth: 0,\n width: { base: \"100%\", sm: \"max-content\" },\n maxWidth: \"100%\",\n }}\n style={{ gridArea: \"actions\", alignSelf: \"center\", justifySelf: \"end\" }}\n >\n {resolvedActions.map(({ label, ...buttonProps }, index) => (\n <Button\n key={buttonProps.id ?? (typeof label === \"string\" ? label : `banner-action-${index}`)}\n {...buttonProps}\n color={color}\n variant={actionVariant(tone, index < resolvedActions.length - 1)}\n style={{\n ...buttonProps.style,\n boxSizing: \"border-box\",\n flex: \"0 1 auto\",\n minHeight: 44,\n maxWidth: \"100%\",\n overflowWrap: \"anywhere\",\n whiteSpace: \"normal\",\n width: \"100%\",\n }}\n >\n {label}\n </Button>\n ))}\n </Box>\n )}\n </Box>\n );\n}\n"],"names":["colors","jsxs","jsx","radii","neutralColors","Text","Box","fontSizes","layout","spacing","ThemeIcon","Group","Badge","index","Button"],"mappings":"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"}
@@ -6,6 +6,7 @@ export interface BannerActionProps extends Omit<ButtonProps, "children" | "color
6
6
  /** Visible action label. */
7
7
  label: ReactNode;
8
8
  }
9
+ export type BannerActions = readonly [BannerActionProps] | readonly [BannerActionProps, BannerActionProps];
9
10
  export interface BannerProps {
10
11
  /** Primary message. Omit when the banner is description-only; set `ariaLabel` for accessibility. */
11
12
  title?: ReactNode;
@@ -21,6 +22,8 @@ export interface BannerProps {
21
22
  badgeLabel?: ReactNode;
22
23
  /** Optional standardized CTA. */
23
24
  action?: BannerActionProps;
25
+ /** Up to two CTAs in visual order: secondary first, primary last. */
26
+ actions?: BannerActions;
24
27
  /** Override the default accessible role. Error defaults to alert; other tones use status. */
25
28
  role?: AriaRole;
26
29
  /** Accessible label for the banner region. Defaults to the string title when possible. */
@@ -32,5 +35,5 @@ export interface BannerProps {
32
35
  * Persistent contextual guidance with semantic inline and page-level presentations.
33
36
  * Position page-level banners in the consuming layout; the component does not use fixed positioning.
34
37
  */
35
- export declare function Banner({ action, ariaLabel, badgeLabel, className, description, icon, presentation, role, style, title, tone, }: BannerProps): import("react/jsx-runtime").JSX.Element;
38
+ export declare function Banner({ action, ariaLabel, badgeLabel, className, description, icon, actions, presentation, role, style, title, tone, }: BannerProps): import("react/jsx-runtime").JSX.Element;
36
39
  //# sourceMappingURL=Banner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIhE,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAG1E,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AACxF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5F,4BAA4B;IAC5B,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,oGAAoG;IACpG,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wDAAwD;IACxD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,kFAAkF;IAClF,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,0EAA0E;IAC1E,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iCAAiC;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,6FAA6F;IAC7F,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAoID;;;GAGG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,YAAuB,EACvB,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAc,GACf,EAAE,WAAW,2CA+Eb"}
1
+ {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIhE,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAG1E,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AACxF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5F,4BAA4B;IAC5B,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GACrB,SAAS,CAAC,iBAAiB,CAAC,GAC5B,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,oGAAoG;IACpG,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wDAAwD;IACxD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,kFAAkF;IAClF,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,0EAA0E;IAC1E,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iCAAiC;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,qEAAqE;IACrE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,6FAA6F;IAC7F,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AA4LD;;;GAGG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,OAAO,EACP,YAAuB,EACvB,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAc,GACf,EAAE,WAAW,2CAwHb"}
@@ -1,11 +1,12 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { radii, neutralColors } from "../../../theme/index.js";
3
3
  import { colors } from "../../../theme/colors.js";
4
4
  import { Badge } from "../../primitives/Badge/Badge.js";
5
5
  import { Button } from "../../primitives/Button/Button.js";
6
- import { Box, Stack } from "../../primitives/layout.js";
7
- import { Group } from "../../../node_modules/@mantine/core/esm/components/Group/Group.js";
6
+ import { Box } from "../../primitives/layout.js";
7
+ import { spacing } from "../../../theme/spacing.js";
8
8
  import { ThemeIcon } from "../../../node_modules/@mantine/core/esm/components/ThemeIcon/ThemeIcon.js";
9
+ import { Group } from "../../../node_modules/@mantine/core/esm/components/Group/Group.js";
9
10
  import { Text } from "../../../node_modules/@mantine/core/esm/components/Text/Text.js";
10
11
  import { fontSizes } from "../../../theme/fontSizes.js";
11
12
  const TONE_COLORS = {
@@ -77,18 +78,63 @@ const surfaceProps = (tone, presentation) => {
77
78
  }
78
79
  };
79
80
  };
80
- const titleColor = (tone, presentation) => {
81
- if (presentation === "page-level") {
82
- const color = TONE_COLORS[tone];
83
- return `${color}.${tone === "neutral" ? 9 : 8}`;
84
- }
85
- return neutralColors[900];
86
- };
87
- const actionVariant = (tone) => {
81
+ const titleColor = () => neutralColors[900];
82
+ const actionVariant = (tone, isSecondary) => {
83
+ if (isSecondary) return "outline";
88
84
  if (tone === "brand") return "light";
89
85
  if (tone === "neutral") return "outline";
90
86
  return "filled";
91
87
  };
88
+ const getBannerLayout = ({
89
+ hasActions,
90
+ hasDescription,
91
+ hasIcon,
92
+ hasTitle
93
+ }) => {
94
+ const mobileColumns = hasIcon ? "40px minmax(0, 1fr)" : "minmax(0, 1fr)";
95
+ const desktopContentColumns = hasIcon ? ["40px"] : [];
96
+ if (hasTitle || hasDescription) {
97
+ desktopContentColumns.push("minmax(0, 1fr)");
98
+ }
99
+ if (hasActions) {
100
+ desktopContentColumns.push("auto");
101
+ }
102
+ const mobileRows = [];
103
+ if (hasIcon && hasTitle) mobileRows.push('"icon title"');
104
+ else if (hasIcon) mobileRows.push('"icon icon"');
105
+ else if (hasTitle) mobileRows.push('"title"');
106
+ if (hasDescription) mobileRows.push(hasIcon ? '"description description"' : '"description"');
107
+ if (hasActions) mobileRows.push(hasIcon ? '"actions actions"' : '"actions"');
108
+ const desktopRows = [];
109
+ const actionCell = hasActions ? " actions" : "";
110
+ if (hasIcon && hasTitle && hasDescription) {
111
+ desktopRows.push(`"icon title${actionCell}"`, `"icon description${actionCell}"`);
112
+ } else if (hasIcon && hasTitle) {
113
+ desktopRows.push(`"icon title${actionCell}"`);
114
+ } else if (hasIcon && hasDescription) {
115
+ desktopRows.push(`"icon description${actionCell}"`);
116
+ } else if (hasIcon) {
117
+ desktopRows.push(`"icon${hasActions ? " actions" : ""}"`);
118
+ } else if (hasTitle && hasDescription) {
119
+ desktopRows.push(`"title${actionCell}"`, `"description${actionCell}"`);
120
+ } else if (hasTitle) {
121
+ desktopRows.push(`"title${actionCell}"`);
122
+ } else if (hasDescription) {
123
+ desktopRows.push(`"description${actionCell}"`);
124
+ } else if (hasActions) {
125
+ desktopRows.push('"actions"');
126
+ }
127
+ return {
128
+ gridTemplateAreas: {
129
+ base: mobileRows.join(" "),
130
+ sm: desktopRows.join(" ")
131
+ },
132
+ gridTemplateColumns: {
133
+ base: mobileColumns,
134
+ sm: desktopContentColumns.join(" ") || "auto"
135
+ }
136
+ };
137
+ };
92
138
  const descriptionTextProps = {
93
139
  size: "sm",
94
140
  c: neutralColors[500],
@@ -117,6 +163,7 @@ function Banner({
117
163
  className,
118
164
  description,
119
165
  icon,
166
+ actions,
120
167
  presentation = "inline",
121
168
  role,
122
169
  style,
@@ -125,24 +172,17 @@ function Banner({
125
172
  }) {
126
173
  const color = TONE_COLORS[tone];
127
174
  const iconNode = icon === void 0 ? /* @__PURE__ */ jsx(DefaultStatusIcon, { tone }) : icon;
175
+ const resolvedActions = actions ?? (action === void 0 ? [] : [action]);
128
176
  const resolvedRole = role ?? (tone === "error" ? "alert" : "status");
129
177
  const resolvedAriaLabel = ariaLabel ?? (typeof title === "string" ? title : void 0);
130
178
  const surface = surfaceProps(tone, presentation);
131
- let actionNode = null;
132
- if (action !== void 0) {
133
- const { label, ...buttonProps } = action;
134
- actionNode = /* @__PURE__ */ jsx(
135
- Button,
136
- {
137
- ...buttonProps,
138
- color,
139
- variant: actionVariant(tone),
140
- style: { flex: "0 0 auto", ...buttonProps.style },
141
- children: label
142
- }
143
- );
144
- }
145
- return /* @__PURE__ */ jsx(
179
+ const layout = getBannerLayout({
180
+ hasActions: resolvedActions.length > 0,
181
+ hasDescription: description !== void 0,
182
+ hasIcon: iconNode !== null,
183
+ hasTitle: title !== void 0 || badgeLabel !== void 0
184
+ });
185
+ return /* @__PURE__ */ jsxs(
146
186
  Box,
147
187
  {
148
188
  "aria-label": resolvedAriaLabel,
@@ -160,7 +200,13 @@ function Banner({
160
200
  ...surface.style,
161
201
  ...style
162
202
  },
163
- children: /* @__PURE__ */ jsxs(Group, { align: "center", gap: "sm", wrap: "wrap", children: [
203
+ sx: {
204
+ display: "grid",
205
+ columnGap: spacing.sm,
206
+ rowGap: spacing.xs,
207
+ ...layout
208
+ },
209
+ children: [
164
210
  iconNode !== null && /* @__PURE__ */ jsx(
165
211
  ThemeIcon,
166
212
  {
@@ -169,28 +215,70 @@ function Banner({
169
215
  radius: "sm",
170
216
  size: 40,
171
217
  variant: "light",
172
- style: { flex: "0 0 auto" },
218
+ style: { gridArea: "icon", alignSelf: "center" },
173
219
  children: iconNode
174
220
  }
175
221
  ),
176
- /* @__PURE__ */ jsxs(Stack, { gap: 4, style: { flex: "1 1 240px", minWidth: 0 }, children: [
177
- title !== void 0 && /* @__PURE__ */ jsxs(Group, { align: "center", gap: "xs", wrap: "wrap", children: [
178
- /* @__PURE__ */ jsx(
179
- Text,
222
+ (title !== void 0 || badgeLabel !== void 0) && /* @__PURE__ */ jsxs(
223
+ Group,
224
+ {
225
+ align: "center",
226
+ gap: "xs",
227
+ wrap: "wrap",
228
+ style: { gridArea: "title", minWidth: 0, overflowWrap: "anywhere" },
229
+ children: [
230
+ title !== void 0 && /* @__PURE__ */ jsx(
231
+ Text,
232
+ {
233
+ fw: 600,
234
+ size: "md",
235
+ c: titleColor(),
236
+ style: { lineHeight: 1.35, minWidth: 0, overflowWrap: "anywhere" },
237
+ children: title
238
+ }
239
+ ),
240
+ badgeLabel !== void 0 && /* @__PURE__ */ jsx(Badge, { color, size: "sm", variant: "light", children: badgeLabel })
241
+ ]
242
+ }
243
+ ),
244
+ description !== void 0 && /* @__PURE__ */ jsx(Box, { style: { gridArea: "description", minWidth: 0, overflowWrap: "anywhere" }, children: /* @__PURE__ */ jsx(BannerDescription, { children: description }) }),
245
+ resolvedActions.length > 0 && /* @__PURE__ */ jsx(
246
+ Box,
247
+ {
248
+ sx: {
249
+ display: "flex",
250
+ flexDirection: { base: "column", sm: "row" },
251
+ alignItems: "stretch",
252
+ justifyContent: "flex-end",
253
+ gap: spacing.xs,
254
+ minWidth: 0,
255
+ width: { base: "100%", sm: "max-content" },
256
+ maxWidth: "100%"
257
+ },
258
+ style: { gridArea: "actions", alignSelf: "center", justifySelf: "end" },
259
+ children: resolvedActions.map(({ label, ...buttonProps }, index) => /* @__PURE__ */ jsx(
260
+ Button,
180
261
  {
181
- fw: 600,
182
- size: "md",
183
- c: titleColor(tone, presentation),
184
- style: { lineHeight: 1.35 },
185
- children: title
186
- }
187
- ),
188
- badgeLabel !== void 0 && /* @__PURE__ */ jsx(Badge, { color, size: "sm", variant: "light", children: badgeLabel })
189
- ] }),
190
- description !== void 0 && /* @__PURE__ */ jsx(BannerDescription, { children: description })
191
- ] }),
192
- actionNode
193
- ] })
262
+ ...buttonProps,
263
+ color,
264
+ variant: actionVariant(tone, index < resolvedActions.length - 1),
265
+ style: {
266
+ ...buttonProps.style,
267
+ boxSizing: "border-box",
268
+ flex: "0 1 auto",
269
+ minHeight: 44,
270
+ maxWidth: "100%",
271
+ overflowWrap: "anywhere",
272
+ whiteSpace: "normal",
273
+ width: "100%"
274
+ },
275
+ children: label
276
+ },
277
+ buttonProps.id ?? (typeof label === "string" ? label : `banner-action-${index}`)
278
+ ))
279
+ }
280
+ )
281
+ ]
194
282
  }
195
283
  );
196
284
  }