@transferwise/components 46.149.0 → 46.149.2

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/main.css CHANGED
@@ -26549,6 +26549,7 @@ a[data-toggle="tooltip"] {
26549
26549
  }
26550
26550
 
26551
26551
  .np-avatar-view .np-avatar-view-content {
26552
+ --circle-border-color: var(--color-sentiment-border-overlay, var(--color-border-neutral));
26552
26553
  color: #37517e;
26553
26554
  color: var(--color-sentiment-content-primary, var(--color-content-primary));
26554
26555
  }
@@ -31955,6 +31956,9 @@ html:not([dir="rtl"]) .np-navigation-option {
31955
31956
  --Prompt-actions-gap: var(--size-8);
31956
31957
  --Prompt-gap: var(--size-10) var(--size-16);
31957
31958
  --Prompt-border-radius: 0;
31959
+ --critical-banner-background-base: transparent;
31960
+ --critical-banner-background-surface: var(--color-sentiment-background-surface);
31961
+ --critical-banner-background: linear-gradient(var(--critical-banner-background-surface), var(--critical-banner-background-surface)), var(--critical-banner-background-base);
31958
31962
  container-type: inline-size;
31959
31963
  position: relative;
31960
31964
  --critical-banner-easing: cubic-bezier(0.9, 0, 0.7, 1);
@@ -31963,6 +31967,11 @@ html:not([dir="rtl"]) .np-navigation-option {
31963
31967
  actions only go full-width below mobile-max token (container query) */
31964
31968
  }
31965
31969
 
31970
+ .wds-critical-banner.wds-prompt--neutral {
31971
+ --critical-banner-background-base: var(--color-background-elevated);
31972
+ background: var(--critical-banner-background);
31973
+ }
31974
+
31966
31975
  .wds-critical-banner--media-image {
31967
31976
  width: 48px;
31968
31977
  width: var(--size-48);
@@ -32028,19 +32037,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32028
32037
  min-width: 0;
32029
32038
  max-width: 480px;
32030
32039
  height: 100%;
32031
- padding-top: 3px;
32032
- }
32033
-
32034
- @media (max-width: 320px) {
32035
- .wds-critical-banner__text-wrapper {
32036
- padding-top: 0;
32037
- }
32038
- }
32039
-
32040
- @container (width < 320px) {
32041
- .wds-critical-banner__text-wrapper {
32042
- padding-top: 0;
32043
- }
32044
32040
  }
32045
32041
 
32046
32042
  .wds-critical-banner--collapsed .wds-critical-banner__title,
@@ -32103,21 +32099,22 @@ html:not([dir="rtl"]) .np-navigation-option {
32103
32099
  inline-size: 100%;
32104
32100
  }
32105
32101
 
32106
- .wds-critical-banner__entry-mask {
32107
- display: grid;
32108
- grid-template-rows: 0fr;
32109
- overflow: hidden;
32110
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
32111
- }
32112
-
32113
32102
  @container critical-banner-overhang (max-width: 600px) {
32114
- .wds-critical-banner__entry-mask {
32103
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
32115
32104
  --critical-banner-mobile-overhang-size: 32px;
32116
- }
32117
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang {
32105
+ --critical-banner-overhang-mask: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), #000 var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size)
32106
+ var(--critical-banner-mobile-overhang-size) no-repeat,
32107
+ radial-gradient(
32108
+ circle at 0% 100%,
32109
+ transparent var(--critical-banner-mobile-overhang-size),
32110
+ #000 var(--critical-banner-mobile-overhang-size)
32111
+ )
32112
+ 100% 0 / var(--critical-banner-mobile-overhang-size)
32113
+ var(--critical-banner-mobile-overhang-size) no-repeat;
32114
+ margin-bottom: 32px;
32118
32115
  margin-bottom: var(--critical-banner-mobile-overhang-size);
32119
32116
  }
32120
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang::after {
32117
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
32121
32118
  content: "";
32122
32119
  position: absolute;
32123
32120
  right: 0;
@@ -32125,22 +32122,9 @@ html:not([dir="rtl"]) .np-navigation-option {
32125
32122
  left: 0;
32126
32123
  height: var(--critical-banner-mobile-overhang-size);
32127
32124
  pointer-events: none;
32128
- background: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat, radial-gradient(circle at 0% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 100% 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat;
32129
- }
32130
- }
32131
-
32132
- .wds-critical-banner__entry-track {
32133
- min-height: 0;
32134
- }
32135
-
32136
- @keyframes wds-critical-banner-reveal-height {
32137
- from {
32138
- grid-template-rows: 0fr;
32139
- overflow: hidden;
32140
- }
32141
- to {
32142
- grid-template-rows: 1fr;
32143
- overflow: visible;
32125
+ background: var(--critical-banner-background);
32126
+ -webkit-mask: var(--critical-banner-overhang-mask);
32127
+ mask: var(--critical-banner-overhang-mask);
32144
32128
  }
32145
32129
  }
32146
32130
 
@@ -32151,11 +32135,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32151
32135
  .wds-critical-banner__toggle {
32152
32136
  transition: none !important;
32153
32137
  }
32154
- .wds-critical-banner__entry-mask {
32155
- animation: none;
32156
- grid-template-rows: 1fr;
32157
- overflow: visible;
32158
- }
32159
32138
  }
32160
32139
 
32161
32140
  .wds-expander-toggle {
@@ -141,13 +141,7 @@ const CriticalBanner = ({
141
141
  }),
142
142
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
143
143
  className: "wds-critical-banner-overhang-query",
144
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
145
- className: "wds-critical-banner__entry-mask",
146
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
147
- className: "wds-critical-banner__entry-track",
148
- children: bannerSurface
149
- })
150
- })
144
+ children: bannerSurface
151
145
  })
152
146
  });
