@xsolla/xui-b2b-notification-panel 0.176.1 → 0.178.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -12
- package/native/index.d.mts +10 -2
- package/native/index.d.ts +10 -2
- package/native/index.js +96 -3
- package/native/index.js.map +1 -1
- package/native/index.mjs +96 -3
- package/native/index.mjs.map +1 -1
- package/package.json +6 -6
- package/web/index.d.mts +10 -2
- package/web/index.d.ts +10 -2
- package/web/index.js +96 -3
- package/web/index.js.map +1 -1
- package/web/index.mjs +96 -3
- package/web/index.mjs.map +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
A full-width horizontal notification bar for persistent inline feedback within B2B page layouts. Stays in place until dismissed and is designed to sit inline within a page or panel rather than as a floating overlay.
|
|
4
4
|
|
|
5
|
+
Two layout variants are available via the `variant` prop:
|
|
6
|
+
|
|
7
|
+
- **`notification`** (default) — a taller banner with an icon frame on the left and a stacked title/description.
|
|
8
|
+
- **`announcement`** — a slim, single-line bar with an inline icon and the title/description on one row. Best for lightweight, page-level notices.
|
|
9
|
+
|
|
5
10
|
For the base (non-B2B) variant, see [`@xsolla/xui-notification-panel`](./notification-panel.md).
|
|
6
11
|
|
|
7
12
|
## Installation
|
|
@@ -38,15 +43,16 @@ import { NotificationPanel } from '@xsolla/xui-b2b-notification-panel';
|
|
|
38
43
|
|
|
39
44
|
| Prop | Type | Default | Description |
|
|
40
45
|
| --- | --- | --- | --- |
|
|
46
|
+
| `variant` | `"notification" \| "announcement"` | `"notification"` | Layout. `notification` is the taller banner with an icon frame; `announcement` is the slim, single-line bar. |
|
|
41
47
|
| `type` | `"alert" \| "warning" \| "success" \| "neutral" \| "brand"` | `"neutral"` | Visual tone of the panel. Controls background, default icon, and `role`. |
|
|
42
48
|
| `title` | `string` | — | Bold title text. |
|
|
43
49
|
| `description` | `string` | — | Secondary description text. |
|
|
44
|
-
| `showIcon` | `boolean` | `true` | Show or hide the icon frame
|
|
50
|
+
| `showIcon` | `boolean` | `true` | Show or hide the icon (the icon frame for `notification`, the inline icon for `announcement`). |
|
|
45
51
|
| `icon` | `ReactNode` | — | Custom icon to replace the default type icon. |
|
|
46
|
-
| `actionButton` | `ActionButtonElement` | — | A `Button` or `
|
|
52
|
+
| `actionButton` | `ActionButtonElement` | — | A `Button`, `IconButton`, or `FlexButton` element. The panel injects styling via `cloneElement` (see below). |
|
|
47
53
|
| `showCloseButton` | `boolean` | `true` | Show or hide the dismiss (×) button. |
|
|
48
54
|
| `onClose` | `() => void` | — | Called when the close button is pressed. |
|
|
49
|
-
| `closeButtonAlign` | `"top" \| "center"` | `"top"` | Vertical alignment of the close button.
|
|
55
|
+
| `closeButtonAlign` | `"top" \| "center"` | `"top"` | Vertical alignment of the close button. Applies to the `notification` variant only (`announcement` is always centered). |
|
|
50
56
|
| `testID` | `string` | — | Test ID for testing frameworks. |
|
|
51
57
|
|
|
52
58
|
Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).
|
|
@@ -54,10 +60,15 @@ Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).
|
|
|
54
60
|
### `ActionButtonElement`
|
|
55
61
|
|
|
56
62
|
```ts
|
|
57
|
-
type ActionButtonElement = React.ReactElement<
|
|
63
|
+
type ActionButtonElement = React.ReactElement<
|
|
64
|
+
ButtonProps | IconButtonProps | FlexButtonProps
|
|
65
|
+
>;
|
|
58
66
|
```
|
|
59
67
|
|
|
60
|
-
The element passed to `actionButton`.
|
|
68
|
+
The element passed to `actionButton`. The panel overrides a small set of props via `cloneElement` so the button matches the design; everything else (`onPress`, `icon`, `children`, etc.) is forwarded as authored. The injected props depend on `variant`:
|
|
69
|
+
|
|
70
|
+
- **`notification`** — `size="xs"`, `variant="tertiary"`, `tone="mono"`. Pass a `Button`.
|
|
71
|
+
- **`announcement`** — `size="xs"`, `variant="primary"`, `background={false}`. Pass a [`FlexButton`](./button.md) so it renders text-only with the designed subtle hover. (`FlexButton` has no `tone`; the Primary palette gives `content.primary` text.)
|
|
61
72
|
|
|
62
73
|
## Examples
|
|
63
74
|
|
|
@@ -77,7 +88,7 @@ import { NotificationPanel } from '@xsolla/xui-b2b-notification-panel';
|
|
|
77
88
|
|
|
78
89
|
### With action button
|
|
79
90
|
|
|
80
|
-
|
|
91
|
+
The panel styles the button to match the design (`size`, `variant`, and `tone`/`background` — see [`ActionButtonElement`](#actionbuttonelement)), so pass a plain `Button`.
|
|
81
92
|
|
|
82
93
|
```tsx
|
|
83
94
|
import { NotificationPanel } from '@xsolla/xui-b2b-notification-panel';
|
|
@@ -87,11 +98,25 @@ import { Button } from '@xsolla/xui-button';
|
|
|
87
98
|
type="warning"
|
|
88
99
|
title="Session expiring"
|
|
89
100
|
description="Your session will expire in 5 minutes."
|
|
90
|
-
actionButton={
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
actionButton={<Button onPress={() => extendSession()}>Extend session</Button>}
|
|
102
|
+
onClose={() => dismiss()}
|
|
103
|
+
/>;
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Announcement variant
|
|
107
|
+
|
|
108
|
+
A slim, single-line bar. Pass a [`FlexButton`](./button.md) as the action so it renders text-only.
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
import { NotificationPanel } from '@xsolla/xui-b2b-notification-panel';
|
|
112
|
+
import { FlexButton } from '@xsolla/xui-button';
|
|
113
|
+
|
|
114
|
+
<NotificationPanel
|
|
115
|
+
variant="announcement"
|
|
116
|
+
type="alert"
|
|
117
|
+
title="Alert notification"
|
|
118
|
+
description="Remove all product restrictions"
|
|
119
|
+
actionButton={<FlexButton onPress={() => openSettings()}>Button</FlexButton>}
|
|
95
120
|
onClose={() => dismiss()}
|
|
96
121
|
/>;
|
|
97
122
|
```
|
|
@@ -155,6 +180,6 @@ import { NotificationPanel } from '@xsolla/xui-b2b-notification-panel';
|
|
|
155
180
|
## Accessibility
|
|
156
181
|
|
|
157
182
|
- `role="alert"` for `type="alert"`; `role="status"` for all other types.
|
|
158
|
-
- `aria-label` on the root is `"<type>
|
|
183
|
+
- `aria-label` on the root is `"<type> <variant>"` (e.g. `"warning notification"`, `"alert announcement"`).
|
|
159
184
|
- The close button is an `IconButton` with `aria-label="Close notification"`.
|
|
160
185
|
- The default type icons are decorative — pass `aria-hidden` on any custom `icon` you supply.
|
package/native/index.d.mts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ThemeOverrideProps } from '@xsolla/xui-core';
|
|
3
|
-
import { ButtonProps, IconButtonProps } from '@xsolla/xui-button';
|
|
3
|
+
import { ButtonProps, IconButtonProps, FlexButtonProps } from '@xsolla/xui-button';
|
|
4
4
|
|
|
5
|
-
type ActionButtonElement = React.ReactElement<ButtonProps | IconButtonProps>;
|
|
5
|
+
type ActionButtonElement = React.ReactElement<ButtonProps | IconButtonProps | FlexButtonProps>;
|
|
6
6
|
interface NotificationPanelProps extends ThemeOverrideProps {
|
|
7
|
+
/**
|
|
8
|
+
* Layout variant.
|
|
9
|
+
* - `notification` (default): full-height banner with an icon frame and a
|
|
10
|
+
* stacked title/description.
|
|
11
|
+
* - `announcement`: slim, single-line bar with an inline icon and the
|
|
12
|
+
* title/description on one row.
|
|
13
|
+
*/
|
|
14
|
+
variant?: "notification" | "announcement";
|
|
7
15
|
/** Visual variant/tone of the notification */
|
|
8
16
|
type?: "alert" | "warning" | "success" | "neutral" | "brand";
|
|
9
17
|
/** Title text (optional) */
|
package/native/index.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ThemeOverrideProps } from '@xsolla/xui-core';
|
|
3
|
-
import { ButtonProps, IconButtonProps } from '@xsolla/xui-button';
|
|
3
|
+
import { ButtonProps, IconButtonProps, FlexButtonProps } from '@xsolla/xui-button';
|
|
4
4
|
|
|
5
|
-
type ActionButtonElement = React.ReactElement<ButtonProps | IconButtonProps>;
|
|
5
|
+
type ActionButtonElement = React.ReactElement<ButtonProps | IconButtonProps | FlexButtonProps>;
|
|
6
6
|
interface NotificationPanelProps extends ThemeOverrideProps {
|
|
7
|
+
/**
|
|
8
|
+
* Layout variant.
|
|
9
|
+
* - `notification` (default): full-height banner with an icon frame and a
|
|
10
|
+
* stacked title/description.
|
|
11
|
+
* - `announcement`: slim, single-line bar with an inline icon and the
|
|
12
|
+
* title/description on one row.
|
|
13
|
+
*/
|
|
14
|
+
variant?: "notification" | "announcement";
|
|
7
15
|
/** Visual variant/tone of the notification */
|
|
8
16
|
type?: "alert" | "warning" | "success" | "neutral" | "brand";
|
|
9
17
|
/** Title text (optional) */
|
package/native/index.js
CHANGED
|
@@ -208,6 +208,7 @@ var import_xui_typography = require("@xsolla/xui-typography");
|
|
|
208
208
|
var import_xui_icons_base = require("@xsolla/xui-icons-base");
|
|
209
209
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
210
210
|
var NotificationPanel = ({
|
|
211
|
+
variant = "notification",
|
|
211
212
|
type = "neutral",
|
|
212
213
|
title,
|
|
213
214
|
description,
|
|
@@ -226,6 +227,7 @@ var NotificationPanel = ({
|
|
|
226
227
|
const typeConfig = {
|
|
227
228
|
alert: {
|
|
228
229
|
panelBg: theme.colors.overlay.alert,
|
|
230
|
+
announcementBg: theme.colors.background.alert.secondary,
|
|
229
231
|
iconFrameBg: theme.colors.overlay.alert,
|
|
230
232
|
iconColor: theme.colors.content.primary,
|
|
231
233
|
buttonTone: "alert",
|
|
@@ -233,6 +235,7 @@ var NotificationPanel = ({
|
|
|
233
235
|
},
|
|
234
236
|
warning: {
|
|
235
237
|
panelBg: theme.colors.overlay.warning,
|
|
238
|
+
announcementBg: theme.colors.background.warning.secondary,
|
|
236
239
|
iconFrameBg: theme.colors.background.warning.primary,
|
|
237
240
|
iconColor: theme.colors.content.primary,
|
|
238
241
|
buttonTone: "mono",
|
|
@@ -240,6 +243,7 @@ var NotificationPanel = ({
|
|
|
240
243
|
},
|
|
241
244
|
success: {
|
|
242
245
|
panelBg: theme.colors.overlay.success,
|
|
246
|
+
announcementBg: theme.colors.background.success.secondary,
|
|
243
247
|
iconFrameBg: theme.colors.background.success.primary,
|
|
244
248
|
iconColor: theme.colors.content.primary,
|
|
245
249
|
buttonTone: "brandExtra",
|
|
@@ -247,6 +251,7 @@ var NotificationPanel = ({
|
|
|
247
251
|
},
|
|
248
252
|
neutral: {
|
|
249
253
|
panelBg: theme.colors.overlay.mono,
|
|
254
|
+
announcementBg: theme.colors.background.neutral.secondary,
|
|
250
255
|
iconFrameBg: theme.colors.overlay.mono,
|
|
251
256
|
iconColor: theme.colors.content.primary,
|
|
252
257
|
buttonTone: "mono",
|
|
@@ -254,6 +259,7 @@ var NotificationPanel = ({
|
|
|
254
259
|
},
|
|
255
260
|
brand: {
|
|
256
261
|
panelBg: theme.colors.overlay.brand,
|
|
262
|
+
announcementBg: theme.colors.background.brand.secondary,
|
|
257
263
|
iconFrameBg: theme.colors.overlay.brand,
|
|
258
264
|
iconColor: theme.colors.content.primary,
|
|
259
265
|
buttonTone: "brand",
|
|
@@ -262,6 +268,93 @@ var NotificationPanel = ({
|
|
|
262
268
|
};
|
|
263
269
|
const currentConfig = typeConfig[type];
|
|
264
270
|
const IconComponent = currentConfig.IconComponent;
|
|
271
|
+
const ariaProps = {
|
|
272
|
+
role: type === "alert" ? "alert" : "status",
|
|
273
|
+
"aria-label": `${type} ${variant}`
|
|
274
|
+
};
|
|
275
|
+
if (variant === "announcement") {
|
|
276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
277
|
+
Box,
|
|
278
|
+
{
|
|
279
|
+
backgroundColor: currentConfig.announcementBg,
|
|
280
|
+
flexDirection: "row",
|
|
281
|
+
alignItems: "center",
|
|
282
|
+
justifyContent: "center",
|
|
283
|
+
padding: config.announcementPadding,
|
|
284
|
+
gap: config.announcementGap,
|
|
285
|
+
overflow: "hidden",
|
|
286
|
+
testID,
|
|
287
|
+
style: {
|
|
288
|
+
backdropFilter: `blur(${config.announcementBlurRadius}px)`
|
|
289
|
+
},
|
|
290
|
+
...ariaProps,
|
|
291
|
+
children: [
|
|
292
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
293
|
+
Box,
|
|
294
|
+
{
|
|
295
|
+
flex: 1,
|
|
296
|
+
minWidth: 0,
|
|
297
|
+
overflow: "hidden",
|
|
298
|
+
flexDirection: "row",
|
|
299
|
+
alignItems: "center",
|
|
300
|
+
gap: config.announcementContentGap,
|
|
301
|
+
children: [
|
|
302
|
+
showIcon && (icon || /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
303
|
+
IconComponent,
|
|
304
|
+
{
|
|
305
|
+
size: config.announcementIconSize,
|
|
306
|
+
color: currentConfig.iconColor,
|
|
307
|
+
variant: "solid"
|
|
308
|
+
}
|
|
309
|
+
)),
|
|
310
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
311
|
+
import_xui_typography.Typography,
|
|
312
|
+
{
|
|
313
|
+
variant: "bodyXsAccent",
|
|
314
|
+
color: theme.colors.content.primary,
|
|
315
|
+
children: title
|
|
316
|
+
}
|
|
317
|
+
),
|
|
318
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_xui_typography.Typography, { variant: "bodyXs", color: theme.colors.content.secondary, children: description })
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
),
|
|
322
|
+
(actionButton || showCloseButton) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
323
|
+
Box,
|
|
324
|
+
{
|
|
325
|
+
flexShrink: 0,
|
|
326
|
+
flexDirection: "row",
|
|
327
|
+
alignItems: "center",
|
|
328
|
+
gap: config.announcementButtonsGap,
|
|
329
|
+
children: [
|
|
330
|
+
(0, import_react.isValidElement)(actionButton) && (0, import_react.cloneElement)(actionButton, {
|
|
331
|
+
size: "xs",
|
|
332
|
+
// Announcement uses a text-only FlexButton (Primary palette →
|
|
333
|
+
// content.primary text, no fill), per the Figma "Flex Button"
|
|
334
|
+
// node. hoverBackground is left at its default so the subtle
|
|
335
|
+
// mono hover overlay from the design is preserved.
|
|
336
|
+
variant: "primary",
|
|
337
|
+
background: false
|
|
338
|
+
}),
|
|
339
|
+
showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
340
|
+
import_xui_button.IconButton,
|
|
341
|
+
{
|
|
342
|
+
variant: "tertiary",
|
|
343
|
+
tone: "mono",
|
|
344
|
+
size: "xs",
|
|
345
|
+
onPress: onClose,
|
|
346
|
+
"aria-label": "Close notification",
|
|
347
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_xui_icons_base.Remove, { size: config.announcementCloseIconSize }),
|
|
348
|
+
hoverBackground: "none"
|
|
349
|
+
}
|
|
350
|
+
)
|
|
351
|
+
]
|
|
352
|
+
}
|
|
353
|
+
)
|
|
354
|
+
]
|
|
355
|
+
}
|
|
356
|
+
);
|
|
357
|
+
}
|
|
265
358
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
266
359
|
Box,
|
|
267
360
|
{
|
|
@@ -271,8 +364,7 @@ var NotificationPanel = ({
|
|
|
271
364
|
alignItems: "stretch",
|
|
272
365
|
overflow: "hidden",
|
|
273
366
|
testID,
|
|
274
|
-
|
|
275
|
-
"aria-label": `${type} notification`,
|
|
367
|
+
...ariaProps,
|
|
276
368
|
children: [
|
|
277
369
|
showIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
278
370
|
Box,
|
|
@@ -328,7 +420,8 @@ var NotificationPanel = ({
|
|
|
328
420
|
children: [
|
|
329
421
|
(0, import_react.isValidElement)(actionButton) && (0, import_react.cloneElement)(actionButton, {
|
|
330
422
|
size: "xs",
|
|
331
|
-
variant: "
|
|
423
|
+
variant: "tertiary",
|
|
424
|
+
tone: "mono"
|
|
332
425
|
}),
|
|
333
426
|
showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
334
427
|
import_xui_button.IconButton,
|
package/native/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.tsx","../../src/NotificationPanel.tsx","../../../../foundation/primitives-native/src/Box.tsx"],"sourcesContent":["export { NotificationPanel } from \"./NotificationPanel\";\nexport type {\n NotificationPanelProps,\n ActionButtonElement,\n} from \"./NotificationPanel\";\n","import React, { cloneElement, isValidElement } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\nimport {\n IconButton,\n type ButtonProps,\n type IconButtonProps,\n} from \"@xsolla/xui-button\";\nimport { Typography } from \"@xsolla/xui-typography\";\nimport {\n ExclamationMarkSq,\n InfoSq,\n CheckCr,\n Remove,\n type BaseIconComponent,\n} from \"@xsolla/xui-icons-base\";\n\nexport type ActionButtonElement = React.ReactElement<\n ButtonProps | IconButtonProps\n>;\n\nexport interface NotificationPanelProps extends ThemeOverrideProps {\n /** Visual variant/tone of the notification */\n type?: \"alert\" | \"warning\" | \"success\" | \"neutral\" | \"brand\";\n /** Title text (optional) */\n title?: string;\n /** Description text (optional) */\n description?: string;\n /** Show/hide the icon frame */\n showIcon?: boolean;\n /** Custom icon override (optional) */\n icon?: React.ReactNode;\n /**\n * Action button (optional - pass any Button/IconButton component).\n * The `tone`, `size`, and `variant` props will be automatically set.\n */\n actionButton?: React.ReactElement;\n /** Show/hide close button */\n showCloseButton?: boolean;\n /** Close button click handler */\n onClose?: () => void;\n /** Vertical alignment of the close button — \"top\" (default) or \"center\" */\n closeButtonAlign?: \"center\" | \"top\";\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const NotificationPanel: React.FC<NotificationPanelProps> = ({\n type = \"neutral\",\n title,\n description,\n showIcon = true,\n icon,\n actionButton,\n showCloseButton = true,\n onClose,\n closeButtonAlign = \"top\",\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const config = theme.sizing.notificationPanel();\n\n const typeConfig: Record<\n NonNullable<NotificationPanelProps[\"type\"]>,\n {\n panelBg: string;\n iconFrameBg: string;\n iconColor: string;\n buttonTone: \"brand\" | \"brandExtra\" | \"alert\" | \"mono\";\n IconComponent: BaseIconComponent;\n }\n > = {\n alert: {\n panelBg: theme.colors.overlay.alert,\n iconFrameBg: theme.colors.overlay.alert,\n iconColor: theme.colors.content.primary,\n buttonTone: \"alert\",\n IconComponent: ExclamationMarkSq,\n },\n warning: {\n panelBg: theme.colors.overlay.warning,\n iconFrameBg: theme.colors.background.warning.primary,\n iconColor: theme.colors.content.primary,\n buttonTone: \"mono\",\n IconComponent: ExclamationMarkSq,\n },\n success: {\n panelBg: theme.colors.overlay.success,\n iconFrameBg: theme.colors.background.success.primary,\n iconColor: theme.colors.content.primary,\n buttonTone: \"brandExtra\",\n IconComponent: CheckCr,\n },\n neutral: {\n panelBg: theme.colors.overlay.mono,\n iconFrameBg: theme.colors.overlay.mono,\n iconColor: theme.colors.content.primary,\n buttonTone: \"mono\",\n IconComponent: InfoSq,\n },\n brand: {\n panelBg: theme.colors.overlay.brand,\n iconFrameBg: theme.colors.overlay.brand,\n iconColor: theme.colors.content.primary,\n buttonTone: \"brand\",\n IconComponent: InfoSq,\n },\n };\n\n const currentConfig = typeConfig[type];\n const IconComponent = currentConfig.IconComponent;\n\n return (\n <Box\n backgroundColor={currentConfig.panelBg}\n borderRadius={config.borderRadius}\n flexDirection=\"row\"\n alignItems=\"stretch\"\n overflow=\"hidden\"\n testID={testID}\n role={type === \"alert\" ? \"alert\" : \"status\"}\n aria-label={`${type} notification`}\n >\n {/* Icon Frame */}\n {showIcon && (\n <Box\n backgroundColor={currentConfig.iconFrameBg}\n width={config.iconFrameWidth}\n alignItems=\"center\"\n justifyContent=\"center\"\n style={{\n borderTopLeftRadius: config.borderRadius,\n borderBottomLeftRadius: config.borderRadius,\n }}\n >\n {icon || (\n <IconComponent\n size={config.iconSize}\n color={currentConfig.iconColor}\n variant=\"solid\"\n />\n )}\n </Box>\n )}\n\n {/* Body */}\n <Box\n flex={1}\n flexDirection=\"row\"\n alignItems=\"center\"\n paddingHorizontal={config.bodyPaddingHorizontal}\n paddingVertical={config.bodyPaddingVertical}\n gap={config.contentGap}\n >\n {/* Text Content */}\n <Box flex={1} gap={config.textGap}>\n {title && (\n <Typography\n variant=\"bodyMdAccent\"\n color={theme.colors.content.primary}\n >\n {title}\n </Typography>\n )}\n {description && (\n <Typography variant=\"bodySm\" color={theme.colors.content.tertiary}>\n {description}\n </Typography>\n )}\n </Box>\n\n {/* Buttons */}\n {(actionButton || showCloseButton) && (\n <Box\n flexDirection=\"row\"\n alignSelf={closeButtonAlign === \"top\" ? \"stretch\" : \"center\"}\n alignItems={closeButtonAlign === \"top\" ? \"flex-start\" : \"center\"}\n justifyContent=\"flex-start\"\n paddingVertical={closeButtonAlign === \"top\" ? 4 : 0}\n gap={config.buttonsGap}\n >\n {isValidElement(actionButton) &&\n cloneElement(actionButton as ActionButtonElement, {\n size: \"xs\",\n variant: \"secondary\",\n })}\n\n {showCloseButton && (\n <IconButton\n variant=\"tertiary\"\n tone=\"mono\"\n size=\"xs\"\n onPress={onClose}\n aria-label=\"Close notification\"\n icon={<Remove size={18} />}\n hoverBackground=\"none\"\n />\n )}\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n\nNotificationPanel.displayName = \"NotificationPanel\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n minWidth,\n minHeight,\n maxWidth,\n maxHeight,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n minWidth: minWidth as DimensionValue,\n minHeight: minHeight as DimensionValue,\n maxWidth: maxWidth as DimensionValue,\n maxHeight: maxHeight as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n"],"mappings":"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","names":["import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.tsx","../../src/NotificationPanel.tsx","../../../../foundation/primitives-native/src/Box.tsx"],"sourcesContent":["export { NotificationPanel } from \"./NotificationPanel\";\nexport type {\n NotificationPanelProps,\n ActionButtonElement,\n} from \"./NotificationPanel\";\n","import React, { cloneElement, isValidElement } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\nimport {\n IconButton,\n type ButtonProps,\n type IconButtonProps,\n type FlexButtonProps,\n} from \"@xsolla/xui-button\";\nimport { Typography } from \"@xsolla/xui-typography\";\nimport {\n ExclamationMarkSq,\n InfoSq,\n CheckCr,\n Remove,\n type BaseIconComponent,\n} from \"@xsolla/xui-icons-base\";\n\nexport type ActionButtonElement = React.ReactElement<\n ButtonProps | IconButtonProps | FlexButtonProps\n>;\n\nexport interface NotificationPanelProps extends ThemeOverrideProps {\n /**\n * Layout variant.\n * - `notification` (default): full-height banner with an icon frame and a\n * stacked title/description.\n * - `announcement`: slim, single-line bar with an inline icon and the\n * title/description on one row.\n */\n variant?: \"notification\" | \"announcement\";\n /** Visual variant/tone of the notification */\n type?: \"alert\" | \"warning\" | \"success\" | \"neutral\" | \"brand\";\n /** Title text (optional) */\n title?: string;\n /** Description text (optional) */\n description?: string;\n /** Show/hide the icon frame */\n showIcon?: boolean;\n /** Custom icon override (optional) */\n icon?: React.ReactNode;\n /**\n * Action button (optional - pass any Button/IconButton component).\n * The `tone`, `size`, and `variant` props will be automatically set.\n */\n actionButton?: React.ReactElement;\n /** Show/hide close button */\n showCloseButton?: boolean;\n /** Close button click handler */\n onClose?: () => void;\n /** Vertical alignment of the close button — \"top\" (default) or \"center\" */\n closeButtonAlign?: \"center\" | \"top\";\n /** Test ID for testing frameworks */\n testID?: string;\n}\n\nexport const NotificationPanel: React.FC<NotificationPanelProps> = ({\n variant = \"notification\",\n type = \"neutral\",\n title,\n description,\n showIcon = true,\n icon,\n actionButton,\n showCloseButton = true,\n onClose,\n closeButtonAlign = \"top\",\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const config = theme.sizing.notificationPanel();\n\n const typeConfig: Record<\n NonNullable<NotificationPanelProps[\"type\"]>,\n {\n panelBg: string;\n /** Background of the slim announcement bar (and inline icon area). */\n announcementBg: string;\n iconFrameBg: string;\n iconColor: string;\n buttonTone: \"brand\" | \"brandExtra\" | \"alert\" | \"mono\";\n IconComponent: BaseIconComponent;\n }\n > = {\n alert: {\n panelBg: theme.colors.overlay.alert,\n announcementBg: theme.colors.background.alert.secondary,\n iconFrameBg: theme.colors.overlay.alert,\n iconColor: theme.colors.content.primary,\n buttonTone: \"alert\",\n IconComponent: ExclamationMarkSq,\n },\n warning: {\n panelBg: theme.colors.overlay.warning,\n announcementBg: theme.colors.background.warning.secondary,\n iconFrameBg: theme.colors.background.warning.primary,\n iconColor: theme.colors.content.primary,\n buttonTone: \"mono\",\n IconComponent: ExclamationMarkSq,\n },\n success: {\n panelBg: theme.colors.overlay.success,\n announcementBg: theme.colors.background.success.secondary,\n iconFrameBg: theme.colors.background.success.primary,\n iconColor: theme.colors.content.primary,\n buttonTone: \"brandExtra\",\n IconComponent: CheckCr,\n },\n neutral: {\n panelBg: theme.colors.overlay.mono,\n announcementBg: theme.colors.background.neutral.secondary,\n iconFrameBg: theme.colors.overlay.mono,\n iconColor: theme.colors.content.primary,\n buttonTone: \"mono\",\n IconComponent: InfoSq,\n },\n brand: {\n panelBg: theme.colors.overlay.brand,\n announcementBg: theme.colors.background.brand.secondary,\n iconFrameBg: theme.colors.overlay.brand,\n iconColor: theme.colors.content.primary,\n buttonTone: \"brand\",\n IconComponent: InfoSq,\n },\n };\n\n const currentConfig = typeConfig[type];\n const IconComponent = currentConfig.IconComponent;\n\n const ariaProps = {\n role: type === \"alert\" ? \"alert\" : \"status\",\n \"aria-label\": `${type} ${variant}`,\n } as const;\n\n if (variant === \"announcement\") {\n return (\n <Box\n backgroundColor={currentConfig.announcementBg}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"center\"\n padding={config.announcementPadding}\n gap={config.announcementGap}\n overflow=\"hidden\"\n testID={testID}\n style={{\n backdropFilter: `blur(${config.announcementBlurRadius}px)`,\n }}\n {...ariaProps}\n >\n {/* Inline content: icon + title + description on a single row */}\n <Box\n flex={1}\n minWidth={0}\n overflow=\"hidden\"\n flexDirection=\"row\"\n alignItems=\"center\"\n gap={config.announcementContentGap}\n >\n {showIcon &&\n (icon || (\n <IconComponent\n size={config.announcementIconSize}\n color={currentConfig.iconColor}\n variant=\"solid\"\n />\n ))}\n {title && (\n <Typography\n variant=\"bodyXsAccent\"\n color={theme.colors.content.primary}\n >\n {title}\n </Typography>\n )}\n {description && (\n <Typography variant=\"bodyXs\" color={theme.colors.content.secondary}>\n {description}\n </Typography>\n )}\n </Box>\n\n {/* Buttons */}\n {(actionButton || showCloseButton) && (\n <Box\n flexShrink={0}\n flexDirection=\"row\"\n alignItems=\"center\"\n gap={config.announcementButtonsGap}\n >\n {isValidElement(actionButton) &&\n cloneElement(actionButton as ActionButtonElement, {\n size: \"xs\",\n // Announcement uses a text-only FlexButton (Primary palette →\n // content.primary text, no fill), per the Figma \"Flex Button\"\n // node. hoverBackground is left at its default so the subtle\n // mono hover overlay from the design is preserved.\n variant: \"primary\",\n background: false,\n })}\n\n {showCloseButton && (\n <IconButton\n variant=\"tertiary\"\n tone=\"mono\"\n size=\"xs\"\n onPress={onClose}\n aria-label=\"Close notification\"\n icon={<Remove size={config.announcementCloseIconSize} />}\n hoverBackground=\"none\"\n />\n )}\n </Box>\n )}\n </Box>\n );\n }\n\n return (\n <Box\n backgroundColor={currentConfig.panelBg}\n borderRadius={config.borderRadius}\n flexDirection=\"row\"\n alignItems=\"stretch\"\n overflow=\"hidden\"\n testID={testID}\n {...ariaProps}\n >\n {/* Icon Frame */}\n {showIcon && (\n <Box\n backgroundColor={currentConfig.iconFrameBg}\n width={config.iconFrameWidth}\n alignItems=\"center\"\n justifyContent=\"center\"\n style={{\n borderTopLeftRadius: config.borderRadius,\n borderBottomLeftRadius: config.borderRadius,\n }}\n >\n {icon || (\n <IconComponent\n size={config.iconSize}\n color={currentConfig.iconColor}\n variant=\"solid\"\n />\n )}\n </Box>\n )}\n\n {/* Body */}\n <Box\n flex={1}\n flexDirection=\"row\"\n alignItems=\"center\"\n paddingHorizontal={config.bodyPaddingHorizontal}\n paddingVertical={config.bodyPaddingVertical}\n gap={config.contentGap}\n >\n {/* Text Content */}\n <Box flex={1} gap={config.textGap}>\n {title && (\n <Typography\n variant=\"bodyMdAccent\"\n color={theme.colors.content.primary}\n >\n {title}\n </Typography>\n )}\n {description && (\n <Typography variant=\"bodySm\" color={theme.colors.content.tertiary}>\n {description}\n </Typography>\n )}\n </Box>\n\n {/* Buttons */}\n {(actionButton || showCloseButton) && (\n <Box\n flexDirection=\"row\"\n alignSelf={closeButtonAlign === \"top\" ? \"stretch\" : \"center\"}\n alignItems={closeButtonAlign === \"top\" ? \"flex-start\" : \"center\"}\n justifyContent=\"flex-start\"\n paddingVertical={closeButtonAlign === \"top\" ? 4 : 0}\n gap={config.buttonsGap}\n >\n {isValidElement(actionButton) &&\n cloneElement(actionButton as ActionButtonElement, {\n size: \"xs\",\n variant: \"tertiary\",\n tone: \"mono\",\n })}\n\n {showCloseButton && (\n <IconButton\n variant=\"tertiary\"\n tone=\"mono\"\n size=\"xs\"\n onPress={onClose}\n aria-label=\"Close notification\"\n icon={<Remove size={18} />}\n hoverBackground=\"none\"\n />\n )}\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n\nNotificationPanel.displayName = \"NotificationPanel\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n minWidth,\n minHeight,\n maxWidth,\n maxHeight,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n minWidth: minWidth as DimensionValue,\n minHeight: minHeight as DimensionValue,\n maxWidth: maxWidth as DimensionValue,\n maxHeight: maxHeight as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n"],"mappings":"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","names":["import_jsx_runtime"]}
|
package/native/index.mjs
CHANGED
|
@@ -193,6 +193,7 @@ import {
|
|
|
193
193
|
} from "@xsolla/xui-icons-base";
|
|
194
194
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
195
195
|
var NotificationPanel = ({
|
|
196
|
+
variant = "notification",
|
|
196
197
|
type = "neutral",
|
|
197
198
|
title,
|
|
198
199
|
description,
|
|
@@ -211,6 +212,7 @@ var NotificationPanel = ({
|
|
|
211
212
|
const typeConfig = {
|
|
212
213
|
alert: {
|
|
213
214
|
panelBg: theme.colors.overlay.alert,
|
|
215
|
+
announcementBg: theme.colors.background.alert.secondary,
|
|
214
216
|
iconFrameBg: theme.colors.overlay.alert,
|
|
215
217
|
iconColor: theme.colors.content.primary,
|
|
216
218
|
buttonTone: "alert",
|
|
@@ -218,6 +220,7 @@ var NotificationPanel = ({
|
|
|
218
220
|
},
|
|
219
221
|
warning: {
|
|
220
222
|
panelBg: theme.colors.overlay.warning,
|
|
223
|
+
announcementBg: theme.colors.background.warning.secondary,
|
|
221
224
|
iconFrameBg: theme.colors.background.warning.primary,
|
|
222
225
|
iconColor: theme.colors.content.primary,
|
|
223
226
|
buttonTone: "mono",
|
|
@@ -225,6 +228,7 @@ var NotificationPanel = ({
|
|
|
225
228
|
},
|
|
226
229
|
success: {
|
|
227
230
|
panelBg: theme.colors.overlay.success,
|
|
231
|
+
announcementBg: theme.colors.background.success.secondary,
|
|
228
232
|
iconFrameBg: theme.colors.background.success.primary,
|
|
229
233
|
iconColor: theme.colors.content.primary,
|
|
230
234
|
buttonTone: "brandExtra",
|
|
@@ -232,6 +236,7 @@ var NotificationPanel = ({
|
|
|
232
236
|
},
|
|
233
237
|
neutral: {
|
|
234
238
|
panelBg: theme.colors.overlay.mono,
|
|
239
|
+
announcementBg: theme.colors.background.neutral.secondary,
|
|
235
240
|
iconFrameBg: theme.colors.overlay.mono,
|
|
236
241
|
iconColor: theme.colors.content.primary,
|
|
237
242
|
buttonTone: "mono",
|
|
@@ -239,6 +244,7 @@ var NotificationPanel = ({
|
|
|
239
244
|
},
|
|
240
245
|
brand: {
|
|
241
246
|
panelBg: theme.colors.overlay.brand,
|
|
247
|
+
announcementBg: theme.colors.background.brand.secondary,
|
|
242
248
|
iconFrameBg: theme.colors.overlay.brand,
|
|
243
249
|
iconColor: theme.colors.content.primary,
|
|
244
250
|
buttonTone: "brand",
|
|
@@ -247,6 +253,93 @@ var NotificationPanel = ({
|
|
|
247
253
|
};
|
|
248
254
|
const currentConfig = typeConfig[type];
|
|
249
255
|
const IconComponent = currentConfig.IconComponent;
|
|
256
|
+
const ariaProps = {
|
|
257
|
+
role: type === "alert" ? "alert" : "status",
|
|
258
|
+
"aria-label": `${type} ${variant}`
|
|
259
|
+
};
|
|
260
|
+
if (variant === "announcement") {
|
|
261
|
+
return /* @__PURE__ */ jsxs(
|
|
262
|
+
Box,
|
|
263
|
+
{
|
|
264
|
+
backgroundColor: currentConfig.announcementBg,
|
|
265
|
+
flexDirection: "row",
|
|
266
|
+
alignItems: "center",
|
|
267
|
+
justifyContent: "center",
|
|
268
|
+
padding: config.announcementPadding,
|
|
269
|
+
gap: config.announcementGap,
|
|
270
|
+
overflow: "hidden",
|
|
271
|
+
testID,
|
|
272
|
+
style: {
|
|
273
|
+
backdropFilter: `blur(${config.announcementBlurRadius}px)`
|
|
274
|
+
},
|
|
275
|
+
...ariaProps,
|
|
276
|
+
children: [
|
|
277
|
+
/* @__PURE__ */ jsxs(
|
|
278
|
+
Box,
|
|
279
|
+
{
|
|
280
|
+
flex: 1,
|
|
281
|
+
minWidth: 0,
|
|
282
|
+
overflow: "hidden",
|
|
283
|
+
flexDirection: "row",
|
|
284
|
+
alignItems: "center",
|
|
285
|
+
gap: config.announcementContentGap,
|
|
286
|
+
children: [
|
|
287
|
+
showIcon && (icon || /* @__PURE__ */ jsx2(
|
|
288
|
+
IconComponent,
|
|
289
|
+
{
|
|
290
|
+
size: config.announcementIconSize,
|
|
291
|
+
color: currentConfig.iconColor,
|
|
292
|
+
variant: "solid"
|
|
293
|
+
}
|
|
294
|
+
)),
|
|
295
|
+
title && /* @__PURE__ */ jsx2(
|
|
296
|
+
Typography,
|
|
297
|
+
{
|
|
298
|
+
variant: "bodyXsAccent",
|
|
299
|
+
color: theme.colors.content.primary,
|
|
300
|
+
children: title
|
|
301
|
+
}
|
|
302
|
+
),
|
|
303
|
+
description && /* @__PURE__ */ jsx2(Typography, { variant: "bodyXs", color: theme.colors.content.secondary, children: description })
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
),
|
|
307
|
+
(actionButton || showCloseButton) && /* @__PURE__ */ jsxs(
|
|
308
|
+
Box,
|
|
309
|
+
{
|
|
310
|
+
flexShrink: 0,
|
|
311
|
+
flexDirection: "row",
|
|
312
|
+
alignItems: "center",
|
|
313
|
+
gap: config.announcementButtonsGap,
|
|
314
|
+
children: [
|
|
315
|
+
isValidElement(actionButton) && cloneElement(actionButton, {
|
|
316
|
+
size: "xs",
|
|
317
|
+
// Announcement uses a text-only FlexButton (Primary palette →
|
|
318
|
+
// content.primary text, no fill), per the Figma "Flex Button"
|
|
319
|
+
// node. hoverBackground is left at its default so the subtle
|
|
320
|
+
// mono hover overlay from the design is preserved.
|
|
321
|
+
variant: "primary",
|
|
322
|
+
background: false
|
|
323
|
+
}),
|
|
324
|
+
showCloseButton && /* @__PURE__ */ jsx2(
|
|
325
|
+
IconButton,
|
|
326
|
+
{
|
|
327
|
+
variant: "tertiary",
|
|
328
|
+
tone: "mono",
|
|
329
|
+
size: "xs",
|
|
330
|
+
onPress: onClose,
|
|
331
|
+
"aria-label": "Close notification",
|
|
332
|
+
icon: /* @__PURE__ */ jsx2(Remove, { size: config.announcementCloseIconSize }),
|
|
333
|
+
hoverBackground: "none"
|
|
334
|
+
}
|
|
335
|
+
)
|
|
336
|
+
]
|
|
337
|
+
}
|
|
338
|
+
)
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
}
|
|
250
343
|
return /* @__PURE__ */ jsxs(
|
|
251
344
|
Box,
|
|
252
345
|
{
|
|
@@ -256,8 +349,7 @@ var NotificationPanel = ({
|
|
|
256
349
|
alignItems: "stretch",
|
|
257
350
|
overflow: "hidden",
|
|
258
351
|
testID,
|
|
259
|
-
|
|
260
|
-
"aria-label": `${type} notification`,
|
|
352
|
+
...ariaProps,
|
|
261
353
|
children: [
|
|
262
354
|
showIcon && /* @__PURE__ */ jsx2(
|
|
263
355
|
Box,
|
|
@@ -313,7 +405,8 @@ var NotificationPanel = ({
|
|
|
313
405
|
children: [
|
|
314
406
|
isValidElement(actionButton) && cloneElement(actionButton, {
|
|
315
407
|
size: "xs",
|
|
316
|
-
variant: "
|
|
408
|
+
variant: "tertiary",
|
|
409
|
+
tone: "mono"
|
|
317
410
|
}),
|
|
318
411
|
showCloseButton && /* @__PURE__ */ jsx2(
|
|
319
412
|
IconButton,
|