@transferwise/components 0.0.0-experimental-18f7655 → 0.0.0-experimental-c087593

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
@@ -32093,25 +32093,39 @@ html:not([dir="rtl"]) .np-navigation-option {
32093
32093
  }
32094
32094
  }
32095
32095
 
32096
- .wds-critical-banner__entry-mask {
32097
- display: grid;
32098
- grid-template-rows: 0fr;
32099
- overflow: hidden;
32100
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
32101
- }
32102
-
32103
- .wds-critical-banner__entry-track {
32104
- min-height: 0;
32105
- }
32106
-
32107
- @keyframes wds-critical-banner-reveal-height {
32108
- from {
32109
- grid-template-rows: 0fr;
32110
- overflow: hidden;
32111
- }
32112
- to {
32113
- grid-template-rows: 1fr;
32114
- overflow: visible;
32096
+ .wds-critical-banner-overhang-query {
32097
+ container-name: critical-banner-overhang;
32098
+ container-type: inline-size;
32099
+ inline-size: 100%;
32100
+ }
32101
+
32102
+ @container critical-banner-overhang (max-width: 600px) {
32103
+ .wds-critical-banner-overhang-query {
32104
+ --critical-banner-mobile-overhang-size: 32px;
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
+ }
32115
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
32116
+ margin-bottom: var(--critical-banner-mobile-overhang-size);
32117
+ }
32118
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
32119
+ content: "";
32120
+ position: absolute;
32121
+ right: 0;
32122
+ bottom: calc(-1 * var(--critical-banner-mobile-overhang-size));
32123
+ left: 0;
32124
+ height: var(--critical-banner-mobile-overhang-size);
32125
+ pointer-events: none;
32126
+ background: var(--critical-banner-background);
32127
+ -webkit-mask: var(--critical-banner-overhang-mask);
32128
+ mask: var(--critical-banner-overhang-mask);
32115
32129
  }
32116
32130
  }
32117
32131
 
@@ -32122,11 +32136,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32122
32136
  .wds-critical-banner__toggle {
32123
32137
  transition: none !important;
32124
32138
  }
32125
- .wds-critical-banner__entry-mask {
32126
- animation: none;
32127
- grid-template-rows: 1fr;
32128
- overflow: visible;
32129
- }
32130
32139
  }
32131
32140
 
32132
32141
  .wds-expander-toggle {
@@ -67,7 +67,7 @@ const CriticalBanner = ({
67
67
  sentiment: sentiment,
68
68
  emphasis: sentiment === 'neutral' ? 'base' : 'elevated',
69
69
  "data-testid": testId,
70
- className: clsx.clsx('wds-critical-banner', {
70
+ className: clsx.clsx('wds-critical-banner', 'wds-critical-banner-overhang', {
71
71
  'wds-critical-banner--collapsed': !resolvedExpanded,
72
72
  'wds-critical-banner--with-two-actions': !!actionSecondary
73
73
  }, className),
@@ -140,11 +140,8 @@ const CriticalBanner = ({
140
140
  actionSecondaryLabel: actionSecondary?.label
141
141
  }),
142
142
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
143
- className: "wds-critical-banner__entry-mask",
144
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
145
- className: "wds-critical-banner__entry-track",
146
- children: bannerSurface
147
- })
143
+ className: "wds-critical-banner-overhang-query",
144
+ children: bannerSurface
148
145
  })
149
146
  });
