@transferwise/components 46.106.0 → 46.108.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 (152) hide show
  1. package/build/actionOption/ActionOption.js.map +1 -1
  2. package/build/actionOption/ActionOption.mjs.map +1 -1
  3. package/build/checkboxOption/CheckboxOption.js.map +1 -1
  4. package/build/checkboxOption/CheckboxOption.mjs.map +1 -1
  5. package/build/header/Header.js +1 -0
  6. package/build/header/Header.js.map +1 -1
  7. package/build/header/Header.mjs +1 -0
  8. package/build/header/Header.mjs.map +1 -1
  9. package/build/legacylistItem/LegacyListItem.js.map +1 -1
  10. package/build/legacylistItem/LegacyListItem.mjs.map +1 -1
  11. package/build/link/Link.js +6 -2
  12. package/build/link/Link.js.map +1 -1
  13. package/build/link/Link.mjs +6 -2
  14. package/build/link/Link.mjs.map +1 -1
  15. package/build/listItem/ListItem.js +28 -16
  16. package/build/listItem/ListItem.js.map +1 -1
  17. package/build/listItem/ListItem.mjs +28 -16
  18. package/build/listItem/ListItem.mjs.map +1 -1
  19. package/build/listItem/ListItemContext.js.map +1 -1
  20. package/build/listItem/ListItemContext.mjs.map +1 -1
  21. package/build/listItem/Navigation/ListItemNavigation.js +1 -3
  22. package/build/listItem/Navigation/ListItemNavigation.js.map +1 -1
  23. package/build/listItem/Navigation/ListItemNavigation.mjs +2 -4
  24. package/build/listItem/Navigation/ListItemNavigation.mjs.map +1 -1
  25. package/build/listItem/Prompt/InlinePrompt/InlinePrompt.js +74 -0
  26. package/build/listItem/Prompt/InlinePrompt/InlinePrompt.js.map +1 -0
  27. package/build/listItem/Prompt/InlinePrompt/InlinePrompt.mjs +72 -0
  28. package/build/listItem/Prompt/InlinePrompt/InlinePrompt.mjs.map +1 -0
  29. package/build/listItem/Prompt/ListItemPrompt.js +10 -15
  30. package/build/listItem/Prompt/ListItemPrompt.js.map +1 -1
  31. package/build/listItem/Prompt/ListItemPrompt.mjs +11 -16
  32. package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -1
  33. package/build/main.css +122 -81
  34. package/build/navigationOption/NavigationOption.js.map +1 -1
  35. package/build/navigationOption/NavigationOption.mjs.map +1 -1
  36. package/build/navigationOptionsList/NavigationOptionsList.js.map +1 -1
  37. package/build/navigationOptionsList/NavigationOptionsList.mjs.map +1 -1
  38. package/build/radioOption/RadioOption.js.map +1 -1
  39. package/build/radioOption/RadioOption.mjs.map +1 -1
  40. package/build/styles/link/Link.css +7 -0
  41. package/build/styles/listItem/ListItem.css +115 -81
  42. package/build/styles/listItem/ListItem.grid.css +11 -3
  43. package/build/styles/listItem/ListItem.vars.css +0 -0
  44. package/build/styles/listItem/Prompt/InlinePrompt/InlinePrompt.css +153 -0
  45. package/build/styles/listItem/Prompt/ListItemPrompt.css +72 -72
  46. package/build/styles/main.css +122 -81
  47. package/build/summary/Summary.js +8 -0
  48. package/build/summary/Summary.js.map +1 -1
  49. package/build/summary/Summary.mjs +8 -0
  50. package/build/summary/Summary.mjs.map +1 -1
  51. package/build/switchOption/SwitchOption.js +8 -0
  52. package/build/switchOption/SwitchOption.js.map +1 -1
  53. package/build/switchOption/SwitchOption.mjs +8 -0
  54. package/build/switchOption/SwitchOption.mjs.map +1 -1
  55. package/build/types/actionOption/ActionOption.d.ts +8 -0
  56. package/build/types/actionOption/ActionOption.d.ts.map +1 -1
  57. package/build/types/checkboxOption/CheckboxOption.d.ts +8 -0
  58. package/build/types/checkboxOption/CheckboxOption.d.ts.map +1 -1
  59. package/build/types/header/Header.d.ts +1 -0
  60. package/build/types/header/Header.d.ts.map +1 -1
  61. package/build/types/legacylistItem/LegacyListItem.d.ts +8 -0
  62. package/build/types/legacylistItem/LegacyListItem.d.ts.map +1 -1
  63. package/build/types/link/Link.d.ts +1 -1
  64. package/build/types/link/Link.d.ts.map +1 -1
  65. package/build/types/listItem/ListItem.d.ts +10 -1
  66. package/build/types/listItem/ListItem.d.ts.map +1 -1
  67. package/build/types/listItem/ListItemContext.d.ts +2 -1
  68. package/build/types/listItem/ListItemContext.d.ts.map +1 -1
  69. package/build/types/listItem/Navigation/ListItemNavigation.d.ts.map +1 -1
  70. package/build/types/listItem/Prompt/InlinePrompt/InlinePrompt.d.ts +15 -0
  71. package/build/types/listItem/Prompt/InlinePrompt/InlinePrompt.d.ts.map +1 -0
  72. package/build/types/listItem/Prompt/InlinePrompt/index.d.ts +3 -0
  73. package/build/types/listItem/Prompt/InlinePrompt/index.d.ts.map +1 -0
  74. package/build/types/listItem/Prompt/ListItemPrompt.d.ts +4 -6
  75. package/build/types/listItem/Prompt/ListItemPrompt.d.ts.map +1 -1
  76. package/build/types/listItem/_stories/helpers.d.ts +1 -1
  77. package/build/types/listItem/_stories/helpers.d.ts.map +1 -1
  78. package/build/types/listItem/_stories/subcomponents.d.ts +4 -0
  79. package/build/types/listItem/_stories/subcomponents.d.ts.map +1 -1
  80. package/build/types/listItem/_stories/variants/helpers.d.ts.map +1 -1
  81. package/build/types/listItem/constants.d.ts +16 -0
  82. package/build/types/listItem/constants.d.ts.map +1 -0
  83. package/build/types/listItem/useListItemControl.d.ts +1 -1
  84. package/build/types/navigationOption/NavigationOption.d.ts +8 -0
  85. package/build/types/navigationOption/NavigationOption.d.ts.map +1 -1
  86. package/build/types/navigationOptionsList/NavigationOptionsList.d.ts +9 -0
  87. package/build/types/navigationOptionsList/NavigationOptionsList.d.ts.map +1 -1
  88. package/build/types/radioOption/RadioOption.d.ts +8 -0
  89. package/build/types/radioOption/RadioOption.d.ts.map +1 -1
  90. package/build/types/summary/Summary.d.ts +8 -0
  91. package/build/types/summary/Summary.d.ts.map +1 -1
  92. package/build/types/switchOption/SwitchOption.d.ts +8 -0
  93. package/build/types/switchOption/SwitchOption.d.ts.map +1 -1
  94. package/package.json +2 -2
  95. package/src/actionOption/ActionOption.story.tsx +4 -0
  96. package/src/actionOption/ActionOption.tsx +8 -0
  97. package/src/checkboxOption/CheckboxOption.story.tsx +4 -0
  98. package/src/checkboxOption/CheckboxOption.tsx +8 -0
  99. package/src/header/Header.story.tsx +14 -0
  100. package/src/header/Header.tsx +2 -0
  101. package/src/legacylistItem/LegacyListItem.story.tsx +4 -0
  102. package/src/legacylistItem/LegacyListItem.tsx +8 -0
  103. package/src/link/Link.css +7 -0
  104. package/src/link/Link.less +8 -0
  105. package/src/link/Link.spec.tsx +28 -0
  106. package/src/link/Link.story.tsx +72 -16
  107. package/src/link/Link.tsx +5 -1
  108. package/src/listItem/ListItem.css +115 -81
  109. package/src/listItem/ListItem.grid.css +11 -3
  110. package/src/listItem/ListItem.grid.less +14 -4
  111. package/src/listItem/ListItem.less +35 -8
  112. package/src/listItem/ListItem.spec.tsx +37 -1
  113. package/src/listItem/ListItem.tsx +47 -21
  114. package/src/listItem/ListItem.vars.css +0 -0
  115. package/src/listItem/ListItem.vars.less +11 -0
  116. package/src/listItem/ListItemContext.tsx +2 -1
  117. package/src/listItem/Navigation/ListItemNavigation.spec.tsx +1 -10
  118. package/src/listItem/Navigation/ListItemNavigation.story.tsx +0 -22
  119. package/src/listItem/Navigation/ListItemNavigation.tsx +2 -3
  120. package/src/listItem/Prompt/InlinePrompt/InlinePrompt.css +153 -0
  121. package/src/listItem/Prompt/InlinePrompt/InlinePrompt.less +162 -0
  122. package/src/listItem/Prompt/InlinePrompt/InlinePrompt.spec.tsx +66 -0
  123. package/src/listItem/Prompt/InlinePrompt/InlinePrompt.tsx +56 -0
  124. package/src/listItem/Prompt/InlinePrompt/index.ts +2 -0
  125. package/src/listItem/Prompt/ListItemPrompt.css +72 -72
  126. package/src/listItem/Prompt/ListItemPrompt.less +2 -130
  127. package/src/listItem/Prompt/ListItemPrompt.spec.tsx +36 -0
  128. package/src/listItem/Prompt/ListItemPrompt.story.tsx +4 -2
  129. package/src/listItem/Prompt/ListItemPrompt.tsx +14 -14
  130. package/src/listItem/_stories/ListItem.disabled.story.tsx +433 -0
  131. package/src/listItem/_stories/ListItem.layout.test.story.tsx +10 -155
  132. package/src/listItem/_stories/ListItem.scenarios.story.tsx +4 -25
  133. package/src/listItem/_stories/ListItem.story.tsx +17 -187
  134. package/src/listItem/_stories/helpers.tsx +23 -6
  135. package/src/listItem/_stories/subcomponents.tsx +19 -2
  136. package/src/listItem/_stories/variants/ListItem.medium.test.story.tsx +1 -1
  137. package/src/listItem/_stories/variants/ListItem.neutral.test.story.tsx +55 -0
  138. package/src/listItem/_stories/variants/ListItem.small.test.story.tsx +1 -1
  139. package/src/listItem/_stories/variants/helpers.tsx +28 -1
  140. package/src/listItem/constants.ts +15 -0
  141. package/src/main.css +122 -81
  142. package/src/navigationOption/NavigationOption.story.tsx +4 -1
  143. package/src/navigationOption/NavigationOption.tsx +8 -0
  144. package/src/navigationOptionsList/NavigationOptionsList.story.tsx +4 -0
  145. package/src/navigationOptionsList/NavigationOptionsList.tsx +9 -0
  146. package/src/radioOption/RadioOption.story.tsx +4 -0
  147. package/src/radioOption/RadioOption.tsx +8 -0
  148. package/src/summary/Summary.story.tsx +4 -0
  149. package/src/summary/Summary.tsx +8 -0
  150. package/src/switchOption/SwitchOption.story.tsx +4 -1
  151. package/src/switchOption/SwitchOption.tsx +8 -0
  152. package/src/table/Table.story.tsx +1 -1
