@transferwise/components 46.107.0 → 46.108.1
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 +1 -0
- package/build/header/Header.js.map +1 -1
- package/build/header/Header.mjs +1 -0
- package/build/header/Header.mjs.map +1 -1
- package/build/link/Link.js +6 -2
- package/build/link/Link.js.map +1 -1
- package/build/link/Link.mjs +6 -2
- package/build/link/Link.mjs.map +1 -1
- package/build/listItem/ListItem.js +20 -8
- package/build/listItem/ListItem.js.map +1 -1
- package/build/listItem/ListItem.mjs +20 -8
- package/build/listItem/ListItem.mjs.map +1 -1
- package/build/listItem/ListItemContext.js.map +1 -1
- package/build/listItem/ListItemContext.mjs.map +1 -1
- package/build/listItem/Navigation/ListItemNavigation.js +1 -3
- package/build/listItem/Navigation/ListItemNavigation.js.map +1 -1
- package/build/listItem/Navigation/ListItemNavigation.mjs +2 -4
- package/build/listItem/Navigation/ListItemNavigation.mjs.map +1 -1
- package/build/listItem/Prompt/InlinePrompt/InlinePrompt.js +74 -0
- package/build/listItem/Prompt/InlinePrompt/InlinePrompt.js.map +1 -0
- package/build/listItem/Prompt/InlinePrompt/InlinePrompt.mjs +72 -0
- package/build/listItem/Prompt/InlinePrompt/InlinePrompt.mjs.map +1 -0
- package/build/listItem/Prompt/ListItemPrompt.js +10 -15
- package/build/listItem/Prompt/ListItemPrompt.js.map +1 -1
- package/build/listItem/Prompt/ListItemPrompt.mjs +11 -16
- package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -1
- package/build/main.css +94 -74
- package/build/styles/link/Link.css +7 -0
- package/build/styles/listItem/ListItem.css +87 -74
- package/build/styles/listItem/Prompt/InlinePrompt/InlinePrompt.css +153 -0
- package/build/styles/listItem/Prompt/ListItemPrompt.css +72 -72
- package/build/styles/main.css +94 -74
- package/build/types/header/Header.d.ts +1 -0
- package/build/types/header/Header.d.ts.map +1 -1
- package/build/types/link/Link.d.ts +1 -1
- package/build/types/link/Link.d.ts.map +1 -1
- package/build/types/listItem/ListItem.d.ts +10 -1
- package/build/types/listItem/ListItem.d.ts.map +1 -1
- package/build/types/listItem/ListItemContext.d.ts +2 -1
- package/build/types/listItem/ListItemContext.d.ts.map +1 -1
- package/build/types/listItem/Navigation/ListItemNavigation.d.ts.map +1 -1
- package/build/types/listItem/Prompt/InlinePrompt/InlinePrompt.d.ts +15 -0
- package/build/types/listItem/Prompt/InlinePrompt/InlinePrompt.d.ts.map +1 -0
- package/build/types/listItem/Prompt/InlinePrompt/index.d.ts +3 -0
- package/build/types/listItem/Prompt/InlinePrompt/index.d.ts.map +1 -0
- package/build/types/listItem/Prompt/ListItemPrompt.d.ts +4 -6
- package/build/types/listItem/Prompt/ListItemPrompt.d.ts.map +1 -1
- package/build/types/listItem/_stories/helpers.d.ts.map +1 -1
- package/build/types/listItem/_stories/subcomponents.d.ts +1 -0
- package/build/types/listItem/_stories/subcomponents.d.ts.map +1 -1
- package/build/types/listItem/useListItemControl.d.ts +1 -1
- package/package.json +4 -4
- package/src/header/Header.story.tsx +14 -0
- package/src/header/Header.tsx +2 -0
- package/src/link/Link.css +7 -0
- package/src/link/Link.less +8 -0
- package/src/link/Link.spec.tsx +28 -0
- package/src/link/Link.story.tsx +72 -16
- package/src/link/Link.tsx +5 -1
- package/src/listItem/ListItem.css +87 -74
- package/src/listItem/ListItem.less +19 -4
- package/src/listItem/ListItem.spec.tsx +33 -0
- package/src/listItem/ListItem.tsx +38 -12
- package/src/listItem/ListItemContext.tsx +2 -1
- package/src/listItem/Navigation/ListItemNavigation.spec.tsx +1 -10
- package/src/listItem/Navigation/ListItemNavigation.story.tsx +0 -22
- package/src/listItem/Navigation/ListItemNavigation.tsx +2 -3
- package/src/listItem/Prompt/InlinePrompt/InlinePrompt.css +153 -0
- package/src/listItem/Prompt/InlinePrompt/InlinePrompt.less +162 -0
- package/src/listItem/Prompt/InlinePrompt/InlinePrompt.spec.tsx +66 -0
- package/src/listItem/Prompt/InlinePrompt/InlinePrompt.tsx +56 -0
- package/src/listItem/Prompt/InlinePrompt/index.ts +2 -0
- package/src/listItem/Prompt/ListItemPrompt.css +72 -72
- package/src/listItem/Prompt/ListItemPrompt.less +2 -130
- package/src/listItem/Prompt/ListItemPrompt.spec.tsx +36 -0
- package/src/listItem/Prompt/ListItemPrompt.story.tsx +4 -2
- package/src/listItem/Prompt/ListItemPrompt.tsx +14 -14
- package/src/listItem/_stories/ListItem.disabled.story.tsx +433 -0
- package/src/listItem/_stories/ListItem.story.tsx +1 -177
- package/src/listItem/_stories/helpers.tsx +1 -0
- package/src/listItem/_stories/subcomponents.tsx +5 -0
- package/src/main.css +94 -74
|
@@ -1,134 +1,6 @@
|
|
|
1
|
+
@import "./InlinePrompt/InlinePrompt.less";
|
|
2
|
+
|
|
1
3
|
.wds-list-item-prompt {
|
|
2
4
|
grid-area: prompt;
|
|
3
|
-
|
|
4
|
-
display: inline-flex;
|
|
5
5
|
justify-self: start;
|
|
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
|
-
a, button {
|
|
22
|
-
text-underline-offset: calc(var(--size-4) / 2);
|
|
23
|
-
&:first-of-type {
|
|
24
|
-
&:before {
|
|
25
|
-
content: '';
|
|
26
|
-
position: absolute;
|
|
27
|
-
inset: 0;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
&.np-prompt-icon {
|
|
33
|
-
padding-left: calc(var(--padding-x-small) - 1px);
|
|
34
|
-
padding-right: var(--padding-x-small);
|
|
35
|
-
display: inline-flex;
|
|
36
|
-
align-items: center;
|
|
37
|
-
gap: var(--size-4);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.np-prompt-icon {
|
|
41
|
-
padding-right: calc(var(--size-12) / 2);
|
|
42
|
-
padding-top: calc(var(--size-4) - 1px);
|
|
43
|
-
padding-bottom: calc(var(--size-4) - 1px);
|
|
44
|
-
|
|
45
|
-
.tw-icon-tags,
|
|
46
|
-
.tw-icon-confetti {
|
|
47
|
-
color: var(--color-sentiment-positive-primary);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
&.negative {
|
|
52
|
-
background-color: var(--color-sentiment-negative-secondary);
|
|
53
|
-
color: var(--color-sentiment-negative-primary);
|
|
54
|
-
a, button {
|
|
55
|
-
color: var(--color-sentiment-negative-primary);
|
|
56
|
-
&:hover {
|
|
57
|
-
color: var(--color-sentiment-negative-primary-hover);
|
|
58
|
-
}
|
|
59
|
-
&:active {
|
|
60
|
-
color: var(--color-sentiment-negative-primary-active);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
.wds-list-item-prompt&:has(a, button) {
|
|
64
|
-
&:hover {
|
|
65
|
-
background-color: var(--color-sentiment-negative-secondary-hover);
|
|
66
|
-
}
|
|
67
|
-
&:active {
|
|
68
|
-
background-color: var(--color-sentiment-negative-secondary-active);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
&.positive,
|
|
73
|
-
&.discount,
|
|
74
|
-
&.savings {
|
|
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-list-item-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
|
-
&.neutral {
|
|
96
|
-
background-color: var(--color-background-neutral);
|
|
97
|
-
color: var(--color-content-primary);
|
|
98
|
-
a, button {
|
|
99
|
-
color: var(--color-content-primary);
|
|
100
|
-
}
|
|
101
|
-
.wds-list-item-prompt&:has(a, button) {
|
|
102
|
-
&:hover {
|
|
103
|
-
background-color: var(--color-background-neutral-hover);
|
|
104
|
-
}
|
|
105
|
-
&:active {
|
|
106
|
-
background-color: var(--color-background-neutral-active);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
&.warning {
|
|
111
|
-
background-color: var(--color-sentiment-warning-secondary);
|
|
112
|
-
color: var(--color-sentiment-warning-content);
|
|
113
|
-
a, button {
|
|
114
|
-
color: var(--color-sentiment-warning-content);
|
|
115
|
-
&:hover {
|
|
116
|
-
color: var(--color-sentiment-warning-content-hover);
|
|
117
|
-
}
|
|
118
|
-
&:active {
|
|
119
|
-
color: var(--color-sentiment-warning-content-active);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
.wds-list-item-prompt&:has(a, button) {
|
|
123
|
-
&:hover {
|
|
124
|
-
// someday we'll have hover and active states for warning
|
|
125
|
-
// background-color: var(--color-sentiment-warning-secondary-hover);
|
|
126
|
-
background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 92%, var(--color-sentiment-warning-primary));
|
|
127
|
-
}
|
|
128
|
-
&:active {
|
|
129
|
-
// background-color: var(--color-sentiment-warning-secondary-active);
|
|
130
|
-
background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 84%, var(--color-sentiment-warning-primary));
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
6
|
}
|
|
@@ -33,4 +33,40 @@ describe('ListItem.Prompt', () => {
|
|
|
33
33
|
expect(screen.getByTestId(iconId)).toBeInTheDocument();
|
|
34
34
|
});
|
|
35
35
|
});
|
|
36
|
+
|
|
37
|
+
describe('muted state', () => {
|
|
38
|
+
it('does not render backslash-cross icon when parent ListItem is disabled and disabledPromptMessage is not', () => {
|
|
39
|
+
render(
|
|
40
|
+
<ListItem
|
|
41
|
+
title="Test Title"
|
|
42
|
+
disabled
|
|
43
|
+
prompt={<ListItem.Prompt>Message</ListItem.Prompt>}
|
|
44
|
+
/>,
|
|
45
|
+
);
|
|
46
|
+
expect(screen.queryByTestId('InlinePrompt_Muted')).not.toBeInTheDocument();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('does not renders backslash-cross icon when parent ListItem is not disabled but disabledPromptMessage is set', () => {
|
|
50
|
+
render(
|
|
51
|
+
<ListItem
|
|
52
|
+
title="Test Title"
|
|
53
|
+
disabledPromptMessage="Test reason"
|
|
54
|
+
prompt={<ListItem.Prompt>Message</ListItem.Prompt>}
|
|
55
|
+
/>,
|
|
56
|
+
);
|
|
57
|
+
expect(screen.queryByTestId('InlinePrompt_Muted')).not.toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('renders backslash-cross icon when parent ListItem is disabled and disabledPromptMessage is provided', () => {
|
|
61
|
+
render(
|
|
62
|
+
<ListItem
|
|
63
|
+
title="Test Title"
|
|
64
|
+
disabled
|
|
65
|
+
disabledPromptMessage="Test reason"
|
|
66
|
+
prompt={<ListItem.Prompt>Message</ListItem.Prompt>}
|
|
67
|
+
/>,
|
|
68
|
+
);
|
|
69
|
+
expect(screen.getByTestId('InlinePrompt_Muted')).toBeInTheDocument();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
36
72
|
});
|
|
@@ -4,12 +4,13 @@ import { lorem10, lorem5 } from '../../test-utils';
|
|
|
4
4
|
import Link from '../../link';
|
|
5
5
|
import List from '../../list';
|
|
6
6
|
import { Sentiment as Sentiments } from '../../common';
|
|
7
|
-
import {
|
|
8
|
-
import { Prompt, type ListItemPromptProps } from './ListItemPrompt';
|
|
7
|
+
import { withoutKey } from '../_stories/helpers';
|
|
9
8
|
import {
|
|
10
9
|
SB_LIST_ITEM_CONTROLS as CONTROLS,
|
|
11
10
|
SB_LIST_ITEM_MEDIA as MEDIA,
|
|
12
11
|
} from '../_stories/subcomponents';
|
|
12
|
+
import { ListItem } from '../ListItem';
|
|
13
|
+
import { Prompt, type ListItemPromptProps } from './ListItemPrompt';
|
|
13
14
|
|
|
14
15
|
const meta: Meta<ListItemPromptProps> = {
|
|
15
16
|
component: Prompt,
|
|
@@ -19,6 +20,7 @@ const meta: Meta<ListItemPromptProps> = {
|
|
|
19
20
|
toc: true,
|
|
20
21
|
},
|
|
21
22
|
},
|
|
23
|
+
decorators: [withoutKey],
|
|
22
24
|
args: {
|
|
23
25
|
sentiment: undefined,
|
|
24
26
|
children: 'You have done a terrible thing',
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import { useContext } from 'react';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { Sentiment } from '../../common';
|
|
4
|
-
import StatusIcon from '../../statusIcon';
|
|
5
|
-
import Body from '../../body';
|
|
6
4
|
import { ListItemContext, type ListItemContextData } from '../ListItemContext';
|
|
5
|
+
import { InlinePrompt, type InlinePromptProps } from './InlinePrompt';
|
|
7
6
|
|
|
8
|
-
export type ListItemPromptProps =
|
|
9
|
-
sentiment?: `${Sentiment.POSITIVE | Sentiment.NEGATIVE | Sentiment.NEUTRAL | Sentiment.WARNING}`;
|
|
10
|
-
children: React.ReactNode;
|
|
11
|
-
};
|
|
7
|
+
export type ListItemPromptProps = Pick<InlinePromptProps, 'children' | 'sentiment' | 'muted'>;
|
|
12
8
|
|
|
13
9
|
/**
|
|
14
|
-
* This component allows for rendering an Inline Prompt. <br />
|
|
10
|
+
* This component allows for rendering an Inline Prompt. <br />
|
|
11
|
+
* In the future it will be a thin wrapper around a standalone component.<br />
|
|
15
12
|
*
|
|
16
13
|
* Please refer to the [Design documentation](https://wise.design/components/list-item#prompt) for details.
|
|
17
14
|
*/
|
|
18
15
|
export const Prompt = ({ sentiment = Sentiment.NEUTRAL, children }: ListItemPromptProps) => {
|
|
19
|
-
const { ids } = useContext<ListItemContextData>(ListItemContext);
|
|
16
|
+
const { ids, props } = useContext<ListItemContextData>(ListItemContext);
|
|
17
|
+
const isLongLivedMuted = props.disabled && Boolean(props.disabledPromptMessage);
|
|
20
18
|
|
|
21
19
|
return (
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
<InlinePrompt
|
|
21
|
+
id={ids.prompt}
|
|
22
|
+
sentiment={sentiment}
|
|
23
|
+
muted={isLongLivedMuted}
|
|
24
|
+
className="wds-list-item-prompt"
|
|
25
|
+
>
|
|
26
|
+
{isLongLivedMuted ? props.disabledPromptMessage : children}
|
|
27
|
+
</InlinePrompt>
|
|
28
28
|
);
|
|
29
29
|
};
|
|
30
30
|
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import { Title, Subtitle, Description, Stories } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
3
|
+
import { MultiCurrency, Plus } from '@transferwise/icons';
|
|
4
|
+
import { lorem10, lorem5 } from '../../test-utils';
|
|
5
|
+
import List from '../../list';
|
|
6
|
+
import Link from '../../link';
|
|
7
|
+
import { ListItem, type ListItemProps } from '../ListItem';
|
|
8
|
+
import type { ListItemPromptProps } from '../Prompt';
|
|
9
|
+
import { disableControls, withoutKey } from './helpers';
|
|
10
|
+
import {
|
|
11
|
+
SB_LIST_ITEM_TEXT as TEXT,
|
|
12
|
+
SB_LIST_ITEM_ADDITIONAL_INFO as INFO,
|
|
13
|
+
SB_LIST_ITEM_CONTROLS as CONTROLS,
|
|
14
|
+
SB_LIST_ITEM_MEDIA as MEDIA,
|
|
15
|
+
} from './subcomponents';
|
|
16
|
+
|
|
17
|
+
const hideControls = disableControls([
|
|
18
|
+
'title',
|
|
19
|
+
'subtitle',
|
|
20
|
+
'valueTitle',
|
|
21
|
+
'valueSubtitle',
|
|
22
|
+
'media',
|
|
23
|
+
'additionalInfo',
|
|
24
|
+
'prompt',
|
|
25
|
+
'control',
|
|
26
|
+
'as',
|
|
27
|
+
'inverted',
|
|
28
|
+
'className',
|
|
29
|
+
'id',
|
|
30
|
+
'valueColumnWidth',
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
const renderPrompt = (sentiment: ListItemPromptProps['sentiment']) => (
|
|
34
|
+
<ListItem.Prompt sentiment={sentiment}>
|
|
35
|
+
This prompt contains an <Link href="#target">external link</Link> too.
|
|
36
|
+
</ListItem.Prompt>
|
|
37
|
+
);
|
|
38
|
+
const disabledPromptMessage = (
|
|
39
|
+
<>
|
|
40
|
+
This item is disabled because <Link href="#target">some reason</Link> has not been satisfied.
|
|
41
|
+
</>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Please refer to the [design documentation](https://wise.design/components/list-item#accessibility:~:text=-,Disabled%20states,-) for more details
|
|
46
|
+
*/
|
|
47
|
+
export default {
|
|
48
|
+
component: ListItem,
|
|
49
|
+
title: 'Content/ListItem/Disabled State',
|
|
50
|
+
tags: ['autodocs'],
|
|
51
|
+
decorators: [withoutKey],
|
|
52
|
+
argTypes: hideControls(),
|
|
53
|
+
args: {
|
|
54
|
+
disabled: true,
|
|
55
|
+
subtitle: TEXT.subtitle,
|
|
56
|
+
valueTitle: TEXT.valueTitle,
|
|
57
|
+
valueSubtitle: TEXT.valueSubtitle,
|
|
58
|
+
media: MEDIA.avatarFlag,
|
|
59
|
+
},
|
|
60
|
+
parameters: {
|
|
61
|
+
docs: {
|
|
62
|
+
canvas: {
|
|
63
|
+
sourceState: 'hidden',
|
|
64
|
+
},
|
|
65
|
+
toc: true,
|
|
66
|
+
page: () => (
|
|
67
|
+
<>
|
|
68
|
+
<Title>Disabled state</Title>
|
|
69
|
+
<Subtitle />
|
|
70
|
+
<Description />
|
|
71
|
+
<Stories />
|
|
72
|
+
</>
|
|
73
|
+
),
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
} satisfies Meta<ListItemProps>;
|
|
77
|
+
type Story = StoryObj<ListItemProps>;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* When dealing with dynamic content, e.g. BFFs or general form submissions, it's a common practice
|
|
81
|
+
* to stop the users from making changes to the inputs while the form is being processed.
|
|
82
|
+
*
|
|
83
|
+
* Because these form states are usually short-lived, and would take at most few seconds to
|
|
84
|
+
* complete, we don't want to introduce any major content changes that could distract
|
|
85
|
+
* the user or, even worse, cause layout shift. That's why, by default, toggling the `disabled`
|
|
86
|
+
* prop will not show any additional visual indicators, apart from the luminosity and opacity
|
|
87
|
+
* changes.
|
|
88
|
+
*/
|
|
89
|
+
export const ShortLived: Story = {
|
|
90
|
+
name: 'Short-lived: fully interactive',
|
|
91
|
+
args: {
|
|
92
|
+
control: CONTROLS.button,
|
|
93
|
+
},
|
|
94
|
+
argTypes: hideControls(['disabledPromptMessage']),
|
|
95
|
+
render: function Render(args) {
|
|
96
|
+
return (
|
|
97
|
+
<List>
|
|
98
|
+
<ListItem {...args} title="No prompt" control={CONTROLS.navigation} />
|
|
99
|
+
<ListItem
|
|
100
|
+
{...args}
|
|
101
|
+
title="Neutral prompt"
|
|
102
|
+
prompt={renderPrompt('neutral')}
|
|
103
|
+
control={CONTROLS.navigation}
|
|
104
|
+
/>
|
|
105
|
+
<ListItem {...args} title="Positive prompt" prompt={renderPrompt('positive')} />
|
|
106
|
+
<ListItem {...args} title="Warning prompt" prompt={renderPrompt('warning')} />
|
|
107
|
+
<ListItem {...args} title="Negative prompt" prompt={renderPrompt('negative')} />
|
|
108
|
+
</List>
|
|
109
|
+
);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* There's a difference between fully and partially interactive ListItems. While setting `disabled`
|
|
115
|
+
* prop on the former applies the visual treatment to the whole item, on the latter ones it only
|
|
116
|
+
* affects the control element (`ListItem.Button` or `ListItem.IconButton`).
|
|
117
|
+
*
|
|
118
|
+
* That way, the inline link or button in the additional info section remains interactive and
|
|
119
|
+
* accessible.
|
|
120
|
+
*/
|
|
121
|
+
export const ShortLivedPartially: Story = {
|
|
122
|
+
name: 'Short-lived: partially interactive',
|
|
123
|
+
args: {
|
|
124
|
+
additionalInfo: INFO.interactive,
|
|
125
|
+
},
|
|
126
|
+
argTypes: hideControls(['spotlight', 'disabledPromptMessage']),
|
|
127
|
+
render: function Render(args) {
|
|
128
|
+
return (
|
|
129
|
+
<List>
|
|
130
|
+
<ListItem
|
|
131
|
+
{...args}
|
|
132
|
+
title="No prompt and disabled control"
|
|
133
|
+
control={CONTROLS.partialButton}
|
|
134
|
+
/>
|
|
135
|
+
<ListItem
|
|
136
|
+
{...args}
|
|
137
|
+
title="Prompt and disabled Button control"
|
|
138
|
+
prompt={renderPrompt('warning')}
|
|
139
|
+
control={CONTROLS.partialButton}
|
|
140
|
+
/>
|
|
141
|
+
<ListItem
|
|
142
|
+
{...args}
|
|
143
|
+
title="Prompt and disabled IconButton control"
|
|
144
|
+
prompt={renderPrompt('positive')}
|
|
145
|
+
control={CONTROLS.partialIconButton}
|
|
146
|
+
/>
|
|
147
|
+
</List>
|
|
148
|
+
);
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* On the other hand, instances of ListItems that are disabled for longer periods of time and
|
|
154
|
+
* remain in such state until some user interaction or event occur, can and should offer extended
|
|
155
|
+
* affordances to the user, so they are aware of the current state of the item and the reason why
|
|
156
|
+
* it's not available to them.
|
|
157
|
+
*
|
|
158
|
+
* To achieve that, we're introducing additional prop `disabledPromptMessage` – it's a
|
|
159
|
+
* prompt content override only used when ListItem is in the disabled state, and it's expected to
|
|
160
|
+
* offer reasoning for why given list item has been disabled.
|
|
161
|
+
*
|
|
162
|
+
* If set, it will render a variant of the `ListItem.Prompt` component with an icon and colour
|
|
163
|
+
* scheme designed specifically for this scenario.
|
|
164
|
+
*
|
|
165
|
+
* Similarly to the short-lived scenario, fully interactive items will apply the visual treatment
|
|
166
|
+
* to the whole item. Prompts will remain interactive.
|
|
167
|
+
*/
|
|
168
|
+
export const LongLived: Story = {
|
|
169
|
+
name: 'Long-lived: fully interactive',
|
|
170
|
+
args: {
|
|
171
|
+
disabledPromptMessage,
|
|
172
|
+
control: CONTROLS.button,
|
|
173
|
+
},
|
|
174
|
+
argTypes: hideControls(['disabledPromptMessage']),
|
|
175
|
+
render: function Render(args) {
|
|
176
|
+
return (
|
|
177
|
+
<List>
|
|
178
|
+
<ListItem
|
|
179
|
+
{...args}
|
|
180
|
+
title="No prompt, no disabledPromptMessage"
|
|
181
|
+
disabledPromptMessage={undefined}
|
|
182
|
+
control={CONTROLS.navigation}
|
|
183
|
+
/>
|
|
184
|
+
<ListItem
|
|
185
|
+
{...args}
|
|
186
|
+
title="No prompt, disabledPromptMessage set"
|
|
187
|
+
control={CONTROLS.navigation}
|
|
188
|
+
/>
|
|
189
|
+
<ListItem
|
|
190
|
+
{...args}
|
|
191
|
+
title="Neutral prompt, disabledPromptMessage set"
|
|
192
|
+
prompt={renderPrompt('neutral')}
|
|
193
|
+
control={CONTROLS.navigation}
|
|
194
|
+
/>
|
|
195
|
+
<ListItem
|
|
196
|
+
{...args}
|
|
197
|
+
title="Positive prompt, disabledPromptMessage set"
|
|
198
|
+
prompt={renderPrompt('positive')}
|
|
199
|
+
/>
|
|
200
|
+
<ListItem
|
|
201
|
+
{...args}
|
|
202
|
+
title="Warning prompt, disabledPromptMessage set"
|
|
203
|
+
prompt={renderPrompt('warning')}
|
|
204
|
+
/>
|
|
205
|
+
<ListItem
|
|
206
|
+
{...args}
|
|
207
|
+
title="Negative prompt, disabledPromptMessage set"
|
|
208
|
+
prompt={renderPrompt('negative')}
|
|
209
|
+
/>
|
|
210
|
+
</List>
|
|
211
|
+
);
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Similarly to the short-lived scenario, partially interactive items will only apply the visual
|
|
217
|
+
* treatment to the control element, leaving the additional info section fully interactive and
|
|
218
|
+
* accessible.
|
|
219
|
+
*
|
|
220
|
+
* While programmatically not required, you will be expected to use the `disabledPromptMessage`
|
|
221
|
+
* prop to offer an explanation to the user on why the item was disabled.
|
|
222
|
+
*/
|
|
223
|
+
export const LongLivedPartially: Story = {
|
|
224
|
+
name: 'Long-lived: partially interactive',
|
|
225
|
+
args: {
|
|
226
|
+
disabledPromptMessage,
|
|
227
|
+
additionalInfo: INFO.interactive,
|
|
228
|
+
},
|
|
229
|
+
argTypes: hideControls(['spotlight', 'disabledPromptMessage']),
|
|
230
|
+
render: function Render(args) {
|
|
231
|
+
return (
|
|
232
|
+
<List>
|
|
233
|
+
<ListItem
|
|
234
|
+
{...args}
|
|
235
|
+
disabledPromptMessage={undefined}
|
|
236
|
+
title="No prompt, no disabledPromptMessage"
|
|
237
|
+
control={CONTROLS.partialButton}
|
|
238
|
+
/>
|
|
239
|
+
<ListItem
|
|
240
|
+
{...args}
|
|
241
|
+
title="No prompt, disabledPromptMessage set"
|
|
242
|
+
control={CONTROLS.partialButton}
|
|
243
|
+
/>
|
|
244
|
+
<ListItem
|
|
245
|
+
{...args}
|
|
246
|
+
title="Prompt set, disabledPromptMessage set"
|
|
247
|
+
prompt={renderPrompt('warning')}
|
|
248
|
+
control={CONTROLS.partialIconButton}
|
|
249
|
+
/>
|
|
250
|
+
<ListItem
|
|
251
|
+
{...args}
|
|
252
|
+
title="Prompt set, disabledPromptMessage set"
|
|
253
|
+
prompt={renderPrompt('positive')}
|
|
254
|
+
control={CONTROLS.partialIconButton}
|
|
255
|
+
/>
|
|
256
|
+
</List>
|
|
257
|
+
);
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
export const AllControls: Story = {
|
|
262
|
+
parameters: {
|
|
263
|
+
docs: {
|
|
264
|
+
canvas: {
|
|
265
|
+
sourceState: 'hidden',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
controls: { disable: true },
|
|
269
|
+
knobs: { disable: true },
|
|
270
|
+
},
|
|
271
|
+
render: (args) => (
|
|
272
|
+
<List>
|
|
273
|
+
<ListItem
|
|
274
|
+
disabled
|
|
275
|
+
media={
|
|
276
|
+
<ListItem.AvatarView>
|
|
277
|
+
<MultiCurrency />
|
|
278
|
+
</ListItem.AvatarView>
|
|
279
|
+
}
|
|
280
|
+
title="Navigation"
|
|
281
|
+
subtitle={lorem5}
|
|
282
|
+
control={<ListItem.Navigation onClick={() => {}} />}
|
|
283
|
+
/>
|
|
284
|
+
<ListItem
|
|
285
|
+
disabled
|
|
286
|
+
media={
|
|
287
|
+
<ListItem.AvatarView>
|
|
288
|
+
<MultiCurrency />
|
|
289
|
+
</ListItem.AvatarView>
|
|
290
|
+
}
|
|
291
|
+
title="Button primary"
|
|
292
|
+
subtitle={lorem5}
|
|
293
|
+
control={<ListItem.Button priority="primary">Primary</ListItem.Button>}
|
|
294
|
+
/>
|
|
295
|
+
<ListItem
|
|
296
|
+
disabled
|
|
297
|
+
media={
|
|
298
|
+
<ListItem.AvatarView>
|
|
299
|
+
<MultiCurrency />
|
|
300
|
+
</ListItem.AvatarView>
|
|
301
|
+
}
|
|
302
|
+
title="Button secondary neutral"
|
|
303
|
+
subtitle={lorem5}
|
|
304
|
+
control={<ListItem.Button>Secondary</ListItem.Button>}
|
|
305
|
+
/>
|
|
306
|
+
<ListItem
|
|
307
|
+
disabled
|
|
308
|
+
media={
|
|
309
|
+
<ListItem.AvatarView>
|
|
310
|
+
<MultiCurrency />
|
|
311
|
+
</ListItem.AvatarView>
|
|
312
|
+
}
|
|
313
|
+
title="Button secondary neutral"
|
|
314
|
+
subtitle={lorem5}
|
|
315
|
+
control={<ListItem.Button priority="secondary-neutral">Secondary Neutral</ListItem.Button>}
|
|
316
|
+
/>
|
|
317
|
+
<ListItem
|
|
318
|
+
disabled
|
|
319
|
+
media={
|
|
320
|
+
<ListItem.AvatarView>
|
|
321
|
+
<MultiCurrency />
|
|
322
|
+
</ListItem.AvatarView>
|
|
323
|
+
}
|
|
324
|
+
title="Button tertiary"
|
|
325
|
+
subtitle={lorem5}
|
|
326
|
+
control={<ListItem.Button priority="tertiary">Tertiary</ListItem.Button>}
|
|
327
|
+
/>
|
|
328
|
+
<ListItem
|
|
329
|
+
disabled
|
|
330
|
+
media={
|
|
331
|
+
<ListItem.AvatarView>
|
|
332
|
+
<MultiCurrency />
|
|
333
|
+
</ListItem.AvatarView>
|
|
334
|
+
}
|
|
335
|
+
title="Icon Button"
|
|
336
|
+
subtitle={lorem5}
|
|
337
|
+
control={
|
|
338
|
+
<ListItem.IconButton>
|
|
339
|
+
<Plus />
|
|
340
|
+
</ListItem.IconButton>
|
|
341
|
+
}
|
|
342
|
+
/>
|
|
343
|
+
<ListItem
|
|
344
|
+
disabled
|
|
345
|
+
media={
|
|
346
|
+
<ListItem.AvatarView>
|
|
347
|
+
<MultiCurrency />
|
|
348
|
+
</ListItem.AvatarView>
|
|
349
|
+
}
|
|
350
|
+
title="Checkbox"
|
|
351
|
+
subtitle={lorem5}
|
|
352
|
+
control={<ListItem.Checkbox />}
|
|
353
|
+
/>
|
|
354
|
+
<ListItem
|
|
355
|
+
disabled
|
|
356
|
+
media={
|
|
357
|
+
<ListItem.AvatarView>
|
|
358
|
+
<MultiCurrency />
|
|
359
|
+
</ListItem.AvatarView>
|
|
360
|
+
}
|
|
361
|
+
title="Checkbox checked"
|
|
362
|
+
subtitle={lorem5}
|
|
363
|
+
control={<ListItem.Checkbox checked />}
|
|
364
|
+
/>
|
|
365
|
+
<ListItem
|
|
366
|
+
disabled
|
|
367
|
+
media={
|
|
368
|
+
<ListItem.AvatarView>
|
|
369
|
+
<MultiCurrency />
|
|
370
|
+
</ListItem.AvatarView>
|
|
371
|
+
}
|
|
372
|
+
title="Checkbox indeterminate"
|
|
373
|
+
subtitle={lorem5}
|
|
374
|
+
control={<ListItem.Checkbox indeterminate />}
|
|
375
|
+
/>
|
|
376
|
+
<ListItem
|
|
377
|
+
disabled
|
|
378
|
+
media={
|
|
379
|
+
<ListItem.AvatarView>
|
|
380
|
+
<MultiCurrency />
|
|
381
|
+
</ListItem.AvatarView>
|
|
382
|
+
}
|
|
383
|
+
title="Switch on"
|
|
384
|
+
subtitle={lorem5}
|
|
385
|
+
control={<ListItem.Switch checked onClick={() => {}} />}
|
|
386
|
+
/>
|
|
387
|
+
<ListItem
|
|
388
|
+
disabled
|
|
389
|
+
media={
|
|
390
|
+
<ListItem.AvatarView>
|
|
391
|
+
<MultiCurrency />
|
|
392
|
+
</ListItem.AvatarView>
|
|
393
|
+
}
|
|
394
|
+
title="Switch off"
|
|
395
|
+
subtitle={lorem5}
|
|
396
|
+
control={<ListItem.Switch onClick={() => {}} />}
|
|
397
|
+
/>
|
|
398
|
+
<ListItem
|
|
399
|
+
disabled
|
|
400
|
+
media={
|
|
401
|
+
<ListItem.AvatarView>
|
|
402
|
+
<MultiCurrency />
|
|
403
|
+
</ListItem.AvatarView>
|
|
404
|
+
}
|
|
405
|
+
title="Switch off"
|
|
406
|
+
subtitle={lorem5}
|
|
407
|
+
control={<ListItem.Radio name="radio" checked />}
|
|
408
|
+
/>
|
|
409
|
+
<ListItem
|
|
410
|
+
disabled
|
|
411
|
+
media={
|
|
412
|
+
<ListItem.AvatarView>
|
|
413
|
+
<MultiCurrency />
|
|
414
|
+
</ListItem.AvatarView>
|
|
415
|
+
}
|
|
416
|
+
title="Switch off"
|
|
417
|
+
subtitle={lorem5}
|
|
418
|
+
control={<ListItem.Radio name="radios" />}
|
|
419
|
+
/>
|
|
420
|
+
<ListItem
|
|
421
|
+
disabled
|
|
422
|
+
media={
|
|
423
|
+
<ListItem.AvatarView>
|
|
424
|
+
<MultiCurrency />
|
|
425
|
+
</ListItem.AvatarView>
|
|
426
|
+
}
|
|
427
|
+
title="Non-interactive"
|
|
428
|
+
subtitle={lorem10}
|
|
429
|
+
additionalInfo={INFO.nonInteractive}
|
|
430
|
+
/>
|
|
431
|
+
</List>
|
|
432
|
+
),
|
|
433
|
+
};
|