150
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 {\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__entry-mask\">\n <div className=\"wds-critical-banner__entry-track\">{bannerSurface}</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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"}
@@ -65,7 +65,7 @@ const CriticalBanner = ({
65
65
  sentiment: sentiment,
66
66
  emphasis: sentiment === 'neutral' ? 'base' : 'elevated',
67
67
  "data-testid": testId,
68
- className: clsx('wds-critical-banner', {
68
+ className: clsx('wds-critical-banner', 'wds-critical-banner-overhang', {
69
69
  'wds-critical-banner--collapsed': !resolvedExpanded,
70
70
  'wds-critical-banner--with-two-actions': !!actionSecondary
71
71
  }, className),
@@ -138,11 +138,8 @@ const CriticalBanner = ({
138
138
  actionSecondaryLabel: actionSecondary?.label
139
139
  }),
140
140
  children: /*#__PURE__*/jsx("div", {
141
- className: "wds-critical-banner__entry-mask",
142
- children: /*#__PURE__*/jsx("div", {
143
- className: "wds-critical-banner__entry-track",
144
- children: bannerSurface
145
- })
141
+ className: "wds-critical-banner-overhang-query",
142
+ children: bannerSurface
146
143
  })
147
144
  });
148
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 {\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__entry-mask\">\n <div className=\"wds-critical-banner__entry-track\">{bannerSurface}</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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDO,MAAMA,cAAc,GAAGA,CAAC;AAC7BC,EAAAA,SAAS,GAAG,UAAU;EACtBC,KAAK;EACLC,WAAW;EACXC,KAAK,GAAG,EAAE;EACVC,MAAM;EACNC,eAAe;AACfC,EAAAA,QAAQ,EAAEC,YAAY;EACtBC,QAAQ;EACRC,EAAE;EACFC,SAAS;AACT,EAAA,aAAa,EAAEC;AAAM,CACD,KAAI;EACxB,MAAM,CAACC,YAAY,EAAEC,SAAS,CAAC,GAAGC,gBAAgB,CAACC,UAAU,CAACC,MAAM,CAAC;EACrE,MAAMC,YAAY,GAAGV,YAAY,KAAKW,SAAS,IAAIV,QAAQ,KAAKU,SAAS;EACzE,MAAM,CAACC,gBAAgB,EAAEC,mBAAmB,CAAC,GAAGC,QAAQ,CAAC,IAAI,CAAC;EAC9D,MAAMC,gBAAgB,GAAGT,SAAS,GAAG,IAAI,GAAGI,YAAY,GAAGV,YAAY,GAAGY,gBAAgB;AAC1F,EAAA,MAAMI,YAAY,GAAGN,YAAY,GAC7BT,QAAQ,GACR,MAAMY,mBAAmB,CAAEI,gBAAgB,IAAK,CAACA,gBAAgB,CAAC;AACtE,EAAA,MAAMC,UAAU,GAAGrB,MAAM,IAAIC,eAAe;AAC5C,EAAA,MAAMqB,OAAO,GAAGC,KAAK,EAAE;AACvB,EAAA,MAAMC,OAAO,GAAGD,KAAK,EAAE;AACvB,EAAA,MAAME,MAAM,GAAGF,KAAK,EAAE;AAEtB,EAAA,MAAMG,iBAAiB,GAAG,CACxB3B,KAAK,CAAC,aAAa,CAAC,GAAGe,SAAS,GAAGQ,OAAO,EAC1C,CAACzB,KAAK,GAAGiB,SAAS,GAAGU,OAAO,CAC7B,CACEG,MAAM,CAACC,OAAO,CAAC,CACfC,IAAI,CAAC,GAAG,CAAC;AAEZ,EAAA,MAAMC,aAAa,gBACjBC,IAAA,CAACC,SAAS,EAAA;AACRC,IAAAA,GAAG,EAAEzB,YAAa;AAClB0B,IAAAA,IAAI,EAAC,OAAO;AACZC,IAAAA,EAAE,EAAEC,eAA+B;AACnC/B,IAAAA,EAAE,EAAEA,EAAG;AACPT,IAAAA,SAAS,EAAEA,SAAU;AACrByC,IAAAA,QAAQ,EAAEzC,SAAS,KAAK,SAAS,GAAG,MAAM,GAAG,UAAW;AACxD,IAAA,aAAA,EAAaW,MAAO;AACpBD,IAAAA,SAAS,EAAEgC,IAAI,CACb,qBAAqB,EACrB,8BAA8B,EAC9B;MACE,gCAAgC,EAAE,CAACpB,gBAAgB;MACnD,uCAAuC,EAAE,CAAC,CAACjB;KAC5C,EACDK,SAAS,CACT;IACFP,KAAK,EAAEwC,iBAAiB,CAAC;MACvBxC,KAAK;MACLH,SAAS;MACT0B,OAAO;AACPkB,MAAAA,YAAY,EAAE;AACf,KAAA,CAAE;IACHC,OAAO,EACLpB,UAAU,gBACRU,IAAA,CAAA,KAAA,EAAA;AAAK,MAAA,aAAA,EAAa,CAACb,gBAAgB,GAAG,IAAI,GAAGJ,SAAU;AAAC4B,MAAAA,KAAK,EAAE;AAAEC,QAAAA,OAAO,EAAE;OAAa;AAAAC,MAAAA,QAAA,GACpF3C,eAAe;AAAA;AACd;AACA4C,MAAAA,GAAA,CAACC,MAAM,EAAA;QACLC,EAAE,EAAA,IAAA;AACFb,QAAAA,IAAI,EAAC,IAAI;AACTc,QAAAA,QAAQ,EAAC,WAAW;QACpBC,IAAI,EAAEhD,eAAe,CAACgD,IAAK;AAC3BC,QAAAA,QAAQ,EAAEhC,gBAAgB,GAAGJ,SAAS,GAAG,EAAG;QAC5CqC,OAAO,EAAElD,eAAe,EAAEkD,OAAQ;QAAAP,QAAA,EAEjC3C,eAAe,CAACmD;OACX,CACT,EACApD,MAAM;AAAA;AACL;AACA6C,MAAAA,GAAA,CAACC,MAAM,EAAA;QACLC,EAAE,EAAA,IAAA;AACFb,QAAAA,IAAI,EAAC,IAAI;AACTc,QAAAA,QAAQ,EAAC,SAAS;QAClBC,IAAI,EAAEjD,MAAM,CAACiD,IAAK;AAClBC,QAAAA,QAAQ,EAAEhC,gBAAgB,GAAGJ,SAAS,GAAG,EAAG;QAC5CqC,OAAO,EAAEnD,MAAM,CAACmD,OAAQ;QAAAP,QAAA,EAEvB5C,MAAM,CAACoD;AAAK,OACP,CACT;KACE,CAAC,GACJtC,SACL;AACDuC,IAAAA,IAAI,EAAC,QAAQ;IACb,iBAAA,EAAiB3B,iBAAiB,IAAIZ,SAAU;AAChD,IAAA,kBAAA,EAAkBhB,WAAW,GAAG2B,MAAM,GAAGX,SAAU;AAAA8B,IAAAA,QAAA,gBAEnDb,IAAA,CAAA,KAAA,EAAA;AAAKzB,MAAAA,SAAS,EAAC,mCAAmC;AAAAsC,MAAAA,QAAA,EAAA,CAC/C/C,KAAK,iBACJgD,GAAA,CAACS,IAAI,EAAA;AACHjD,QAAAA,EAAE,EAAEmB,OAAQ;QACZ+B,IAAI,EAAEC,UAAU,CAACC,eAAgB;AACjCnD,QAAAA,SAAS,EAAC,yDAAyD;AAAAsC,QAAAA,QAAA,EAElE/C;AAAK,OACF,CACP,EACAC,WAAW,iBACV+C,GAAA,CAACS,IAAI,EAAA;AACHjD,QAAAA,EAAE,EAAEoB,MAAO;AACXnB,QAAAA,SAAS,EAAEgC,IAAI,CAAC,8BAA8B,EAAE,kCAAkC,EAAE;UAClF,8CAA8C,EAAE,CAAC,CAACzC;AACnD,SAAA,CAAE;AAAA+C,QAAAA,QAAA,EAEF9C;AAAW,OACR,CACP;AAAA,KACE,CACL,eAAA+C,GAAA,CAACa,cAAc,EAAA;AACbxD,MAAAA,QAAQ,EAAEgB,gBAAiB;AAC3BgB,MAAAA,IAAI,EAAE,EAAG;AACT5B,MAAAA,SAAS,EAAC,6BAA6B;AACvCF,MAAAA,QAAQ,EAAEe;AAAa,KAAA,CAE3B;AAAA,GAAW,CACZ;EAED,oBACE0B,GAAA,CAACc,UAAU,EAAA;AACT,IAAA,WAAA,EAAU,WAAW;IACrBC,gBAAgB,EAAEC,uBAAuB,CAAC;MACxChE,KAAK;MACLC,WAAW;AACXI,MAAAA,QAAQ,EAAEgB,gBAAgB;MAC1B4C,WAAW,EAAE9D,MAAM,EAAEoD,KAAK;MAC1BW,oBAAoB,EAAE9D,eAAe,EAAEmD;AACxC,KAAA,CAAE;AAAAR,IAAAA,QAAA,eAEHC,GAAA,CAAA,KAAA,EAAA;AAAKvC,MAAAA,SAAS,EAAC,oCAAoC;AAAAsC,MAAAA,QAAA,EAAEd;KAAmB;AAC1E,GAAY,CAAC;AAEjB;;;;"}
@@ -32093,25 +32093,39 @@ html:not([dir="rtl"]) .np-navigation-option {
32093
32093
  }
32094
32094
  }
32095
32095
 
32096
- .wds-critical-banner__entry-mask {
32097
- display: grid;
32098
- grid-template-rows: 0fr;
32099
- overflow: hidden;
32100
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
32101
- }
32102
-
32103
- .wds-critical-banner__entry-track {
32104
- min-height: 0;
32105
- }
32106
-
32107
- @keyframes wds-critical-banner-reveal-height {
32108
- from {
32109
- grid-template-rows: 0fr;
32110
- overflow: hidden;
32111
- }
32112
- to {
32113
- grid-template-rows: 1fr;
32114
- overflow: visible;
32096
+ .wds-critical-banner-overhang-query {
32097
+ container-name: critical-banner-overhang;
32098
+ container-type: inline-size;
32099
+ inline-size: 100%;
32100
+ }
32101
+
32102
+ @container critical-banner-overhang (max-width: 600px) {
32103
+ .wds-critical-banner-overhang-query {
32104
+ --critical-banner-mobile-overhang-size: 32px;
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
+ }
32115
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
32116
+ margin-bottom: var(--critical-banner-mobile-overhang-size);
32117
+ }
32118
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
32119
+ content: "";
32120
+ position: absolute;
32121
+ right: 0;
32122
+ bottom: calc(-1 * var(--critical-banner-mobile-overhang-size));
32123
+ left: 0;
32124
+ height: var(--critical-banner-mobile-overhang-size);
32125
+ pointer-events: none;
32126
+ background: var(--critical-banner-background);
32127
+ -webkit-mask: var(--critical-banner-overhang-mask);
32128
+ mask: var(--critical-banner-overhang-mask);
32115
32129
  }
32116
32130
  }
32117
32131
 
@@ -32122,11 +32136,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32122
32136
  .wds-critical-banner__toggle {
32123
32137
  transition: none !important;
32124
32138
  }
32125
- .wds-critical-banner__entry-mask {
32126
- animation: none;
32127
- grid-template-rows: 1fr;
32128
- overflow: visible;
32129
- }
32130
32139
  }
