@transferwise/components 46.131.1 → 46.132.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/build/common/liveRegion/LiveRegion.js +46 -7
  2. package/build/common/liveRegion/LiveRegion.js.map +1 -1
  3. package/build/common/liveRegion/LiveRegion.mjs +46 -7
  4. package/build/common/liveRegion/LiveRegion.mjs.map +1 -1
  5. package/build/flowNavigation/FlowNavigation.js +1 -0
  6. package/build/flowNavigation/FlowNavigation.js.map +1 -1
  7. package/build/flowNavigation/FlowNavigation.mjs +1 -0
  8. package/build/flowNavigation/FlowNavigation.mjs.map +1 -1
  9. package/build/main.css +52 -1
  10. package/build/overlayHeader/OverlayHeader.js +1 -0
  11. package/build/overlayHeader/OverlayHeader.js.map +1 -1
  12. package/build/overlayHeader/OverlayHeader.mjs +1 -0
  13. package/build/overlayHeader/OverlayHeader.mjs.map +1 -1
  14. package/build/prompt/InfoPrompt/InfoPrompt.js +2 -0
  15. package/build/prompt/InfoPrompt/InfoPrompt.js.map +1 -1
  16. package/build/prompt/InfoPrompt/InfoPrompt.mjs +2 -0
  17. package/build/prompt/InfoPrompt/InfoPrompt.mjs.map +1 -1
  18. package/build/styles/common/liveRegion/LiveRegion.css +3 -0
  19. package/build/styles/css/neptune.css +48 -1
  20. package/build/styles/main.css +52 -1
  21. package/build/styles/styles/less/neptune.css +48 -1
  22. package/build/types/common/liveRegion/LiveRegion.d.ts +5 -2
  23. package/build/types/common/liveRegion/LiveRegion.d.ts.map +1 -1
  24. package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts.map +1 -1
  25. package/package.json +2 -2
  26. package/src/alert/Alert.story.tsx +0 -6
  27. package/src/button/_stories/Button.story.tsx +0 -5
  28. package/src/checkboxButton/CheckboxButton.story.tsx +0 -1
  29. package/src/circularButton/CircularButton.story.tsx +0 -1
  30. package/src/common/liveRegion/LiveRegion.css +3 -0
  31. package/src/common/liveRegion/LiveRegion.less +3 -0
  32. package/src/common/liveRegion/LiveRegion.test.tsx +69 -2
  33. package/src/common/liveRegion/LiveRegion.tsx +77 -8
  34. package/src/dateLookup/DateLookup.test.story.tsx +0 -7
  35. package/src/dateLookup/DateLookup.test.tsx +22 -0
  36. package/src/display/Display.story.tsx +15 -1
  37. package/src/expressiveMoneyInput/ExpressiveMoneyInput.story.tsx +0 -1
  38. package/src/header/Header.story.tsx +0 -5
  39. package/src/inputWithDisplayFormat/InputWithDisplayFormat.story.tsx +0 -1
  40. package/src/inputs/SelectInput/_stories/SelectInput.docs.mdx +62 -0
  41. package/src/inputs/SelectInput/_stories/SelectInput.story.tsx +796 -220
  42. package/src/inputs/SelectInput/_stories/SelectInput.test.story.tsx +433 -4
  43. package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.story.tsx +0 -5
  44. package/src/listItem/AvatarLayout/ListItemAvatarLayout.story.tsx +0 -5
  45. package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +0 -5
  46. package/src/listItem/Button/ListItemButton.story.tsx +0 -5
  47. package/src/listItem/Checkbox/ListItemCheckbox.story.tsx +0 -5
  48. package/src/listItem/IconButton/ListItemIconButton.story.tsx +0 -5
  49. package/src/listItem/Image/ListItemImage.story.tsx +0 -5
  50. package/src/listItem/Navigation/ListItemNavigation.story.tsx +0 -5
  51. package/src/listItem/Prompt/ListItemPrompt.story.tsx +1 -5
  52. package/src/listItem/Radio/ListItemRadio.story.tsx +0 -5
  53. package/src/listItem/Switch/ListItemSwitch.story.tsx +0 -5
  54. package/src/listItem/_stories/ListItem.disabled.story.tsx +0 -1
  55. package/src/listItem/_stories/ListItem.scenarios.story.tsx +0 -1
  56. package/src/listItem/_stories/ListItem.story.tsx +0 -5
  57. package/src/main.css +52 -1
  58. package/src/main.less +1 -0
  59. package/src/modal/Modal.story.tsx +0 -1
  60. package/src/popover/Popover.story.tsx +0 -1
  61. package/src/prompt/ActionPrompt/ActionPrompt.story.tsx +0 -5
  62. package/src/prompt/InfoPrompt/InfoPrompt.story.tsx +0 -5
  63. package/src/prompt/InfoPrompt/InfoPrompt.test.story.tsx +142 -5
  64. package/src/prompt/InfoPrompt/InfoPrompt.test.tsx +11 -6
  65. package/src/prompt/InfoPrompt/InfoPrompt.tsx +2 -1
  66. package/src/prompt/InlinePrompt/InlinePrompt.story.tsx +0 -5
  67. package/src/provider/theme/ThemeProvider.story.tsx +8 -0
  68. package/src/sentimentSurface/SentimentSurface.story.tsx +0 -5
  69. package/src/sticky/Sticky.story.tsx +0 -1
  70. package/src/styles/less/core/_typography.less +15 -2
  71. package/src/styles/less/neptune.css +48 -1
  72. package/src/tokens/tokens.story.tsx +1 -1
