@transferwise/components 0.0.0-experimental-46c532c → 0.0.0-experimental-e523720
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/build/prompt/InfoPrompt/InfoPrompt.js +1 -1
- package/build/prompt/InfoPrompt/InfoPrompt.js.map +1 -1
- package/build/prompt/InfoPrompt/InfoPrompt.mjs +2 -2
- package/build/prompt/InfoPrompt/InfoPrompt.mjs.map +1 -1
- package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts +2 -3
- package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts.map +1 -1
- package/package.json +1 -2
- package/src/prompt/InfoPrompt/InfoPrompt.story.tsx +0 -42
- package/src/prompt/InfoPrompt/InfoPrompt.test.tsx +1 -65
- package/src/prompt/InfoPrompt/InfoPrompt.tsx +4 -15
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Neptune is the Design System built by and used at TransferWise. Neptune Web is the Neptune framework for Web. Neptune Web provides a way to build high quality, consistent user experiences on the web with ease.
|
|
6
6
|
|
|
7
|
-
This is the Neptune Web React component library. It
|
|
7
|
+
This is the Neptune Web React component library. It includes all necessary base CSS styles.
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
@@ -23,7 +23,7 @@ npm install @transferwise/components react react-dom prop-types @wise/art
|
|
|
23
23
|
|
|
24
24
|
```js
|
|
25
25
|
// These CSS files should be imported once in your application
|
|
26
|
-
import '@transferwise/
|
|
26
|
+
import '@transferwise/components/build/styles/css/neptune.css';
|
|
27
27
|
import '@transferwise/components/build/main.css';
|
|
28
28
|
|
|
29
29
|
import en from '@transferwise/components/build/i18n/en.json';
|
|
@@ -45,7 +45,7 @@ const InfoPrompt = ({
|
|
|
45
45
|
...restProps
|
|
46
46
|
}) => {
|
|
47
47
|
const [shouldFire, setShouldFire] = React.useState();
|
|
48
|
-
const announceOnChange = [title,
|
|
48
|
+
const announceOnChange = [title, description, action?.label].filter(Boolean).join('|');
|
|
49
49
|
const statusIconSentiment = sentiment$1 === 'success' ? sentiment.Sentiment.POSITIVE : sentiment$1;
|
|
50
50
|
const handleTouchStart = () => {
|
|
51
51
|
setShouldFire(true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoPrompt.js","sources":["../../../src/prompt/InfoPrompt/InfoPrompt.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"InfoPrompt.js","sources":["../../../src/prompt/InfoPrompt/InfoPrompt.tsx"],"sourcesContent":["import { HTMLAttributes, ReactNode, useState } from 'react';\nimport { LiveRegion, Sentiment, Typography } from '../../common';\nimport type { AriaLive } from '../../common';\nimport { GiftBox } from '@transferwise/icons';\nimport type { Sentiment as SurfaceSentiment } from '../../sentimentSurface';\nimport StatusIcon from '../../statusIcon';\nimport { clsx } from 'clsx';\nimport Body from '../../body';\nimport Link, { LinkProps } from '../../link';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nexport type InfoPromptAction = Pick<LinkProps, 'href' | 'target' | 'onClick'> & {\n /**\n * The label text for the action link\n */\n label: string;\n};\n\nexport type InfoPromptMedia = {\n /**\n * The icon/image asset to display.\n * The asset should include its own accessibility attributes (e.g. title, aria-label) if it conveys meaning.\n */\n asset: ReactNode;\n};\n\nexport type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'aria-live' | 'role'> &\n Pick<PrimitivePromptProps, 'data-testid'> & {\n /**\n * The sentiment determines the colour scheme\n * @default 'neutral'\n */\n sentiment?: SurfaceSentiment;\n /**\n * Handler called when the close button is clicked.\n * If not provided, the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Custom media to override the default status icon.\n * Success and proposition sentiments support 2 status variations: standard checkmark & confetti.\n */\n media?: InfoPromptMedia;\n /**\n * Action link to be displayed below the description\n */\n action?: InfoPromptAction;\n /**\n * Title content for the prompt\n */\n title?: string;\n /**\n * Description text for the prompt (required)\n */\n description: string;\n className?: string;\n /**\n * Sets the ARIA live region politeness level.\n * - `'polite'` — announced after the current speech (default)\n * - `'assertive'` — interrupts the current speech immediately\n * - `'off'` — disables the live region entirely\n * @default 'polite'\n */\n 'aria-live'?: AriaLive;\n };\n\n/**\n * `InfoPrompt` displays important contextual messages to users within a screen.\n * It provides a visually distinct way to communicate information, warnings, errors,\n * or positive feedback with optional actions and dismissal capabilities.\n *\n * Use this component to replace the deprecated `Alert` component (run codemod to migrate: **`npx \\@wise/wds-codemods@latest info-prompt`**).\n *\n * Guidance can be found in the [design system](https://wise.design/components/info-prompt).\n */\nexport const InfoPrompt = ({\n sentiment = 'neutral',\n onDismiss,\n media,\n action,\n title,\n description,\n className,\n 'aria-live': ariaLive = 'polite',\n 'data-testid': dataTestId,\n ...restProps\n}: InfoPromptProps) => {\n const [shouldFire, setShouldFire] = useState<boolean>();\n const announceOnChange = [title, description, action?.label].filter(Boolean).join('|');\n const statusIconSentiment =\n sentiment === 'success'\n ? Sentiment.POSITIVE\n : (sentiment as Exclude<SurfaceSentiment, 'proposition'>);\n\n const handleTouchStart = () => {\n setShouldFire(true);\n };\n\n const handleTouchEnd = () => {\n if (shouldFire && action?.href) {\n if (action.target === '_blank') {\n window.top?.open(action.href, '_blank', 'noopener, noreferrer');\n } else {\n window.top?.location.assign(action.href);\n }\n }\n setShouldFire(false);\n };\n\n const handleTouchMove = () => {\n setShouldFire(false);\n };\n\n const renderMedia = () => {\n if (media) {\n return <span className=\"wds-info-prompt__media\">{media.asset}</span>;\n }\n\n if (sentiment === 'proposition') {\n return (\n <span className=\"wds-info-prompt__media\">\n <GiftBox />\n </span>\n );\n }\n\n return <StatusIcon size={24} sentiment={statusIconSentiment} />;\n };\n\n // Render content directly in LiveRegion\n return (\n <LiveRegion aria-live={ariaLive} announceOnChange={announceOnChange}>\n <PrimitivePrompt\n sentiment={sentiment}\n media={renderMedia()}\n data-testid={dataTestId}\n className={clsx('wds-info-prompt', className)}\n {...restProps}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchMove={handleTouchMove}\n onDismiss={onDismiss}\n >\n <div className=\"wds-info-prompt__content\">\n {title && (\n <Body className=\"wds-info-prompt__title\" type={Typography.BODY_LARGE_BOLD} as=\"span\">\n {title}\n </Body>\n )}\n <Body as=\"span\" className=\"wds-info-prompt__description\">\n {description}\n </Body>\n {action && (\n <Link\n href={action.href}\n target={action.target}\n type={Typography.LINK_DEFAULT}\n className=\"wds-info-prompt__action\"\n onClick={action.onClick}\n >\n {action.label}\n </Link>\n )}\n </div>\n </PrimitivePrompt>\n </LiveRegion>\n );\n};\n"],"names":["InfoPrompt","sentiment","onDismiss","media","action","title","description","className","ariaLive","dataTestId","restProps","shouldFire","setShouldFire","useState","announceOnChange","label","filter","Boolean","join","statusIconSentiment","Sentiment","POSITIVE","handleTouchStart","handleTouchEnd","href","target","window","top","open","location","assign","handleTouchMove","renderMedia","_jsx","children","asset","GiftBox","StatusIcon","size","LiveRegion","PrimitivePrompt","clsx","onTouchStart","onTouchEnd","onTouchMove","_jsxs","Body","type","Typography","BODY_LARGE_BOLD","as","Link","LINK_DEFAULT","onClick"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState
|
|
1
|
+
import { useState } from 'react';
|
|
2
2
|
import '../../common/theme.mjs';
|
|
3
3
|
import '../../common/direction.mjs';
|
|
4
4
|
import '@transferwise/neptune-tokens';
|
|
@@ -43,7 +43,7 @@ const InfoPrompt = ({
|
|
|
43
43
|
...restProps
|
|
44
44
|
}) => {
|
|
45
45
|
const [shouldFire, setShouldFire] = useState();
|
|
46
|
-
const announceOnChange = [title,
|
|
46
|
+
const announceOnChange = [title, description, action?.label].filter(Boolean).join('|');
|
|
47
47
|
const statusIconSentiment = sentiment === 'success' ? Sentiment.POSITIVE : sentiment;
|
|
48
48
|
const handleTouchStart = () => {
|
|
49
49
|
setShouldFire(true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoPrompt.mjs","sources":["../../../src/prompt/InfoPrompt/InfoPrompt.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"InfoPrompt.mjs","sources":["../../../src/prompt/InfoPrompt/InfoPrompt.tsx"],"sourcesContent":["import { HTMLAttributes, ReactNode, useState } from 'react';\nimport { LiveRegion, Sentiment, Typography } from '../../common';\nimport type { AriaLive } from '../../common';\nimport { GiftBox } from '@transferwise/icons';\nimport type { Sentiment as SurfaceSentiment } from '../../sentimentSurface';\nimport StatusIcon from '../../statusIcon';\nimport { clsx } from 'clsx';\nimport Body from '../../body';\nimport Link, { LinkProps } from '../../link';\nimport { PrimitivePrompt, PrimitivePromptProps } from '../PrimitivePrompt';\n\nexport type InfoPromptAction = Pick<LinkProps, 'href' | 'target' | 'onClick'> & {\n /**\n * The label text for the action link\n */\n label: string;\n};\n\nexport type InfoPromptMedia = {\n /**\n * The icon/image asset to display.\n * The asset should include its own accessibility attributes (e.g. title, aria-label) if it conveys meaning.\n */\n asset: ReactNode;\n};\n\nexport type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'aria-live' | 'role'> &\n Pick<PrimitivePromptProps, 'data-testid'> & {\n /**\n * The sentiment determines the colour scheme\n * @default 'neutral'\n */\n sentiment?: SurfaceSentiment;\n /**\n * Handler called when the close button is clicked.\n * If not provided, the close button is hidden.\n */\n onDismiss?: () => void;\n /**\n * Custom media to override the default status icon.\n * Success and proposition sentiments support 2 status variations: standard checkmark & confetti.\n */\n media?: InfoPromptMedia;\n /**\n * Action link to be displayed below the description\n */\n action?: InfoPromptAction;\n /**\n * Title content for the prompt\n */\n title?: string;\n /**\n * Description text for the prompt (required)\n */\n description: string;\n className?: string;\n /**\n * Sets the ARIA live region politeness level.\n * - `'polite'` — announced after the current speech (default)\n * - `'assertive'` — interrupts the current speech immediately\n * - `'off'` — disables the live region entirely\n * @default 'polite'\n */\n 'aria-live'?: AriaLive;\n };\n\n/**\n * `InfoPrompt` displays important contextual messages to users within a screen.\n * It provides a visually distinct way to communicate information, warnings, errors,\n * or positive feedback with optional actions and dismissal capabilities.\n *\n * Use this component to replace the deprecated `Alert` component (run codemod to migrate: **`npx \\@wise/wds-codemods@latest info-prompt`**).\n *\n * Guidance can be found in the [design system](https://wise.design/components/info-prompt).\n */\nexport const InfoPrompt = ({\n sentiment = 'neutral',\n onDismiss,\n media,\n action,\n title,\n description,\n className,\n 'aria-live': ariaLive = 'polite',\n 'data-testid': dataTestId,\n ...restProps\n}: InfoPromptProps) => {\n const [shouldFire, setShouldFire] = useState<boolean>();\n const announceOnChange = [title, description, action?.label].filter(Boolean).join('|');\n const statusIconSentiment =\n sentiment === 'success'\n ? Sentiment.POSITIVE\n : (sentiment as Exclude<SurfaceSentiment, 'proposition'>);\n\n const handleTouchStart = () => {\n setShouldFire(true);\n };\n\n const handleTouchEnd = () => {\n if (shouldFire && action?.href) {\n if (action.target === '_blank') {\n window.top?.open(action.href, '_blank', 'noopener, noreferrer');\n } else {\n window.top?.location.assign(action.href);\n }\n }\n setShouldFire(false);\n };\n\n const handleTouchMove = () => {\n setShouldFire(false);\n };\n\n const renderMedia = () => {\n if (media) {\n return <span className=\"wds-info-prompt__media\">{media.asset}</span>;\n }\n\n if (sentiment === 'proposition') {\n return (\n <span className=\"wds-info-prompt__media\">\n <GiftBox />\n </span>\n );\n }\n\n return <StatusIcon size={24} sentiment={statusIconSentiment} />;\n };\n\n // Render content directly in LiveRegion\n return (\n <LiveRegion aria-live={ariaLive} announceOnChange={announceOnChange}>\n <PrimitivePrompt\n sentiment={sentiment}\n media={renderMedia()}\n data-testid={dataTestId}\n className={clsx('wds-info-prompt', className)}\n {...restProps}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchMove={handleTouchMove}\n onDismiss={onDismiss}\n >\n <div className=\"wds-info-prompt__content\">\n {title && (\n <Body className=\"wds-info-prompt__title\" type={Typography.BODY_LARGE_BOLD} as=\"span\">\n {title}\n </Body>\n )}\n <Body as=\"span\" className=\"wds-info-prompt__description\">\n {description}\n </Body>\n {action && (\n <Link\n href={action.href}\n target={action.target}\n type={Typography.LINK_DEFAULT}\n className=\"wds-info-prompt__action\"\n onClick={action.onClick}\n >\n {action.label}\n </Link>\n )}\n </div>\n </PrimitivePrompt>\n </LiveRegion>\n );\n};\n"],"names":["InfoPrompt","sentiment","onDismiss","media","action","title","description","className","ariaLive","dataTestId","restProps","shouldFire","setShouldFire","useState","announceOnChange","label","filter","Boolean","join","statusIconSentiment","Sentiment","POSITIVE","handleTouchStart","handleTouchEnd","href","target","window","top","open","location","assign","handleTouchMove","renderMedia","_jsx","children","asset","GiftBox","StatusIcon","size","LiveRegion","PrimitivePrompt","clsx","onTouchStart","onTouchEnd","onTouchMove","_jsxs","Body","type","Typography","BODY_LARGE_BOLD","as","Link","LINK_DEFAULT","onClick"],"mappings":"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"}
|
|
@@ -41,10 +41,9 @@ export type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'ar
|
|
|
41
41
|
*/
|
|
42
42
|
title?: string;
|
|
43
43
|
/**
|
|
44
|
-
* Description
|
|
45
|
-
* If the description contains an interactive element, the `action` prop must not be used simultaneously.
|
|
44
|
+
* Description text for the prompt (required)
|
|
46
45
|
*/
|
|
47
|
-
description:
|
|
46
|
+
description: string;
|
|
48
47
|
className?: string;
|
|
49
48
|
/**
|
|
50
49
|
* Sets the ARIA live region politeness level.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoPrompt.d.ts","sourceRoot":"","sources":["../../../../src/prompt/InfoPrompt/InfoPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"InfoPrompt.d.ts","sourceRoot":"","sources":["../../../../src/prompt/InfoPrompt/InfoPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,SAAS,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI5E,OAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAmB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,GAAG;IAC9E;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC,GAChG,IAAI,CAAC,oBAAoB,EAAE,aAAa,CAAC,GAAG;IAC1C;;;OAGG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;OAGG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC;CACxB,CAAC;AAEJ;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GAAI,wIAWxB,eAAe,gCAiFjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@transferwise/components",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-e523720",
|
|
4
4
|
"description": "Neptune React components",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -92,7 +92,6 @@
|
|
|
92
92
|
"storybook-addon-tag-badges": "^3.1.0",
|
|
93
93
|
"storybook-addon-test-codegen": "^3.0.1",
|
|
94
94
|
"@transferwise/less-config": "3.1.2",
|
|
95
|
-
"@transferwise/neptune-css": "14.28.0",
|
|
96
95
|
"@wise/components-theming": "1.10.2",
|
|
97
96
|
"@wise/wds-configs": "0.0.0"
|
|
98
97
|
},
|
|
@@ -6,7 +6,6 @@ import { Confetti, GiftBox, Star, Suitcase, Briefcase, Plane } from '@transferwi
|
|
|
6
6
|
import { lorem10, lorem20 } from '../../test-utils';
|
|
7
7
|
import Button from '../../button';
|
|
8
8
|
import Title from '../../title';
|
|
9
|
-
import Link from '../../link';
|
|
10
9
|
import { InfoPrompt, InfoPromptProps, InfoPromptMedia } from './InfoPrompt';
|
|
11
10
|
|
|
12
11
|
const withComponentGrid =
|
|
@@ -233,47 +232,6 @@ export const WithAction: StoryObj<InfoPromptProps> = {
|
|
|
233
232
|
),
|
|
234
233
|
};
|
|
235
234
|
|
|
236
|
-
/**
|
|
237
|
-
* The `description` prop accepts rich content (ReactNode), allowing inline interactive elements
|
|
238
|
-
* such as links that can trigger a popover.
|
|
239
|
-
*
|
|
240
|
-
* **Important**: If the description contains an interactive element, do not use the `action` prop
|
|
241
|
-
* simultaneously — InfoPrompt should have at most one interaction.
|
|
242
|
-
*/
|
|
243
|
-
export const WithRichDescription: StoryObj<InfoPromptProps> = {
|
|
244
|
-
render: (args: InfoPromptProps) => (
|
|
245
|
-
<>
|
|
246
|
-
<InfoPrompt
|
|
247
|
-
{...args}
|
|
248
|
-
sentiment="neutral"
|
|
249
|
-
description={
|
|
250
|
-
<>
|
|
251
|
-
Your transfer is subject to our{' '}
|
|
252
|
-
<Link href="/fees" target="_blank" type="link-default">
|
|
253
|
-
fee schedule
|
|
254
|
-
</Link>
|
|
255
|
-
.
|
|
256
|
-
</>
|
|
257
|
-
}
|
|
258
|
-
/>
|
|
259
|
-
<InfoPrompt
|
|
260
|
-
{...args}
|
|
261
|
-
sentiment="warning"
|
|
262
|
-
title="Verification Required"
|
|
263
|
-
description={
|
|
264
|
-
<>
|
|
265
|
-
Please{' '}
|
|
266
|
-
<Link href="/verify" type="link-default">
|
|
267
|
-
verify your identity
|
|
268
|
-
</Link>{' '}
|
|
269
|
-
to continue sending money.
|
|
270
|
-
</>
|
|
271
|
-
}
|
|
272
|
-
/>
|
|
273
|
-
</>
|
|
274
|
-
),
|
|
275
|
-
};
|
|
276
|
-
|
|
277
235
|
/**
|
|
278
236
|
* When `onDismiss` is provided, a close button appears allowing users to dismiss the prompt.
|
|
279
237
|
* Note: The component itself is not automatically removed - you must handle state management.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { WDS_LIVE_REGION_DELAY_MS } from '../../common/constants';
|
|
1
|
+
import { fireEvent, mockMatchMedia, render, screen, userEvent, waitFor } from '../../test-utils';
|
|
3
2
|
import { resetLiveRegionAnnouncementQueue } from '../../common/liveRegion/LiveRegion';
|
|
4
3
|
import { InfoPrompt, InfoPromptProps } from './InfoPrompt';
|
|
5
4
|
|
|
@@ -16,74 +15,11 @@ describe('InfoPrompt', () => {
|
|
|
16
15
|
resetLiveRegionAnnouncementQueue();
|
|
17
16
|
});
|
|
18
17
|
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
jest.clearAllTimers();
|
|
21
|
-
jest.useRealTimers();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
18
|
it('renders description', () => {
|
|
25
19
|
render(<InfoPrompt {...defaultProps} />);
|
|
26
20
|
expect(screen.getByText('Prompt description')).toBeInTheDocument();
|
|
27
21
|
});
|
|
28
22
|
|
|
29
|
-
it('renders rich-content description (ReactNode)', () => {
|
|
30
|
-
render(
|
|
31
|
-
<InfoPrompt
|
|
32
|
-
description={
|
|
33
|
-
<>
|
|
34
|
-
See our <a href="/fees">fee schedule</a>.
|
|
35
|
-
</>
|
|
36
|
-
}
|
|
37
|
-
/>,
|
|
38
|
-
);
|
|
39
|
-
expect(screen.getByRole('link', { name: 'fee schedule', hidden: true })).toBeInTheDocument();
|
|
40
|
-
expect(screen.getByRole('link', { name: 'fee schedule', hidden: true })).toHaveAttribute(
|
|
41
|
-
'href',
|
|
42
|
-
'/fees',
|
|
43
|
-
);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('re-announces when rich-content description text changes', () => {
|
|
47
|
-
jest.useFakeTimers();
|
|
48
|
-
|
|
49
|
-
const { rerender } = render(
|
|
50
|
-
<InfoPrompt
|
|
51
|
-
description={
|
|
52
|
-
<>
|
|
53
|
-
See our <a href="/fees">fee schedule</a>.
|
|
54
|
-
</>
|
|
55
|
-
}
|
|
56
|
-
/>,
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
act(() => {
|
|
60
|
-
jest.advanceTimersByTime(WDS_LIVE_REGION_DELAY_MS);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const liveRegion = screen.getByRole('status');
|
|
64
|
-
expect(liveRegion.firstElementChild).not.toHaveAttribute('aria-hidden');
|
|
65
|
-
expect(liveRegion).toHaveTextContent('See our fee schedule.');
|
|
66
|
-
|
|
67
|
-
rerender(
|
|
68
|
-
<InfoPrompt
|
|
69
|
-
description={
|
|
70
|
-
<>
|
|
71
|
-
Read the updated <a href="/fees">pricing guide</a>.
|
|
72
|
-
</>
|
|
73
|
-
}
|
|
74
|
-
/>,
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
expect(liveRegion.firstElementChild).toHaveAttribute('aria-hidden', 'true');
|
|
78
|
-
|
|
79
|
-
act(() => {
|
|
80
|
-
jest.advanceTimersByTime(WDS_LIVE_REGION_DELAY_MS);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
expect(liveRegion.firstElementChild).not.toHaveAttribute('aria-hidden');
|
|
84
|
-
expect(liveRegion).toHaveTextContent('Read the updated pricing guide.');
|
|
85
|
-
});
|
|
86
|
-
|
|
87
23
|
it('renders title when provided', () => {
|
|
88
24
|
render(<InfoPrompt {...defaultProps} title="Test Title" />);
|
|
89
25
|
expect(screen.getByText('Test Title')).toBeInTheDocument();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HTMLAttributes, ReactNode, useState } from 'react';
|
|
2
2
|
import { LiveRegion, Sentiment, Typography } from '../../common';
|
|
3
3
|
import type { AriaLive } from '../../common';
|
|
4
4
|
import { GiftBox } from '@transferwise/icons';
|
|
@@ -50,10 +50,9 @@ export type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'ar
|
|
|
50
50
|
*/
|
|
51
51
|
title?: string;
|
|
52
52
|
/**
|
|
53
|
-
* Description
|
|
54
|
-
* If the description contains an interactive element, the `action` prop must not be used simultaneously.
|
|
53
|
+
* Description text for the prompt (required)
|
|
55
54
|
*/
|
|
56
|
-
description:
|
|
55
|
+
description: string;
|
|
57
56
|
className?: string;
|
|
58
57
|
/**
|
|
59
58
|
* Sets the ARIA live region politeness level.
|
|
@@ -87,17 +86,7 @@ export const InfoPrompt = ({
|
|
|
87
86
|
...restProps
|
|
88
87
|
}: InfoPromptProps) => {
|
|
89
88
|
const [shouldFire, setShouldFire] = useState<boolean>();
|
|
90
|
-
const announceOnChange = [
|
|
91
|
-
title,
|
|
92
|
-
Children.toArray(description)
|
|
93
|
-
.map((child) =>
|
|
94
|
-
isValidElement<{ children?: ReactNode }>(child) ? child.props.children : child,
|
|
95
|
-
)
|
|
96
|
-
.join(''),
|
|
97
|
-
action?.label,
|
|
98
|
-
]
|
|
99
|
-
.filter(Boolean)
|
|
100
|
-
.join('|');
|
|
89
|
+
const announceOnChange = [title, description, action?.label].filter(Boolean).join('|');
|
|
101
90
|
const statusIconSentiment =
|
|
102
91
|
sentiment === 'success'
|
|
103
92
|
? Sentiment.POSITIVE
|