32131
32140
 
32132
32141
  .wds-expander-toggle {
@@ -122,23 +122,38 @@
122
122
  min-width: fit-content;
123
123
  }
124
124
  }
125
- .wds-critical-banner__entry-mask {
126
- display: grid;
127
- grid-template-rows: 0fr;
128
- overflow: hidden;
129
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
130
- }
131
- .wds-critical-banner__entry-track {
132
- min-height: 0;
133
- }
134
- @keyframes wds-critical-banner-reveal-height {
135
- from {
136
- grid-template-rows: 0fr;
137
- overflow: hidden;
125
+ .wds-critical-banner-overhang-query {
126
+ container-name: critical-banner-overhang;
127
+ container-type: inline-size;
128
+ inline-size: 100%;
129
+ }
130
+ @container critical-banner-overhang (max-width: 600px) {
131
+ .wds-critical-banner-overhang-query {
132
+ --critical-banner-mobile-overhang-size: 32px;
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
+ }
143
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
144
+ margin-bottom: var(--critical-banner-mobile-overhang-size);
138
145
  }
139
- to {
140
- grid-template-rows: 1fr;
141
- overflow: visible;
146
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
147
+ content: "";
148
+ position: absolute;
149
+ right: 0;
150
+ bottom: calc(-1 * var(--critical-banner-mobile-overhang-size));
151
+ left: 0;
152
+ height: var(--critical-banner-mobile-overhang-size);
153
+ pointer-events: none;
154
+ background: var(--critical-banner-background);
155
+ -webkit-mask: var(--critical-banner-overhang-mask);
156
+ mask: var(--critical-banner-overhang-mask);
142
157
  }
143
158
  }
144
159
  @media (prefers-reduced-motion: reduce) {
@@ -148,9 +163,4 @@
148
163
  .wds-critical-banner__toggle {
149
164
  transition: none !important;
150
165
  }
151
- .wds-critical-banner__entry-mask {
152
- animation: none;
153
- grid-template-rows: 1fr;
154
- overflow: visible;
155
- }
156
166
  }
@@ -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,gCA6HrB,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": "0.0.0-experimental-18f7655",
3
+ "version": "0.0.0-experimental-c087593",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
package/src/main.css CHANGED
@@ -32093,25 +32093,39 @@ html:not([dir="rtl"]) .np-navigation-option {
32093
32093
  }
32094
32094
  }