@@ -6,7 +6,7 @@ import {
6
6
  type PropsWithChildren,
7
7
  type ReactNode,
8
8
  } from 'react';
9
- import { Typography } from '../common';
9
+ import { Sentiment, Typography } from '../common';
10
10
  import Body from '../body';
11
11
  import { AdditionalInfo } from './AdditionalInfo';
12
12
  import { IconButton, type ListItemIconButtonProps } from './IconButton';
@@ -50,7 +50,16 @@ export type ListItemProps = {
50
50
  * Swaps vertical hierarchy of title and subtitle and their corresponding right values.
51
51
  */
52
52
  inverted?: boolean;
53
+ /**
54
+ * Disables the control and renders the ListItem in greyscale and with slightly decreased opacity.
55
+ */
53
56
  disabled?: boolean;
57
+ /**
58
+ * If set, it'll extend the `disabled` state, overriding existing or injecting uniquely styled prompt with the message provided via this prop. <br />
59
+ * **NB:** This message cannot house more than **1** link or inline button.<br />
60
+ * **NB:** It must be used together with `disabled` prop and will be disregarded otherwise.
61
+ */
62
+ disabledPromptMessage?: ReactNode;
54
63
  /**
55
64
  * Highlights the list item as an action to be taken or already taken. <br />
56
65
  */
@@ -111,6 +120,7 @@ export const ListItem = ({
111
120
  valueSubtitle,
112
121
  control = null,
113
122
  disabled,
123
+ disabledPromptMessage,
114
124
  className,
115
125
  valueColumnWidth,
116
126
  id,
@@ -126,7 +136,7 @@ export const ListItem = ({
126
136
  ...(valueTitle ? { valueTitle: `${idPrefix}_value-title` } : {}),
127
137
  ...(valueSubtitle ? { valueSubtitle: `${idPrefix}_value-subtitle` } : {}),
128
138
  control: `${idPrefix}_control`,
129
- ...(prompt ? { prompt: `${idPrefix}_prompt` } : {}),
139
+ ...(prompt || (disabled && disabledPromptMessage) ? { prompt: `${idPrefix}_prompt` } : {}),
130
140
  ...(additionalInfo ? { additionalInfo: `${idPrefix}_additional-info` } : {}),
131
141
  };
132
142
 
@@ -159,8 +169,9 @@ export const ListItem = ({
159
169
  setControlProps,
160
170
  setMediaSize,
161
171
  ids,
162
- props: { disabled, inverted },
172
+ props: { disabled, inverted, disabledPromptMessage },
163
173
  mediaSize,
174
+ isPartiallyInteractive,
164
175
  describedByIds,
165
176
  }),
166
177
  [describedByIds, mediaSize],
@@ -175,7 +186,7 @@ export const ListItem = ({
175
186
  const hasMedia = Boolean(media);
176
187
  const hasControl = Boolean(control);
177
188
  const hasInfo = Boolean(additionalInfo);
178
- const hasPrompt = Boolean(prompt);
189
+ const hasPrompt = Boolean(prompt) || (disabled && Boolean(disabledPromptMessage));
179
190
 
180
191
  /* eslint-disable functional/immutable-data */
181
192
  if (hasMedia && hasControl) {
@@ -223,14 +234,20 @@ export const ListItem = ({
223
234
  'wds-list-item-partially-interactive': isPartiallyInteractive,
224
235
  [`wds-list-item-spotlight wds-list-item-spotlight-${spotlight}`]:
225
236
  isFullyInteractive && !!spotlight,
226
- disabled,
237
+ disabled: disabled && !isPartiallyInteractive,
238
+ 'disabled--has-prompt-reason': !disabledPromptMessage && disabled && !isPartiallyInteractive,
227
239
  },
228
240
  className,
229
241
  )}
230
242
  id={id}
231
243
  aria-disabled={disabled}
244
+ style={
245
+ {
246
+ '--wds-list-item-value-min-height': mediaSize ? `${mediaSize}px` : undefined,
247
+ } as React.CSSProperties
248
+ }
232
249
  >
233
- {spotlight === 'inactive' && (
250
+ {isFullyInteractive && spotlight === 'inactive' && (
234
251
  <svg aria-hidden="true" className="wds-list-item-spotlight__border">
235
252
  <rect />
236
253
  </svg>
@@ -242,6 +259,7 @@ export const ListItem = ({
242
259
  subtitle,
243
260
  additionalInfo,
244
261
  disabled,
262
+ disabledPromptMessage,
245
263
  prompt,
246
264
  controlType,
247
265
  controlProps,
@@ -256,11 +274,7 @@ export const ListItem = ({
256
274
  style={valueColumnWidth ? gridColumnsStyle : undefined}
257
275
  >
258
276
  {/* Title + Subtitle + Values - Group */}
259
- <span
260
- className={clsx({
261
- 'wds-list-item-body-center': title && !subtitle,
262
- })}
263
- >
277
+ <span className="wds-list-item-titles">
264
278
  {(() => {
265
279
  const titles = [
266
280
  <Body
@@ -287,8 +301,6 @@ export const ListItem = ({
287
301
  <span
288
302
  className={clsx('wds-list-item-value', {
289
303
  'flex-column': valueTitle !== undefined || valueSubtitle !== undefined,
290
- 'wds-list-item-body-center':
291
- (valueTitle && !valueSubtitle) || (!valueTitle && valueSubtitle),
292
304
  })}
293
305
  >
294
306
  {(() => {
@@ -326,6 +338,8 @@ export const ListItem = ({
326
338
  <Body
327
339
  className={clsx('wds-list-item-control-wrapper', {
328
340
  'wds-list-item-button-control': controlType === 'button',
341
+ 'wds-list-item-button-control--hasPrompt':
342
+ controlType === 'button' && Boolean(prompt),
329
343
  })}
330
344
  style={
331
345
  {
@@ -347,14 +361,17 @@ type ViewProps = PropsWithChildren<{
347
361
  controlType?: ListItemTypes;
348
362
  controlProps?: ListItemControlProps;
349
363
  }> &
350
- Pick<ListItemProps, 'subtitle' | 'additionalInfo' | 'disabled' | 'prompt' | 'className'>;
364
+ Pick<
365
+ ListItemProps,
366
+ 'subtitle' | 'additionalInfo' | 'prompt' | 'disabled' | 'disabledPromptMessage' | 'className'
367
+ >;
351
368
 
352
369
  function View({
353
370
  children,
354
- subtitle,
355
371
  additionalInfo,
356
372
  prompt,
357
373
  disabled,
374
+ disabledPromptMessage,
358
375
  isPartiallyInteractive,
359
376
  controlType = 'non-interactive',
360
377
  controlProps,
@@ -365,12 +382,21 @@ function View({
365
382
 
366
383
  const isHrefProvided = isLinkControl && !!(controlProps as ListItemNavigationProps)?.href;
367
384
 
368
- const renderExtras = () => (
369
- <>
370
- {additionalInfo}
371
- {prompt}
372
- </>
373
- );
385
+ const renderExtras = () => {
386
+ const resolvedPrompt =
387
+ disabled && disabledPromptMessage && !prompt ? (
388
+ <Prompt sentiment={Sentiment.NEUTRAL}>{disabledPromptMessage}</Prompt>
389
+ ) : (
390
+ prompt
391
+ );
392
+
393
+ return (
394
+ <>
395
+ {additionalInfo}
396
+ {resolvedPrompt}
397
+ </>
398
+ );
399
+ };
374
400
 
375
401
  if (isLinkControl && isHrefProvided) {
376
402
  return (
File without changes
@@ -0,0 +1,11 @@
1
+ // List item has 3 unique layouts managed through container queries:
2
+ // * width <= cq-min
3
+ // * cq-min < width <= cq-max
4
+ // * width > cq-max
5
+ //
6
+ // ⚠️ These values must be kept in sync with:
7
+ // `packages/components/src/listItem/constants.ts`
8
+ //
9
+ // @see https://storybook.wise.design/?path=/story/content-listitem--responsiveness
10
+ @wds-list-item-cq-min: 240;
11
+ @wds-list-item-cq-max: 308;
@@ -16,8 +16,9 @@ export type ListItemContextData = {
16
16
  control: string;
17
17
  prompt?: string;
18
18
  };
19
- props: Pick<ListItemProps, 'disabled' | 'inverted'>;
19
+ props: Pick<ListItemProps, 'disabled' | 'inverted' | 'disabledPromptMessage'>;
20
20
  mediaSize?: ListItemMediaSize;
21
+ isPartiallyInteractive?: boolean;
21
22
  describedByIds: string;
22
23
  };
23
24
 
@@ -25,8 +25,7 @@ describe('ListItem.Navigation', () => {
25
25
  disabled: true,
26
26
  control: <ListItem.Navigation onClick={jest.fn()} />,
27
27
  });
28
- expect(screen.getByTestId('backslash-circle-icon')).toBeInTheDocument();
29
- expect(screen.queryByRole('button')).not.toBeInTheDocument();
28
+ expect(screen.queryByRole('button')).toBeDisabled();
30
29
  expect(screen.queryByRole('link')).not.toBeInTheDocument();
31
30
  });
32
31
  });
@@ -48,14 +47,6 @@ describe('ListItem.Navigation', () => {
48
47
  expect(link).toHaveAttribute('rel', 'noopener noreferrer');
49
48
  });
50
49
 
51
- it('renders disabled icon when ListItem is disabled', () => {
52
- renderWith({
53
- disabled: true,
54
- control: <ListItem.Navigation href="wise.com" />,
55
- });
56
- expect(screen.getByTestId('backslash-circle-icon')).toBeInTheDocument();
57
- });
58
-
59
50
  it('handles onClick events', async () => {
60
51
  const handleClick = jest.fn();
61
52
  renderWith({ control: <ListItem.Navigation href="#target" onClick={handleClick} /> });
@@ -90,25 +90,3 @@ export const AsButton: Story = {
90
90
  );
91
91
  },
92
92
  };
93
-
94
- /**
95
- * Unlike other controls, the Navigation control has a custom disabled state
96
- * for improved discoverability, accessibility and overall UX.
97
- */
98
- export const Disabled: Story = {
99
- render: (args) => {
100
- return (
101
- <List>
102
- <ListItem
103
- disabled
104
- control={<ListItem.Navigation {...args} />}
105
- title="This option is disabled"
106
- subtitle={lorem10}
107
- additionalInfo={INFO.nonInteractive}
108
- prompt={PROMPTS.interactive}
109
- media={MEDIA.avatarSingle}
110
- />
111
- </List>
112
- );
113
- },
114
- };
@@ -1,4 +1,4 @@
1
- import { ChevronRight, BackslashCircle } from '@transferwise/icons';
1
+ import { ChevronRight } from '@transferwise/icons';
2
2
  import type { ButtonProps } from '../../button/Button.types';
3
3
  import { useListItemControl } from '../useListItemControl';
4
4
  import { PrimitiveButton } from '../../primitives';
@@ -20,12 +20,11 @@ export const Navigation = function Navigation({ href, ...props }: ListItemNaviga
20
20
  const { ids, describedByIds } = useContext(ListItemContext);
21
21
  const icon = <ChevronRight size={16} />;
22
22
 
23
- if (baseItemProps.disabled) return <BackslashCircle size={24} />;
24
-
25
23
  return href ? (
26
24
  <>{icon}</>
27
25
  ) : (
28
26
  <PrimitiveButton
27
+ disabled={baseItemProps.disabled}
29
28
  aria-describedby={describedByIds}
30
29
  id={ids.control}
31
30
  className="btn-unstyled wds-list-item-control"
@@ -0,0 +1,153 @@
1
+ .wds-inline-prompt {
2
+ display: inline-flex;
3
+ text-align: left;
4
+ padding-top: calc(8px / 2);
5
+ padding-top: calc(var(--padding-x-small) / 2);
6
+ padding-bottom: calc(8px / 2);
7
+ padding-bottom: calc(var(--padding-x-small) / 2);
8
+ padding-left: calc(8px - 1px);
9
+ padding-left: calc(var(--padding-x-small) - 1px);
10
+ padding-right: 8px;
11
+ padding-right: var(--padding-x-small);
12
+ border-radius: 10px;
13
+ border-radius: var(--radius-small);
14
+ word-break: break-word;
15
+ word-wrap: break-word;
16
+ }
17
+ .wds-inline-prompt:has(a),
18
+ .wds-inline-prompt:has(button) {
19
+ position: relative;
20
+ z-index: 1;
21
+ }
22
+ .wds-inline-prompt--muted {
23
+ opacity: 0.93;
24
+ filter: grayscale(1);
25
+ }
26
+ .wds-inline-prompt a,
27
+ .wds-inline-prompt button {
28
+ text-underline-offset: calc(4px / 2);
29
+ text-underline-offset: calc(var(--size-4) / 2);
30
+ }
31
+ .wds-inline-prompt a:first-of-type:before,
32
+ .wds-inline-prompt button:first-of-type:before {
33
+ content: '';
34
+ position: absolute;
35
+ inset: 0;
36
+ }
37
+ .wds-inline-prompt__media-wrapper {
38
+ padding-right: calc(12px / 2);
39
+ padding-right: calc(var(--size-12) / 2);
40
+ padding-top: calc(4px - 1px);
41
+ padding-top: calc(var(--size-4) - 1px);
42
+ padding-bottom: calc(4px - 1px);
43
+ padding-bottom: calc(var(--size-4) - 1px);
44
+ }
45
+ .wds-inline-prompt__media-wrapper .tw-icon-tags,
46
+ .wds-inline-prompt__media-wrapper .tw-icon-confetti {
47
+ color: var(--color-sentiment-positive-primary);
48
+ }
49
+ .wds-inline-prompt--negative {
50
+ background-color: var(--color-sentiment-negative-secondary);
51
+ color: var(--color-sentiment-negative-primary);
52
+ }
53
+ .wds-inline-prompt--negative a,
54
+ .wds-inline-prompt--negative button {
55
+ color: var(--color-sentiment-negative-primary);
56
+ }
57
+ .wds-inline-prompt--negative a:hover,
58
+ .wds-inline-prompt--negative button:hover {
59
+ color: var(--color-sentiment-negative-primary-hover);
60
+ }
61
+ .wds-inline-prompt--negative a:active,
62
+ .wds-inline-prompt--negative button:active {
63
+ color: var(--color-sentiment-negative-primary-active);
64
+ }
65
+ .wds-inline-prompt.wds-inline-prompt--negative:has(a, button):hover {
66
+ background-color: var(--color-sentiment-negative-secondary-hover);
67
+ }
68
+ .wds-inline-prompt.wds-inline-prompt--negative:has(a, button):active {
69
+ background-color: var(--color-sentiment-negative-secondary-active);
70
+ }
71
+ .wds-inline-prompt--positive {
72
+ background-color: var(--color-sentiment-positive-secondary);
73
+ color: var(--color-sentiment-positive-primary);
74
+ }
75
+ .wds-inline-prompt--positive a,
76
+ .wds-inline-prompt--positive button {
77
+ color: var(--color-sentiment-positive-primary);
78
+ }
79
+ .wds-inline-prompt--positive a:hover,
80
+ .wds-inline-prompt--positive button:hover {
81
+ color: var(--color-sentiment-positive-primary-hover);
82
+ }
83
+ .wds-inline-prompt--positive a:active,
84
+ .wds-inline-prompt--positive button:active {
85
+ color: var(--color-sentiment-positive-primary-active);
86
+ }
87
+ .wds-inline-prompt.wds-inline-prompt--positive:has(a, button):hover {
88
+ background-color: var(--color-sentiment-positive-secondary-hover);
89
+ }
90
+ .wds-inline-prompt.wds-inline-prompt--positive:has(a, button):active {
91
+ background-color: var(--color-sentiment-positive-secondary-active);
92
+ }
93
+ .wds-inline-prompt--proposition {
94
+ background-color: var(--color-sentiment-positive-secondary);
95
+ color: var(--color-sentiment-positive-primary);
96
+ }
97
+ .wds-inline-prompt--proposition a,
98
+ .wds-inline-prompt--proposition button {
99
+ color: var(--color-sentiment-positive-primary);
100
+ }
101
+ .wds-inline-prompt--proposition a:hover,
102
+ .wds-inline-prompt--proposition button:hover {
103
+ color: var(--color-sentiment-positive-primary-hover);
104
+ }
105
+ .wds-inline-prompt--proposition a:active,
106
+ .wds-inline-prompt--proposition button:active {
107
+ color: var(--color-sentiment-positive-primary-active);
108
+ }
109
+ .wds-inline-prompt.wds-inline-prompt--proposition:has(a, button):hover {
110
+ background-color: var(--color-sentiment-positive-secondary-hover);
111
+ }
112
+ .wds-inline-prompt.wds-inline-prompt--proposition:has(a, button):active {
113
+ background-color: var(--color-sentiment-positive-secondary-active);
114
+ }
115
+ .wds-inline-prompt--neutral {
116
+ background-color: rgba(134,167,189,0.10196);
117
+ background-color: var(--color-background-neutral);
118
+ color: #37517e;
119
+ color: var(--color-content-primary);
120
+ }
121
+ .wds-inline-prompt--neutral a,
122
+ .wds-inline-prompt--neutral button {
123
+ color: #37517e;
124
+ color: var(--color-content-primary);
125
+ }
126
+ .wds-inline-prompt.wds-inline-prompt--neutral:has(a, button):hover {
127
+ background-color: var(--color-background-neutral-hover);
128
+ }
129
+ .wds-inline-prompt.wds-inline-prompt--neutral:has(a, button):active {
130
+ background-color: var(--color-background-neutral-active);
131
+ }
132
+ .wds-inline-prompt--warning {
133
+ background-color: var(--color-sentiment-warning-secondary);
134
+ color: var(--color-sentiment-warning-content);
135
+ }
136
+ .wds-inline-prompt--warning a,
137
+ .wds-inline-prompt--warning button {
138
+ color: var(--color-sentiment-warning-content);
139
+ }
140
+ .wds-inline-prompt--warning a:hover,
141
+ .wds-inline-prompt--warning button:hover {
142
+ color: var(--color-sentiment-warning-content-hover);
143
+ }
144
+ .wds-inline-prompt--warning a:active,
145
+ .wds-inline-prompt--warning button:active {
146
+ color: var(--color-sentiment-warning-content-active);
147
+ }
148
+ .wds-inline-prompt.wds-inline-prompt--warning:has(a, button):hover {
149
+ background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 92%, var(--color-sentiment-warning-primary));
150
+ }
151
+ .wds-inline-prompt.wds-inline-prompt--warning:has(a, button):active {
152
+ background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 84%, var(--color-sentiment-warning-primary));
153
+ }
@@ -0,0 +1,162 @@
1
+ /// @FIXME all tokens here need to be adjusted after
2
+ /// the new sentiment tokens land
3
+
4
+ .wds-inline-prompt {
5
+ display: inline-flex;
6
+ text-align: left;
7
+ padding-top: calc(var(--padding-x-small) / 2);
8
+ padding-bottom: calc(var(--padding-x-small) / 2);
9
+ padding-left: calc(var(--padding-x-small) - 1px);
10
+ padding-right: var(--padding-x-small);
11
+ border-radius: var(--radius-small);
12
+ word-break: break-word;
13
+ overflow-wrap: break-word;
14
+
15
+ &:has(a),
16
+ &:has(button) {
17
+ position: relative;
18
+ z-index: 1;
19
+ }
20
+
21
+ &--muted {
22
+ opacity: .93;
23
+ filter: grayscale(1);
24
+ }
25
+
26
+ a, button {
27
+ text-underline-offset: calc(var(--size-4) / 2);
28
+ &:first-of-type {
29
+ &:before {
30
+ content: '';
31
+ position: absolute;
32
+ inset: 0;
33
+ }
34
+ }
35
+ }
36
+
37
+ &__media-wrapper {
38
+ padding-right: calc(var(--size-12) / 2);
39
+ padding-top: calc(var(--size-4) - 1px);
40
+ padding-bottom: calc(var(--size-4) - 1px);
41
+
42
+ .tw-icon-tags,
43
+ .tw-icon-confetti {
44
+ color: var(--color-sentiment-positive-primary);
45
+ }
46
+ }
47
+
48
+ &--negative {
49
+ background-color: var(--color-sentiment-negative-secondary);
50
+ color: var(--color-sentiment-negative-primary);
51
+
52
+ a, button {
53
+ color: var(--color-sentiment-negative-primary);
54
+
55
+ &:hover {
56
+ color: var(--color-sentiment-negative-primary-hover);
57
+ }
58
+
59
+ &:active {
60
+ color: var(--color-sentiment-negative-primary-active);
61
+ }
62
+ }
63
+
64
+ .wds-inline-prompt&:has(a, button) {
65
+ &:hover {
66
+ background-color: var(--color-sentiment-negative-secondary-hover);
67
+ }
68
+ &:active {
69
+ background-color: var(--color-sentiment-negative-secondary-active);
70
+ }
71
+ }
72
+ }
73
+
74
+ &--positive {
75
+ background-color: var(--color-sentiment-positive-secondary);
76
+ color: var(--color-sentiment-positive-primary);
77
+ a, button {
78
+ color: var(--color-sentiment-positive-primary);
79
+ &:hover {
80
+ color: var(--color-sentiment-positive-primary-hover);
81
+ }
82
+ &:active {
83
+ color: var(--color-sentiment-positive-primary-active);
84
+ }
85
+ }
86
+ .wds-inline-prompt&:has(a, button) {
87
+ &:hover {
88
+ background-color: var(--color-sentiment-positive-secondary-hover);
89
+ }
90
+ &:active {
91
+ background-color: var(--color-sentiment-positive-secondary-active);
92
+ }
93
+ }
94
+ }
95
+
96
+ &--proposition {
97
+ background-color: var(--color-sentiment-positive-secondary);
98
+
99
+ color: var(--color-sentiment-positive-primary);
100
+
101
+ a, button {
102
+ color: var(--color-sentiment-positive-primary);
103
+ &:hover {
104
+ color: var(--color-sentiment-positive-primary-hover);
105
+ }
106
+ &:active {
107
+ color: var(--color-sentiment-positive-primary-active);
108
+ }
109
+ }
110
+
111
+ .wds-inline-prompt&:has(a, button) {
112
+ &:hover {
113
+ background-color: var(--color-sentiment-positive-secondary-hover);
114
+ }
115
+ &:active {
116
+ background-color: var(--color-sentiment-positive-secondary-active);
117
+ }
118
+ }
119
+ }
120
+
121
+ &--neutral {
122
+ background-color: var(--color-background-neutral);
123
+ color: var(--color-content-primary);
124
+
125
+ a, button {
126
+ color: var(--color-content-primary);
127
+ }
128
+
129
+ .wds-inline-prompt&:has(a, button) {
130
+ &:hover {
131
+ background-color: var(--color-background-neutral-hover);
132
+ }
133
+ &:active {
134
+ background-color: var(--color-background-neutral-active);
135
+ }
136
+ }
137
+ }
138
+
139
+ &--warning {
140
+ background-color: var(--color-sentiment-warning-secondary);
141
+ color: var(--color-sentiment-warning-content);
142
+
143
+ a, button {
144
+ color: var(--color-sentiment-warning-content);
145
+ &:hover {
146
+ color: var(--color-sentiment-warning-content-hover);
147
+ }
148
+ &:active {
149
+ color: var(--color-sentiment-warning-content-active);
150
+ }
151
+ }
152
+
153
+ .wds-inline-prompt&:has(a, button) {
154
+ &:hover {
155
+ background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 92%, var(--color-sentiment-warning-primary));
156
+ }
157
+ &:active {
158
+ background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 84%, var(--color-sentiment-warning-primary));
159
+ }
160
+ }
161
+ }
162
+ }
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { mockMatchMedia, render, screen } from '../../../test-utils';
3
+ import { InlinePrompt, InlinePromptProps } from './InlinePrompt';
4
+ import { Sentiment } from '../../../common';
5
+
6
+ mockMatchMedia();
7
+
8
+ describe('InlinePrompt', () => {
9
+ const defaultProps: InlinePromptProps = {
10
+ children: 'Prompt message',
11
+ };
12
+
13
+ it('renders children', () => {
14
+ render(<InlinePrompt {...defaultProps}>Hello world</InlinePrompt>);
15
+ expect(screen.getByText('Hello world')).toBeInTheDocument();
16
+ });
17
+
18
+ describe('renders with each sentiment', () => {
19
+ it.each([Sentiment.POSITIVE, Sentiment.NEUTRAL, Sentiment.NEGATIVE, Sentiment.WARNING])(
20
+ 'renders with sentiment %s',
21
+ (sentiment) => {
22
+ render(
23
+ <InlinePrompt
24
+ {...defaultProps}
25
+ sentiment={sentiment as InlinePromptProps['sentiment']}
26
+ />,
27
+ );
28
+ expect(screen.getByText('Prompt message').parentElement).toHaveClass(
29
+ `wds-inline-prompt--${sentiment}`,
30
+ );
31
+ },
32
+ );
33
+ });
34
+
35
+ it('renders muted state', () => {
36
+ render(<InlinePrompt {...defaultProps} muted />);
37
+ screen.debug(undefined, 99999999);
38
+ expect(screen.getByText('Prompt message').parentElement).toHaveClass(
39
+ 'wds-inline-prompt--muted',
40
+ );
41
+ expect(screen.getByTestId('InlinePrompt_Muted')).toBeInTheDocument();
42
+ });
43
+
44
+ it('renders loading state', () => {
45
+ render(<InlinePrompt {...defaultProps} loading />);
46
+ screen.debug(undefined, 99999999);
47
+ expect(screen.getByText('Prompt message').parentElement).toHaveClass(
48
+ 'wds-inline-prompt--loading',
49
+ );
50
+ expect(screen.getByTestId('InlinePrompt_ProcessIndicator')).toBeInTheDocument();
51
+ });
52
+
53
+ it('applies custom className, id, and data-testid', () => {
54
+ render(
55
+ <InlinePrompt
56
+ {...defaultProps}
57
+ className="custom-class"
58
+ id="custom-id"
59
+ data-testid="custom-test"
60
+ />,
61
+ );
62
+ const el = screen.getByTestId('custom-test');
63
+ expect(el).toHaveClass('custom-class');
64
+ expect(el).toHaveAttribute('id', 'custom-id');
65
+ });
66
+ });