153
147
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CriticalBanner.js","sources":["../../../src/prompt/CriticalBanner/CriticalBanner.tsx"],"sourcesContent":["import { ElementType, ReactNode, useId, useState } from 'react';\nimport { clsx } from 'clsx';\n\nimport Body from '../../body';\nimport Button from '../../button';\nimport Container from '../../container';\nimport { Breakpoint, LiveRegion, Typography } from '../../common';\nimport { ButtonProps } from '../../button/Button.types';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nimport { renderPromptMedia, PromptMedia } from '../helpers/promptMedia';\nimport { ExpanderToggle } from '../common/Expander/Expander';\nimport { buildAnnouncementString } from './helpers';\nimport { useContainerSize } from '../../common/hooks/useContainerSize';\n\nexport type CriticalBannerProps = {\n title?: ReactNode;\n description: ReactNode;\n media?: PromptMedia;\n action?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {\n label: ButtonProps['children'];\n };\n actionSecondary?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {\n label: ButtonProps['children'];\n };\n sentiment?: Exclude<PrimitivePromptProps['sentiment'], 'proposition'>;\n /**\n * Controls whether the description and actions are visible, as a controlled component.\n * When collapsed with a title, only the title is shown.\n * When collapsed without a title, the description is trimmed to 2 lines.\n *\n * Note: On desktop (container width >= 768px), the banner is always expanded\n * regardless of this prop value.\n */\n expanded?: boolean;\n /**\n * Called when the user clicks the chevron toggle.\n * If not provided, the component will manage expanded state internally.\n */\n onToggle?: () => void;\n} & Pick<PrimitivePromptProps, 'id' | 'className' | 'data-testid'>;\n\n/**\n * A full-width, non-dismissible banner for critical messages such as account blocks or\n * time-sensitive actions that require immediate user attention.\n\n * @see {@link https://docs.wise.design/components/critical-banner Design Spec}\n */\nexport const CriticalBanner = ({\n sentiment = 'negative',\n title,\n description,\n media = {},\n action,\n actionSecondary,\n expanded: expandedProp,\n onToggle,\n id,\n className,\n 'data-testid': testId,\n}: CriticalBannerProps) => {\n const [containerRef, isDesktop] = useContainerSize(Breakpoint.MEDIUM);\n const isControlled = expandedProp !== undefined && onToggle !== undefined;\n const [internalExpanded, setInternalExpanded] = useState(true);\n const resolvedExpanded = isDesktop ? true : isControlled ? expandedProp : internalExpanded;\n const handleToggle = isControlled\n ? onToggle\n : () => setInternalExpanded((previousExpanded) => !previousExpanded);\n const hasActions = action ?? actionSecondary;\n const mediaId = useId();\n const titleId = useId();\n const descId = useId();\n\n const ariaLabelledByIds = [\n media['aria-hidden'] ? undefined : mediaId,\n !title ? undefined : titleId,\n ]\n .filter(Boolean)\n .join(' ');\n\n const bannerSurface = (\n <Container\n ref={containerRef}\n size=\"fluid\"\n as={PrimitivePrompt as ElementType}\n id={id}\n sentiment={sentiment}\n emphasis={sentiment === 'neutral' ? 'base' : 'elevated'}\n data-testid={testId}\n className={clsx(\n 'wds-critical-banner',\n 'wds-critical-banner-overhang',\n {\n 'wds-critical-banner--collapsed': !resolvedExpanded,\n 'wds-critical-banner--with-two-actions': !!actionSecondary,\n },\n className,\n )}\n media={renderPromptMedia({\n media,\n sentiment,\n mediaId,\n imgClassName: 'wds-critical-banner--media-image',\n })}\n actions={\n hasActions ? (\n <div aria-hidden={!resolvedExpanded ? true : undefined} style={{ display: 'contents' }}>\n {actionSecondary && (\n // @ts-expect-error onClick type mismatch\n <Button\n v2\n size=\"md\"\n priority=\"secondary\"\n href={actionSecondary.href}\n tabIndex={resolvedExpanded ? undefined : -1}\n onClick={actionSecondary?.onClick}\n >\n {actionSecondary.label}\n </Button>\n )}\n {action && (\n // @ts-expect-error onClick type mismatch\n <Button\n v2\n size=\"md\"\n priority=\"primary\"\n href={action.href}\n tabIndex={resolvedExpanded ? undefined : -1}\n onClick={action.onClick}\n >\n {action.label}\n </Button>\n )}\n </div>\n ) : undefined\n }\n role=\"region\"\n aria-labelledby={ariaLabelledByIds || undefined}\n aria-describedby={description ? descId : undefined}\n >\n <div className=\"wds-critical-banner__text-wrapper\">\n {title && (\n <Body\n id={titleId}\n type={Typography.BODY_LARGE_BOLD}\n className=\"wds-critical-banner__content wds-critical-banner__title\"\n >\n {title}\n </Body>\n )}\n {description && (\n <Body\n id={descId}\n className={clsx('wds-critical-banner__content', 'wds-critical-banner__description', {\n 'wds-critical-banner__description--with-title': !!title,\n })}\n >\n {description}\n </Body>\n )}\n </div>\n <ExpanderToggle\n expanded={resolvedExpanded}\n size={24}\n className=\"wds-critical-banner__toggle\"\n onToggle={handleToggle}\n />\n </Container>\n );\n\n return (\n <LiveRegion\n aria-live=\"assertive\"\n announceOnChange={buildAnnouncementString({\n title,\n description,\n expanded: resolvedExpanded,\n actionLabel: action?.label,\n actionSecondaryLabel: actionSecondary?.label,\n })}\n >\n <div className=\"wds-critical-banner-overhang-query\">\n <div className=\"wds-critical-banner__entry-mask\">\n <div className=\"wds-critical-banner__entry-track\">{bannerSurface}</div>\n </div>\n </div>\n </LiveRegion>\n );\n};\n\nexport default CriticalBanner;\n"],"names":["CriticalBanner","sentiment","title","description","media","action","actionSecondary","expanded","expandedProp","onToggle","id","className","testId","containerRef","isDesktop","useContainerSize","Breakpoint","MEDIUM","isControlled","undefined","internalExpanded","setInternalExpanded","useState","resolvedExpanded","handleToggle","previousExpanded","hasActions","mediaId","useId","titleId","descId","ariaLabelledByIds","filter","Boolean","join","bannerSurface","_jsxs","Container","ref","size","as","PrimitivePrompt","emphasis","clsx","renderPromptMedia","imgClassName","actions","style","display","children","_jsx","Button","v2","priority","href","tabIndex","onClick","label","role","Body","type","Typography","BODY_LARGE_BOLD","ExpanderToggle","LiveRegion","announceOnChange","buildAnnouncementString","actionLabel","actionSecondaryLabel"],"mappings":"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"}
1
+ {"version":3,"file":"CriticalBanner.js","sources":["../../../src/prompt/CriticalBanner/CriticalBanner.tsx"],"sourcesContent":["import { ElementType, ReactNode, useId, useState } from 'react';\nimport { clsx } from 'clsx';\n\nimport Body from '../../body';\nimport Button from '../../button';\nimport Container from '../../container';\nimport { Breakpoint, LiveRegion, Typography } from '../../common';\nimport { ButtonProps } from '../../button/Button.types';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nimport { renderPromptMedia, PromptMedia } from '../helpers/promptMedia';\nimport { ExpanderToggle } from '../common/Expander/Expander';\nimport { buildAnnouncementString } from './helpers';\nimport { useContainerSize } from '../../common/hooks/useContainerSize';\n\nexport type CriticalBannerProps = {\n title?: ReactNode;\n description: ReactNode;\n media?: PromptMedia;\n action?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {\n label: ButtonProps['children'];\n };\n actionSecondary?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {\n label: ButtonProps['children'];\n };\n sentiment?: Exclude<PrimitivePromptProps['sentiment'], 'proposition'>;\n /**\n * Controls whether the description and actions are visible, as a controlled component.\n * When collapsed with a title, only the title is shown.\n * When collapsed without a title, the description is trimmed to 2 lines.\n *\n * Note: On desktop (container width >= 768px), the banner is always expanded\n * regardless of this prop value.\n */\n expanded?: boolean;\n /**\n * Called when the user clicks the chevron toggle.\n * If not provided, the component will manage expanded state internally.\n */\n onToggle?: () => void;\n} & Pick<PrimitivePromptProps, 'id' | 'className' | 'data-testid'>;\n\n/**\n * A full-width, non-dismissible banner for critical messages such as account blocks or\n * time-sensitive actions that require immediate user attention.\n\n * @see {@link https://docs.wise.design/components/critical-banner Design Spec}\n */\nexport const CriticalBanner = ({\n sentiment = 'negative',\n title,\n description,\n media = {},\n action,\n actionSecondary,\n expanded: expandedProp,\n onToggle,\n id,\n className,\n 'data-testid': testId,\n}: CriticalBannerProps) => {\n const [containerRef, isDesktop] = useContainerSize(Breakpoint.MEDIUM);\n const isControlled = expandedProp !== undefined && onToggle !== undefined;\n const [internalExpanded, setInternalExpanded] = useState(true);\n const resolvedExpanded = isDesktop ? true : isControlled ? expandedProp : internalExpanded;\n const handleToggle = isControlled\n ? onToggle\n : () => setInternalExpanded((previousExpanded) => !previousExpanded);\n const hasActions = action ?? actionSecondary;\n const mediaId = useId();\n const titleId = useId();\n const descId = useId();\n\n const ariaLabelledByIds = [\n media['aria-hidden'] ? undefined : mediaId,\n !title ? undefined : titleId,\n ]\n .filter(Boolean)\n .join(' ');\n\n const bannerSurface = (\n <Container\n ref={containerRef}\n size=\"fluid\"\n as={PrimitivePrompt as ElementType}\n id={id}\n sentiment={sentiment}\n emphasis={sentiment === 'neutral' ? 'base' : 'elevated'}\n data-testid={testId}\n className={clsx(\n 'wds-critical-banner',\n 'wds-critical-banner-overhang',\n {\n 'wds-critical-banner--collapsed': !resolvedExpanded,\n 'wds-critical-banner--with-two-actions': !!actionSecondary,\n },\n className,\n )}\n media={renderPromptMedia({\n media,\n sentiment,\n mediaId,\n imgClassName: 'wds-critical-banner--media-image',\n })}\n actions={\n hasActions ? (\n <div aria-hidden={!resolvedExpanded ? true : undefined} style={{ display: 'contents' }}>\n {actionSecondary && (\n // @ts-expect-error onClick type mismatch\n <Button\n v2\n size=\"md\"\n priority=\"secondary\"\n href={actionSecondary.href}\n tabIndex={resolvedExpanded ? undefined : -1}\n onClick={actionSecondary?.onClick}\n >\n {actionSecondary.label}\n </Button>\n )}\n {action && (\n // @ts-expect-error onClick type mismatch\n <Button\n v2\n size=\"md\"\n priority=\"primary\"\n href={action.href}\n tabIndex={resolvedExpanded ? undefined : -1}\n onClick={action.onClick}\n >\n {action.label}\n </Button>\n )}\n </div>\n ) : undefined\n }\n role=\"region\"\n aria-labelledby={ariaLabelledByIds || undefined}\n aria-describedby={description ? descId : undefined}\n >\n <div className=\"wds-critical-banner__text-wrapper\">\n {title && (\n <Body\n id={titleId}\n type={Typography.BODY_LARGE_BOLD}\n className=\"wds-critical-banner__content wds-critical-banner__title\"\n >\n {title}\n </Body>\n )}\n {description && (\n <Body\n id={descId}\n className={clsx('wds-critical-banner__content', 'wds-critical-banner__description', {\n 'wds-critical-banner__description--with-title': !!title,\n })}\n >\n {description}\n </Body>\n )}\n </div>\n <ExpanderToggle\n expanded={resolvedExpanded}\n size={24}\n className=\"wds-critical-banner__toggle\"\n onToggle={handleToggle}\n />\n </Container>\n );\n\n return (\n <LiveRegion\n aria-live=\"assertive\"\n announceOnChange={buildAnnouncementString({\n title,\n description,\n expanded: resolvedExpanded,\n actionLabel: action?.label,\n actionSecondaryLabel: actionSecondary?.label,\n })}\n >\n <div className=\"wds-critical-banner-overhang-query\">{bannerSurface}</div>\n </LiveRegion>\n );\n};\n\nexport default CriticalBanner;\n"],"names":["CriticalBanner","sentiment","title","description","media","action","actionSecondary","expanded","expandedProp","onToggle","id","className","testId","containerRef","isDesktop","useContainerSize","Breakpoint","MEDIUM","isControlled","undefined","internalExpanded","setInternalExpanded","useState","resolvedExpanded","handleToggle","previousExpanded","hasActions","mediaId","useId","titleId","descId","ariaLabelledByIds","filter","Boolean","join","bannerSurface","_jsxs","Container","ref","size","as","PrimitivePrompt","emphasis","clsx","renderPromptMedia","imgClassName","actions","style","display","children","_jsx","Button","v2","priority","href","tabIndex","onClick","label","role","Body","type","Typography","BODY_LARGE_BOLD","ExpanderToggle","LiveRegion","announceOnChange","buildAnnouncementString","actionLabel","actionSecondaryLabel"],"mappings":"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"}
@@ -139,13 +139,7 @@ const CriticalBanner = ({
139
139
  }),