32095
32095
 
32096
- .wds-critical-banner__entry-mask {
32097
- display: grid;
32098
- grid-template-rows: 0fr;
32099
- overflow: hidden;
32100
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
32101
- }
32102
-
32103
- .wds-critical-banner__entry-track {
32104
- min-height: 0;
32105
- }
32106
-
32107
- @keyframes wds-critical-banner-reveal-height {
32108
- from {
32109
- grid-template-rows: 0fr;
32110
- overflow: hidden;
32111
- }
32112
- to {
32113
- grid-template-rows: 1fr;
32114
- overflow: visible;
32096
+ .wds-critical-banner-overhang-query {
32097
+ container-name: critical-banner-overhang;
32098
+ container-type: inline-size;
32099
+ inline-size: 100%;
32100
+ }
32101
+
32102
+ @container critical-banner-overhang (max-width: 600px) {
32103
+ .wds-critical-banner-overhang-query {
32104
+ --critical-banner-mobile-overhang-size: 32px;
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
+ }
32115
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
32116
+ margin-bottom: var(--critical-banner-mobile-overhang-size);
32117
+ }
32118
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
32119
+ content: "";
32120
+ position: absolute;
32121
+ right: 0;
32122
+ bottom: calc(-1 * var(--critical-banner-mobile-overhang-size));
32123
+ left: 0;
32124
+ height: var(--critical-banner-mobile-overhang-size);
32125
+ pointer-events: none;
32126
+ background: var(--critical-banner-background);
32127
+ -webkit-mask: var(--critical-banner-overhang-mask);
32128
+ mask: var(--critical-banner-overhang-mask);
32115
32129
  }
32116
32130
  }
