import { Title, Subtitle, Description, Stories } from '@storybook/addon-docs/blocks';
import { Meta, StoryObj } from '@storybook/react-webpack5';
import { MultiCurrency, Plus } from '@transferwise/icons';
import { lorem10, lorem5 } from '../../test-utils';
import List from '../../list';
import Link from '../../link';
import { ListItem, type ListItemProps } from '../ListItem';
import type { ListItemPromptProps } from '../Prompt';
import { disableControls, withoutKey } from './helpers';
import {
SB_LIST_ITEM_TEXT as TEXT,
SB_LIST_ITEM_ADDITIONAL_INFO as INFO,
SB_LIST_ITEM_CONTROLS as CONTROLS,
SB_LIST_ITEM_MEDIA as MEDIA,
} from './subcomponents';
const hideControls = disableControls([
'title',
'subtitle',
'valueTitle',
'valueSubtitle',
'media',
'additionalInfo',
'prompt',
'control',
'as',
'inverted',
'className',
'id',
'valueColumnWidth',
]);
const renderPrompt = (sentiment: ListItemPromptProps['sentiment']) => (
This prompt contains an external link too.
);
const disabledPromptMessage = (
<>
This item is disabled because some reason has not been satisfied.
>
);
/**
* Please refer to the [design documentation](https://wise.design/components/list-item#accessibility:~:text=-,Disabled%20states,-) for more details
*/
export default {
component: ListItem,
title: 'Content/ListItem/Disabled State',
tags: ['autodocs'],
decorators: [withoutKey],
argTypes: hideControls(),
args: {
disabled: true,
subtitle: TEXT.subtitle,
valueTitle: TEXT.valueTitle,
valueSubtitle: TEXT.valueSubtitle,
media: MEDIA.avatarFlag,
},
parameters: {
docs: {
canvas: {
sourceState: 'hidden',
},
page: () => (
<>
Disabled state
>
),
},
},
} satisfies Meta;
type Story = StoryObj;
/**
* When dealing with dynamic content, e.g. BFFs or general form submissions, it's a common practice
* to stop the users from making changes to the inputs while the form is being processed.
*
* Because these form states are usually short-lived, and would take at most few seconds to
* complete, we don't want to introduce any major content changes that could distract
* the user or, even worse, cause layout shift. That's why, by default, toggling the `disabled`
* prop will not show any additional visual indicators, apart from the luminosity and opacity
* changes.
*/
export const ShortLived: Story = {
name: 'Short-lived: fully interactive',
args: {
control: CONTROLS.button,
},
argTypes: hideControls(['disabledPromptMessage']),
render: function Render(args) {
return (
);
},
};
/**
* There's a difference between fully and partially interactive ListItems. While setting `disabled`
* prop on the former applies the visual treatment to the whole item, on the latter ones it only
* affects the control element (`ListItem.Button` or `ListItem.IconButton`).
*
* That way, the inline link or button in the additional info section remains interactive and
* accessible.
*/
export const ShortLivedPartially: Story = {
name: 'Short-lived: partially interactive',
args: {
additionalInfo: INFO.interactive,
},
argTypes: hideControls(['spotlight', 'disabledPromptMessage']),
render: function Render(args) {
return (
);
},
};
/**
* On the other hand, instances of ListItems that are disabled for longer periods of time and
* remain in such state until some user interaction or event occur, can and should offer extended
* affordances to the user, so they are aware of the current state of the item and the reason why
* it's not available to them.
*
* To achieve that, we're introducing additional prop `disabledPromptMessage` – it's a
* prompt content override only used when ListItem is in the disabled state, and it's expected to
* offer reasoning for why given list item has been disabled.
*
* If set, it will render a variant of the `ListItem.Prompt` component with an icon and colour
* scheme designed specifically for this scenario.
*
* Similarly to the short-lived scenario, fully interactive items will apply the visual treatment
* to the whole item. Prompts will remain interactive.
*/
export const LongLived: Story = {
name: 'Long-lived: fully interactive',
args: {
disabledPromptMessage,
control: CONTROLS.button,
},
argTypes: hideControls(['disabledPromptMessage']),
render: function Render(args) {
return (
);
},
};
/**
* Similarly to the short-lived scenario, partially interactive items will only apply the visual
* treatment to the control element, leaving the additional info section fully interactive and
* accessible.
*
* While programmatically not required, you will be expected to use the `disabledPromptMessage`
* prop to offer an explanation to the user on why the item was disabled.
*/
export const LongLivedPartially: Story = {
name: 'Long-lived: partially interactive',
args: {
disabledPromptMessage,
additionalInfo: INFO.interactive,
},
argTypes: hideControls(['spotlight', 'disabledPromptMessage']),
render: function Render(args) {
return (
);
},
};
export const AllControls: Story = {
parameters: {
docs: {
canvas: {
sourceState: 'hidden',
},
},
controls: { disable: true },
knobs: { disable: true },
},
render: (args) => (
}
title="Navigation"
subtitle={lorem5}
control={ {}} />}
/>
}
title="Button primary"
subtitle={lorem5}
control={Primary}
/>
}
title="Button secondary neutral"
subtitle={lorem5}
control={Secondary}
/>
}
title="Button secondary neutral"
subtitle={lorem5}
control={Secondary Neutral}
/>
}
title="Button tertiary"
subtitle={lorem5}
control={Tertiary}
/>
}
title="Icon Button"
subtitle={lorem5}
control={
}
/>
}
title="Checkbox"
subtitle={lorem5}
control={}
/>
}
title="Checkbox checked"
subtitle={lorem5}
control={}
/>
}
title="Checkbox indeterminate"
subtitle={lorem5}
control={}
/>
}
title="Switch on"
subtitle={lorem5}
control={ {}} />}
/>
}
title="Switch off"
subtitle={lorem5}
control={ {}} />}
/>
}
title="Switch off"
subtitle={lorem5}
control={}
/>
}
title="Switch off"
subtitle={lorem5}
control={}
/>
}
title="Non-interactive"
subtitle={lorem10}
additionalInfo={
Which has bold,strong,emphasis
}
/>
),
};