@transferwise/components 46.136.1 → 46.137.1
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/build/common/hooks/useContainerSize.js +30 -0
- package/build/common/hooks/useContainerSize.js.map +1 -0
- package/build/common/hooks/useContainerSize.mjs +28 -0
- package/build/common/hooks/useContainerSize.mjs.map +1 -0
- package/build/common/hooks/useResizeObserver.js +3 -3
- package/build/common/hooks/useResizeObserver.js.map +1 -1
- package/build/common/hooks/useResizeObserver.mjs +3 -3
- package/build/common/hooks/useResizeObserver.mjs.map +1 -1
- package/build/criticalBanner/CriticalCommsBanner.js +3 -0
- package/build/criticalBanner/CriticalCommsBanner.js.map +1 -1
- package/build/criticalBanner/CriticalCommsBanner.mjs +3 -0
- package/build/criticalBanner/CriticalCommsBanner.mjs.map +1 -1
- package/build/field/Field.js +3 -2
- package/build/field/Field.js.map +1 -1
- package/build/field/Field.mjs +3 -2
- package/build/field/Field.mjs.map +1 -1
- package/build/i18n/cs.json +2 -0
- package/build/i18n/cs.json.js +2 -0
- package/build/i18n/cs.json.js.map +1 -1
- package/build/i18n/cs.json.mjs +2 -0
- package/build/i18n/cs.json.mjs.map +1 -1
- package/build/i18n/de.json +2 -0
- package/build/i18n/de.json.js +2 -0
- package/build/i18n/de.json.js.map +1 -1
- package/build/i18n/de.json.mjs +2 -0
- package/build/i18n/de.json.mjs.map +1 -1
- package/build/i18n/en.json +2 -0
- package/build/i18n/en.json.js +2 -0
- package/build/i18n/en.json.js.map +1 -1
- package/build/i18n/en.json.mjs +2 -0
- package/build/i18n/en.json.mjs.map +1 -1
- package/build/i18n/es.json +2 -0
- package/build/i18n/es.json.js +2 -0
- package/build/i18n/es.json.js.map +1 -1
- package/build/i18n/es.json.mjs +2 -0
- package/build/i18n/es.json.mjs.map +1 -1
- package/build/i18n/fr.json +2 -0
- package/build/i18n/fr.json.js +2 -0
- package/build/i18n/fr.json.js.map +1 -1
- package/build/i18n/fr.json.mjs +2 -0
- package/build/i18n/fr.json.mjs.map +1 -1
- package/build/i18n/hu.json +2 -0
- package/build/i18n/hu.json.js +2 -0
- package/build/i18n/hu.json.js.map +1 -1
- package/build/i18n/hu.json.mjs +2 -0
- package/build/i18n/hu.json.mjs.map +1 -1
- package/build/i18n/id.json +2 -0
- package/build/i18n/id.json.js +2 -0
- package/build/i18n/id.json.js.map +1 -1
- package/build/i18n/id.json.mjs +2 -0
- package/build/i18n/id.json.mjs.map +1 -1
- package/build/i18n/it.json +2 -0
- package/build/i18n/it.json.js +2 -0
- package/build/i18n/it.json.js.map +1 -1
- package/build/i18n/it.json.mjs +2 -0
- package/build/i18n/it.json.mjs.map +1 -1
- package/build/i18n/ja.json +2 -0
- package/build/i18n/ja.json.js +2 -0
- package/build/i18n/ja.json.js.map +1 -1
- package/build/i18n/ja.json.mjs +2 -0
- package/build/i18n/ja.json.mjs.map +1 -1
- package/build/i18n/nl.json +2 -0
- package/build/i18n/nl.json.js +2 -0
- package/build/i18n/nl.json.js.map +1 -1
- package/build/i18n/nl.json.mjs +2 -0
- package/build/i18n/nl.json.mjs.map +1 -1
- package/build/i18n/pl.json +2 -0
- package/build/i18n/pl.json.js +2 -0
- package/build/i18n/pl.json.js.map +1 -1
- package/build/i18n/pl.json.mjs +2 -0
- package/build/i18n/pl.json.mjs.map +1 -1
- package/build/i18n/pt.json +2 -0
- package/build/i18n/pt.json.js +2 -0
- package/build/i18n/pt.json.js.map +1 -1
- package/build/i18n/pt.json.mjs +2 -0
- package/build/i18n/pt.json.mjs.map +1 -1
- package/build/i18n/ro.json +2 -0
- package/build/i18n/ro.json.js +2 -0
- package/build/i18n/ro.json.js.map +1 -1
- package/build/i18n/ro.json.mjs +2 -0
- package/build/i18n/ro.json.mjs.map +1 -1
- package/build/i18n/ru.json +2 -0
- package/build/i18n/ru.json.js +2 -0
- package/build/i18n/ru.json.js.map +1 -1
- package/build/i18n/ru.json.mjs +2 -0
- package/build/i18n/ru.json.mjs.map +1 -1
- package/build/i18n/th.json +2 -0
- package/build/i18n/th.json.js +2 -0
- package/build/i18n/th.json.js.map +1 -1
- package/build/i18n/th.json.mjs +2 -0
- package/build/i18n/th.json.mjs.map +1 -1
- package/build/i18n/tr.json +2 -0
- package/build/i18n/tr.json.js +2 -0
- package/build/i18n/tr.json.js.map +1 -1
- package/build/i18n/tr.json.mjs +2 -0
- package/build/i18n/tr.json.mjs.map +1 -1
- package/build/i18n/zh-CN.json +2 -0
- package/build/i18n/zh-CN.json.js +2 -0
- package/build/i18n/zh-CN.json.js.map +1 -1
- package/build/i18n/zh-CN.json.mjs +2 -0
- package/build/i18n/zh-CN.json.mjs.map +1 -1
- package/build/i18n/zh-HK.json +2 -0
- package/build/i18n/zh-HK.json.js +2 -0
- package/build/i18n/zh-HK.json.js.map +1 -1
- package/build/i18n/zh-HK.json.mjs +2 -0
- package/build/i18n/zh-HK.json.mjs.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/index.mjs +1 -0
- package/build/index.mjs.map +1 -1
- package/build/listItem/Prompt/ListItemPrompt.js +3 -2
- package/build/listItem/Prompt/ListItemPrompt.js.map +1 -1
- package/build/listItem/Prompt/ListItemPrompt.mjs +3 -2
- package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -1
- package/build/logo/Logo.js +77 -25
- package/build/logo/Logo.js.map +1 -1
- package/build/logo/Logo.mjs +79 -27
- package/build/logo/Logo.mjs.map +1 -1
- package/build/logo/logo-assets.js +68 -97
- package/build/logo/logo-assets.js.map +1 -1
- package/build/logo/logo-assets.mjs +62 -90
- package/build/logo/logo-assets.mjs.map +1 -1
- package/build/main.css +225 -59
- package/build/prompt/ActionPrompt/ActionPrompt.js +8 -40
- package/build/prompt/ActionPrompt/ActionPrompt.js.map +1 -1
- package/build/prompt/ActionPrompt/ActionPrompt.mjs +8 -40
- package/build/prompt/ActionPrompt/ActionPrompt.mjs.map +1 -1
- package/build/prompt/CriticalBanner/CriticalBanner.js +143 -0
- package/build/prompt/CriticalBanner/CriticalBanner.js.map +1 -0
- package/build/prompt/CriticalBanner/CriticalBanner.mjs +141 -0
- package/build/prompt/CriticalBanner/CriticalBanner.mjs.map +1 -0
- package/build/prompt/CriticalBanner/helpers.js +29 -0
- package/build/prompt/CriticalBanner/helpers.js.map +1 -0
- package/build/prompt/CriticalBanner/helpers.mjs +26 -0
- package/build/prompt/CriticalBanner/helpers.mjs.map +1 -0
- package/build/prompt/InfoPrompt/InfoPrompt.js +3 -2
- package/build/prompt/InfoPrompt/InfoPrompt.js.map +1 -1
- package/build/prompt/InfoPrompt/InfoPrompt.mjs +3 -2
- package/build/prompt/InfoPrompt/InfoPrompt.mjs.map +1 -1
- package/build/prompt/PrimitivePrompt/PrimitivePrompt.js +11 -4
- package/build/prompt/PrimitivePrompt/PrimitivePrompt.js.map +1 -1
- package/build/prompt/PrimitivePrompt/PrimitivePrompt.mjs +11 -4
- package/build/prompt/PrimitivePrompt/PrimitivePrompt.mjs.map +1 -1
- package/build/prompt/common/Expander/Expander.js +35 -0
- package/build/prompt/common/Expander/Expander.js.map +1 -0
- package/build/prompt/common/Expander/Expander.messages.js +17 -0
- package/build/prompt/common/Expander/Expander.messages.js.map +1 -0
- package/build/prompt/common/Expander/Expander.messages.mjs +13 -0
- package/build/prompt/common/Expander/Expander.messages.mjs.map +1 -0
- package/build/prompt/common/Expander/Expander.mjs +33 -0
- package/build/prompt/common/Expander/Expander.mjs.map +1 -0
- package/build/prompt/helpers/promptMedia.js +52 -0
- package/build/prompt/helpers/promptMedia.js.map +1 -0
- package/build/prompt/helpers/promptMedia.mjs +50 -0
- package/build/prompt/helpers/promptMedia.mjs.map +1 -0
- package/build/styles/css/neptune.css +0 -1
- package/build/styles/logo/Logo.css +3 -23
- package/build/styles/main.css +225 -59
- package/build/styles/prompt/CriticalBanner/CriticalBanner.css +134 -0
- package/build/styles/prompt/CriticalBanner/CriticalBanner.vars.css +0 -0
- package/build/styles/prompt/InfoPrompt/InfoPrompt.css +24 -0
- package/build/styles/prompt/common/Expander/Expander.css +8 -0
- package/build/styles/styles/less/neptune.css +0 -1
- package/build/typeahead/Typeahead.js +3 -2
- package/build/typeahead/Typeahead.js.map +1 -1
- package/build/typeahead/Typeahead.mjs +3 -2
- package/build/typeahead/Typeahead.mjs.map +1 -1
- package/build/types/common/hooks/useContainerSize.d.ts +14 -0
- package/build/types/common/hooks/useContainerSize.d.ts.map +1 -0
- package/build/types/common/hooks/useResizeObserver.d.ts +1 -1
- package/build/types/common/hooks/useResizeObserver.d.ts.map +1 -1
- package/build/types/criticalBanner/CriticalCommsBanner.d.ts +3 -0
- package/build/types/criticalBanner/CriticalCommsBanner.d.ts.map +1 -1
- package/build/types/index.d.ts +2 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/logo/Logo.d.ts +33 -1
- package/build/types/logo/Logo.d.ts.map +1 -1
- package/build/types/logo/logo-assets.d.ts +33 -9
- package/build/types/logo/logo-assets.d.ts.map +1 -1
- package/build/types/prompt/ActionPrompt/ActionPrompt.d.ts +2 -11
- package/build/types/prompt/ActionPrompt/ActionPrompt.d.ts.map +1 -1
- package/build/types/prompt/CriticalBanner/CriticalBanner.d.ts +39 -0
- package/build/types/prompt/CriticalBanner/CriticalBanner.d.ts.map +1 -0
- package/build/types/prompt/CriticalBanner/helpers.d.ts +18 -0
- package/build/types/prompt/CriticalBanner/helpers.d.ts.map +1 -0
- package/build/types/prompt/CriticalBanner/index.d.ts +3 -0
- package/build/types/prompt/CriticalBanner/index.d.ts.map +1 -0
- package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts.map +1 -1
- package/build/types/prompt/PrimitivePrompt/PrimitivePrompt.d.ts +35 -3
- package/build/types/prompt/PrimitivePrompt/PrimitivePrompt.d.ts.map +1 -1
- package/build/types/prompt/common/Expander/Expander.d.ts +20 -0
- package/build/types/prompt/common/Expander/Expander.d.ts.map +1 -0
- package/build/types/prompt/common/Expander/Expander.messages.d.ts +14 -0
- package/build/types/prompt/common/Expander/Expander.messages.d.ts.map +1 -0
- package/build/types/prompt/helpers/promptMedia.d.ts +22 -0
- package/build/types/prompt/helpers/promptMedia.d.ts.map +1 -0
- package/build/types/prompt/index.d.ts +2 -0
- package/build/types/prompt/index.d.ts.map +1 -1
- package/build/types/test-utils/index.d.ts +4 -0
- package/build/types/test-utils/index.d.ts.map +1 -1
- package/package.json +22 -18
- package/src/alert/Alert.story.tsx +30 -1
- package/src/avatarWrapper/AvatarWrapper.story.tsx +1 -1
- package/src/button/_stories/Button.story.tsx +11 -0
- package/src/common/hooks/useContainerSize.test.tsx +125 -0
- package/src/common/hooks/useContainerSize.ts +32 -0
- package/src/common/hooks/useResizeObserver.ts +3 -2
- package/src/criticalBanner/CriticalCommsBanner.story.tsx +4 -0
- package/src/criticalBanner/CriticalCommsBanner.test.story.tsx +1 -1
- package/src/criticalBanner/CriticalCommsBanner.tsx +3 -0
- package/src/i18n/cs.json +2 -0
- package/src/i18n/de.json +2 -0
- package/src/i18n/en.json +2 -0
- package/src/i18n/es.json +2 -0
- package/src/i18n/fr.json +2 -0
- package/src/i18n/hu.json +2 -0
- package/src/i18n/id.json +2 -0
- package/src/i18n/it.json +2 -0
- package/src/i18n/ja.json +2 -0
- package/src/i18n/nl.json +2 -0
- package/src/i18n/pl.json +2 -0
- package/src/i18n/pt.json +2 -0
- package/src/i18n/ro.json +2 -0
- package/src/i18n/ru.json +2 -0
- package/src/i18n/th.json +2 -0
- package/src/i18n/tr.json +2 -0
- package/src/i18n/zh-CN.json +2 -0
- package/src/i18n/zh-HK.json +2 -0
- package/src/index.ts +2 -2
- package/src/logo/Logo.css +3 -23
- package/src/logo/Logo.less +3 -29
- package/src/logo/Logo.story.tsx +117 -89
- package/src/logo/Logo.test.story.tsx +15 -24
- package/src/logo/Logo.tsx +90 -28
- package/src/logo/logo-assets.tsx +36 -92
- package/src/main.css +225 -59
- package/src/main.less +3 -1
- package/src/prompt/ActionPrompt/ActionPrompt.tsx +9 -62
- package/src/prompt/CriticalBanner/CriticalBanner.accessibility.docs.mdx +113 -0
- package/src/prompt/CriticalBanner/CriticalBanner.css +134 -0
- package/src/prompt/CriticalBanner/CriticalBanner.less +155 -0
- package/src/prompt/CriticalBanner/CriticalBanner.story.tsx +635 -0
- package/src/prompt/CriticalBanner/CriticalBanner.test.story.tsx +422 -0
- package/src/prompt/CriticalBanner/CriticalBanner.tsx +179 -0
- package/src/prompt/CriticalBanner/CriticalBanner.vars.css +0 -0
- package/src/prompt/CriticalBanner/CriticalBanner.vars.less +6 -0
- package/src/prompt/CriticalBanner/helpers.ts +39 -0
- package/src/prompt/CriticalBanner/index.ts +2 -0
- package/src/prompt/InfoPrompt/InfoPrompt.css +24 -0
- package/src/prompt/InfoPrompt/InfoPrompt.less +23 -0
- package/src/prompt/InfoPrompt/InfoPrompt.tsx +5 -1
- package/src/prompt/PrimitivePrompt/PrimitivePrompt.tsx +56 -40
- package/src/prompt/common/Expander/Expander.css +8 -0
- package/src/prompt/common/Expander/Expander.less +9 -0
- package/src/prompt/common/Expander/Expander.messages.ts +14 -0
- package/src/prompt/common/Expander/Expander.test.tsx +167 -0
- package/src/prompt/common/Expander/Expander.tsx +83 -0
- package/src/prompt/helpers/promptMedia.tsx +79 -0
- package/src/prompt/index.ts +4 -0
- package/src/radio/Radio.story.tsx +1 -1
- package/src/section/Section.story.tsx +2 -8
- package/src/sentimentSurface/SentimentSurface.story.tsx +43 -17
- package/src/statusIcon/StatusIcon.test.tsx +0 -2
- package/src/styles/less/neptune.css +0 -1
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
import { useState, useEffect, useRef, type ReactNode } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import { Meta, StoryObj, Decorator } from '@storybook/react-webpack5';
|
|
4
|
+
import { fn } from 'storybook/test';
|
|
5
|
+
import { Bank, Briefcase, Star, Travel } from '@transferwise/icons';
|
|
6
|
+
import Button from '../../button';
|
|
7
|
+
import { CriticalBanner, type CriticalBannerProps } from './CriticalBanner';
|
|
8
|
+
import { withVariantConfig } from '../../../.storybook/helpers';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* **Design guidance**: <a href="https://wise.design/components/critical-banner" target="_blank">wise.design/components/critical-banner</a>
|
|
12
|
+
*
|
|
13
|
+
* Can be controlled or uncontrolled. When `onToggle` is provided, the consumer manages the expanded state via `expanded` and the banner calls `onToggle` when the user clicks the chevron. When `onToggle` is not provided, the banner manages its own expanded state internally and toggles it when the user clicks the chevron.
|
|
14
|
+
*/
|
|
15
|
+
const meta = {
|
|
16
|
+
component: CriticalBanner,
|
|
17
|
+
title: 'Prompts/CriticalBanner',
|
|
18
|
+
tags: ['new'],
|
|
19
|
+
parameters: { docs: { toc: true } },
|
|
20
|
+
args: {
|
|
21
|
+
title: 'Your account requires verification',
|
|
22
|
+
description: 'Please verify your identity to continue using all features.',
|
|
23
|
+
sentiment: 'negative',
|
|
24
|
+
expanded: true,
|
|
25
|
+
action: { label: 'Verify now', onClick: fn() },
|
|
26
|
+
actionSecondary: undefined,
|
|
27
|
+
media: undefined,
|
|
28
|
+
id: undefined,
|
|
29
|
+
className: undefined,
|
|
30
|
+
'data-testid': undefined,
|
|
31
|
+
onToggle: fn(),
|
|
32
|
+
},
|
|
33
|
+
argTypes: {
|
|
34
|
+
sentiment: {
|
|
35
|
+
control: 'radio',
|
|
36
|
+
options: ['negative', 'warning', 'neutral', 'success'],
|
|
37
|
+
},
|
|
38
|
+
title: {
|
|
39
|
+
control: 'text',
|
|
40
|
+
table: { type: { summary: 'ReactNode' } },
|
|
41
|
+
},
|
|
42
|
+
description: {
|
|
43
|
+
control: 'text',
|
|
44
|
+
table: { type: { summary: 'ReactNode' } },
|
|
45
|
+
},
|
|
46
|
+
expanded: { control: 'boolean' },
|
|
47
|
+
media: {
|
|
48
|
+
control: false,
|
|
49
|
+
description: 'Replaces the default Status Icon with a custom image or AvatarView.',
|
|
50
|
+
table: {
|
|
51
|
+
type: {
|
|
52
|
+
summary: 'PromptMedia',
|
|
53
|
+
detail:
|
|
54
|
+
'{ imgSrc?: string; avatar?: { imgSrc?: string; profileName?: string; profileType?: string; asset?: ReactNode; badge?: { flagCode: string } }; aria-label?: string }',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
action: {
|
|
59
|
+
control: false,
|
|
60
|
+
table: {
|
|
61
|
+
type: {
|
|
62
|
+
summary: 'CriticalBannerAction',
|
|
63
|
+
detail: '{ label: ReactNode; onClick?: () => void; href?: string; target?: string }',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
actionSecondary: {
|
|
68
|
+
control: false,
|
|
69
|
+
table: {
|
|
70
|
+
type: {
|
|
71
|
+
summary: 'CriticalBannerActionSecondary',
|
|
72
|
+
detail: '{ label: ReactNode; onClick?: () => void; href?: string; target?: string }',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
id: { table: { category: 'Common' } },
|
|
77
|
+
className: { table: { category: 'Common' } },
|
|
78
|
+
'data-testid': { table: { category: 'Common' } },
|
|
79
|
+
onToggle: { table: { disable: true } },
|
|
80
|
+
},
|
|
81
|
+
} satisfies Meta<typeof CriticalBanner>;
|
|
82
|
+
|
|
83
|
+
export default meta;
|
|
84
|
+
type Story = StoryObj<typeof CriticalBanner>;
|
|
85
|
+
|
|
86
|
+
type PreviewStoryArgs = CriticalBannerProps & {
|
|
87
|
+
previewMedia: CriticalBannerProps['media'];
|
|
88
|
+
previewSecondaryAction: boolean;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const MEDIA_OPTIONS: Record<string, CriticalBannerProps['media']> = {
|
|
92
|
+
undefined,
|
|
93
|
+
'Custom image': { imgSrc: '../../wise-card.svg' },
|
|
94
|
+
'Avatar: Photo': { avatar: { imgSrc: '../../avatar-rectangle-fox.webp' } },
|
|
95
|
+
'Avatar: Business (GB)': {
|
|
96
|
+
avatar: { profileType: 'BUSINESS', badge: { flagCode: 'GB' } },
|
|
97
|
+
},
|
|
98
|
+
'Avatar: Personal (EU)': {
|
|
99
|
+
avatar: { profileType: 'PERSONAL', badge: { flagCode: 'EU' } },
|
|
100
|
+
},
|
|
101
|
+
'Avatar: Bank icon': { avatar: { asset: <Bank /> } },
|
|
102
|
+
'Avatar: Star icon': { avatar: { asset: <Star /> } },
|
|
103
|
+
'Avatar: Travel icon': { avatar: { asset: <Travel /> } },
|
|
104
|
+
'Avatar: Briefcase icon': { avatar: { asset: <Briefcase /> } },
|
|
105
|
+
'Avatar: Initials': { avatar: { profileName: 'John Doe' } },
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const previewArgTypes = {
|
|
109
|
+
previewMedia: {
|
|
110
|
+
name: 'Preview with `media`',
|
|
111
|
+
control: 'select',
|
|
112
|
+
options: Object.keys(MEDIA_OPTIONS),
|
|
113
|
+
mapping: MEDIA_OPTIONS,
|
|
114
|
+
table: { category: 'Storybook Preview' },
|
|
115
|
+
},
|
|
116
|
+
previewSecondaryAction: {
|
|
117
|
+
name: 'Preview with `actionSecondary`',
|
|
118
|
+
control: 'boolean',
|
|
119
|
+
table: { category: 'Storybook Preview' },
|
|
120
|
+
},
|
|
121
|
+
} as const;
|
|
122
|
+
|
|
123
|
+
/** Renders children inside an iframe that inherits the parent page's stylesheets. */
|
|
124
|
+
function IframeContainer({ width, children }: { width: number; children: ReactNode }) {
|
|
125
|
+
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
126
|
+
const [mountNode, setMountNode] = useState<HTMLElement | null>(null);
|
|
127
|
+
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
const iframe = iframeRef.current;
|
|
130
|
+
if (!iframe) return;
|
|
131
|
+
|
|
132
|
+
const doc = iframe.contentDocument;
|
|
133
|
+
if (!doc) return;
|
|
134
|
+
|
|
135
|
+
doc.head.innerHTML = '';
|
|
136
|
+
Array.from(document.styleSheets).forEach((sheet) => {
|
|
137
|
+
try {
|
|
138
|
+
if (sheet.href) {
|
|
139
|
+
const link = doc.createElement('link');
|
|
140
|
+
link.rel = 'stylesheet';
|
|
141
|
+
link.href = sheet.href;
|
|
142
|
+
doc.head.appendChild(link);
|
|
143
|
+
} else if (sheet.cssRules) {
|
|
144
|
+
const style = doc.createElement('style');
|
|
145
|
+
style.textContent = Array.from(sheet.cssRules)
|
|
146
|
+
.map((r) => r.cssText)
|
|
147
|
+
.join('\n');
|
|
148
|
+
doc.head.appendChild(style);
|
|
149
|
+
}
|
|
150
|
+
} catch {
|
|
151
|
+
// Skip cross-origin sheets
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
doc.body.style.margin = '0';
|
|
156
|
+
setMountNode(doc.body);
|
|
157
|
+
}, []);
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<iframe
|
|
161
|
+
ref={iframeRef}
|
|
162
|
+
title={`${width}px preview`}
|
|
163
|
+
sandbox="allow-same-origin"
|
|
164
|
+
style={{
|
|
165
|
+
width,
|
|
166
|
+
height: 300,
|
|
167
|
+
border: '1px solid var(--color-border-neutral)',
|
|
168
|
+
borderRadius: 8,
|
|
169
|
+
overflow: 'hidden',
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
{mountNode && createPortal(children, mountNode)}
|
|
173
|
+
</iframe>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const ContainerDecorator: Decorator = (Story) => (
|
|
178
|
+
<div
|
|
179
|
+
style={{
|
|
180
|
+
width: '100%',
|
|
181
|
+
display: 'flex',
|
|
182
|
+
flexDirection: 'column',
|
|
183
|
+
gap: '1rem',
|
|
184
|
+
}}
|
|
185
|
+
>
|
|
186
|
+
<Story />
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Interactive playground with all controls.
|
|
192
|
+
*/
|
|
193
|
+
export const Playground: StoryObj<PreviewStoryArgs> = {
|
|
194
|
+
args: {
|
|
195
|
+
previewMedia: undefined,
|
|
196
|
+
previewSecondaryAction: true,
|
|
197
|
+
},
|
|
198
|
+
argTypes: {
|
|
199
|
+
...previewArgTypes,
|
|
200
|
+
},
|
|
201
|
+
render: function Render(args: PreviewStoryArgs) {
|
|
202
|
+
const { previewMedia, previewSecondaryAction, ...props } = args;
|
|
203
|
+
const [expanded, setExpanded] = useState(args.expanded);
|
|
204
|
+
|
|
205
|
+
useEffect(() => {
|
|
206
|
+
setExpanded(args.expanded);
|
|
207
|
+
}, [args.expanded]);
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<CriticalBanner
|
|
211
|
+
{...props}
|
|
212
|
+
expanded={expanded}
|
|
213
|
+
media={previewMedia}
|
|
214
|
+
actionSecondary={
|
|
215
|
+
previewSecondaryAction ? { label: 'Learn more', onClick: fn() } : undefined
|
|
216
|
+
}
|
|
217
|
+
onToggle={() => setExpanded(!expanded)}
|
|
218
|
+
/>
|
|
219
|
+
);
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* There are four sentiments, with negative being the default.
|
|
225
|
+
*/
|
|
226
|
+
export const Sentiments: Story = {
|
|
227
|
+
decorators: [ContainerDecorator],
|
|
228
|
+
parameters: {
|
|
229
|
+
docs: {
|
|
230
|
+
source: {
|
|
231
|
+
code: `<CriticalBanner sentiment="negative" ... />
|
|
232
|
+
<CriticalBanner sentiment="warning" ... />
|
|
233
|
+
<CriticalBanner sentiment="neutral" ... />
|
|
234
|
+
<CriticalBanner sentiment="success" ... />`,
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
argTypes: {
|
|
239
|
+
sentiment: { table: { disable: true } },
|
|
240
|
+
title: { table: { disable: true } },
|
|
241
|
+
description: { table: { disable: true } },
|
|
242
|
+
action: { table: { disable: true } },
|
|
243
|
+
actionSecondary: { table: { disable: true } },
|
|
244
|
+
media: { table: { disable: true } },
|
|
245
|
+
expanded: { table: { disable: true } },
|
|
246
|
+
onToggle: { table: { disable: true } },
|
|
247
|
+
id: { table: { disable: true } },
|
|
248
|
+
className: { table: { disable: true } },
|
|
249
|
+
'data-testid': { table: { disable: true } },
|
|
250
|
+
},
|
|
251
|
+
render: function Render() {
|
|
252
|
+
return (
|
|
253
|
+
<>
|
|
254
|
+
{(['negative', 'warning', 'neutral', 'success'] as const).map((sentiment) => (
|
|
255
|
+
<CriticalBanner
|
|
256
|
+
key={sentiment}
|
|
257
|
+
sentiment={sentiment}
|
|
258
|
+
title={`This is a critical banner with ${sentiment} sentiment`}
|
|
259
|
+
description="Complete the required action to regain full access."
|
|
260
|
+
action={{ label: 'Take action', onClick: fn() }}
|
|
261
|
+
actionSecondary={{ label: 'Learn more', onClick: fn() }}
|
|
262
|
+
/>
|
|
263
|
+
))}
|
|
264
|
+
</>
|
|
265
|
+
);
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Banners can have just a primary action, both primary and secondary, or no actions at all.
|
|
271
|
+
*/
|
|
272
|
+
export const Actions: Story = {
|
|
273
|
+
decorators: [ContainerDecorator],
|
|
274
|
+
parameters: {
|
|
275
|
+
docs: {
|
|
276
|
+
source: {
|
|
277
|
+
code: `<CriticalBanner
|
|
278
|
+
title="..."
|
|
279
|
+
/>
|
|
280
|
+
<CriticalBanner
|
|
281
|
+
title="..."
|
|
282
|
+
action={{ label: 'Verify identity', onClick: () => {} }} />
|
|
283
|
+
<CriticalBanner
|
|
284
|
+
title="..."
|
|
285
|
+
action={{ label: 'Verify now', onClick: () => {} }}
|
|
286
|
+
actionSecondary={{ label: 'Contact support', onClick: () => {} }}
|
|
287
|
+
/>`,
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
argTypes: {
|
|
292
|
+
sentiment: { table: { disable: true } },
|
|
293
|
+
title: { table: { disable: true } },
|
|
294
|
+
description: { table: { disable: true } },
|
|
295
|
+
action: { table: { disable: true } },
|
|
296
|
+
actionSecondary: { table: { disable: true } },
|
|
297
|
+
media: { table: { disable: true } },
|
|
298
|
+
expanded: { table: { disable: true } },
|
|
299
|
+
onToggle: { table: { disable: true } },
|
|
300
|
+
id: { table: { disable: true } },
|
|
301
|
+
className: { table: { disable: true } },
|
|
302
|
+
'data-testid': { table: { disable: true } },
|
|
303
|
+
},
|
|
304
|
+
render: function Render() {
|
|
305
|
+
return (
|
|
306
|
+
<>
|
|
307
|
+
<CriticalBanner sentiment="negative" title="No actions" description="Description" />
|
|
308
|
+
<CriticalBanner
|
|
309
|
+
sentiment="warning"
|
|
310
|
+
title="Primary action only"
|
|
311
|
+
description="Description"
|
|
312
|
+
action={{ label: 'Verify identity', onClick: fn() }}
|
|
313
|
+
/>
|
|
314
|
+
<CriticalBanner
|
|
315
|
+
sentiment="success"
|
|
316
|
+
title="Primary and secondary actions"
|
|
317
|
+
description="Description"
|
|
318
|
+
action={{ label: 'Verify now', onClick: fn() }}
|
|
319
|
+
actionSecondary={{ label: 'Contact support', onClick: fn() }}
|
|
320
|
+
/>
|
|
321
|
+
</>
|
|
322
|
+
);
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Each sentiment has a default status icon. Override it with a custom image or an AvatarView.
|
|
328
|
+
*/
|
|
329
|
+
export const MediaTypes: Story = {
|
|
330
|
+
decorators: [ContainerDecorator],
|
|
331
|
+
parameters: {
|
|
332
|
+
docs: {
|
|
333
|
+
source: {
|
|
334
|
+
code: `{/* Default — sentiment icon */}
|
|
335
|
+
<CriticalBanner sentiment="neutral" />
|
|
336
|
+
|
|
337
|
+
{/* Custom image */}
|
|
338
|
+
<CriticalBanner media={{ imgSrc: '/card.svg', 'aria-label': 'Wise card' }} ... />
|
|
339
|
+
|
|
340
|
+
{/* Avatar with photo */}
|
|
341
|
+
<CriticalBanner media={{ avatar: { imgSrc: '/photo.webp' } }} ... />
|
|
342
|
+
|
|
343
|
+
{/* Avatar with initials */}
|
|
344
|
+
<CriticalBanner media={{ avatar: { profileName: 'John Doe' } }} ... />
|
|
345
|
+
|
|
346
|
+
{/* Avatar with custom icon */}
|
|
347
|
+
<CriticalBanner media={{ avatar: { asset: <Bank /> } }} ... />
|
|
348
|
+
|
|
349
|
+
{/* Business Profile with flag badge */}
|
|
350
|
+
<CriticalBanner media={{ avatar: { profileType: 'BUSINESS', badge: { flagCode: 'GB' } } }} ... />`,
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
argTypes: {
|
|
355
|
+
sentiment: { table: { disable: true } },
|
|
356
|
+
title: { table: { disable: true } },
|
|
357
|
+
description: { table: { disable: true } },
|
|
358
|
+
action: { table: { disable: true } },
|
|
359
|
+
actionSecondary: { table: { disable: true } },
|
|
360
|
+
media: { table: { disable: true } },
|
|
361
|
+
expanded: { table: { disable: true } },
|
|
362
|
+
onToggle: { table: { disable: true } },
|
|
363
|
+
id: { table: { disable: true } },
|
|
364
|
+
className: { table: { disable: true } },
|
|
365
|
+
'data-testid': { table: { disable: true } },
|
|
366
|
+
},
|
|
367
|
+
render: function Render() {
|
|
368
|
+
const [expandedStates, setExpandedStates] = useState<Record<string, boolean>>({
|
|
369
|
+
default: true,
|
|
370
|
+
image: true,
|
|
371
|
+
avatarPhoto: true,
|
|
372
|
+
avatarInitials: true,
|
|
373
|
+
avatarIcon: true,
|
|
374
|
+
businessBadge: true,
|
|
375
|
+
personalBadge: true,
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
const toggle = (key: string) => setExpandedStates((prev) => ({ ...prev, [key]: !prev[key] }));
|
|
379
|
+
|
|
380
|
+
return (
|
|
381
|
+
<>
|
|
382
|
+
<CriticalBanner
|
|
383
|
+
sentiment="neutral"
|
|
384
|
+
title="Default status icon"
|
|
385
|
+
description="When no media is provided, the sentiment's default icon is displayed."
|
|
386
|
+
action={{ label: 'Continue', onClick: fn() }}
|
|
387
|
+
expanded={expandedStates.default}
|
|
388
|
+
onToggle={() => toggle('default')}
|
|
389
|
+
/>
|
|
390
|
+
<CriticalBanner
|
|
391
|
+
sentiment="neutral"
|
|
392
|
+
title="Custom image"
|
|
393
|
+
description="Your card has been blocked for security reasons."
|
|
394
|
+
media={{ imgSrc: '../../wise-card.svg', 'aria-label': 'Wise debit card' }}
|
|
395
|
+
action={{ label: 'Unblock card', onClick: fn() }}
|
|
396
|
+
expanded={expandedStates.image}
|
|
397
|
+
onToggle={() => toggle('image')}
|
|
398
|
+
/>
|
|
399
|
+
<CriticalBanner
|
|
400
|
+
sentiment="neutral"
|
|
401
|
+
title="Avatar with photo"
|
|
402
|
+
description="The default badge is the status icon for the sentiment."
|
|
403
|
+
media={{ avatar: { imgSrc: '../../avatar-rectangle-fox.webp' } }}
|
|
404
|
+
action={{ label: 'Update photo', onClick: fn() }}
|
|
405
|
+
expanded={expandedStates.avatarPhoto}
|
|
406
|
+
onToggle={() => toggle('avatarPhoto')}
|
|
407
|
+
/>
|
|
408
|
+
<CriticalBanner
|
|
409
|
+
sentiment="neutral"
|
|
410
|
+
title="Avatar with initials"
|
|
411
|
+
description="The default badge is the status icon for the sentiment."
|
|
412
|
+
media={{ avatar: { profileName: 'John Doe' } }}
|
|
413
|
+
action={{ label: 'Complete profile', onClick: fn() }}
|
|
414
|
+
expanded={expandedStates.avatarInitials}
|
|
415
|
+
onToggle={() => toggle('avatarInitials')}
|
|
416
|
+
/>
|
|
417
|
+
<CriticalBanner
|
|
418
|
+
sentiment="neutral"
|
|
419
|
+
title="Avatar with custom icon"
|
|
420
|
+
description="The default badge is the status icon for the sentiment."
|
|
421
|
+
media={{ avatar: { asset: <Bank title="Bank account" /> } }}
|
|
422
|
+
action={{ label: 'Connect bank', onClick: fn() }}
|
|
423
|
+
expanded={expandedStates.avatarIcon}
|
|
424
|
+
onToggle={() => toggle('avatarIcon')}
|
|
425
|
+
/>
|
|
426
|
+
<CriticalBanner
|
|
427
|
+
sentiment="neutral"
|
|
428
|
+
title="Business profile with badge"
|
|
429
|
+
description="Your business account requires additional documentation."
|
|
430
|
+
media={{ avatar: { profileType: 'BUSINESS', badge: { flagCode: 'GB' } } }}
|
|
431
|
+
action={{ label: 'Upload documents', onClick: fn() }}
|
|
432
|
+
expanded={expandedStates.businessBadge}
|
|
433
|
+
onToggle={() => toggle('businessBadge')}
|
|
434
|
+
/>
|
|
435
|
+
</>
|
|
436
|
+
);
|
|
437
|
+
},
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* The banner can be fully controlled — the parent can pass in the `expanded` state.
|
|
442
|
+
* Clicking the chevron calls `onToggle`, and external buttons can also toggle expansion.
|
|
443
|
+
* We recommend tracking the state that the user has set `expanded` to and keeping it there on page refresh.
|
|
444
|
+
*
|
|
445
|
+
* When the banner is shown on wider screens, it will always be fully expanded.
|
|
446
|
+
*/
|
|
447
|
+
export const Expanded: Story = {
|
|
448
|
+
parameters: {
|
|
449
|
+
docs: {
|
|
450
|
+
source: {
|
|
451
|
+
code: `const [expanded, setExpanded] = useState(true);
|
|
452
|
+
|
|
453
|
+
<Button onClick={() => setExpanded(!expanded)}>
|
|
454
|
+
{expanded ? 'Collapse' : 'Expand'}
|
|
455
|
+
</Button>
|
|
456
|
+
|
|
457
|
+
<CriticalBanner
|
|
458
|
+
...
|
|
459
|
+
expanded={expanded}
|
|
460
|
+
onToggle={() => setExpanded(!expanded)}
|
|
461
|
+
/>`,
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
argTypes: {
|
|
466
|
+
sentiment: { table: { disable: true } },
|
|
467
|
+
title: { table: { disable: true } },
|
|
468
|
+
description: { table: { disable: true } },
|
|
469
|
+
action: { table: { disable: true } },
|
|
470
|
+
actionSecondary: { table: { disable: true } },
|
|
471
|
+
media: { table: { disable: true } },
|
|
472
|
+
expanded: { table: { disable: true } },
|
|
473
|
+
onToggle: { table: { disable: true } },
|
|
474
|
+
id: { table: { disable: true } },
|
|
475
|
+
className: { table: { disable: true } },
|
|
476
|
+
'data-testid': { table: { disable: true } },
|
|
477
|
+
},
|
|
478
|
+
render: function Render() {
|
|
479
|
+
const [expanded, setExpanded] = useState(true);
|
|
480
|
+
|
|
481
|
+
return (
|
|
482
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', width: '100%' }}>
|
|
483
|
+
<div>
|
|
484
|
+
<Button v2 onClick={() => setExpanded(!expanded)}>
|
|
485
|
+
{expanded ? 'Collapse externally' : 'Expand externally'}
|
|
486
|
+
</Button>
|
|
487
|
+
</div>
|
|
488
|
+
<CriticalBanner
|
|
489
|
+
sentiment="negative"
|
|
490
|
+
title="Your account requires verification"
|
|
491
|
+
description="Please verify your identity to continue using all features. This process typically takes 2–3 minutes."
|
|
492
|
+
action={{ label: 'Verify now', onClick: fn() }}
|
|
493
|
+
actionSecondary={{ label: 'Learn more', onClick: fn() }}
|
|
494
|
+
expanded={expanded}
|
|
495
|
+
onToggle={() => setExpanded(!expanded)}
|
|
496
|
+
/>
|
|
497
|
+
</div>
|
|
498
|
+
);
|
|
499
|
+
},
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* When the banner has no title, the description remains visible when collapsed and
|
|
504
|
+
* is clamped to 2 lines. With a title, only the title is shown when collapsed.
|
|
505
|
+
*/
|
|
506
|
+
export const CollapsedBehaviour: Story = {
|
|
507
|
+
decorators: [ContainerDecorator],
|
|
508
|
+
|
|
509
|
+
argTypes: {
|
|
510
|
+
sentiment: { table: { disable: true } },
|
|
511
|
+
title: { table: { disable: true } },
|
|
512
|
+
description: { table: { disable: true } },
|
|
513
|
+
action: { table: { disable: true } },
|
|
514
|
+
actionSecondary: { table: { disable: true } },
|
|
515
|
+
media: { table: { disable: true } },
|
|
516
|
+
expanded: { table: { disable: true } },
|
|
517
|
+
onToggle: { table: { disable: true } },
|
|
518
|
+
id: { table: { disable: true } },
|
|
519
|
+
className: { table: { disable: true } },
|
|
520
|
+
'data-testid': { table: { disable: true } },
|
|
521
|
+
},
|
|
522
|
+
render: function Render() {
|
|
523
|
+
const [expanded1, setExpanded1] = useState(false);
|
|
524
|
+
const [expanded2, setExpanded2] = useState(false);
|
|
525
|
+
|
|
526
|
+
return (
|
|
527
|
+
<>
|
|
528
|
+
<CriticalBanner
|
|
529
|
+
sentiment="negative"
|
|
530
|
+
title="Collapsed with title"
|
|
531
|
+
description="This description is hidden when collapsed because the title provides enough context."
|
|
532
|
+
action={{ label: 'Take action', onClick: fn() }}
|
|
533
|
+
expanded={expanded1}
|
|
534
|
+
onToggle={() => setExpanded1(!expanded1)}
|
|
535
|
+
/>
|
|
536
|
+
<CriticalBanner
|
|
537
|
+
sentiment="warning"
|
|
538
|
+
description="When there is no title, the description stays visible but is clamped to a maximum of two lines. This ensures the user always sees some context even in the collapsed state, because there is no title to summarise the message."
|
|
539
|
+
action={{ label: 'Take action', onClick: fn() }}
|
|
540
|
+
expanded={expanded2}
|
|
541
|
+
onToggle={() => setExpanded2(!expanded2)}
|
|
542
|
+
/>
|
|
543
|
+
</>
|
|
544
|
+
);
|
|
545
|
+
},
|
|
546
|
+
...withVariantConfig(['mobile'], {
|
|
547
|
+
parameters: {
|
|
548
|
+
docs: {
|
|
549
|
+
canvas: { sourceState: 'hidden' },
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
}),
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Above 768px the collapse toggle disappears and the banner is always fully expanded. The buttons are not block displayed.
|
|
557
|
+
* Below 768px the user can collapse and expand the banner and the buttons are displayed as block elements.
|
|
558
|
+
* Eventually the buttons stack.
|
|
559
|
+
*/
|
|
560
|
+
export const Responsiveness: Story = {
|
|
561
|
+
parameters: {
|
|
562
|
+
docs: {
|
|
563
|
+
canvas: { sourceState: 'hidden' },
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
argTypes: {
|
|
567
|
+
sentiment: { table: { disable: true } },
|
|
568
|
+
title: { table: { disable: true } },
|
|
569
|
+
description: { table: { disable: true } },
|
|
570
|
+
action: { table: { disable: true } },
|
|
571
|
+
actionSecondary: { table: { disable: true } },
|
|
572
|
+
media: { table: { disable: true } },
|
|
573
|
+
expanded: { table: { disable: true } },
|
|
574
|
+
onToggle: { table: { disable: true } },
|
|
575
|
+
id: { table: { disable: true } },
|
|
576
|
+
className: { table: { disable: true } },
|
|
577
|
+
'data-testid': { table: { disable: true } },
|
|
578
|
+
},
|
|
579
|
+
render: function Render() {
|
|
580
|
+
return (
|
|
581
|
+
<div style={{ display: 'flex', gap: 16, alignItems: 'start', minWidth: 1500 }}>
|
|
582
|
+
{[200, 350, 600].map((width) => (
|
|
583
|
+
<IframeContainer key={width} width={width}>
|
|
584
|
+
<CriticalBanner
|
|
585
|
+
sentiment="warning"
|
|
586
|
+
title="Your account requires verification"
|
|
587
|
+
description="Please verify your identity to continue using all features."
|
|
588
|
+
action={{ label: 'Verify now', onClick: fn() }}
|
|
589
|
+
actionSecondary={{ label: 'Learn more', onClick: fn() }}
|
|
590
|
+
/>
|
|
591
|
+
</IframeContainer>
|
|
592
|
+
))}
|
|
593
|
+
</div>
|
|
594
|
+
);
|
|
595
|
+
},
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* The text container is capped at 480px for optimal readability, even though
|
|
600
|
+
* the banner itself stretches to the full available width.
|
|
601
|
+
*/
|
|
602
|
+
export const ParagraphWidth: Story = {
|
|
603
|
+
parameters: {
|
|
604
|
+
docs: {
|
|
605
|
+
canvas: { sourceState: 'hidden' },
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
argTypes: {
|
|
609
|
+
sentiment: { table: { disable: true } },
|
|
610
|
+
title: { table: { disable: true } },
|
|
611
|
+
description: { table: { disable: true } },
|
|
612
|
+
action: { table: { disable: true } },
|
|
613
|
+
actionSecondary: { table: { disable: true } },
|
|
614
|
+
media: { table: { disable: true } },
|
|
615
|
+
expanded: { table: { disable: true } },
|
|
616
|
+
onToggle: { table: { disable: true } },
|
|
617
|
+
id: { table: { disable: true } },
|
|
618
|
+
className: { table: { disable: true } },
|
|
619
|
+
'data-testid': { table: { disable: true } },
|
|
620
|
+
},
|
|
621
|
+
render: function Render() {
|
|
622
|
+
const [expanded, setExpanded] = useState(true);
|
|
623
|
+
|
|
624
|
+
return (
|
|
625
|
+
<CriticalBanner
|
|
626
|
+
sentiment="negative"
|
|
627
|
+
title="The text container is capped at 480px for optimal readability, even though the banner itself stretches to the full available width."
|
|
628
|
+
description="To restore access, you'll need to verify your identity. This involves confirming your personal details and uploading a valid government-issued ID. The process typically takes 2–3 minutes, and your account will be restored immediately after successful verification."
|
|
629
|
+
action={{ label: 'Verify now', onClick: fn() }}
|
|
630
|
+
expanded={expanded}
|
|
631
|
+
onToggle={() => setExpanded(!expanded)}
|
|
632
|
+
/>
|
|
633
|
+
);
|
|
634
|
+
},
|
|
635
|
+
};
|