Skip to content

Commit

Permalink
Add do not prefix to DoDontList (#153)
Browse files Browse the repository at this point in the history
* DoDontList don't item includes text `do not`, tests to cover

* add prefixText prop and tests for DoDontList

* Better documentation for DoDontList
  • Loading branch information
KaiSpencer authored Apr 13, 2023
1 parent 37b6729 commit f652811
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 7 deletions.
19 changes: 16 additions & 3 deletions src/components/do-dont-list/DoDontList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { HTMLProps, createContext, useContext } from 'react';
import React, {HTMLProps, createContext, useContext, ReactNode} from 'react';
import classNames from 'classnames';
import { Tick, Cross } from '../icons';
import HeadingLevel, { HeadingLevelType } from '../../util/HeadingLevel';
Expand Down Expand Up @@ -43,13 +43,26 @@ const DoDontList: DoDontList = ({

interface DoDontItemProps extends HTMLProps<HTMLLIElement> {
listItemType?: ListType;
prefixText?: ReactNode
}

const DoDontItem: React.FC<DoDontItemProps> = ({ children, listItemType, ...rest }) => {
const DoDontItem: React.FC<DoDontItemProps> = ({prefixText, listItemType,children, ...rest }) => {
const listItem = useContext(DoDontListContext);
const defaultPrefix = (listItemType || listItem) === 'do' ? null : 'do not ';
const actualPrefix = prefixText === undefined ? defaultPrefix : prefixText;
return (
<li {...rest}>
{(listItemType || listItem) === 'do' ? <Tick /> : <Cross />}
{(listItemType || listItem) === 'do' ? (
<>
<Tick />
{actualPrefix}
</>
) : (
<>
<Cross />
{actualPrefix}
</>
)}
{children}
</li>
);
Expand Down
45 changes: 45 additions & 0 deletions src/components/do-dont-list/__tests__/DoDontList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,50 @@ describe('DoDontList', () => {
doList.unmount();
dontList.unmount();
});

it("dont item includes 'do not' by default", () => {
const dontList = mount(
<DoDontList listType="dont">
<DoDontList.Item>do something bad</DoDontList.Item>
</DoDontList>,
);
expect(dontList.find('.nhsuk-list--cross').text()).toEqual('do not do something bad');
dontList.unmount();
});

it("items render custom prefix text", () => {
const doList = mount(
<DoDontList listType="do">
<DoDontList.Item prefixText="do ">something good 1</DoDontList.Item>
<DoDontList.Item>something good 2</DoDontList.Item>
<DoDontList.Item prefixText={<span>also do </span>}>something good 3</DoDontList.Item>
<DoDontList.Item prefixText={undefined}>something good 4</DoDontList.Item>
<DoDontList.Item prefixText={null}>something good 5</DoDontList.Item>
</DoDontList>,
);
const dontList = mount(
<DoDontList listType="dont">
<DoDontList.Item prefixText="do not ">do something bad 1</DoDontList.Item>
<DoDontList.Item>do something bad 2</DoDontList.Item>
<DoDontList.Item prefixText={<span>don&apos;t do </span>}>something bad 3</DoDontList.Item>
<DoDontList.Item prefixText={undefined}>something bad 4</DoDontList.Item>
<DoDontList.Item prefixText={null}>something bad 5</DoDontList.Item>
</DoDontList>,
);
expect(doList.find('.nhsuk-list--tick').childAt(0).text()).toBe('do something good 1');
expect(doList.find('.nhsuk-list--tick').childAt(1).text()).toBe('something good 2');
expect(doList.find('.nhsuk-list--tick').childAt(2).text()).toBe('also do something good 3');
expect(doList.find('.nhsuk-list--tick').childAt(3).text()).toBe('something good 4');
expect(doList.find('.nhsuk-list--tick').childAt(4).text()).toBe('something good 5');

expect(dontList.find('.nhsuk-list--cross').childAt(0).text()).toBe('do not do something bad 1');
expect(dontList.find('.nhsuk-list--cross').childAt(1).text()).toBe('do not do something bad 2');
expect(dontList.find('.nhsuk-list--cross').childAt(2).text()).toBe('don\'t do something bad 3');
expect(dontList.find('.nhsuk-list--cross').childAt(3).text()).toBe('do not something bad 4');
expect(dontList.find('.nhsuk-list--cross').childAt(4).text()).toBe('something bad 5');

doList.unmount();
dontList.unmount();
})
});
});
48 changes: 44 additions & 4 deletions stories/Components/DoDontList.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import { Meta, StoryObj } from '@storybook/react';
*
* As long as a `listType` is supplied to the `DoDontList` component, all subcomponents will render as desired. If you require a `DoDontList.Item` to be different, a `listItemType` prop can be supplied to force the type.
*
*
* The `DoDontList.Item` component can also accept a `prefixText` prop, which can be used to override the default prefix text.
*
* See the <b><a href="#custom-prefix-text" >custom prefix text</a></b> story for an example.
*
* ## Usage
*
* ### Standard
Expand Down Expand Up @@ -57,12 +62,47 @@ export const Do: Story = {
export const Dont: Story = {
render: () => (
<DoDontList listType="dont">
<DoDontList.Item>do not burst a blister yourself</DoDontList.Item>
<DoDontList.Item>do not peel the skin off a burst blister</DoDontList.Item>
<DoDontList.Item>do not pick at the edges of the remaining skin</DoDontList.Item>
<DoDontList.Item>burst a blister yourself</DoDontList.Item>
<DoDontList.Item>peel the skin off a burst blister</DoDontList.Item>
<DoDontList.Item>pick at the edges of the remaining skin</DoDontList.Item>
<DoDontList.Item>
do not wear the shoes or use the equipment that caused your blister until it heals
wear the shoes or use the equipment that caused your blister until it heals
</DoDontList.Item>
</DoDontList>
),
};

/**
* By default DoDontList's of type "dont" will have Items prefixed with `do not`
*
* This is the recommended usage, <b><a href="https://service-manual.nhs.uk/design-system/components/do-and-dont-lists#research">as stated in the Service Manual</a></b>
*
* However, if you need to override this, you can supply a `prefixText` prop to the `DoDontList.Item` component.
*
* This is optional and of type `ReactNode`, so you can supply a string, a JSX element, or `undefined` or `null`
*
* See the table below and click the `Show code` button on the story for examples of each.
*
* | Value | Outcome |
* |-----------|---------------------------------------------|
* | undefined | The default `do not` text will be displayed |
* | null | There will be no prefix |
* | string | The string will be displayed |
* | JSX | The JSX will be rendered, such as `<span>` |
*/
export const CustomPrefixText: Story = {
render: () => (
<DoDontList listType="dont">
<DoDontList.Item prefixText="You must not">burst a blister yourself</DoDontList.Item>
<DoDontList.Item prefixText={undefined}>peel the skin off a burst blister</DoDontList.Item>
<DoDontList.Item prefixText={null}>pick at the edges of the remaining skin</DoDontList.Item>
<DoDontList.Item prefixText={<span>please dont </span>}>
wear the shoes or use the equipment that caused your blister until it heals
</DoDontList.Item>
<DoDontList.Item>
wear the shoes or use the equipment that caused your blister until it heals
</DoDontList.Item>
</DoDontList>

),
}

0 comments on commit f652811

Please sign in to comment.