package/src/main.css CHANGED
@@ -3492,10 +3492,57 @@ a,
3492
3492
  .np-text-display-large,
3493
3493
  .np-text-display-medium,
3494
3494
  .np-text-display-small {
3495
- font-family: "Wise Sans", Inter, sans-serif;
3495
+ font-family: 'Wise Sans', 'Inter', sans-serif;
3496
+ font-family: var(--font-family-display);
3496
3497
  font-synthesis: none;
3497
3498
  }
3498
3499
 
3500
+ :lang(ja) .display-1,
3501
+ :lang(ja) .display-2,
3502
+ :lang(ja) .display-3,
3503
+ :lang(ja) .display-4,
3504
+ :lang(ja) .display-5,
3505
+ :lang(ja) .np-text-display-extra-large,
3506
+ :lang(ja) .np-text-display-large,
3507
+ :lang(ja) .np-text-display-medium,
3508
+ :lang(ja) .np-text-display-small,
3509
+ :lang(th) .display-1,
3510
+ :lang(th) .display-2,
3511
+ :lang(th) .display-3,
3512
+ :lang(th) .display-4,
3513
+ :lang(th) .display-5,
3514
+ :lang(th) .np-text-display-extra-large,
3515
+ :lang(th) .np-text-display-large,
3516
+ :lang(th) .np-text-display-medium,
3517
+ :lang(th) .np-text-display-small,
3518
+ :lang(zh-CN) .display-1,
3519
+ :lang(zh-CN) .display-2,
3520
+ :lang(zh-CN) .display-3,
3521
+ :lang(zh-CN) .display-4,
3522
+ :lang(zh-CN) .display-5,
3523
+ :lang(zh-CN) .np-text-display-extra-large,
3524
+ :lang(zh-CN) .np-text-display-large,
3525
+ :lang(zh-CN) .np-text-display-medium,
3526
+ :lang(zh-CN) .np-text-display-small,
3527
+ :lang(zh-HK) .display-1,
3528
+ :lang(zh-HK) .display-2,
3529
+ :lang(zh-HK) .display-3,
3530
+ :lang(zh-HK) .display-4,
3531
+ :lang(zh-HK) .display-5,
3532
+ :lang(zh-HK) .np-text-display-extra-large,
3533
+ :lang(zh-HK) .np-text-display-large,
3534
+ :lang(zh-HK) .np-text-display-medium,
3535
+ :lang(zh-HK) .np-text-display-small {
3536
+ /**
3537
+ * Wise Sans covers extended Latin glyphs for logged-in experiences and a small subset
3538
+ * of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
3539
+ * font files are browser-cached and we carried over to launchpad, where it causes issues
3540
+ * for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
3541
+ */
3542
+ font-family: 'Inter', Helvetica, Arial, sans-serif;
3543
+ font-family: var(--font-family-regular);
3544
+ }
3545
+
3499
3546
  /* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
3500
3547
 
3501
3548
  .np-text-display-extra-large,
@@ -28096,6 +28143,10 @@ a[data-toggle="tooltip"] {
28096
28143
  --Card-padding: var(--size-16);
28097
28144
  }
28098
28145
 
28146
+ .wds-LiveRegion {
28147
+ width: 100%;
28148
+ }
28149
+
28099
28150
  .np-bottom-sheet {
28100
28151
  border-radius: 10px 10px 0 0;
28101
28152
  }
package/src/main.less CHANGED
@@ -22,6 +22,7 @@
22
22
  @import "./circularButton/CircularButton.less";
23
23
  @import "./common/circle/Circle.less";
24
24
  @import "./common/baseCard/BaseCard.less";
25
+ @import "./common/liveRegion/LiveRegion.less";
25
26
  @import "./common/bottomSheet/BottomSheet.less";
26
27
  @import "./common/closeButton/CloseButton.less";
27
28
  @import "./common/Option/Option.less";
@@ -10,7 +10,6 @@ import { lorem10, lorem100, lorem1000 } from '../test-utils';
10
10
  export default {
11
11
  component: Modal,
12
12
  title: 'Dialogs/Modal',
13
-
14
13
  args: {
15
14
  size: 'md',
16
15
  position: 'center',
@@ -26,7 +26,6 @@ const Content = () => (
26
26
  export default {
27
27
  component: Popover,
28
28
  title: 'Dialogs/Popover',
29
-
30
29
  args: {
31
30
  preferredPlacement: Position.BOTTOM,
32
31
  title: 'Guaranteed rate',
@@ -82,11 +82,6 @@ const meta: Meta<typeof ActionPrompt> = {
82
82
  },
83
83
  },
84
84
  },
85
- parameters: {
86
- docs: {
87
- toc: true,
88
- },
89
- },
90
85
  };
91
86
 
92
87
  export default meta;
@@ -66,11 +66,6 @@ export default {
66
66
  },
67
67
  },
68
68
  },
69
- parameters: {
70
- docs: {
71
- toc: true,
72
- },
73
- },
74
69
  } satisfies Meta<InfoPromptProps>;
75
70
 
76
71
  /**
@@ -40,7 +40,6 @@ const wait = async (duration = 500) =>
40
40
  export const DismissInteraction: Story = {
41
41
  play: async ({ canvasElement, step }) => {
42
42
  const canvas = within(canvasElement);
43
- const dismissButton = canvas.getByRole('button', { name: /close/i });
44
43
 
45
44
  await step('Verify prompt is visible', async () => {
46
45
  await waitFor(async () =>
@@ -49,6 +48,7 @@ export const DismissInteraction: Story = {
49
48
  });
50
49
 
51
50
  await step('Click the dismiss button', async () => {
51
+ const dismissButton = canvas.getByRole('button', { name: /close/i, hidden: true });
52
52
  await userEvent.click(dismissButton);
53
53
  });
54
54
 
@@ -120,7 +120,6 @@ export const DismissViaKeyboard: Story = {
120
120
  export const ActionClickInteraction: Story = {
121
121
  play: async ({ canvasElement, step }) => {
122
122
  const canvas = within(canvasElement);
123
- const actionLink = canvas.getByRole('link', { name: 'Learn more' });
124
123
 
125
124
  await step('Verify prompt with action is visible', async () => {
126
125
  await waitFor(async () =>
@@ -129,6 +128,7 @@ export const ActionClickInteraction: Story = {
129
128
  });
130
129
 
131
130
  await step('Click the action link', async () => {
131
+ const actionLink = await waitFor(() => canvas.getByRole('link', { name: 'Learn more' }));
132
132
  await userEvent.click(actionLink);
133
133
  });
134
134
 
@@ -165,7 +165,6 @@ export const ActionClickInteraction: Story = {
165
165
  export const MultipleDismissInteraction: Story = {
166
166
  play: async ({ canvasElement, step }) => {
167
167
  const canvas = within(canvasElement);
168
- const dismissButtons = canvas.getAllByRole('button', { name: /close/i });
169
168
 
170
169
  await step('Verify all prompts are visible', async () => {
171
170
  await waitFor(async () => {
@@ -177,6 +176,7 @@ export const MultipleDismissInteraction: Story = {
177
176
 
178
177
  await step('Dismiss the warning prompt', async () => {
179
178
  // Click the second dismiss button (warning)
179
+ const dismissButtons = canvas.getAllByRole('button', { name: /close/i, hidden: true });
180
180
  await userEvent.click(dismissButtons[1]);
181
181
  });
182
182
 
@@ -220,13 +220,13 @@ export const MultipleDismissInteraction: Story = {
220
220
  export const TouchInteraction: Story = {
221
221
  play: async ({ canvasElement, step }) => {
222
222
  const canvas = within(canvasElement);
223
- const actionLink = canvas.getByRole('link', { name: 'Navigate' });
224
223
 
225
224
  await step('Verify prompt with action is visible', async () => {
226
225
  await waitFor(async () => expect(canvas.getByText('Tap the prompt.')).toBeInTheDocument());
227
226
  });
228
227
 
229
228
  await step('Click the action (simulating touch)', async () => {
229
+ const actionLink = await waitFor(() => canvas.getByRole('link', { name: 'Navigate' }));
230
230
  await userEvent.click(actionLink);
231
231
  });
232
232
 
@@ -352,6 +352,143 @@ export const LiveRegionAssertive: Story = {
352
352
  },
353
353
  };
354
354
 
355
+ /**
356
+ * Test that a polite InfoPrompt added to the DOM gets a delayed live region.
357
+ */
358
+ export const LiveRegionPoliteWhenAddedToDom: Story = {
359
+ play: async ({ canvasElement, step }) => {
360
+ const canvas = within(canvasElement);
361
+
362
+ await step('Verify prompt is not in the DOM before trigger', async () => {
363
+ await expect(canvas.queryByText('Polite prompt added later')).not.toBeInTheDocument();
364
+ await expect(canvas.queryByRole('status')).not.toBeInTheDocument();
365
+ });
366
+
367
+ await step('Add two prompts to the DOM', async () => {
368
+ const addButton = canvas.getByRole('button', { name: 'Add polite prompt' });
369
+ await userEvent.click(addButton);
370
+ await userEvent.click(addButton);
371
+ });
372
+
373
+ await step('Verify delayed polite live regions appear with content', async () => {
374
+ await expect(canvas.getByText('Polite prompt added later 1')).toBeInTheDocument();
375
+ await expect(canvas.getByText('Polite prompt added later 2')).toBeInTheDocument();
376
+ const initialLiveRegions = canvas.queryAllByRole('status');
377
+ await expect(initialLiveRegions).toHaveLength(2);
378
+ await expect(initialLiveRegions[0].firstElementChild).toHaveAttribute('aria-hidden', 'true');
379
+ await expect(initialLiveRegions[1].firstElementChild).toHaveAttribute('aria-hidden', 'true');
380
+
381
+ await waitFor(async () => {
382
+ const liveRegions = canvas.getAllByRole('status');
383
+ await expect(liveRegions).toHaveLength(2);
384
+ await expect(liveRegions[0]).toHaveAttribute('aria-live', 'polite');
385
+ await expect(liveRegions[1]).toHaveAttribute('aria-live', 'polite');
386
+ await expect(liveRegions[0]).toHaveAttribute('aria-atomic', 'true');
387
+ await expect(liveRegions[1]).toHaveAttribute('aria-atomic', 'true');
388
+ await expect(liveRegions[0].firstElementChild).not.toHaveAttribute('aria-hidden');
389
+ await expect(liveRegions[1].firstElementChild).not.toHaveAttribute('aria-hidden');
390
+ await expect(
391
+ within(liveRegions[0]).getByText('Polite prompt added later 1'),
392
+ ).toBeInTheDocument();
393
+ await expect(
394
+ within(liveRegions[1]).getByText('Polite prompt added later 2'),
395
+ ).toBeInTheDocument();
396
+ });
397
+ });
398
+ },
399
+ render: function Render(args: InfoPromptProps) {
400
+ const [promptIndexes, setPromptIndexes] = useState<number[]>([]);
401
+
402
+ const addPrompt = () => {
403
+ setPromptIndexes((previousIndexes) => [...previousIndexes, previousIndexes.length + 1]);
404
+ };
405
+
406
+ return (
407
+ <>
408
+ <button type="button" onClick={addPrompt}>
409
+ Add polite prompt
410
+ </button>
411
+ {promptIndexes.map((promptIndex) => (
412
+ <InfoPrompt
413
+ key={`polite-${promptIndex}`}
414
+ {...args}
415
+ description={`Polite prompt added later ${promptIndex}`}
416
+ />
417
+ ))}
418
+ </>
419
+ );
420
+ },
421
+ };
422
+
423
+ /**
424
+ * Test that an assertive InfoPrompt added to the DOM gets a delayed live region.
425
+ */
426
+ export const LiveRegionAssertiveWhenAddedToDom: Story = {
427
+ play: async ({ canvasElement, step }) => {
428
+ const canvas = within(canvasElement);
429
+
430
+ await step('Verify prompt is not in the DOM before trigger', async () => {
431
+ await expect(canvas.queryByText('Assertive prompt added later')).not.toBeInTheDocument();
432
+ await expect(canvas.queryByRole('alert')).not.toBeInTheDocument();
433
+ });
434
+
435
+ await step('Add two prompts to the DOM', async () => {
436
+ const addButton = canvas.getByRole('button', { name: 'Add assertive prompt' });
437
+ await userEvent.click(addButton);
438
+ await userEvent.click(addButton);
439
+ });
440
+
441
+ await step('Verify delayed assertive live regions appear with content', async () => {
442
+ await expect(canvas.getByText('Assertive prompt added later 1')).toBeInTheDocument();
443
+ await expect(canvas.getByText('Assertive prompt added later 2')).toBeInTheDocument();
444
+ const initialLiveRegions = canvas.queryAllByRole('alert');
445
+ await expect(initialLiveRegions).toHaveLength(2);
446
+ await expect(initialLiveRegions[0].firstElementChild).toHaveAttribute('aria-hidden', 'true');
447
+ await expect(initialLiveRegions[1].firstElementChild).toHaveAttribute('aria-hidden', 'true');
448
+
449
+ await waitFor(async () => {
450
+ const liveRegions = canvas.getAllByRole('alert');
451
+ await expect(liveRegions).toHaveLength(2);
452
+ await expect(liveRegions[0]).toHaveAttribute('aria-live', 'assertive');
453
+ await expect(liveRegions[1]).toHaveAttribute('aria-live', 'assertive');
454
+ await expect(liveRegions[0]).toHaveAttribute('aria-atomic', 'true');
455
+ await expect(liveRegions[1]).toHaveAttribute('aria-atomic', 'true');
456
+ await expect(liveRegions[0].firstElementChild).not.toHaveAttribute('aria-hidden');
457
+ await expect(liveRegions[1].firstElementChild).not.toHaveAttribute('aria-hidden');
458
+ await expect(
459
+ within(liveRegions[0]).getByText('Assertive prompt added later 1'),
460
+ ).toBeInTheDocument();
461
+ await expect(
462
+ within(liveRegions[1]).getByText('Assertive prompt added later 2'),
463
+ ).toBeInTheDocument();
464
+ });
465
+ });
466
+ },
467
+ render: function Render(args: InfoPromptProps) {
468
+ const [promptIndexes, setPromptIndexes] = useState<number[]>([]);
469
+
470
+ const addPrompt = () => {
471
+ setPromptIndexes((previousIndexes) => [...previousIndexes, previousIndexes.length + 1]);
472
+ };
473
+
474
+ return (
475
+ <>
476
+ <button type="button" onClick={addPrompt}>
477
+ Add assertive prompt
478
+ </button>
479
+ {promptIndexes.map((promptIndex) => (
480
+ <InfoPrompt
481
+ key={`assertive-${promptIndex}`}
482
+ {...args}
483
+ description={`Assertive prompt added later ${promptIndex}`}
484
+ aria-live="assertive"
485
+ />
486
+ ))}
487
+ </>
488
+ );
489
+ },
490
+ };
491
+
355
492
  /**
356
493
  * Test that aria-live="off" renders without a live region wrapper.
357
494
  */