140
140
  children: /*#__PURE__*/jsx("div", {
141
141
  className: "wds-critical-banner-overhang-query",
142
- children: /*#__PURE__*/jsx("div", {
143
- className: "wds-critical-banner__entry-mask",
144
- children: /*#__PURE__*/jsx("div", {
145
- className: "wds-critical-banner__entry-track",
146
- children: bannerSurface
147
- })
148
- })
142
+ children: bannerSurface
149
143
  })
150
144
  });
151
145
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CriticalBanner.mjs","sources":["../../../src/prompt/CriticalBanner/CriticalBanner.tsx"],"sourcesContent":["import { ElementType, ReactNode, useId, useState } from 'react';\nimport { clsx } from 'clsx';\n\nimport Body from '../../body';\nimport Button from '../../button';\nimport Container from '../../container';\nimport { Breakpoint, LiveRegion, Typography } from '../../common';\nimport { ButtonProps } from '../../button/Button.types';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nimport { renderPromptMedia, PromptMedia } from '../helpers/promptMedia';\nimport { ExpanderToggle } from '../common/Expander/Expander';\nimport { buildAnnouncementString } from './helpers';\nimport { useContainerSize } from '../../common/hooks/useContainerSize';\n\nexport type CriticalBannerProps = {\n title?: ReactNode;\n description: ReactNode;\n media?: PromptMedia;\n action?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {\n label: ButtonProps['children'];\n };\n actionSecondary?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {\n label: ButtonProps['children'];\n };\n sentiment?: Exclude<PrimitivePromptProps['sentiment'], 'proposition'>;\n /**\n * Controls whether the description and actions are visible, as a controlled component.\n * When collapsed with a title, only the title is shown.\n * When collapsed without a title, the description is trimmed to 2 lines.\n *\n * Note: On desktop (container width >= 768px), the banner is always expanded\n * regardless of this prop value.\n */\n expanded?: boolean;\n /**\n * Called when the user clicks the chevron toggle.\n * If not provided, the component will manage expanded state internally.\n */\n onToggle?: () => void;\n} & Pick<PrimitivePromptProps, 'id' | 'className' | 'data-testid'>;\n\n/**\n * A full-width, non-dismissible banner for critical messages such as account blocks or\n * time-sensitive actions that require immediate user attention.\n\n * @see {@link https://docs.wise.design/components/critical-banner Design Spec}\n */\nexport const CriticalBanner = ({\n sentiment = 'negative',\n title,\n description,\n media = {},\n action,\n actionSecondary,\n expanded: expandedProp,\n onToggle,\n id,\n className,\n 'data-testid': testId,\n}: CriticalBannerProps) => {\n const [containerRef, isDesktop] = useContainerSize(Breakpoint.MEDIUM);\n const isControlled = expandedProp !== undefined && onToggle !== undefined;\n const [internalExpanded, setInternalExpanded] = useState(true);\n const resolvedExpanded = isDesktop ? true : isControlled ? expandedProp : internalExpanded;\n const handleToggle = isControlled\n ? onToggle\n : () => setInternalExpanded((previousExpanded) => !previousExpanded);\n const hasActions = action ?? actionSecondary;\n const mediaId = useId();\n const titleId = useId();\n const descId = useId();\n\n const ariaLabelledByIds = [\n media['aria-hidden'] ? undefined : mediaId,\n !title ? undefined : titleId,\n ]\n .filter(Boolean)\n .join(' ');\n\n const bannerSurface = (\n <Container\n ref={containerRef}\n size=\"fluid\"\n as={PrimitivePrompt as ElementType}\n id={id}\n sentiment={sentiment}\n emphasis={sentiment === 'neutral' ? 'base' : 'elevated'}\n data-testid={testId}\n className={clsx(\n 'wds-critical-banner',\n 'wds-critical-banner-overhang',\n {\n 'wds-critical-banner--collapsed': !resolvedExpanded,\n 'wds-critical-banner--with-two-actions': !!actionSecondary,\n },\n className,\n )}\n media={renderPromptMedia({\n media,\n sentiment,\n mediaId,\n imgClassName: 'wds-critical-banner--media-image',\n })}\n actions={\n hasActions ? (\n <div aria-hidden={!resolvedExpanded ? true : undefined} style={{ display: 'contents' }}>\n {actionSecondary && (\n // @ts-expect-error onClick type mismatch\n <Button\n v2\n size=\"md\"\n priority=\"secondary\"\n href={actionSecondary.href}\n tabIndex={resolvedExpanded ? undefined : -1}\n onClick={actionSecondary?.onClick}\n >\n {actionSecondary.label}\n </Button>\n )}\n {action && (\n // @ts-expect-error onClick type mismatch\n <Button\n v2\n size=\"md\"\n priority=\"primary\"\n href={action.href}\n tabIndex={resolvedExpanded ? undefined : -1}\n onClick={action.onClick}\n >\n {action.label}\n </Button>\n )}\n </div>\n ) : undefined\n }\n role=\"region\"\n aria-labelledby={ariaLabelledByIds || undefined}\n aria-describedby={description ? descId : undefined}\n >\n <div className=\"wds-critical-banner__text-wrapper\">\n {title && (\n <Body\n id={titleId}\n type={Typography.BODY_LARGE_BOLD}\n className=\"wds-critical-banner__content wds-critical-banner__title\"\n >\n {title}\n </Body>\n )}\n {description && (\n <Body\n id={descId}\n className={clsx('wds-critical-banner__content', 'wds-critical-banner__description', {\n 'wds-critical-banner__description--with-title': !!title,\n })}\n >\n {description}\n </Body>\n )}\n </div>\n <ExpanderToggle\n expanded={resolvedExpanded}\n size={24}\n className=\"wds-critical-banner__toggle\"\n onToggle={handleToggle}\n />\n </Container>\n );\n\n return (\n <LiveRegion\n aria-live=\"assertive\"\n announceOnChange={buildAnnouncementString({\n title,\n description,\n expanded: resolvedExpanded,\n actionLabel: action?.label,\n actionSecondaryLabel: actionSecondary?.label,\n })}\n >\n <div className=\"wds-critical-banner-overhang-query\">\n <div className=\"wds-critical-banner__entry-mask\">\n <div className=\"wds-critical-banner__entry-track\">{bannerSurface}</div>\n </div>\n </div>\n </LiveRegion>\n );\n};\n\nexport default CriticalBanner;\n"],"names":["CriticalBanner","sentiment","title","description","media","action","actionSecondary","expanded","expandedProp","onToggle","id","className","testId","containerRef","isDesktop","useContainerSize","Breakpoint","MEDIUM","isControlled","undefined","internalExpanded","setInternalExpanded","useState","resolvedExpanded","handleToggle","previousExpanded","hasActions","mediaId","useId","titleId","descId","ariaLabelledByIds","filter","Boolean","join","bannerSurface","_jsxs","Container","ref","size","as","PrimitivePrompt","emphasis","clsx","renderPromptMedia","imgClassName","actions","style","display","children","_jsx","Button","v2","priority","href","tabIndex","onClick","label","role","Body","type","Typography","BODY_LARGE_BOLD","ExpanderToggle","LiveRegion","announceOnChange","buildAnnouncementString","actionLabel","actionSecondaryLabel"],"mappings":"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"}
1
+ {"version":3,"file":"CriticalBanner.mjs","sources":["../../../src/prompt/CriticalBanner/CriticalBanner.tsx"],"sourcesContent":["import { ElementType, ReactNode, useId, useState } from 'react';\nimport { clsx } from 'clsx';\n\nimport Body from '../../body';\nimport Button from '../../button';\nimport Container from '../../container';\nimport { Breakpoint, LiveRegion, Typography } from '../../common';\nimport { ButtonProps } from '../../button/Button.types';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nimport { renderPromptMedia, PromptMedia } from '../helpers/promptMedia';\nimport { ExpanderToggle } from '../common/Expander/Expander';\nimport { buildAnnouncementString } from './helpers';\nimport { useContainerSize } from '../../common/hooks/useContainerSize';\n\nexport type CriticalBannerProps = {\n title?: ReactNode;\n description: ReactNode;\n media?: PromptMedia;\n action?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {\n label: ButtonProps['children'];\n };\n actionSecondary?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {\n label: ButtonProps['children'];\n };\n sentiment?: Exclude<PrimitivePromptProps['sentiment'], 'proposition'>;\n /**\n * Controls whether the description and actions are visible, as a controlled component.\n * When collapsed with a title, only the title is shown.\n * When collapsed without a title, the description is trimmed to 2 lines.\n *\n * Note: On desktop (container width >= 768px), the banner is always expanded\n * regardless of this prop value.\n */\n expanded?: boolean;\n /**\n * Called when the user clicks the chevron toggle.\n * If not provided, the component will manage expanded state internally.\n */\n onToggle?: () => void;\n} & Pick<PrimitivePromptProps, 'id' | 'className' | 'data-testid'>;\n\n/**\n * A full-width, non-dismissible banner for critical messages such as account blocks or\n * time-sensitive actions that require immediate user attention.\n\n * @see {@link https://docs.wise.design/components/critical-banner Design Spec}\n */\nexport const CriticalBanner = ({\n sentiment = 'negative',\n title,\n description,\n media = {},\n action,\n actionSecondary,\n expanded: expandedProp,\n onToggle,\n id,\n className,\n 'data-testid': testId,\n}: CriticalBannerProps) => {\n const [containerRef, isDesktop] = useContainerSize(Breakpoint.MEDIUM);\n const isControlled = expandedProp !== undefined && onToggle !== undefined;\n const [internalExpanded, setInternalExpanded] = useState(true);\n const resolvedExpanded = isDesktop ? true : isControlled ? expandedProp : internalExpanded;\n const handleToggle = isControlled\n ? onToggle\n : () => setInternalExpanded((previousExpanded) => !previousExpanded);\n const hasActions = action ?? actionSecondary;\n const mediaId = useId();\n const titleId = useId();\n const descId = useId();\n\n const ariaLabelledByIds = [\n media['aria-hidden'] ? undefined : mediaId,\n !title ? undefined : titleId,\n ]\n .filter(Boolean)\n .join(' ');\n\n const bannerSurface = (\n <Container\n ref={containerRef}\n size=\"fluid\"\n as={PrimitivePrompt as ElementType}\n id={id}\n sentiment={sentiment}\n emphasis={sentiment === 'neutral' ? 'base' : 'elevated'}\n data-testid={testId}\n className={clsx(\n 'wds-critical-banner',\n 'wds-critical-banner-overhang',\n {\n 'wds-critical-banner--collapsed': !resolvedExpanded,\n 'wds-critical-banner--with-two-actions': !!actionSecondary,\n },\n className,\n )}\n media={renderPromptMedia({\n media,\n sentiment,\n mediaId,\n imgClassName: 'wds-critical-banner--media-image',\n })}\n actions={\n hasActions ? (\n <div aria-hidden={!resolvedExpanded ? true : undefined} style={{ display: 'contents' }}>\n {actionSecondary && (\n // @ts-expect-error onClick type mismatch\n <Button\n v2\n size=\"md\"\n priority=\"secondary\"\n href={actionSecondary.href}\n tabIndex={resolvedExpanded ? undefined : -1}\n onClick={actionSecondary?.onClick}\n >\n {actionSecondary.label}\n </Button>\n )}\n {action && (\n // @ts-expect-error onClick type mismatch\n <Button\n v2\n size=\"md\"\n priority=\"primary\"\n href={action.href}\n tabIndex={resolvedExpanded ? undefined : -1}\n onClick={action.onClick}\n >\n {action.label}\n </Button>\n )}\n </div>\n ) : undefined\n }\n role=\"region\"\n aria-labelledby={ariaLabelledByIds || undefined}\n aria-describedby={description ? descId : undefined}\n >\n <div className=\"wds-critical-banner__text-wrapper\">\n {title && (\n <Body\n id={titleId}\n type={Typography.BODY_LARGE_BOLD}\n className=\"wds-critical-banner__content wds-critical-banner__title\"\n >\n {title}\n </Body>\n )}\n {description && (\n <Body\n id={descId}\n className={clsx('wds-critical-banner__content', 'wds-critical-banner__description', {\n 'wds-critical-banner__description--with-title': !!title,\n })}\n >\n {description}\n </Body>\n )}\n </div>\n <ExpanderToggle\n expanded={resolvedExpanded}\n size={24}\n className=\"wds-critical-banner__toggle\"\n onToggle={handleToggle}\n />\n </Container>\n );\n\n return (\n <LiveRegion\n aria-live=\"assertive\"\n announceOnChange={buildAnnouncementString({\n title,\n description,\n expanded: resolvedExpanded,\n actionLabel: action?.label,\n actionSecondaryLabel: actionSecondary?.label,\n })}\n >\n <div className=\"wds-critical-banner-overhang-query\">{bannerSurface}</div>\n </LiveRegion>\n );\n};\n\nexport default CriticalBanner;\n"],"names":["CriticalBanner","sentiment","title","description","media","action","actionSecondary","expanded","expandedProp","onToggle","id","className","testId","containerRef","isDesktop","useContainerSize","Breakpoint","MEDIUM","isControlled","undefined","internalExpanded","setInternalExpanded","useState","resolvedExpanded","handleToggle","previousExpanded","hasActions","mediaId","useId","titleId","descId","ariaLabelledByIds","filter","Boolean","join","bannerSurface","_jsxs","Container","ref","size","as","PrimitivePrompt","emphasis","clsx","renderPromptMedia","imgClassName","actions","style","display","children","_jsx","Button","v2","priority","href","tabIndex","onClick","label","role","Body","type","Typography","BODY_LARGE_BOLD","ExpanderToggle","LiveRegion","announceOnChange","buildAnnouncementString","actionLabel","actionSecondaryLabel"],"mappings":"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"}
@@ -25,6 +25,7 @@
25
25
  background-color: var(--color-interactive-accent);
