@transferwise/components 46.103.1 → 46.105.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.
- package/build/header/Header.js +60 -43
- package/build/header/Header.js.map +1 -1
- package/build/header/Header.mjs +57 -43
- package/build/header/Header.mjs.map +1 -1
- package/build/i18n/cs.json +2 -0
- package/build/i18n/cs.json.js +2 -0
- package/build/i18n/cs.json.js.map +1 -1
- package/build/i18n/cs.json.mjs +2 -0
- package/build/i18n/cs.json.mjs.map +1 -1
- package/build/i18n/es.json +2 -0
- package/build/i18n/es.json.js +2 -0
- package/build/i18n/es.json.js.map +1 -1
- package/build/i18n/es.json.mjs +2 -0
- package/build/i18n/es.json.mjs.map +1 -1
- package/build/i18n/th.json +2 -0
- package/build/i18n/th.json.js +2 -0
- package/build/i18n/th.json.js.map +1 -1
- package/build/i18n/th.json.mjs +2 -0
- package/build/i18n/th.json.mjs.map +1 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/index.mjs +2 -1
- package/build/index.mjs.map +1 -1
- package/build/inputs/SelectInput.js +1 -1
- package/build/inputs/SelectInput.js.map +1 -1
- package/build/inputs/SelectInput.mjs +1 -1
- package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.js +56 -0
- package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.js.map +1 -0
- package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.mjs +54 -0
- package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.mjs.map +1 -0
- package/build/listItem/AvatarLayout/ListItemAvatarLayout.js +23 -0
- package/build/listItem/AvatarLayout/ListItemAvatarLayout.js.map +1 -0
- package/build/listItem/AvatarLayout/ListItemAvatarLayout.mjs +21 -0
- package/build/listItem/AvatarLayout/ListItemAvatarLayout.mjs.map +1 -0
- package/build/listItem/AvatarView/ListItemAvatarView.js +23 -0
- package/build/listItem/AvatarView/ListItemAvatarView.js.map +1 -0
- package/build/listItem/AvatarView/ListItemAvatarView.mjs +21 -0
- package/build/listItem/AvatarView/ListItemAvatarView.mjs.map +1 -0
- package/build/listItem/Button/ListItemButton.js +43 -0
- package/build/listItem/Button/ListItemButton.js.map +1 -0
- package/build/listItem/Button/ListItemButton.mjs +41 -0
- package/build/listItem/Button/ListItemButton.mjs.map +1 -0
- package/build/listItem/Checkbox/ListItemCheckbox.js +30 -0
- package/build/listItem/Checkbox/ListItemCheckbox.js.map +1 -0
- package/build/listItem/Checkbox/ListItemCheckbox.mjs +28 -0
- package/build/listItem/Checkbox/ListItemCheckbox.mjs.map +1 -0
- package/build/listItem/IconButton/ListItemIconButton.js +56 -0
- package/build/listItem/IconButton/ListItemIconButton.js.map +1 -0
- package/build/listItem/IconButton/ListItemIconButton.mjs +54 -0
- package/build/listItem/IconButton/ListItemIconButton.mjs.map +1 -0
- package/build/listItem/Image/ListItemImage.js +31 -0
- package/build/listItem/Image/ListItemImage.js.map +1 -0
- package/build/listItem/Image/ListItemImage.mjs +29 -0
- package/build/listItem/Image/ListItemImage.mjs.map +1 -0
- package/build/listItem/ListItem.js +311 -0
- package/build/listItem/ListItem.js.map +1 -0
- package/build/listItem/ListItem.mjs +306 -0
- package/build/listItem/ListItem.mjs.map +1 -0
- package/build/listItem/ListItemContext.js +8 -0
- package/build/listItem/ListItemContext.js.map +1 -0
- package/build/listItem/ListItemContext.mjs +6 -0
- package/build/listItem/ListItemContext.mjs.map +1 -0
- package/build/listItem/Navigation/ListItemNavigation.js +44 -0
- package/build/listItem/Navigation/ListItemNavigation.js.map +1 -0
- package/build/listItem/Navigation/ListItemNavigation.mjs +42 -0
- package/build/listItem/Navigation/ListItemNavigation.mjs.map +1 -0
- package/build/listItem/Prompt/ListItemPrompt.js +59 -0
- package/build/listItem/Prompt/ListItemPrompt.js.map +1 -0
- package/build/listItem/Prompt/ListItemPrompt.mjs +54 -0
- package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -0
- package/build/listItem/Radio/ListItemRadio.js +30 -0
- package/build/listItem/Radio/ListItemRadio.js.map +1 -0
- package/build/listItem/Radio/ListItemRadio.mjs +28 -0
- package/build/listItem/Radio/ListItemRadio.mjs.map +1 -0
- package/build/listItem/Switch/ListItemSwitch.js +30 -0
- package/build/listItem/Switch/ListItemSwitch.js.map +1 -0
- package/build/listItem/Switch/ListItemSwitch.mjs +28 -0
- package/build/listItem/Switch/ListItemSwitch.mjs.map +1 -0
- package/build/listItem/useListItemControl.js +22 -0
- package/build/listItem/useListItemControl.js.map +1 -0
- package/build/listItem/useListItemControl.mjs +20 -0
- package/build/listItem/useListItemControl.mjs.map +1 -0
- package/build/listItem/useListItemMedia.js +21 -0
- package/build/listItem/useListItemMedia.js.map +1 -0
- package/build/listItem/useListItemMedia.mjs +19 -0
- package/build/listItem/useListItemMedia.mjs.map +1 -0
- package/build/main.css +794 -14
- package/build/styles/header/Header.css +21 -14
- package/build/styles/listItem/ListItem.css +773 -0
- package/build/styles/listItem/ListItem.grid.css +370 -0
- package/build/styles/listItem/Prompt/ListItemPrompt.css +157 -0
- package/build/styles/main.css +794 -14
- package/build/title/Title.js +10 -4
- package/build/title/Title.js.map +1 -1
- package/build/title/Title.mjs +6 -4
- package/build/title/Title.mjs.map +1 -1
- package/build/types/header/Header.d.ts +27 -11
- package/build/types/header/Header.d.ts.map +1 -1
- package/build/types/header/index.d.ts +1 -0
- package/build/types/header/index.d.ts.map +1 -1
- package/build/types/index.d.ts +3 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/listItem/AdditionalInfo/ListItemAdditionalInfo.d.ts +15 -0
- package/build/types/listItem/AdditionalInfo/ListItemAdditionalInfo.d.ts.map +1 -0
- package/build/types/listItem/AdditionalInfo/index.d.ts +3 -0
- package/build/types/listItem/AdditionalInfo/index.d.ts.map +1 -0
- package/build/types/listItem/AvatarLayout/ListItemAvatarLayout.d.ts +18 -0
- package/build/types/listItem/AvatarLayout/ListItemAvatarLayout.d.ts.map +1 -0
- package/build/types/listItem/AvatarLayout/index.d.ts +3 -0
- package/build/types/listItem/AvatarLayout/index.d.ts.map +1 -0
- package/build/types/listItem/AvatarView/ListItemAvatarView.d.ts +16 -0
- package/build/types/listItem/AvatarView/ListItemAvatarView.d.ts.map +1 -0
- package/build/types/listItem/AvatarView/index.d.ts +3 -0
- package/build/types/listItem/AvatarView/index.d.ts.map +1 -0
- package/build/types/listItem/Button/ListItemButton.d.ts +20 -0
- package/build/types/listItem/Button/ListItemButton.d.ts.map +1 -0
- package/build/types/listItem/Button/index.d.ts +3 -0
- package/build/types/listItem/Button/index.d.ts.map +1 -0
- package/build/types/listItem/Checkbox/ListItemCheckbox.d.ts +14 -0
- package/build/types/listItem/Checkbox/ListItemCheckbox.d.ts.map +1 -0
- package/build/types/listItem/Checkbox/index.d.ts +3 -0
- package/build/types/listItem/Checkbox/index.d.ts.map +1 -0
- package/build/types/listItem/IconButton/ListItemIconButton.d.ts +18 -0
- package/build/types/listItem/IconButton/ListItemIconButton.d.ts.map +1 -0
- package/build/types/listItem/IconButton/index.d.ts +3 -0
- package/build/types/listItem/IconButton/index.d.ts.map +1 -0
- package/build/types/listItem/Image/ListItemImage.d.ts +25 -0
- package/build/types/listItem/Image/ListItemImage.d.ts.map +1 -0
- package/build/types/listItem/Image/index.d.ts +3 -0
- package/build/types/listItem/Image/index.d.ts.map +1 -0
- package/build/types/listItem/ListItem.d.ts +111 -0
- package/build/types/listItem/ListItem.d.ts.map +1 -0
- package/build/types/listItem/ListItemContext.d.ts +21 -0
- package/build/types/listItem/ListItemContext.d.ts.map +1 -0
- package/build/types/listItem/Navigation/ListItemNavigation.d.ts +15 -0
- package/build/types/listItem/Navigation/ListItemNavigation.d.ts.map +1 -0
- package/build/types/listItem/Navigation/index.d.ts +3 -0
- package/build/types/listItem/Navigation/index.d.ts.map +1 -0
- package/build/types/listItem/Prompt/ListItemPrompt.d.ts +16 -0
- package/build/types/listItem/Prompt/ListItemPrompt.d.ts.map +1 -0
- package/build/types/listItem/Prompt/index.d.ts +3 -0
- package/build/types/listItem/Prompt/index.d.ts.map +1 -0
- package/build/types/listItem/Radio/ListItemRadio.d.ts +14 -0
- package/build/types/listItem/Radio/ListItemRadio.d.ts.map +1 -0
- package/build/types/listItem/Radio/index.d.ts +3 -0
- package/build/types/listItem/Radio/index.d.ts.map +1 -0
- package/build/types/listItem/Switch/ListItemSwitch.d.ts +14 -0
- package/build/types/listItem/Switch/ListItemSwitch.d.ts.map +1 -0
- package/build/types/listItem/Switch/index.d.ts +3 -0
- package/build/types/listItem/Switch/index.d.ts.map +1 -0
- package/build/types/listItem/_stories/helpers.d.ts +27 -0
- package/build/types/listItem/_stories/helpers.d.ts.map +1 -0
- package/build/types/listItem/_stories/subcomponents.d.ts +18 -0
- package/build/types/listItem/_stories/subcomponents.d.ts.map +1 -0
- package/build/types/listItem/index.d.ts +14 -0
- package/build/types/listItem/index.d.ts.map +1 -0
- package/build/types/listItem/test-utils.d.ts +7 -0
- package/build/types/listItem/test-utils.d.ts.map +1 -0
- package/build/types/listItem/useListItemControl.d.ts +5 -0
- package/build/types/listItem/useListItemControl.d.ts.map +1 -0
- package/build/types/listItem/useListItemMedia.d.ts +6 -0
- package/build/types/listItem/useListItemMedia.d.ts.map +1 -0
- package/build/types/title/Title.d.ts +4 -5
- package/build/types/title/Title.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/button/Button.spec.tsx +25 -1
- package/src/button/Button.story.tsx +1 -0
- package/src/header/Header.accessibility.docs.mdx +85 -0
- package/src/header/Header.css +21 -14
- package/src/header/Header.less +17 -10
- package/src/header/Header.spec.tsx +68 -50
- package/src/header/Header.story.tsx +190 -36
- package/src/header/Header.tsx +96 -65
- package/src/header/index.ts +1 -0
- package/src/i18n/cs.json +2 -0
- package/src/i18n/es.json +2 -0
- package/src/i18n/th.json +2 -0
- package/src/iconButton/iconButton.spec.tsx +31 -0
- package/src/index.ts +16 -0
- package/src/legacylistItem/LegacyListItem.story.tsx +1 -1
- package/src/legacylistItem/LegacyListItem.tests.story.tsx +2 -1
- package/src/list/List.story.tsx +13 -3
- package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.spec.tsx +56 -0
- package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.story.tsx +198 -0
- package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.tsx +36 -0
- package/src/listItem/AdditionalInfo/index.ts +2 -0
- package/src/listItem/AvatarLayout/ListItemAvatarLayout.spec.tsx +59 -0
- package/src/listItem/AvatarLayout/ListItemAvatarLayout.story.tsx +124 -0
- package/src/listItem/AvatarLayout/ListItemAvatarLayout.tsx +27 -0
- package/src/listItem/AvatarLayout/index.ts +2 -0
- package/src/listItem/AvatarView/ListItemAvatarView.spec.tsx +75 -0
- package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +339 -0
- package/src/listItem/AvatarView/ListItemAvatarView.tsx +27 -0
- package/src/listItem/AvatarView/index.ts +2 -0
- package/src/listItem/Button/ListItemButton.spec.tsx +90 -0
- package/src/listItem/Button/ListItemButton.story.tsx +473 -0
- package/src/listItem/Button/ListItemButton.tsx +56 -0
- package/src/listItem/Button/index.ts +2 -0
- package/src/listItem/Checkbox/ListItemCheckbox.spec.tsx +82 -0
- package/src/listItem/Checkbox/ListItemCheckbox.story.tsx +128 -0
- package/src/listItem/Checkbox/ListItemCheckbox.tsx +33 -0
- package/src/listItem/Checkbox/index.ts +2 -0
- package/src/listItem/IconButton/ListItemIconButton.spec.tsx +131 -0
- package/src/listItem/IconButton/ListItemIconButton.story.tsx +284 -0
- package/src/listItem/IconButton/ListItemIconButton.tsx +73 -0
- package/src/listItem/IconButton/index.ts +2 -0
- package/src/listItem/Image/ListItemImage.spec.tsx +30 -0
- package/src/listItem/Image/ListItemImage.story.tsx +80 -0
- package/src/listItem/Image/ListItemImage.tsx +46 -0
- package/src/listItem/Image/index.ts +2 -0
- package/src/listItem/ListItem.css +773 -0
- package/src/listItem/ListItem.grid.css +370 -0
- package/src/listItem/ListItem.grid.less +622 -0
- package/src/listItem/ListItem.less +291 -0
- package/src/listItem/ListItem.spec.tsx +1511 -0
- package/src/listItem/ListItem.tsx +440 -0
- package/src/listItem/ListItemContext.tsx +26 -0
- package/src/listItem/Navigation/ListItemNavigation.spec.tsx +67 -0
- package/src/listItem/Navigation/ListItemNavigation.story.tsx +114 -0
- package/src/listItem/Navigation/ListItemNavigation.tsx +39 -0
- package/src/listItem/Navigation/index.ts +2 -0
- package/src/listItem/Prompt/ListItemPrompt.css +157 -0
- package/src/listItem/Prompt/ListItemPrompt.less +134 -0
- package/src/listItem/Prompt/ListItemPrompt.spec.tsx +36 -0
- package/src/listItem/Prompt/ListItemPrompt.story.tsx +204 -0
- package/src/listItem/Prompt/ListItemPrompt.tsx +32 -0
- package/src/listItem/Prompt/index.ts +2 -0
- package/src/listItem/Radio/ListItemRadio.spec.tsx +66 -0
- package/src/listItem/Radio/ListItemRadio.story.tsx +111 -0
- package/src/listItem/Radio/ListItemRadio.tsx +33 -0
- package/src/listItem/Radio/index.ts +2 -0
- package/src/listItem/Switch/ListItemSwitch.spec.tsx +47 -0
- package/src/listItem/Switch/ListItemSwitch.story.tsx +79 -0
- package/src/listItem/Switch/ListItemSwitch.tsx +33 -0
- package/src/listItem/Switch/index.ts +2 -0
- package/src/listItem/_stories/ListItem.focus.test.story.tsx +265 -0
- package/src/listItem/_stories/ListItem.layout.test.story.tsx +374 -0
- package/src/listItem/_stories/ListItem.scenarios.story.tsx +228 -0
- package/src/listItem/_stories/ListItem.story.tsx +774 -0
- package/src/listItem/_stories/ListItem.variants.test.story.tsx +274 -0
- package/src/listItem/_stories/helpers.tsx +53 -0
- package/src/listItem/_stories/subcomponents.tsx +141 -0
- package/src/listItem/index.ts +14 -0
- package/src/listItem/test-utils.tsx +33 -0
- package/src/listItem/useListItemControl.tsx +18 -0
- package/src/listItem/useListItemMedia.tsx +16 -0
- package/src/main.css +794 -14
- package/src/main.less +1 -0
- package/src/primitives/PrimitiveAnchor/test/PrimitiveAnchor.spec.tsx +15 -4
- package/src/title/Title.tsx +25 -12
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
|
+
import { fn } from 'storybook/test';
|
|
3
|
+
import { Freeze, ArrowRight } from '@transferwise/icons';
|
|
4
|
+
import List from '../../list';
|
|
5
|
+
import { ListItem } from '../ListItem';
|
|
6
|
+
import {
|
|
7
|
+
SB_LIST_ITEM_ADDITIONAL_INFO as INFO,
|
|
8
|
+
SB_LIST_ITEM_MEDIA as MEDIA,
|
|
9
|
+
} from '../_stories/subcomponents';
|
|
10
|
+
import { disableControls } from '../_stories/helpers';
|
|
11
|
+
import type { ListItemButtonProps } from './ListItemButton';
|
|
12
|
+
|
|
13
|
+
const hideControls = disableControls([
|
|
14
|
+
'onClick',
|
|
15
|
+
'children',
|
|
16
|
+
'className',
|
|
17
|
+
'addonStart',
|
|
18
|
+
'addonEnd',
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Convenience controls for previewing rich markup,
|
|
23
|
+
* not otherwise possible via Storybook
|
|
24
|
+
*/
|
|
25
|
+
type PreviewStoryArgs = ListItemButtonProps & {
|
|
26
|
+
previewAddonStart: boolean | ListItemButtonProps['addonStart'];
|
|
27
|
+
previewAddonEnd: boolean | ListItemButtonProps['addonEnd'];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const previewArgTypes = {
|
|
31
|
+
previewAddonStart: {
|
|
32
|
+
control: 'boolean',
|
|
33
|
+
name: 'Preview with `addonStart`',
|
|
34
|
+
mapping: {
|
|
35
|
+
true: { type: 'icon', value: <Freeze /> },
|
|
36
|
+
},
|
|
37
|
+
description: '**NB:** ListItem.Button only supports icon addons.',
|
|
38
|
+
table: {
|
|
39
|
+
category: 'Preview options',
|
|
40
|
+
type: {
|
|
41
|
+
summary: undefined,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
previewAddonEnd: {
|
|
46
|
+
control: 'boolean',
|
|
47
|
+
name: 'Preview with `addonEnd`',
|
|
48
|
+
mapping: {
|
|
49
|
+
true: { type: 'icon', value: <ArrowRight /> },
|
|
50
|
+
},
|
|
51
|
+
description: '**NB:** ListItem.Button only supports icon addons.',
|
|
52
|
+
table: {
|
|
53
|
+
category: 'Preview options',
|
|
54
|
+
type: {
|
|
55
|
+
summary: undefined,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
} as const;
|
|
60
|
+
|
|
61
|
+
const getPropsForPreview = (args: PreviewStoryArgs) => {
|
|
62
|
+
const { previewAddonStart, previewAddonEnd, ...props } = args as {
|
|
63
|
+
previewAddonStart: ListItemButtonProps['addonStart'];
|
|
64
|
+
previewAddonEnd: ListItemButtonProps['addonEnd'];
|
|
65
|
+
[key: string]: any;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return [
|
|
69
|
+
props,
|
|
70
|
+
{
|
|
71
|
+
addonStart: previewAddonStart,
|
|
72
|
+
addonEnd: previewAddonEnd,
|
|
73
|
+
},
|
|
74
|
+
] as const;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const meta: Meta<typeof ListItem.Button> = {
|
|
78
|
+
component: ListItem.Button,
|
|
79
|
+
title: 'Content/ListItem/ListItem.Button',
|
|
80
|
+
parameters: {
|
|
81
|
+
docs: {
|
|
82
|
+
toc: true,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
args: {
|
|
86
|
+
partiallyInteractive: false,
|
|
87
|
+
priority: 'secondary-neutral',
|
|
88
|
+
sentiment: undefined,
|
|
89
|
+
loading: undefined,
|
|
90
|
+
href: undefined,
|
|
91
|
+
target: undefined,
|
|
92
|
+
as: undefined,
|
|
93
|
+
addonStart: undefined,
|
|
94
|
+
addonEnd: undefined,
|
|
95
|
+
className: undefined,
|
|
96
|
+
children: 'Click me',
|
|
97
|
+
onClick: fn(),
|
|
98
|
+
},
|
|
99
|
+
argTypes: {
|
|
100
|
+
children: {
|
|
101
|
+
table: {
|
|
102
|
+
type: { summary: 'ReactNode' },
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
loading: {
|
|
106
|
+
control: 'boolean',
|
|
107
|
+
description: 'Toggles the loading state',
|
|
108
|
+
},
|
|
109
|
+
priority: {
|
|
110
|
+
control: 'radio',
|
|
111
|
+
options: ['unset (undefined)', 'primary', 'secondary', 'secondary-neutral', 'tertiary'],
|
|
112
|
+
mapping: {
|
|
113
|
+
'unset (undefined)': undefined,
|
|
114
|
+
},
|
|
115
|
+
description: 'Sets a visual hierarchy amongst the buttons displayed on the screen',
|
|
116
|
+
},
|
|
117
|
+
sentiment: {
|
|
118
|
+
options: ['unset (undefined)', 'default', 'negative'],
|
|
119
|
+
mapping: {
|
|
120
|
+
'unset (undefined)': undefined,
|
|
121
|
+
},
|
|
122
|
+
description:
|
|
123
|
+
'Sets a visual hierarchy amongst the buttons displayed on the screen. <br /> **NB:** `negative` variant only affects the `primary` and `secondary` priorities.',
|
|
124
|
+
},
|
|
125
|
+
href: {
|
|
126
|
+
control: 'text',
|
|
127
|
+
description: 'If set, the component will render as an HTML anchor.',
|
|
128
|
+
},
|
|
129
|
+
target: {
|
|
130
|
+
control: 'select',
|
|
131
|
+
options: [undefined, '_blank', '_self', '_parent', '_top'],
|
|
132
|
+
description:
|
|
133
|
+
'The `target` attribute for HTML anchor. If set to `_blank`, `rel="noopener noreferrer"` is automatically added to the rendered node.',
|
|
134
|
+
},
|
|
135
|
+
addonStart: {
|
|
136
|
+
description: 'Icon accessory to be displayed before the label',
|
|
137
|
+
},
|
|
138
|
+
addonEnd: {
|
|
139
|
+
description: 'Icon accessory to be displayed after the label',
|
|
140
|
+
},
|
|
141
|
+
onClick: {
|
|
142
|
+
table: {
|
|
143
|
+
type: { summary: '(event: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void' },
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
} satisfies Meta<ListItemButtonProps>;
|
|
148
|
+
|
|
149
|
+
export default meta;
|
|
150
|
+
|
|
151
|
+
type Story = StoryObj<ListItemButtonProps>;
|
|
152
|
+
|
|
153
|
+
export const Playground: StoryObj<PreviewStoryArgs> = {
|
|
154
|
+
tags: ['!autodocs'],
|
|
155
|
+
render: (args: PreviewStoryArgs) => {
|
|
156
|
+
const [props, previewProps] = getPropsForPreview(args);
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<List>
|
|
160
|
+
<ListItem
|
|
161
|
+
title="List item title"
|
|
162
|
+
subtitle="Subtitle goes here"
|
|
163
|
+
media={MEDIA.avatarSingle}
|
|
164
|
+
control={<ListItem.Button {...props} {...previewProps} />}
|
|
165
|
+
additionalInfo={INFO.nonInteractive}
|
|
166
|
+
/>
|
|
167
|
+
</List>
|
|
168
|
+
);
|
|
169
|
+
},
|
|
170
|
+
args: {
|
|
171
|
+
previewAddonStart: false,
|
|
172
|
+
previewAddonEnd: false,
|
|
173
|
+
},
|
|
174
|
+
argTypes: {
|
|
175
|
+
...previewArgTypes,
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* By default, ListItem is fully interactive, which means its whole surface is clickable
|
|
181
|
+
* and triggers the control. To remain WCAG-compliant there can be no nested interactive
|
|
182
|
+
* elements inside the item.<br />
|
|
183
|
+
*
|
|
184
|
+
* To work around this limitation, this control also allows for a partially interactive mode,
|
|
185
|
+
* which can be enabled via `partiallyInteractive` prop. Once set, only the control will
|
|
186
|
+
* remain interactive, which allows for interactive element to be attached to the
|
|
187
|
+
* `ListItem.AdditionalInfo`. This allows for more complex layouts while still providing a
|
|
188
|
+
* clear, accessible action point for users. <br />
|
|
189
|
+
*
|
|
190
|
+
* If you still require a fully interactive ListItem, you can alternatively use `ListItem.Prompt`
|
|
191
|
+
* which allows for a single instance of a link or an inline button.
|
|
192
|
+
*
|
|
193
|
+
* Refer to the [design documentation](https://wise.design/components/list-item#interaction) for details.
|
|
194
|
+
*/
|
|
195
|
+
export const Interactivity: StoryObj<PreviewStoryArgs> = {
|
|
196
|
+
args: {
|
|
197
|
+
children: 'Action',
|
|
198
|
+
previewAddonStart: false,
|
|
199
|
+
previewAddonEnd: false,
|
|
200
|
+
},
|
|
201
|
+
argTypes: {
|
|
202
|
+
...hideControls(['partiallyInteractive']),
|
|
203
|
+
...previewArgTypes,
|
|
204
|
+
},
|
|
205
|
+
render: (args: PreviewStoryArgs) => {
|
|
206
|
+
const [props, previewProps] = getPropsForPreview(args);
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<List>
|
|
210
|
+
<ListItem
|
|
211
|
+
title="Fully interactive ListItem"
|
|
212
|
+
subtitle="Button in fully interactive context"
|
|
213
|
+
media={MEDIA.avatarSingle}
|
|
214
|
+
control={<ListItem.Button {...props} {...previewProps} />}
|
|
215
|
+
/>
|
|
216
|
+
|
|
217
|
+
<ListItem
|
|
218
|
+
title="Partially interactive ListItem"
|
|
219
|
+
subtitle="Button in partially interactive context"
|
|
220
|
+
media={MEDIA.avatarSingle}
|
|
221
|
+
control={<ListItem.Button {...props} {...previewProps} partiallyInteractive />}
|
|
222
|
+
/>
|
|
223
|
+
</List>
|
|
224
|
+
);
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* If `href` prop is set, the component will be automatically rendered as an HTML anchor element.
|
|
230
|
+
*/
|
|
231
|
+
export const AsAnchor: StoryObj<PreviewStoryArgs> = {
|
|
232
|
+
args: {
|
|
233
|
+
children: 'Visit link',
|
|
234
|
+
href: 'https://wise.com',
|
|
235
|
+
target: '_blank',
|
|
236
|
+
previewAddonStart: false,
|
|
237
|
+
previewAddonEnd: false,
|
|
238
|
+
},
|
|
239
|
+
argTypes: {
|
|
240
|
+
...hideControls(['partiallyInteractive']),
|
|
241
|
+
...previewArgTypes,
|
|
242
|
+
},
|
|
243
|
+
render: (args: PreviewStoryArgs) => {
|
|
244
|
+
const [props, previewProps] = getPropsForPreview(args);
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
<List>
|
|
248
|
+
<ListItem
|
|
249
|
+
title="List item with a Button control"
|
|
250
|
+
subtitle="But it renders as HTML anchor element"
|
|
251
|
+
media={MEDIA.avatarSingle}
|
|
252
|
+
control={<ListItem.Button {...props} {...previewProps} />}
|
|
253
|
+
/>
|
|
254
|
+
</List>
|
|
255
|
+
);
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* There are two different types of button – default and negative – designed to emphasise the nature of the action. <br />
|
|
261
|
+
* **NB:** Sentiment only applies to `primary` and `secondary` priorities. <br />
|
|
262
|
+
* [Design documentation](https://wise.design/components/button#types)
|
|
263
|
+
*/
|
|
264
|
+
export const Sentiment: StoryObj<PreviewStoryArgs> = {
|
|
265
|
+
args: {
|
|
266
|
+
children: 'Button text',
|
|
267
|
+
previewAddonStart: false,
|
|
268
|
+
previewAddonEnd: false,
|
|
269
|
+
},
|
|
270
|
+
argTypes: {
|
|
271
|
+
...hideControls(['sentiment', 'priority']),
|
|
272
|
+
...previewArgTypes,
|
|
273
|
+
},
|
|
274
|
+
render: (args: PreviewStoryArgs) => {
|
|
275
|
+
const [props, previewProps] = getPropsForPreview(args);
|
|
276
|
+
|
|
277
|
+
return (
|
|
278
|
+
<List>
|
|
279
|
+
<ListItem
|
|
280
|
+
title="Default Sentiment - Primary"
|
|
281
|
+
subtitle="Default sentiment with primary priority"
|
|
282
|
+
media={MEDIA.avatarSingle}
|
|
283
|
+
control={
|
|
284
|
+
<ListItem.Button {...props} {...previewProps} priority="primary">
|
|
285
|
+
Default Sentiment
|
|
286
|
+
</ListItem.Button>
|
|
287
|
+
}
|
|
288
|
+
/>
|
|
289
|
+
<ListItem
|
|
290
|
+
title="Negative Sentiment - Primary"
|
|
291
|
+
subtitle="Negative sentiment with primary priority"
|
|
292
|
+
media={MEDIA.avatarSingle}
|
|
293
|
+
control={
|
|
294
|
+
<ListItem.Button {...props} {...previewProps} priority="primary" sentiment="negative">
|
|
295
|
+
Negative Sentiment
|
|
296
|
+
</ListItem.Button>
|
|
297
|
+
}
|
|
298
|
+
/>
|
|
299
|
+
<ListItem
|
|
300
|
+
title="Default Sentiment - Secondary"
|
|
301
|
+
subtitle="Default sentiment with secondary priority"
|
|
302
|
+
media={MEDIA.avatarSingle}
|
|
303
|
+
control={
|
|
304
|
+
<ListItem.Button {...props} {...previewProps} priority="secondary">
|
|
305
|
+
Default Sentiment
|
|
306
|
+
</ListItem.Button>
|
|
307
|
+
}
|
|
308
|
+
/>
|
|
309
|
+
<ListItem
|
|
310
|
+
title="Negative Sentiment - Secondary"
|
|
311
|
+
subtitle="Negative sentiment with secondary priority"
|
|
312
|
+
media={MEDIA.avatarSingle}
|
|
313
|
+
control={
|
|
314
|
+
<ListItem.Button {...props} {...previewProps} priority="secondary" sentiment="negative">
|
|
315
|
+
Negative Sentiment
|
|
316
|
+
</ListItem.Button>
|
|
317
|
+
}
|
|
318
|
+
/>
|
|
319
|
+
</List>
|
|
320
|
+
);
|
|
321
|
+
},
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Priorities set a visual hierarchy amongst the buttons displayed on the
|
|
326
|
+
* screen to help more important buttons to take precedence over others. <br />
|
|
327
|
+
* [Design documentation](https://wise.design/components/button#priorities)
|
|
328
|
+
*/
|
|
329
|
+
export const Priority: StoryObj<PreviewStoryArgs> = {
|
|
330
|
+
args: {
|
|
331
|
+
children: 'Button text',
|
|
332
|
+
previewAddonStart: false,
|
|
333
|
+
previewAddonEnd: false,
|
|
334
|
+
},
|
|
335
|
+
argTypes: {
|
|
336
|
+
...hideControls(['priority']),
|
|
337
|
+
...previewArgTypes,
|
|
338
|
+
},
|
|
339
|
+
render: (args: PreviewStoryArgs) => {
|
|
340
|
+
const [props, previewProps] = getPropsForPreview(args);
|
|
341
|
+
|
|
342
|
+
return (
|
|
343
|
+
<List>
|
|
344
|
+
<ListItem
|
|
345
|
+
title="Primary Priority"
|
|
346
|
+
subtitle="Primary priority (default)"
|
|
347
|
+
media={MEDIA.avatarSingle}
|
|
348
|
+
control={
|
|
349
|
+
<ListItem.Button {...props} {...previewProps} priority="primary">
|
|
350
|
+
Primary Priority
|
|
351
|
+
</ListItem.Button>
|
|
352
|
+
}
|
|
353
|
+
/>
|
|
354
|
+
<ListItem
|
|
355
|
+
title="Secondary Priority"
|
|
356
|
+
subtitle="Secondary priority"
|
|
357
|
+
media={MEDIA.avatarSingle}
|
|
358
|
+
control={
|
|
359
|
+
<ListItem.Button {...props} {...previewProps} priority="secondary">
|
|
360
|
+
Secondary Priority
|
|
361
|
+
</ListItem.Button>
|
|
362
|
+
}
|
|
363
|
+
/>
|
|
364
|
+
<ListItem
|
|
365
|
+
title="Secondary Neutral Priority"
|
|
366
|
+
subtitle="Secondary neutral priority"
|
|
367
|
+
media={MEDIA.avatarSingle}
|
|
368
|
+
control={
|
|
369
|
+
<ListItem.Button {...props} {...previewProps} priority="secondary-neutral">
|
|
370
|
+
Secondary Neutral Priority
|
|
371
|
+
</ListItem.Button>
|
|
372
|
+
}
|
|
373
|
+
/>
|
|
374
|
+
<ListItem
|
|
375
|
+
title="Tertiary Priority"
|
|
376
|
+
subtitle="Tertiary priority"
|
|
377
|
+
media={MEDIA.avatarSingle}
|
|
378
|
+
control={
|
|
379
|
+
<ListItem.Button {...props} {...previewProps} priority="tertiary">
|
|
380
|
+
Tertiary Priority
|
|
381
|
+
</ListItem.Button>
|
|
382
|
+
}
|
|
383
|
+
/>
|
|
384
|
+
</List>
|
|
385
|
+
);
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Button in loading state.
|
|
391
|
+
*/
|
|
392
|
+
export const Loading: StoryObj<PreviewStoryArgs> = {
|
|
393
|
+
args: {
|
|
394
|
+
loading: true,
|
|
395
|
+
previewAddonStart: false,
|
|
396
|
+
previewAddonEnd: false,
|
|
397
|
+
},
|
|
398
|
+
argTypes: {
|
|
399
|
+
...hideControls(['loading']),
|
|
400
|
+
...previewArgTypes,
|
|
401
|
+
},
|
|
402
|
+
render: (args: PreviewStoryArgs) => {
|
|
403
|
+
const [props, previewProps] = getPropsForPreview(args);
|
|
404
|
+
|
|
405
|
+
return (
|
|
406
|
+
<List>
|
|
407
|
+
<ListItem
|
|
408
|
+
title="Loading Button"
|
|
409
|
+
subtitle="Button in loading state"
|
|
410
|
+
media={MEDIA.avatarSingle}
|
|
411
|
+
control={
|
|
412
|
+
<ListItem.Button {...props} {...previewProps}>
|
|
413
|
+
Loading Button
|
|
414
|
+
</ListItem.Button>
|
|
415
|
+
}
|
|
416
|
+
additionalInfo={INFO.nonInteractive}
|
|
417
|
+
/>
|
|
418
|
+
</List>
|
|
419
|
+
);
|
|
420
|
+
},
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const addonProps = {
|
|
424
|
+
addonStart: { type: 'icon', value: <Freeze /> },
|
|
425
|
+
addonEnd: { type: 'icon', value: <ArrowRight /> },
|
|
426
|
+
} as const;
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Icons can be displayed before and after the button label. <br />
|
|
430
|
+
* **NB:** ListItem.Button only supports icon addons.
|
|
431
|
+
*/
|
|
432
|
+
export const WithIcons: Story = {
|
|
433
|
+
args: {
|
|
434
|
+
children: 'Button text',
|
|
435
|
+
},
|
|
436
|
+
argTypes: hideControls(),
|
|
437
|
+
render: (args: ListItemButtonProps) => {
|
|
438
|
+
return (
|
|
439
|
+
<List>
|
|
440
|
+
<ListItem
|
|
441
|
+
title="With Start Icon"
|
|
442
|
+
subtitle="Button with icon before the label"
|
|
443
|
+
media={MEDIA.avatarSingle}
|
|
444
|
+
control={
|
|
445
|
+
<ListItem.Button {...args} addonStart={addonProps.addonStart}>
|
|
446
|
+
With start icon
|
|
447
|
+
</ListItem.Button>
|
|
448
|
+
}
|
|
449
|
+
/>
|
|
450
|
+
<ListItem
|
|
451
|
+
title="With End Icon"
|
|
452
|
+
subtitle="Button with icon after the label"
|
|
453
|
+
media={MEDIA.avatarSingle}
|
|
454
|
+
control={
|
|
455
|
+
<ListItem.Button {...args} addonEnd={addonProps.addonEnd}>
|
|
456
|
+
With end icon
|
|
457
|
+
</ListItem.Button>
|
|
458
|
+
}
|
|
459
|
+
/>
|
|
460
|
+
<ListItem
|
|
461
|
+
title="With Both Icons"
|
|
462
|
+
subtitle="Button with icons before and after the label"
|
|
463
|
+
media={MEDIA.avatarSingle}
|
|
464
|
+
control={
|
|
465
|
+
<ListItem.Button {...args} {...addonProps}>
|
|
466
|
+
With both icons
|
|
467
|
+
</ListItem.Button>
|
|
468
|
+
}
|
|
469
|
+
/>
|
|
470
|
+
</List>
|
|
471
|
+
);
|
|
472
|
+
},
|
|
473
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import ButtonComp, { type ButtonAddonIcon, type NewButtonProps } from '../../button';
|
|
4
|
+
import { useListItemControl } from '../useListItemControl';
|
|
5
|
+
import { ListItemContext } from '../ListItemContext';
|
|
6
|
+
|
|
7
|
+
export type ListItemButtonProps = Omit<
|
|
8
|
+
NewButtonProps,
|
|
9
|
+
'v2' | 'size' | 'disabled' | 'block' | 'addonStart'
|
|
10
|
+
> & {
|
|
11
|
+
/**
|
|
12
|
+
* Toggles the [interactivity strategy](https://storybook.wise.design/?path=/docs/content-listitem--docs#interactivity) for the whole ListItem.
|
|
13
|
+
*/
|
|
14
|
+
partiallyInteractive?: boolean;
|
|
15
|
+
addonStart?: ButtonAddonIcon;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* This component allows for rendering a Button control. It's a thin wrapper around the
|
|
20
|
+
* [Button component](https://storybook.wise.design/?path=/docs/content-button--docs), but offers only
|
|
21
|
+
* a subset of its features in line with the ListItem's constraints. <br />
|
|
22
|
+
* <br />
|
|
23
|
+
* Please refer to the [Design documentation](https://wise.design/components/list-item---button) for details.
|
|
24
|
+
*/
|
|
25
|
+
export const Button = ({
|
|
26
|
+
priority = 'secondary-neutral',
|
|
27
|
+
partiallyInteractive,
|
|
28
|
+
...props
|
|
29
|
+
}: ListItemButtonProps) => {
|
|
30
|
+
const { baseItemProps } = useListItemControl('button', { partiallyInteractive, ...props });
|
|
31
|
+
const { ids, describedByIds } = useContext(ListItemContext);
|
|
32
|
+
|
|
33
|
+
const commonProps = {
|
|
34
|
+
...props,
|
|
35
|
+
className: clsx(
|
|
36
|
+
'wds-list-item-control',
|
|
37
|
+
!partiallyInteractive && props.href && 'wds-list-item-control_pseudo-element',
|
|
38
|
+
),
|
|
39
|
+
id: ids.control,
|
|
40
|
+
priority,
|
|
41
|
+
v2: true,
|
|
42
|
+
size: 'sm',
|
|
43
|
+
disabled: baseItemProps.disabled,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const buttonContentId = props.href || partiallyInteractive ? '' : `${ids.control}_content`;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<ButtonComp
|
|
50
|
+
aria-describedby={`${buttonContentId} ${describedByIds}`}
|
|
51
|
+
{...(commonProps as NewButtonProps)}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
Button.displayName = 'ListItem.Button';
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { render, screen } from '../../test-utils';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { ListItem, type ListItemProps } from '../ListItem';
|
|
4
|
+
|
|
5
|
+
describe('ListItem.Checkbox', () => {
|
|
6
|
+
const renderWith = (overrides: Partial<ListItemProps> = {}) =>
|
|
7
|
+
render(<ListItem title="Test title" {...overrides} />);
|
|
8
|
+
|
|
9
|
+
it('renders checkbox', () => {
|
|
10
|
+
renderWith({ control: <ListItem.Checkbox /> });
|
|
11
|
+
expect(screen.getByRole('checkbox')).toBeInTheDocument();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('checked state', () => {
|
|
15
|
+
it('reflects checked state', () => {
|
|
16
|
+
renderWith({ control: <ListItem.Checkbox checked onChange={jest.fn()} /> });
|
|
17
|
+
expect(screen.getByRole('checkbox')).toBeChecked();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('reflects unchecked state', () => {
|
|
21
|
+
renderWith({ control: <ListItem.Checkbox checked={false} onChange={jest.fn()} /> });
|
|
22
|
+
expect(screen.getByRole('checkbox')).not.toBeChecked();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('supports indeterminate state', () => {
|
|
26
|
+
renderWith({ control: <ListItem.Checkbox indeterminate /> });
|
|
27
|
+
expect(screen.getByRole('checkbox')).toHaveProperty('indeterminate', true);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('interactivity', () => {
|
|
32
|
+
it('handles onChange events', async () => {
|
|
33
|
+
const handleChange = jest.fn();
|
|
34
|
+
renderWith({ control: <ListItem.Checkbox checked={false} onChange={handleChange} /> });
|
|
35
|
+
|
|
36
|
+
await userEvent.click(screen.getByRole('checkbox'));
|
|
37
|
+
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('is disabled when ListItem is disabled', () => {
|
|
41
|
+
renderWith({
|
|
42
|
+
disabled: true,
|
|
43
|
+
control: <ListItem.Checkbox checked={false} onChange={jest.fn()} />,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
expect(screen.getByRole('checkbox')).toBeDisabled();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('handles onFocus events', async () => {
|
|
50
|
+
const handleFocus = jest.fn();
|
|
51
|
+
renderWith({
|
|
52
|
+
control: <ListItem.Checkbox checked={false} onFocus={handleFocus} onChange={() => {}} />,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
await userEvent.tab();
|
|
56
|
+
expect(handleFocus).toHaveBeenCalledTimes(1);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('handles onBlur events', async () => {
|
|
60
|
+
const handleBlur = jest.fn();
|
|
61
|
+
renderWith({
|
|
62
|
+
control: <ListItem.Checkbox checked={false} onBlur={handleBlur} onChange={() => {}} />,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const checkbox = screen.getByRole('checkbox');
|
|
66
|
+
await userEvent.click(checkbox);
|
|
67
|
+
await userEvent.tab();
|
|
68
|
+
expect(handleBlur).toHaveBeenCalledTimes(1);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('supports name and value attributes', () => {
|
|
73
|
+
const checkboxName = 'test-checkbox';
|
|
74
|
+
const checkboxValue = 'test-value';
|
|
75
|
+
renderWith({ control: <ListItem.Checkbox name={checkboxName} value={checkboxValue} /> });
|
|
76
|
+
|
|
77
|
+
const checkbox = screen.getByRole('checkbox');
|
|
78
|
+
expect(checkbox).toHaveAttribute('name', checkboxName);
|
|
79
|
+
// eslint-disable-next-line jest-dom/prefer-to-have-value
|
|
80
|
+
expect(checkbox).toHaveAttribute('value', checkboxValue);
|
|
81
|
+
});
|
|
82
|
+
});
|