@@ -390,7 +527,7 @@ export const LiveRegionDismiss: Story = {
390
527
  });
391
528
 
392
529
  await step('Dismiss the prompt', async () => {
393
- const dismissButton = canvas.getByRole('button', { name: /close/i });
530
+ const dismissButton = canvas.getByRole('button', { name: /close/i, hidden: true });
394
531
  await userEvent.click(dismissButton);
395
532
  });
396
533
 
@@ -1,4 +1,5 @@
1
- import { fireEvent, mockMatchMedia, render, screen, userEvent } from '../../test-utils';
1
+ import { fireEvent, mockMatchMedia, render, screen, userEvent, waitFor } from '../../test-utils';
2
+ import { resetLiveRegionAnnouncementQueue } from '../../common/liveRegion/LiveRegion';
2
3
  import { InfoPrompt, InfoPromptProps } from './InfoPrompt';
3
4
 
4
5
  mockMatchMedia();
@@ -10,6 +11,10 @@ describe('InfoPrompt', () => {
10
11
  description: 'Prompt description',
11
12
  };
12
13
 
14
+ beforeEach(() => {
15
+ resetLiveRegionAnnouncementQueue();
16
+ });
17
+
13
18
  it('renders description', () => {
14
19
  render(<InfoPrompt {...defaultProps} />);
15
20
  expect(screen.getByText('Prompt description')).toBeInTheDocument();
@@ -59,23 +64,23 @@ describe('InfoPrompt', () => {
59
64
  });
60
65
 
61
66
  describe('action', () => {
62
- it('should render action link when action is provided with href', () => {
67
+ it('should render action link when action is provided with href', async () => {
63
68
  render(
64
69
  <InfoPrompt {...defaultProps} action={{ label: 'Learn more', href: '/learn-more' }} />,
65
70
  );
66
- const actionLink = screen.getByRole('link', { name: 'Learn more' });
71
+ const actionLink = await screen.findByRole('link', { name: 'Learn more' });
67
72
  expect(actionLink).toBeInTheDocument();
68
73
  expect(actionLink).toHaveAttribute('href', '/learn-more');
69
74
  });
70
75
 
71
- it('should render action link with target when provided', () => {
76
+ it('should render action link with target when provided', async () => {
72
77
  render(
73
78
  <InfoPrompt
74
79
  {...defaultProps}
75
80
  action={{ label: 'External link', href: 'https://example.com', target: '_blank' }}
76
81
  />,
77
82
  );
78
- const actionLink = screen.getByRole('link', { name: /External link/i });
83
+ const actionLink = await screen.findByRole('link', { name: /External link/i });
79
84
  expect(actionLink).toHaveAttribute('target', '_blank');
80
85
  });
81
86
 
@@ -83,7 +88,7 @@ describe('InfoPrompt', () => {
83
88
  const user = userEvent.setup();
84
89
  const onClick = jest.fn();
85
90
  render(<InfoPrompt {...defaultProps} action={{ label: 'Click me', onClick }} />);
86
- const actionButton = screen.getByRole('button', { name: 'Click me' });
91
+ const actionButton = await screen.findByRole('button', { name: 'Click me' });
87
92
  await user.click(actionButton);
88
93
  expect(onClick).toHaveBeenCalledTimes(1);
89
94
  });
@@ -86,6 +86,7 @@ export const InfoPrompt = ({
86
86
  ...restProps
87
87
  }: InfoPromptProps) => {
88
88
  const [shouldFire, setShouldFire] = useState<boolean>();
89
+ const announceOnChange = [title, description, action?.label].filter(Boolean).join('|');
89
90
  const statusIconSentiment =
90
91
  sentiment === 'success'
91
92
  ? Sentiment.POSITIVE
@@ -124,7 +125,7 @@ export const InfoPrompt = ({
124
125
 
125
126
  // Render content directly in LiveRegion
126
127
  return (
127
- <LiveRegion aria-live={ariaLive}>
128
+ <LiveRegion aria-live={ariaLive} announceOnChange={announceOnChange}>
128
129
  <PrimitivePrompt
129
130
  sentiment={sentiment}
130
131
  media={renderMedia()}
@@ -53,11 +53,6 @@ export default {
53
53
  },
54
54
  },
55
55
  },
56
- parameters: {
57
- docs: {
58
- toc: true,
59
- },
60
- },
61
56
  } satisfies Meta<InlinePromptProps>;
62
57
 
63
58
  /**
@@ -24,6 +24,14 @@ export default {
24
24
  component: ThemeProvider,
25
25
  title: 'Foundations/ThemeProvider',
26
26
  tags: ['!manifest'],
27
+ parameters: {
28
+ docs: {
29
+ description: {
30
+ component:
31
+ 'Components require `ThemeProvider` from `@wise/components-theming` to be wrapped around your application for theming support. Available themes include: `personal`, `business`, `platform`, and variants with different color schemes.',
32
+ },
33
+ },
34
+ },
27
35
  } satisfies Meta<typeof ThemeProvider>;
28
36
 
29
37
  type Story = StoryObj<typeof ThemeProvider>;
@@ -102,11 +102,6 @@ const meta: Meta<typeof SentimentSurface> = {
102
102
  'data-testid': undefined,
103
103
  children: 'This is a sentiment surface',
104
104
  },
105
- parameters: {
106
- docs: {
107
- toc: true,
108
- },
109
- },
110
105
  };
111
106
 
112
107
  export default meta;
@@ -6,7 +6,6 @@ import { allModes } from '../../.storybook/modes';
6
6
  const meta: Meta<typeof Sticky> = {
7
7
  component: Sticky,
8
8
  title: 'Dialogs/Sticky',
9
-
10
9
  args: {
11
10
  open: true,
12
11
  position: 'bottom', // Default position
@@ -25,7 +25,7 @@ h6,
25
25
  line-height: var(--line-height-title);
26
26
  letter-spacing: 0;
27
27
  .np-text-hyphenated;
28
-
28
+
29
29
  + p,
30
30
  + ul:not(.list-unstyled),
31
31
  + ol:not(.list-unstyled) {
@@ -204,8 +204,21 @@ a,
204
204
  .np-text-display-large,
205
205
  .np-text-display-medium,
206
206
  .np-text-display-small {
207
- font-family: "Wise Sans", Inter, sans-serif;
207
+ font-family: var(--font-family-display);
208
208
  font-synthesis: none;
209
+
210
+ :lang(ja) &,
211
+ :lang(th) &,
212
+ :lang(zh-CN) &,
213
+ :lang(zh-HK) & {
214
+ /**
215
+ * Wise Sans covers extended Latin glyphs for logged-in experiences and a small subset
216
+ * of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
217
+ * font files are browser-cached and we carried over to launchpad, where it causes issues
218
+ * for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
219
+ */
220
+ font-family: var(--font-family-regular);
221
+ }
209
222
  }
210
223
 
211
224
  /* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
@@ -3492,10 +3492,57 @@ a,
3492
3492
  .np-text-display-large,
3493
3493
  .np-text-display-medium,
3494
3494
  .np-text-display-small {
3495
- font-family: "Wise Sans", Inter, sans-serif;
3495
+ font-family: 'Wise Sans', 'Inter', sans-serif;
3496
+ font-family: var(--font-family-display);
3496
3497
  font-synthesis: none;
3497
3498
  }
3498
3499
 
3500
+ :lang(ja) .display-1,
3501
+ :lang(ja) .display-2,
3502
+ :lang(ja) .display-3,
3503
+ :lang(ja) .display-4,
3504
+ :lang(ja) .display-5,
3505
+ :lang(ja) .np-text-display-extra-large,
3506
+ :lang(ja) .np-text-display-large,
3507
+ :lang(ja) .np-text-display-medium,
3508
+ :lang(ja) .np-text-display-small,
3509
+ :lang(th) .display-1,
3510
+ :lang(th) .display-2,
3511
+ :lang(th) .display-3,
3512
+ :lang(th) .display-4,
3513
+ :lang(th) .display-5,
3514
+ :lang(th) .np-text-display-extra-large,
3515
+ :lang(th) .np-text-display-large,
3516
+ :lang(th) .np-text-display-medium,
3517
+ :lang(th) .np-text-display-small,
3518
+ :lang(zh-CN) .display-1,
3519
+ :lang(zh-CN) .display-2,
3520
+ :lang(zh-CN) .display-3,
3521
+ :lang(zh-CN) .display-4,
3522
+ :lang(zh-CN) .display-5,
3523
+ :lang(zh-CN) .np-text-display-extra-large,
3524
+ :lang(zh-CN) .np-text-display-large,
3525
+ :lang(zh-CN) .np-text-display-medium,
3526
+ :lang(zh-CN) .np-text-display-small,
3527
+ :lang(zh-HK) .display-1,
3528
+ :lang(zh-HK) .display-2,
3529
+ :lang(zh-HK) .display-3,
3530
+ :lang(zh-HK) .display-4,
3531
+ :lang(zh-HK) .display-5,
3532
+ :lang(zh-HK) .np-text-display-extra-large,
3533
+ :lang(zh-HK) .np-text-display-large,
3534
+ :lang(zh-HK) .np-text-display-medium,
3535
+ :lang(zh-HK) .np-text-display-small {
3536
+ /**
3537
+ * Wise Sans covers extended Latin glyphs for logged-in experiences and a small subset
3538
+ * of Japanese ones for the logged out ones (exposed by the Editorial DS). Unfortunately,
3539
+ * font files are browser-cached and we carried over to launchpad, where it causes issues
3540
+ * for unsupported locales, especially those that share glyphs, like Japanese and Chinese.
3541
+ */
3542
+ font-family: 'Inter', Helvetica, Arial, sans-serif;
3543
+ font-family: var(--font-family-regular);
3544
+ }
3545
+
3499
3546
  /* DEPRECATED(.np-text-display-extra-large): use .np-text-display-large instead */
3500
3547
 
3501
3548
  .np-text-display-extra-large,
@@ -7,7 +7,7 @@ import IconButton from '../iconButton';
7
7
  import Body from '../body';
8
8
 
9
9
  const meta: Meta = {
10
- title: 'Foundations/tokens',
10
+ title: 'Foundations/Tokens',
11
11
  tags: ['!autodocs', '!manifest'],
12
12
  };
13
13