26
26
  }
27
27
  .np-avatar-view .np-avatar-view-content {
28
+ --circle-border-color: var(--color-sentiment-border-overlay, var(--color-border-neutral));
28
29
  color: #37517e;
29
30
  color: var(--color-sentiment-content-primary, var(--color-content-primary));
30
31
  }
@@ -26549,6 +26549,7 @@ a[data-toggle="tooltip"] {
26549
26549
  }
26550
26550
 
26551
26551
  .np-avatar-view .np-avatar-view-content {
26552
+ --circle-border-color: var(--color-sentiment-border-overlay, var(--color-border-neutral));
26552
26553
  color: #37517e;
26553
26554
  color: var(--color-sentiment-content-primary, var(--color-content-primary));
26554
26555
  }
@@ -31955,6 +31956,9 @@ html:not([dir="rtl"]) .np-navigation-option {
31955
31956
  --Prompt-actions-gap: var(--size-8);
31956
31957
  --Prompt-gap: var(--size-10) var(--size-16);
31957
31958
  --Prompt-border-radius: 0;
31959
+ --critical-banner-background-base: transparent;
31960
+ --critical-banner-background-surface: var(--color-sentiment-background-surface);
31961
+ --critical-banner-background: linear-gradient(var(--critical-banner-background-surface), var(--critical-banner-background-surface)), var(--critical-banner-background-base);
31958
31962
  container-type: inline-size;
31959
31963
  position: relative;
31960
31964
  --critical-banner-easing: cubic-bezier(0.9, 0, 0.7, 1);
@@ -31963,6 +31967,11 @@ html:not([dir="rtl"]) .np-navigation-option {
31963
31967
  actions only go full-width below mobile-max token (container query) */
31964
31968
  }
31965
31969
 
31970
+ .wds-critical-banner.wds-prompt--neutral {
31971
+ --critical-banner-background-base: var(--color-background-elevated);
31972
+ background: var(--critical-banner-background);
31973
+ }
31974
+
31966
31975
  .wds-critical-banner--media-image {
31967
31976
  width: 48px;
31968
31977
  width: var(--size-48);
@@ -32028,19 +32037,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32028
32037
  min-width: 0;
32029
32038
  max-width: 480px;
32030
32039
  height: 100%;
32031
- padding-top: 3px;
32032
- }
32033
-
32034
- @media (max-width: 320px) {
32035
- .wds-critical-banner__text-wrapper {
32036
- padding-top: 0;
32037
- }
32038
- }
32039
-
32040
- @container (width < 320px) {
32041
- .wds-critical-banner__text-wrapper {
32042
- padding-top: 0;
32043
- }
32044
32040
  }
32045
32041
 
32046
32042
  .wds-critical-banner--collapsed .wds-critical-banner__title,
@@ -32103,21 +32099,22 @@ html:not([dir="rtl"]) .np-navigation-option {
32103
32099
  inline-size: 100%;
32104
32100
  }
32105
32101
 
32106
- .wds-critical-banner__entry-mask {
32107
- display: grid;
32108
- grid-template-rows: 0fr;
32109
- overflow: hidden;
32110
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
32111
- }
32112
-
32113
32102
  @container critical-banner-overhang (max-width: 600px) {
32114
- .wds-critical-banner__entry-mask {
32103
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
32115
32104
  --critical-banner-mobile-overhang-size: 32px;
32116
- }
32117
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang {
32105
+ --critical-banner-overhang-mask: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), #000 var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size)
32106
+ var(--critical-banner-mobile-overhang-size) no-repeat,
32107
+ radial-gradient(
32108
+ circle at 0% 100%,
32109
+ transparent var(--critical-banner-mobile-overhang-size),
32110
+ #000 var(--critical-banner-mobile-overhang-size)
32111
+ )
32112
+ 100% 0 / var(--critical-banner-mobile-overhang-size)
32113
+ var(--critical-banner-mobile-overhang-size) no-repeat;
32114
+ margin-bottom: 32px;
32118
32115
  margin-bottom: var(--critical-banner-mobile-overhang-size);
32119
32116
  }
32120
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang::after {
32117
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
32121
32118
  content: "";
32122
32119
  position: absolute;
32123
32120
  right: 0;
@@ -32125,22 +32122,9 @@ html:not([dir="rtl"]) .np-navigation-option {
32125
32122
  left: 0;
32126
32123
  height: var(--critical-banner-mobile-overhang-size);
32127
32124
  pointer-events: none;
32128
- background: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat, radial-gradient(circle at 0% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 100% 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat;
32129
- }
32130
- }
32131
-
32132
- .wds-critical-banner__entry-track {
32133
- min-height: 0;
32134
- }
32135
-
32136
- @keyframes wds-critical-banner-reveal-height {
32137
- from {
32138
- grid-template-rows: 0fr;
32139
- overflow: hidden;
32140
- }
32141
- to {
32142
- grid-template-rows: 1fr;
32143
- overflow: visible;
32125
+ background: var(--critical-banner-background);
32126
+ -webkit-mask: var(--critical-banner-overhang-mask);
32127
+ mask: var(--critical-banner-overhang-mask);
32144
32128
  }
32145
32129
  }
32146
32130
 
@@ -32151,11 +32135,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32151
32135
  .wds-critical-banner__toggle {
32152
32136
  transition: none !important;
32153
32137
  }
32154
- .wds-critical-banner__entry-mask {
32155
- animation: none;
32156
- grid-template-rows: 1fr;
32157
- overflow: visible;
32158
- }
32159
32138
  }
32160
32139
 
32161
32140
  .wds-expander-toggle {
@@ -4,6 +4,9 @@
4
4
  --Prompt-actions-gap: var(--size-8);
5
5
  --Prompt-gap: var(--size-10) var(--size-16);
6
6
  --Prompt-border-radius: 0;
7
+ --critical-banner-background-base: transparent;
8
+ --critical-banner-background-surface: var(--color-sentiment-background-surface);
9
+ --critical-banner-background: linear-gradient(var(--critical-banner-background-surface), var(--critical-banner-background-surface)), var(--critical-banner-background-base);
7
10
  container-type: inline-size;
8
11
  position: relative;
9
12
  --critical-banner-easing: cubic-bezier(0.9, 0, 0.7, 1);
@@ -11,6 +14,10 @@
11
14
  /* Override PrimitivePrompt's --screen-sm-max actions behaviour:
12
15
  actions only go full-width below mobile-max token (container query) */
13
16
  }
17
+ .wds-critical-banner.wds-prompt--neutral {
18
+ --critical-banner-background-base: var(--color-background-elevated);
19
+ background: var(--critical-banner-background);
20
+ }
14
21
  .wds-critical-banner--media-image {
15
22
  width: 48px;
16
23
  width: var(--size-48);
@@ -68,17 +75,6 @@
68
75
  min-width: 0;
69
76
  max-width: 480px;
70
77
  height: 100%;
71
- padding-top: 3px;
72
- }
73
- @media (max-width: 320px) {
74
- .wds-critical-banner__text-wrapper {
75
- padding-top: 0;
76
- }
77
- }
78
- @container (width < 320px) {
79
- .wds-critical-banner__text-wrapper {
80
- padding-top: 0;
81
- }
82
78
  }
83
79
  .wds-critical-banner--collapsed .wds-critical-banner__title,
84
80
  .wds-critical-banner--collapsed .wds-critical-banner__description {
@@ -131,20 +127,22 @@
131
127
  container-type: inline-size;
132
128
  inline-size: 100%;
133
129
  }
134
- .wds-critical-banner__entry-mask {
135
- display: grid;
136
- grid-template-rows: 0fr;
137
- overflow: hidden;
138
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
139
- }
140
130
  @container critical-banner-overhang (max-width: 600px) {
141
- .wds-critical-banner__entry-mask {
131
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
142
132
  --critical-banner-mobile-overhang-size: 32px;
143
- }
144
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang {
133
+ --critical-banner-overhang-mask: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), #000 var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size)
134
+ var(--critical-banner-mobile-overhang-size) no-repeat,
135
+ radial-gradient(
136
+ circle at 0% 100%,
137
+ transparent var(--critical-banner-mobile-overhang-size),
138
+ #000 var(--critical-banner-mobile-overhang-size)
139
+ )
140
+ 100% 0 / var(--critical-banner-mobile-overhang-size)
141
+ var(--critical-banner-mobile-overhang-size) no-repeat;
142
+ margin-bottom: 32px;
145
143
  margin-bottom: var(--critical-banner-mobile-overhang-size);
146
144
  }
147
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang::after {
145
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
148
146
  content: "";
149
147
  position: absolute;
150
148
  right: 0;
@@ -152,20 +150,9 @@
152
150
  left: 0;
153
151
  height: var(--critical-banner-mobile-overhang-size);
154
152
  pointer-events: none;
155
- background: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat, radial-gradient(circle at 0% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 100% 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat;
156
- }
157
- }
158
- .wds-critical-banner__entry-track {
159
- min-height: 0;
160
- }
161
- @keyframes wds-critical-banner-reveal-height {
162
- from {
163
- grid-template-rows: 0fr;
164
- overflow: hidden;
165
- }
166
- to {
167
- grid-template-rows: 1fr;
168
- overflow: visible;
153
+ background: var(--critical-banner-background);
154
+ -webkit-mask: var(--critical-banner-overhang-mask);
155
+ mask: var(--critical-banner-overhang-mask);
169
156
  }
170
157
  }
171
158
  @media (prefers-reduced-motion: reduce) {
@@ -175,9 +162,4 @@
175
162
  .wds-critical-banner__toggle {
176
163
  transition: none !important;
177
164
  }
178
- .wds-critical-banner__entry-mask {
179
- animation: none;
180
- grid-template-rows: 1fr;
181
- overflow: visible;
182
- }
183
165
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CriticalBanner.d.ts","sourceRoot":"","sources":["../../../../src/prompt/CriticalBanner/CriticalBanner.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,SAAS,EAAmB,MAAM,OAAO,CAAC;AAOhE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAmB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EAAqB,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAKxE,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC,GAAG;QAC1D,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;KAChC,CAAC;IACF,eAAe,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC,GAAG;QACnE,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;KAChC,CAAC;IACF,SAAS,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC,CAAC;IACtE;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,GAAG,IAAI,CAAC,oBAAoB,EAAE,IAAI,GAAG,WAAW,GAAG,aAAa,CAAC,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,4IAY5B,mBAAmB,gCAgIrB,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"CriticalBanner.d.ts","sourceRoot":"","sources":["../../../../src/prompt/CriticalBanner/CriticalBanner.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,SAAS,EAAmB,MAAM,OAAO,CAAC;AAOhE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAmB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EAAqB,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAKxE,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC,GAAG;QAC1D,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;KAChC,CAAC;IACF,eAAe,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC,GAAG;QACnE,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;KAChC,CAAC;IACF,SAAS,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC,CAAC;IACtE;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,GAAG,IAAI,CAAC,oBAAoB,EAAE,IAAI,GAAG,WAAW,GAAG,aAAa,CAAC,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,4IAY5B,mBAAmB,gCA4HrB,CAAC;AAEF,eAAe,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/components",
3
- "version": "46.149.0",
3
+ "version": "46.149.2",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -25,6 +25,7 @@
25
25
  background-color: var(--color-interactive-accent);
26
26
  }
27
27
  .np-avatar-view .np-avatar-view-content {
28
+ --circle-border-color: var(--color-sentiment-border-overlay, var(--color-border-neutral));
28
29
  color: #37517e;
29
30
  color: var(--color-sentiment-content-primary, var(--color-content-primary));
30
31
  }
@@ -1,7 +1,9 @@
1
- @import './Dot.less';
1
+ @import "./Dot.less";
2
2
 
3
3
  .np-avatar-view {
4
4
  .np-avatar-view-content {
5
+ --circle-border-color: var(--color-sentiment-border-overlay, var(--color-border-neutral));
6
+
5
7
  color: var(--color-sentiment-content-primary, var(--color-content-primary));
6
8
  }
7
9
 
package/src/main.css CHANGED
@@ -26549,6 +26549,7 @@ a[data-toggle="tooltip"] {
26549
26549
  }
26550
26550
 
26551
26551
  .np-avatar-view .np-avatar-view-content {
26552
+ --circle-border-color: var(--color-sentiment-border-overlay, var(--color-border-neutral));
26552
26553
  color: #37517e;
26553
26554
  color: var(--color-sentiment-content-primary, var(--color-content-primary));
26554
26555
  }
@@ -31955,6 +31956,9 @@ html:not([dir="rtl"]) .np-navigation-option {
31955
31956
  --Prompt-actions-gap: var(--size-8);
31956
31957
  --Prompt-gap: var(--size-10) var(--size-16);
31957
31958
  --Prompt-border-radius: 0;
31959
+ --critical-banner-background-base: transparent;
31960
+ --critical-banner-background-surface: var(--color-sentiment-background-surface);
31961
+ --critical-banner-background: linear-gradient(var(--critical-banner-background-surface), var(--critical-banner-background-surface)), var(--critical-banner-background-base);
31958
31962
  container-type: inline-size;
31959
31963
  position: relative;
31960
31964
  --critical-banner-easing: cubic-bezier(0.9, 0, 0.7, 1);
@@ -31963,6 +31967,11 @@ html:not([dir="rtl"]) .np-navigation-option {
31963
31967
  actions only go full-width below mobile-max token (container query) */
31964
31968
  }
31965
31969
 
31970
+ .wds-critical-banner.wds-prompt--neutral {
31971
+ --critical-banner-background-base: var(--color-background-elevated);
31972
+ background: var(--critical-banner-background);
31973
+ }
31974
+
31966
31975
  .wds-critical-banner--media-image {
31967
31976
  width: 48px;
31968
31977
  width: var(--size-48);
@@ -32028,19 +32037,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32028
32037
  min-width: 0;
32029
32038
  max-width: 480px;
32030
32039
  height: 100%;
32031
- padding-top: 3px;
32032
- }
32033
-
32034
- @media (max-width: 320px) {
32035
- .wds-critical-banner__text-wrapper {
32036
- padding-top: 0;
32037
- }
32038
- }
32039
-
32040
- @container (width < 320px) {
32041
- .wds-critical-banner__text-wrapper {
32042
- padding-top: 0;
32043
- }
32044
32040
  }
32045
32041
 
32046
32042
  .wds-critical-banner--collapsed .wds-critical-banner__title,
@@ -32103,21 +32099,22 @@ html:not([dir="rtl"]) .np-navigation-option {
32103
32099
  inline-size: 100%;
32104
32100
  }
32105
32101
 
32106
- .wds-critical-banner__entry-mask {
32107
- display: grid;
32108
- grid-template-rows: 0fr;
32109
- overflow: hidden;
32110
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
32111
- }
32112
-
32113
32102
  @container critical-banner-overhang (max-width: 600px) {
32114
- .wds-critical-banner__entry-mask {
32103
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
32115
32104
  --critical-banner-mobile-overhang-size: 32px;
32116
- }
32117
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang {
32105
+ --critical-banner-overhang-mask: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), #000 var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size)
32106
+ var(--critical-banner-mobile-overhang-size) no-repeat,
32107
+ radial-gradient(
32108
+ circle at 0% 100%,
32109
+ transparent var(--critical-banner-mobile-overhang-size),
32110
+ #000 var(--critical-banner-mobile-overhang-size)
32111
+ )
32112
+ 100% 0 / var(--critical-banner-mobile-overhang-size)
32113
+ var(--critical-banner-mobile-overhang-size) no-repeat;
32114
+ margin-bottom: 32px;
32118
32115
  margin-bottom: var(--critical-banner-mobile-overhang-size);
32119
32116
  }
32120
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang::after {
32117
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
32121
32118
  content: "";
32122
32119
  position: absolute;
32123
32120
  right: 0;
@@ -32125,22 +32122,9 @@ html:not([dir="rtl"]) .np-navigation-option {
32125
32122
  left: 0;
32126
32123
  height: var(--critical-banner-mobile-overhang-size);
32127
32124
  pointer-events: none;
32128
- background: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat, radial-gradient(circle at 0% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 100% 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat;
32129
- }
32130
- }
32131
-
32132
- .wds-critical-banner__entry-track {
32133
- min-height: 0;
32134
- }
32135
-
32136
- @keyframes wds-critical-banner-reveal-height {
32137
- from {
32138
- grid-template-rows: 0fr;
32139
- overflow: hidden;
32140
- }
32141
- to {
32142
- grid-template-rows: 1fr;
32143
- overflow: visible;
32125
+ background: var(--critical-banner-background);
32126
+ -webkit-mask: var(--critical-banner-overhang-mask);
32127
+ mask: var(--critical-banner-overhang-mask);
32144
32128
  }
32145
32129
  }
32146
32130
 
@@ -32151,11 +32135,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32151
32135
  .wds-critical-banner__toggle {
32152
32136
  transition: none !important;
32153
32137
  }
32154
- .wds-critical-banner__entry-mask {
32155
- animation: none;
32156
- grid-template-rows: 1fr;
32157
- overflow: visible;
32158
- }
32159
32138
  }
32160
32139
 
32161
32140
  .wds-expander-toggle {
@@ -66,10 +66,7 @@ Screen readers announce the banner content whenever:
66
66
 
67
67
  ## Reduced Motion
68
68
 
69
- `CriticalBanner` respects the user's reduced motion preference. When reduced motion is on, the component does not show:
70
-
71
- - the entry animation that reveals the banner from above when it first appears
72
- - the collapse and expand animation used when the user toggles the banner content
69
+ `CriticalBanner` respects the user's reduced motion preference. When reduced motion is on, the component does not show the collapse and expand animation used when the user toggles the banner content.
73
70
 
74
71
  The same content is still rendered and announced. Reduced motion only removes the visual movement.
75
72
 
@@ -4,6 +4,9 @@
4
4
  --Prompt-actions-gap: var(--size-8);
5
5
  --Prompt-gap: var(--size-10) var(--size-16);
6
6
  --Prompt-border-radius: 0;
7
+ --critical-banner-background-base: transparent;
8
+ --critical-banner-background-surface: var(--color-sentiment-background-surface);
9
+ --critical-banner-background: linear-gradient(var(--critical-banner-background-surface), var(--critical-banner-background-surface)), var(--critical-banner-background-base);
7
10
  container-type: inline-size;
8
11
  position: relative;
9
12
  --critical-banner-easing: cubic-bezier(0.9, 0, 0.7, 1);
@@ -11,6 +14,10 @@
11
14
  /* Override PrimitivePrompt's --screen-sm-max actions behaviour:
12
15
  actions only go full-width below mobile-max token (container query) */
13
16
  }
17
+ .wds-critical-banner.wds-prompt--neutral {
18
+ --critical-banner-background-base: var(--color-background-elevated);
19
+ background: var(--critical-banner-background);
20
+ }
14
21
  .wds-critical-banner--media-image {
15
22
  width: 48px;
16
23
  width: var(--size-48);
@@ -68,17 +75,6 @@
68
75
  min-width: 0;
69
76
  max-width: 480px;
70
77
  height: 100%;
71
- padding-top: 3px;
72
- }
73
- @media (max-width: 320px) {
74
- .wds-critical-banner__text-wrapper {
75
- padding-top: 0;
76
- }
77
- }
78
- @container (width < 320px) {
79
- .wds-critical-banner__text-wrapper {
80
- padding-top: 0;
81
- }
82
78
  }
83
79
  .wds-critical-banner--collapsed .wds-critical-banner__title,
84
80
  .wds-critical-banner--collapsed .wds-critical-banner__description {
@@ -131,20 +127,22 @@
131
127
  container-type: inline-size;
132
128
  inline-size: 100%;
133
129
  }
134
- .wds-critical-banner__entry-mask {
135
- display: grid;
136
- grid-template-rows: 0fr;
137
- overflow: hidden;
138
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
139
- }
140
130
  @container critical-banner-overhang (max-width: 600px) {
141
- .wds-critical-banner__entry-mask {
131
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
142
132
  --critical-banner-mobile-overhang-size: 32px;
143
- }
144
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang {
133
+ --critical-banner-overhang-mask: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), #000 var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size)
134
+ var(--critical-banner-mobile-overhang-size) no-repeat,
135
+ radial-gradient(
136
+ circle at 0% 100%,
137
+ transparent var(--critical-banner-mobile-overhang-size),
138
+ #000 var(--critical-banner-mobile-overhang-size)
139
+ )
140
+ 100% 0 / var(--critical-banner-mobile-overhang-size)
141
+ var(--critical-banner-mobile-overhang-size) no-repeat;
142
+ margin-bottom: 32px;
145
143
  margin-bottom: var(--critical-banner-mobile-overhang-size);
146
144
  }
147
- .wds-critical-banner__entry-mask .wds-critical-banner-overhang::after {
145
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
148
146
  content: "";
149
147
  position: absolute;
150
148
  right: 0;
@@ -152,20 +150,9 @@
152
150
  left: 0;
153
151
  height: var(--critical-banner-mobile-overhang-size);
154
152
  pointer-events: none;
155
- background: radial-gradient(circle at 100% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 0 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat, radial-gradient(circle at 0% 100%, transparent var(--critical-banner-mobile-overhang-size), var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)) 100% 0 / var(--critical-banner-mobile-overhang-size) var(--critical-banner-mobile-overhang-size) no-repeat;
156
- }
157
- }
158
- .wds-critical-banner__entry-track {
159
- min-height: 0;
160
- }
161
- @keyframes wds-critical-banner-reveal-height {
162
- from {
163
- grid-template-rows: 0fr;
164
- overflow: hidden;
165
- }
166
- to {
167
- grid-template-rows: 1fr;
168
- overflow: visible;
153
+ background: var(--critical-banner-background);
154
+ -webkit-mask: var(--critical-banner-overhang-mask);
155
+ mask: var(--critical-banner-overhang-mask);
169
156
  }
170
157
  }
171
158
  @media (prefers-reduced-motion: reduce) {
@@ -175,9 +162,4 @@
175
162
  .wds-critical-banner__toggle {
176
163
  transition: none !important;
177
164
  }
178
- .wds-critical-banner__entry-mask {
179
- animation: none;
180
- grid-template-rows: 1fr;
181
- overflow: visible;
182
- }
183
165
  }
@@ -7,6 +7,16 @@
7
7
  --Prompt-actions-gap: var(--size-8);
8
8
  --Prompt-gap: var(--size-10) var(--size-16);
9
9
  --Prompt-border-radius: 0;
10
+ --critical-banner-background-base: transparent;
11
+ --critical-banner-background-surface: var(--color-sentiment-background-surface);
12
+ // The sentiment surface can be translucent, so layer it over an opaque base
13
+ // for neutral banners and their mobile overhang.
14
+ --critical-banner-background:
15
+ linear-gradient(
16
+ var(--critical-banner-background-surface),
17
+ var(--critical-banner-background-surface)
18
+ ),
19
+ var(--critical-banner-background-base);
10
20
  container-type: inline-size;
11
21
  position: relative;
12
22
 
@@ -14,6 +24,11 @@
14
24
  --critical-banner-easing: cubic-bezier(0.9, 0, 0.7, 1);
15
25
  --critical-banner-duration: 150ms;
16
26
 
27
+ &.wds-prompt--neutral {
28
+ --critical-banner-background-base: var(--color-background-elevated);
29
+ background: var(--critical-banner-background);
30
+ }
31
+
17
32
  &--media-image {
18
33
  width: var(--size-48);
19
34
  height: var(--size-48);
@@ -79,16 +94,6 @@
79
94
  min-width: 0;
80
95
  max-width: 480px;
81
96
  height: 100%;
82
-
83
- // Padding prevents text shifting when collapsing/expanding layout shift
84
- padding-top: 3px;
85
-
86
- @media (--screen-400-zoom) {
87
- padding-top: 0;
88
- }
89
- @container (width < @screen-xs-min) {
90
- padding-top: 0;
91
- }
92
97
  }
93
98
 
94
99
  &--collapsed &__title,
@@ -146,25 +151,30 @@
146
151
  }
147
152
  }
148
153
 
149
- // Entry animation: after a 500ms delay, reveal the already-positioned banner
150
- // over 400ms. The mask clips only during the reveal, then becomes visible so the
151
- // overhang and actions are not clipped after the animation.
152
154
  .wds-critical-banner-overhang-query {
153
155
  container-name: critical-banner-overhang;
154
156
  container-type: inline-size;
155
157
  inline-size: 100%;
156
- }
157
-
158
- .wds-critical-banner__entry-mask {
159
- display: grid;
160
- grid-template-rows: 0fr;
161
- overflow: hidden;
162
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
163
158
 
164
159
  @container critical-banner-overhang (max-width: @wds-critical-banner-mobile-overhang-max) {
165
- --critical-banner-mobile-overhang-size: 32px;
166
-
167
160
  .wds-critical-banner-overhang {
161
+ --critical-banner-mobile-overhang-size: 32px;
162
+ --critical-banner-overhang-mask:
163
+ radial-gradient(
164
+ circle at 100% 100%,
165
+ transparent var(--critical-banner-mobile-overhang-size),
166
+ #000 var(--critical-banner-mobile-overhang-size)
167
+ )
168
+ 0 0 / var(--critical-banner-mobile-overhang-size)
169
+ var(--critical-banner-mobile-overhang-size) no-repeat,
170
+ radial-gradient(
171
+ circle at 0% 100%,
172
+ transparent var(--critical-banner-mobile-overhang-size),
173
+ #000 var(--critical-banner-mobile-overhang-size)
174
+ )
175
+ 100% 0 / var(--critical-banner-mobile-overhang-size)
176
+ var(--critical-banner-mobile-overhang-size) no-repeat;
177
+
168
178
  margin-bottom: var(--critical-banner-mobile-overhang-size);
169
179
 
170
180
  &::after {
@@ -175,42 +185,14 @@
175
185
  left: 0;
176
186
  height: var(--critical-banner-mobile-overhang-size);
177
187
  pointer-events: none;
178
- background:
179
- radial-gradient(
180
- circle at 100% 100%,
181
- transparent var(--critical-banner-mobile-overhang-size),
182
- var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)
183
- )
184
- 0 0 / var(--critical-banner-mobile-overhang-size)
185
- var(--critical-banner-mobile-overhang-size) no-repeat,
186
- radial-gradient(
187
- circle at 0% 100%,
188
- transparent var(--critical-banner-mobile-overhang-size),
189
- var(--color-sentiment-background-surface) var(--critical-banner-mobile-overhang-size)
190
- )
191
- 100% 0 / var(--critical-banner-mobile-overhang-size)
192
- var(--critical-banner-mobile-overhang-size) no-repeat;
188
+ background: var(--critical-banner-background);
189
+ -webkit-mask: var(--critical-banner-overhang-mask);
190
+ mask: var(--critical-banner-overhang-mask);
193
191
  }
194
192
  }
195
193
  }
196
194
  }