32117
32131
 
@@ -32122,11 +32136,6 @@ html:not([dir="rtl"]) .np-navigation-option {
32122
32136
  .wds-critical-banner__toggle {
32123
32137
  transition: none !important;
32124
32138
  }
32125
- .wds-critical-banner__entry-mask {
32126
- animation: none;
32127
- grid-template-rows: 1fr;
32128
- overflow: visible;
32129
- }
32130
32139
  }
32131
32140
 
32132
32141
  .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
 
@@ -122,23 +122,38 @@
122
122
  min-width: fit-content;
123
123
  }
124
124
  }
125
- .wds-critical-banner__entry-mask {
126
- display: grid;
127
- grid-template-rows: 0fr;
128
- overflow: hidden;
129
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
130
- }
131
- .wds-critical-banner__entry-track {
132
- min-height: 0;
133
- }
134
- @keyframes wds-critical-banner-reveal-height {
135
- from {
136
- grid-template-rows: 0fr;
137
- overflow: hidden;
125
+ .wds-critical-banner-overhang-query {
126
+ container-name: critical-banner-overhang;
127
+ container-type: inline-size;
128
+ inline-size: 100%;
129
+ }
130
+ @container critical-banner-overhang (max-width: 600px) {
131
+ .wds-critical-banner-overhang-query {
132
+ --critical-banner-mobile-overhang-size: 32px;
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
+ }
143
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang {
144
+ margin-bottom: var(--critical-banner-mobile-overhang-size);
138
145
  }
139
- to {
140
- grid-template-rows: 1fr;
141
- overflow: visible;
146
+ .wds-critical-banner-overhang-query .wds-critical-banner-overhang::after {
147
+ content: "";
148
+ position: absolute;
149
+ right: 0;
150
+ bottom: calc(-1 * var(--critical-banner-mobile-overhang-size));
151
+ left: 0;
152
+ height: var(--critical-banner-mobile-overhang-size);
153
+ pointer-events: none;
154
+ background: var(--critical-banner-background);
155
+ -webkit-mask: var(--critical-banner-overhang-mask);
156
+ mask: var(--critical-banner-overhang-mask);
142
157
  }
143
158
  }
144
159
  @media (prefers-reduced-motion: reduce) {
@@ -148,9 +163,4 @@
148
163
  .wds-critical-banner__toggle {
149
164
  transition: none !important;
150
165
  }
151
- .wds-critical-banner__entry-mask {
152
- animation: none;
153
- grid-template-rows: 1fr;
154
- overflow: visible;
155
- }
156
166
  }
@@ -10,7 +10,7 @@
10
10
  --critical-banner-background-base: transparent;
11
11
  --critical-banner-background-surface: var(--color-sentiment-background-surface);
12
12
  // The sentiment surface can be translucent, so layer it over an opaque base
13
- // for neutral banners.
13
+ // for neutral banners and their mobile overhang.
14
14
  --critical-banner-background:
15
15
  linear-gradient(
16
16
  var(--critical-banner-background-surface),
@@ -151,29 +151,45 @@
151
151
  }
152
152
  }
153
153
 
154
- // Entry animation: after a 500ms delay, reveal the already-positioned banner
155
- // over 400ms. The mask clips only during the reveal, then becomes visible so
156
- // actions are not clipped after the animation.
157
- .wds-critical-banner__entry-mask {
158
- display: grid;
159
- grid-template-rows: 0fr;
160
- overflow: hidden;
161
- animation: wds-critical-banner-reveal-height 400ms cubic-bezier(0.3, 0, 0.1, 1) 500ms both;
162
- }
163
-
164
- .wds-critical-banner__entry-track {
165
- min-height: 0;
166
- }
167
-
168
- @keyframes wds-critical-banner-reveal-height {
169
- from {
170
- grid-template-rows: 0fr;
171
- overflow: hidden;
172
- }
173
-
174
- to {
175
- grid-template-rows: 1fr;
176
- overflow: visible;
154
+ .wds-critical-banner-overhang-query {
155
+ container-name: critical-banner-overhang;
156
+ container-type: inline-size;
157
+ inline-size: 100%;
158
+
159
+ @container critical-banner-overhang (max-width: @wds-critical-banner-mobile-overhang-max) {
160
+ --critical-banner-mobile-overhang-size: 32px;
161
+ --critical-banner-overhang-mask:
162
+ radial-gradient(
163
+ circle at 100% 100%,
164
+ transparent var(--critical-banner-mobile-overhang-size),
165
+ #000 var(--critical-banner-mobile-overhang-size)
166
+ )
167
+ 0 0 / var(--critical-banner-mobile-overhang-size)
168
+ var(--critical-banner-mobile-overhang-size) no-repeat,
169
+ radial-gradient(
170
+ circle at 0% 100%,
171
+ transparent var(--critical-banner-mobile-overhang-size),
172
+ #000 var(--critical-banner-mobile-overhang-size)
173
+ )
174
+ 100% 0 / var(--critical-banner-mobile-overhang-size)
175
+ var(--critical-banner-mobile-overhang-size) no-repeat;
176
+
177
+ .wds-critical-banner-overhang {
178
+ margin-bottom: var(--critical-banner-mobile-overhang-size);
179
+
180
+ &::after {
181
+ content: "";
182
+ position: absolute;
183
+ right: 0;
184
+ bottom: calc(-1 * var(--critical-banner-mobile-overhang-size));
185
+ left: 0;
186
+ height: var(--critical-banner-mobile-overhang-size);
187
+ pointer-events: none;
188
+ background: var(--critical-banner-background);
189
+ -webkit-mask: var(--critical-banner-overhang-mask);
190
+ mask: var(--critical-banner-overhang-mask);
191
+ }
192
+ }
177
193
  }
178
194
  }
179
195
 
@@ -185,10 +201,4 @@
185
201
  .wds-critical-banner__toggle {
186
202
  transition: none !important;
187
203
  }
188
-
189
- .wds-critical-banner__entry-mask {
190
- animation: none;
191
- grid-template-rows: 1fr;
192
- overflow: visible;
193
- }
194
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);
@@ -584,18 +561,24 @@ export const Responsiveness: Story = {
584
561
  };
585
562
 
586
563
  /**
587
- * Mobile-only entry animation: the banner reveals from above.
564
+ * Mobile viewport regression test for the overhang.
565
+ * The overhang is always applied below 600px.
588
566
  */
589
- export const AnimatedEntry: Story = {
590
- args: {
591
- title: 'Your account is restricted.',
592
- description: 'Review your personal details to get your account active again.',
593
- action: { label: 'Review details', onClick: fn() },
594
- },
567
+ export const MobileOverhang: Story = {
595
568
  argTypes: hiddenArgTypes,
596
- render: (args) => <AnimatedEntryPreview {...args} />,
569
+ render: function Render() {
570
+ return (
571
+ <div style={{ width: 350 }}>
572
+ <CriticalBanner
573
+ sentiment="negative"
574
+ title="Your account requires verification"
575
+ description="Please verify your identity to continue using all features."
576
+ action={{ label: 'Verify now', onClick: fn() }}
577
+ />
578
+ </div>
579
+ );
580
+ },
597
581
  parameters: {
598
- layout: 'fullscreen',
599
582
  docs: {
600
583
  canvas: { sourceState: 'hidden' },
601
584
  },
@@ -21,7 +21,6 @@ const wait = async (ms: number) =>
21
21
  });
22
22
 
23
23
  const ANIMATION_DURATION = 200; // 150ms animation + 50ms buffer
24
- const ENTRY_ANIMATION_DURATION = 950; // 500ms delay + 400ms animation + 50ms buffer
25
24
 
26
25
  const longDescription =
27
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.';
@@ -151,7 +150,7 @@ export const MobileVariants: Story = {
151
150
  ...withVariantConfig(['mobile']),
152
151
  };
153
152
 
154
- /** Neutral background regression test with page content scrolled under the sticky banner. */
153
+ /** Neutral background regression test with page content scrolled under the mobile overhang. */
155
154
  export const BackgroundIsNotTransparent: Story = {
156
155
  args: {
157
156
  sentiment: 'neutral',
@@ -198,7 +197,6 @@ export const BackgroundIsNotTransparent: Story = {
198
197
 
199
198
  if (scrollContainer) {
200
199
  scrollContainer.scrollTop = 250;
201
- await wait(ENTRY_ANIMATION_DURATION);
202
200
  }
203
201
  },
204
202
  ...withVariantConfig(['mobile'], {
@@ -208,25 +206,6 @@ export const BackgroundIsNotTransparent: Story = {
208
206
  }),
209
207
  };
210
208
 
211
- /** Mobile entry animation visual regression test. */
212
- export const AnimatedEntryMobile: Story = {
213
- render: function Render() {
214
- return (
215
- <CriticalBanner
216
- sentiment="negative"
217
- title="Your account is restricted."
218
- description="Review your personal details to get your account active again."
219
- action={{ label: 'Review details', onClick: fn() }}
220
- />
221
- );
222
- },
223
- ...withVariantConfig(['mobile'], {
224
- parameters: {
225
- chromatic: { pauseAnimationAtEnd: true },
226
- },
227
- }),
228
- };
229
-
230
209
  /**
231
210
  * Tests keyboard navigation and interaction:
232
211
  * - Tab focuses the first chevron toggle button
@@ -15,23 +15,15 @@ describe('CriticalBanner', () => {
15
15
  resetLiveRegionAnnouncementQueue();
16
16
  });
17
17
 
18
- it('renders without mobile overhang markup', () => {
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
  );
22
22
 
23
23
  expect(screen.getByTestId('critical-banner')).toBeInTheDocument();
24
- expect(container.querySelector('.wds-critical-banner-overhang')).not.toBeInTheDocument();
25
- expect(container.querySelector('.wds-critical-banner-overhang-query')).not.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();
24
+ expect(container.querySelector('.wds-critical-banner-overhang')).toBeInTheDocument();
25
+ expect(container.querySelector('.wds-critical-banner-overhang-query')).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
  });
@@ -89,6 +89,7 @@ export const CriticalBanner = ({
89
89
  data-testid={testId}
90
90
  className={clsx(
91
91
  'wds-critical-banner',
92
+ 'wds-critical-banner-overhang',
92
93
  {
93
94
  'wds-critical-banner--collapsed': !resolvedExpanded,
94
95
  'wds-critical-banner--with-two-actions': !!actionSecondary,
@@ -178,9 +179,7 @@ export const CriticalBanner = ({
178
179
  actionSecondaryLabel: actionSecondary?.label,
179
180
  })}
180
181
  >
181
- <div className="wds-critical-banner__entry-mask">
182
- <div className="wds-critical-banner__entry-track">{bannerSurface}</div>
183
- </div>
182
+ <div className="wds-critical-banner-overhang-query">{bannerSurface}</div>
184
183
  </LiveRegion>
185
184
  );
186
185
  };
@@ -3,4 +3,5 @@
3
3
  // * collapse toggle is visible below collapsible-max token
4
4
  // At some point in the not too distant future hopefully these two value will be the same but because of launchpad quirks, for now they'll be different
5
5
  @wds-critical-banner-action-wrapper-max: 600px;
6
+ @wds-critical-banner-mobile-overhang-max: 600px;
6
7
  @wds-critical-banner-collapsible-max: 768px;