197
195
 
198
- .wds-critical-banner__entry-track {
199
- min-height: 0;
200
- }
201
-
202
- @keyframes wds-critical-banner-reveal-height {
203
- from {
204
- grid-template-rows: 0fr;
205
- overflow: hidden;
206
- }
207
-
208
- to {
209
- grid-template-rows: 1fr;
210
- overflow: visible;
211
- }
212
- }
213
-
214
196
  // Reduced motion support
215
197
  @media (prefers-reduced-motion: reduce) {
216
198
  .wds-critical-banner__description,
@@ -219,10 +201,4 @@
219
201
  .wds-critical-banner__toggle {
220
202
  transition: none !important;
221
203
  }
222
-
223
- .wds-critical-banner__entry-mask {
224
- animation: none;
225
- grid-template-rows: 1fr;
226
- overflow: visible;
227
- }
228
204
  }
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useMemo, useRef, type ReactNode } from 'react';
1
+ import { useState, useEffect, useRef, type ReactNode } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
3
  import { Meta, StoryObj, Decorator } from '@storybook/react-webpack5';
4
4
  import { fn } from 'storybook/test';
@@ -137,29 +137,6 @@ const hiddenArgTypes = {
137
137
  'data-testid': { table: { disable: true } },
138
138
  } as const;
139
139
 
140
- const AnimatedEntryPreview = (args: CriticalBannerProps) => {
141
- const { id = 'animated-entry' } = args;
142
- const [bannerInstance, setBannerInstance] = useState(0);
143
- const animatedBanner = useMemo(
144
- () => ({
145
- ...args,
146
- id: `${id}-${bannerInstance}`,
147
- }),
148
- [args, bannerInstance, id],
149
- );
150
-
151
- return (
152
- <>
153
- <CriticalBanner key={animatedBanner.id} {...animatedBanner} />
154
- <div className="p-t-3">
155
- <Button block v2 onClick={() => setBannerInstance((current) => current + 1)}>
156
- Replay
157
- </Button>
158
- </div>
159
- </>
160
- );
161
- };
162
-
163
140
  /** Renders children inside an iframe that inherits the parent page's stylesheets. */
164
141
  function IframeContainer({ width, children }: { width: number; children: ReactNode }) {
165
142
  const iframeRef = useRef<HTMLIFrameElement>(null);
@@ -351,12 +328,17 @@ export const Actions: Story = {
351
328
  * Each sentiment has a default status icon. Override it with a custom image or an AvatarView.
352
329
  */
353
330
  export const MediaTypes: Story = {
331
+ args: {
332
+ sentiment: 'neutral',
333
+ },
354
334
  decorators: [ContainerDecorator('2rem')],
355
335
  parameters: {
356
336
  docs: {
357
337
  source: {
358
- code: `{/* Default sentiment icon */}
359
- <CriticalBanner sentiment="neutral" />
338
+ code: `{/* Change sentiment using the story controls */}
339
+
340
+ {/* Default — sentiment icon */}
341
+ <CriticalBanner sentiment={sentiment} />
360
342
 
361
343
  {/* Custom image */}
362
344
  <CriticalBanner media={{ imgSrc: '/card.svg', 'aria-label': 'Wise card' }} ... />
@@ -375,8 +357,14 @@ export const MediaTypes: Story = {
375
357
  },
376
358
  },
377
359
  },
378
- argTypes: hiddenArgTypes,
379
- render: function Render() {
360
+ argTypes: {
361
+ ...hiddenArgTypes,
362
+ sentiment: {
363
+ control: 'radio',
364
+ options: ['negative', 'warning', 'neutral', 'success'],
365
+ },
366
+ },
367
+ render: function Render({ sentiment }) {
380
368
  const [expandedStates, setExpandedStates] = useState<Record<string, boolean>>({
381
369
  default: true,
382
370
  image: true,
@@ -392,7 +380,7 @@ export const MediaTypes: Story = {
392
380
  return (
393
381
  <>
394
382
  <CriticalBanner
395
- sentiment="neutral"
383
+ sentiment={sentiment}
396
384
  title="Default status icon"
397
385
  description="When no media is provided, the sentiment's default icon is displayed."
398
386
  action={{ label: 'Continue', onClick: fn() }}
@@ -400,7 +388,7 @@ export const MediaTypes: Story = {
400
388
  onToggle={() => toggle('default')}
401
389
  />
402
390
  <CriticalBanner
403
- sentiment="neutral"
391
+ sentiment={sentiment}
404
392
  title="Custom image"
405
393
  description="Your card has been blocked for security reasons."
406
394
  media={{ imgSrc: '../../wise-card.svg', 'aria-label': 'Wise debit card' }}
@@ -409,7 +397,7 @@ export const MediaTypes: Story = {
409
397
  onToggle={() => toggle('image')}
410
398
  />
411
399
  <CriticalBanner
412
- sentiment="neutral"
400
+ sentiment={sentiment}
413
401
  title="Avatar with photo"
414
402
  description="The default badge is the status icon for the sentiment."
415
403
  media={{ avatar: { imgSrc: '../../avatar-rectangle-fox.webp' } }}
@@ -418,7 +406,7 @@ export const MediaTypes: Story = {
418
406
  onToggle={() => toggle('avatarPhoto')}
419
407
  />
420
408
  <CriticalBanner
421
- sentiment="neutral"
409
+ sentiment={sentiment}
422
410
  title="Avatar with initials"
423
411
  description="The default badge is the status icon for the sentiment."
424
412
  media={{ avatar: { profileName: 'John Doe' } }}
@@ -427,7 +415,7 @@ export const MediaTypes: Story = {
427
415
  onToggle={() => toggle('avatarInitials')}
428
416
  />
429
417
  <CriticalBanner
430
- sentiment="neutral"
418
+ sentiment={sentiment}
431
419
  title="Avatar with custom icon"
432
420
  description="The default badge is the status icon for the sentiment."
433
421
  media={{ avatar: { asset: <Bank title="Bank account" /> } }}
@@ -436,7 +424,7 @@ export const MediaTypes: Story = {
436
424
  onToggle={() => toggle('avatarIcon')}
437
425
  />
438
426
  <CriticalBanner
439
- sentiment="neutral"
427
+ sentiment={sentiment}
440
428
  title="Business profile with badge"
441
429
  description="Your business account requires additional documentation."
442
430
  media={{ avatar: { profileType: 'BUSINESS', badge: { flagCode: 'GB' } } }}
@@ -597,25 +585,6 @@ export const MobileOverhang: Story = {
597
585
  },
598
586
  };
599
587
 
600
- /**
601
- * Mobile-only entry animation: the banner reveals from above.
602
- */
603
- export const AnimatedEntry: Story = {
604
- args: {
605
- title: 'Your account is restricted.',
606
- description: 'Review your personal details to get your account active again.',
607
- action: { label: 'Review details', onClick: fn() },
608
- },
609
- argTypes: hiddenArgTypes,
610
- render: (args) => <AnimatedEntryPreview {...args} />,
611
- parameters: {
612
- layout: 'fullscreen',
613
- docs: {
614
- canvas: { sourceState: 'hidden' },
615
- },
616
- },
617
- };
618
-
619
588
  /**
620
589
  * The text container is capped at 480px for optimal readability, even though
621
590
  * the banner itself stretches to the full available width.
@@ -25,6 +25,19 @@ const ANIMATION_DURATION = 200; // 150ms animation + 50ms buffer
25
25
  const longDescription =
26
26
  'We have detected unusual activity on your account that does not match your typical usage patterns. To protect your funds and personal information, we have temporarily restricted access. Please verify your identity to restore full access to your account.';
27
27
 
28
+ const BACKGROUND_SCROLL_CONTENT = [
29
+ 'Manage your card settings, limits, and delivery details from this page.',
30
+ 'Your recent payments, subscriptions, and cash withdrawals will appear here.',
31
+ 'Freeze your card any time if it is lost, stolen, or somewhere unexpected.',
32
+ 'Set spending limits for online, in-store, and contactless payments.',
33
+ 'Add your card to a digital wallet for quicker checkout in supported stores.',
34
+ 'Choose the currency balance you want to spend from before you travel.',
35
+ 'Review fees before using an ATM or paying in a currency you do not hold.',
36
+ 'Order a replacement card if yours is damaged or about to expire.',
37
+ 'Keep your delivery address up to date so new cards arrive in the right place.',
38
+ 'Contact support if a card payment looks unfamiliar or incorrect.',
39
+ ];
40
+
28
41
  function AllVariants({ gap = '1rem' }: { gap?: string }) {
29
42
  const [states, setStates] = useState({
30
43
  negativeExpanded: true,
@@ -137,21 +150,58 @@ export const MobileVariants: Story = {
137
150
  ...withVariantConfig(['mobile']),
138
151
  };
139
152
 
140
- /** Mobile entry animation visual regression test. */
141
- export const AnimatedEntryMobile: Story = {
142
- render: function Render() {
153
+ /** Neutral background regression test with page content scrolled under the mobile overhang. */
154
+ export const BackgroundIsNotTransparent: Story = {
155
+ args: {
156
+ sentiment: 'neutral',
157
+ },
158
+ argTypes: {
159
+ sentiment: {
160
+ control: 'radio',
161
+ options: ['negative', 'warning', 'neutral', 'success'],
162
+ },
163
+ },
164
+ render: function Render({ sentiment }) {
143
165
  return (
144
- <CriticalBanner
145
- sentiment="negative"
146
- title="Your account is restricted."
147
- description="Review your personal details to get your account active again."
148
- action={{ label: 'Review details', onClick: fn() }}
149
- />
166
+ <div
167
+ data-testid="background-scroll-container"
168
+ style={{
169
+ width: 350,
170
+ height: 640,
171
+ overflowY: 'auto',
172
+ border: '1px solid var(--color-border-neutral)',
173
+ }}
174
+ >
175
+ <div style={{ position: 'sticky', top: 0, zIndex: 1 }}>
176
+ <CriticalBanner
177
+ sentiment={sentiment}
178
+ title="Your account requires verification"
179
+ description="Please verify your identity to continue using all features."
180
+ action={{ label: 'Verify now', onClick: fn() }}
181
+ />
182
+ </div>
183
+ <main style={{ padding: 'var(--size-24) var(--size-16) var(--size-48)' }}>
184
+ <h1 style={{ margin: '0 0 var(--size-8)', fontSize: 32, lineHeight: 1.1 }}>Debit card</h1>
185
+ <p style={{ margin: '0 0 var(--size-24)' }}>Spend in 150+ currencies</p>
186
+ {BACKGROUND_SCROLL_CONTENT.map((paragraph) => (
187
+ <p key={paragraph}>{paragraph}</p>
188
+ ))}
189
+ </main>
190
+ </div>
150
191
  );
151
192
  },
193
+ play: async ({ canvasElement }) => {
194
+ const scrollContainer = canvasElement.querySelector(
195
+ '[data-testid="background-scroll-container"]',
196
+ );
197
+
198
+ if (scrollContainer) {
199
+ scrollContainer.scrollTop = 250;
200
+ }
201
+ },
152
202
  ...withVariantConfig(['mobile'], {
153
203
  parameters: {
154
- chromatic: { pauseAnimationAtEnd: true },
204
+ controls: { include: ['sentiment'] },
155
205
  },
156
206
  }),
157
207
  };
@@ -15,7 +15,7 @@ describe('CriticalBanner', () => {
15
15
  resetLiveRegionAnnouncementQueue();
16
16
  });
17
17
 
18
- it('applies mobile overhang classes by default', () => {
18
+ it('renders mobile overhang markup without entry animation markup', () => {
19
19
  const { container } = render(
20
20
  <CriticalBanner {...defaultProps} data-testid="critical-banner" />,
21
21
  );
@@ -23,15 +23,7 @@ describe('CriticalBanner', () => {
23
23
  expect(screen.getByTestId('critical-banner')).toBeInTheDocument();
24
24
  expect(container.querySelector('.wds-critical-banner-overhang')).toBeInTheDocument();
25
25
  expect(container.querySelector('.wds-critical-banner-overhang-query')).toBeInTheDocument();
26
- });
27
-
28
- it('wraps the banner in the css entry animation structure', () => {
29
- const { container } = render(
30
- <CriticalBanner {...defaultProps} data-testid="critical-banner" />,
31
- );
32
-
33
- expect(screen.getByTestId('critical-banner')).toBeInTheDocument();
34
- expect(container.querySelector('.wds-critical-banner__entry-mask')).toBeInTheDocument();
35
- expect(container.querySelector('.wds-critical-banner__entry-track')).toBeInTheDocument();
26
+ expect(container.querySelector('.wds-critical-banner__entry-mask')).not.toBeInTheDocument();
27
+ expect(container.querySelector('.wds-critical-banner__entry-track')).not.toBeInTheDocument();
36
28
  });
37
29
  });
@@ -179,11 +179,7 @@ export const CriticalBanner = ({
179
179
  actionSecondaryLabel: actionSecondary?.label,
180
180
  })}
181
181
  >
182
- <div className="wds-critical-banner-overhang-query">
183
- <div className="wds-critical-banner__entry-mask">
184
- <div className="wds-critical-banner__entry-track">{bannerSurface}</div>
185
- </div>
186
- </div>
182
+ <div className="wds-critical-banner-overhang-query">{bannerSurface}</div>
187
183
  </LiveRegion>
188
184
  );
189
185
  };