Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New components WIP #201

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions docs/upgrade-to-4.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,117 @@ You can now specify prefixes and/or suffixes for your text inputs. These are exp
```
<TextInput prefix="£" suffix="pounds" />
```

### Exclusive option for checkboxes

Added "None of the above" exclusive behaviour to checkboxes - allowing all checkboxes in a group to be automatically unchecked when the "None of the above" option is checked. To use this feature, a new prop is available on `Checkbox.Box` - set the `exclusive` prop to make that option exclusive, e.g.

```
<Checkboxes id="symptoms" name="symptoms" hint="Select all the symptoms you have.">
<Checkboxes.Box value="sore-throat">Sore throat</Checkboxes.Box>
<Checkboxes.Box value="runny-nose">Runny nose</Checkboxes.Box>
<Checkboxes.Box value="muscle-pain">Muscle or joint pain</Checkboxes.Box>
<Checkboxes.Divider />
<Checkboxes.Box value="none" exclusive>
None
</Checkboxes.Box>
</Checkboxes>
```

### New component - Character Count

See [the Digital Service Manual](https://service-manual.nhs.uk/design-system/components/character-count) for information.
Usage:

```
<CharacterCount
maxLength={150}
countType={CharacterCountType.Characters}
textAreaId="more-details"
>
<Label htmlFor="more-details">Can you provide more detail?</Label>
<Textarea id="more-details" className="nhsuk-js-character-count" name="more-details" rows={5} />
</CharacterCount>
```

### New component - Tabs

See [the Digital Service Manual](https://service-manual.nhs.uk/design-system/components/tabs) for information.
Usage:

```
<Tabs>
<Tabs.Title>Contents</Tabs.Title>
<Tabs.List>
<Tabs.ListItem id="past-day">Past day</Tabs.ListItem>
<Tabs.ListItem id="past-week">Past week</Tabs.ListItem>
<Tabs.ListItem id="past-month">Past month</Tabs.ListItem>
</Tabs.List>
<Tabs.Contents id="past-day">
<div>Past day contents go here</div>
</Tabs.Contents>
<Tabs.Contents id="past-week">
<div>Past week contents go here</div>
</Tabs.Contents>
<Tabs.Contents id="past-month">
<div>Past month contents go here</div>
</Tabs.Contents>
</Tabs>
```

### New card variants

Two new card variants have been added - `primary` and `secondary`.

#### Primary

More information can be found in the [NHS digital service manual](https://service-manual.nhs.uk/design-system/components/card#primary-card-with-chevron)

Usage:

```
<Card clickable primary>
<Card.Content>
<Card.Heading>
<Card.Link href="#">Primary card heading</Card.Link>
</Card.Heading>
<Card.Description>Primary card description</Card.Description>
<ChevronRightCircle />
</Card.Content>
</Card>
```

#### Secondary

More information can be found in the [NHS digital service manual](https://service-manual.nhs.uk/design-system/components/card#secondary-card)

Usage:

```
<Card clickable secondary>
<Card.Content>
<Card.Heading>
<Card.Link href="#">Secondary card heading</Card.Link>
</Card.Heading>
<Card.Description>Secondary card description</Card.Description>
</Card.Content>
</Card>
```

## Notes for maintainers

Ensure you are using an update to date copy of `yarn`

```
# Remove yarn
npm -g remove yarn
# Enable corepack
corepack enable
# Set yarn version
yarn set version stable
```
3 changes: 3 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ describe('Index', () => {
'Button',
'ButtonLink',
'Card',
'CharacterCount',
'CharacterCountType',
'Checkboxes',
'ChevronLeftIcon',
'ChevronRightIcon',
Expand Down Expand Up @@ -56,6 +58,7 @@ describe('Index', () => {
'SmallEmdashIcon',
'SummaryList',
'Table',
'Tabs',
'Tag',
'TextInput',
'Textarea',
Expand Down
73 changes: 73 additions & 0 deletions src/components/content-presentation/tabs/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
'use client';
import classNames from 'classnames';
import React, { HTMLAttributes, useEffect } from 'react';
import HeadingLevel, { HeadingLevelType } from '../../../util/HeadingLevel';
import TabsJs from 'nhsuk-frontend/packages/components/tabs/tabs.js';

type TabsProps = HTMLAttributes<HTMLDivElement>;

type TabTitleProps = { children: React.ReactNode; headingLevel?: HeadingLevelType };

type TabListProps = {
children: React.ReactNode;
};

type TabListItemProps = {
id: string;
children: React.ReactNode;
};

type TabContentsProps = {
id: string;
children: React.ReactNode;
};

const TabTitle: React.FC<TabTitleProps> = ({ children, headingLevel = 'h2' }) => (
<HeadingLevel className="nhsuk-tabs__title" headingLevel={headingLevel}>
{children}
</HeadingLevel>
);

const TabList: React.FC<TabListProps> = ({ children }) => (
<ul className="nhsuk-tabs__list">{children}</ul>
);

const TabListItem: React.FC<TabListItemProps> = ({ id, children }) => (
<li className="nhsuk-tabs__list-item">
<a className="nhsuk-tabs__tab" href={`#${id}`}>
{children}
</a>
</li>
);

const TabContents: React.FC<TabContentsProps> = ({ id, children }) => (
<div className="nhsuk-tabs__panel" id={id}>
{children}
</div>
);

interface Tabs extends React.FC<TabsProps> {
Title: React.FC<TabTitleProps>;
List: React.FC<TabListProps>;
ListItem: React.FC<TabListItemProps>;
Contents: React.FC<TabContentsProps>;
}

const Tabs: Tabs = ({ className, children, ...rest }) => {
useEffect(() => {
TabsJs();
}, []);

return (
<div className={classNames('nhsuk-tabs', className)} data-module="nhsuk-tabs" {...rest}>
{children}
</div>
);
};

Tabs.Title = TabTitle;
Tabs.List = TabList;
Tabs.ListItem = TabListItem;
Tabs.Contents = TabContents;

export default Tabs;
32 changes: 32 additions & 0 deletions src/components/content-presentation/tabs/__tests__/Tabs.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { render } from '@testing-library/react';
import Tabs from '../Tabs';

describe('The tabs component', () => {
it('Matches the snapshot', () => {
const { container } = render(
<Tabs>
<Tabs.Title>Contents</Tabs.Title>
<Tabs.List>
<Tabs.ListItem id="past-day">Past day</Tabs.ListItem>
<Tabs.ListItem id="past-week">Past week</Tabs.ListItem>
<Tabs.ListItem id="past-month">Past month</Tabs.ListItem>
</Tabs.List>

<Tabs.Contents id="past-day">
<div>Past day contents go here</div>
</Tabs.Contents>

<Tabs.Contents id="past-week">
<div>Past week contents go here</div>
</Tabs.Contents>

<Tabs.Contents id="past-month">
<div>Past month contents go here</div>
</Tabs.Contents>
</Tabs>,
);

expect(container).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`The tabs component Matches the snapshot 1`] = `
<div>
<div
class="nhsuk-tabs"
data-module="nhsuk-tabs"
>
<h2
class="nhsuk-tabs__title"
>
Contents
</h2>
<ul
class="nhsuk-tabs__list"
role="tablist"
>
<li
class="nhsuk-tabs__list-item nhsuk-tabs__list-item--selected"
role="presentation"
>
<a
aria-controls="past-day"
aria-selected="true"
class="nhsuk-tabs__tab"
href="#past-day"
id="tab_past-day"
role="tab"
tabindex="0"
>
Past day
</a>
</li>
<li
class="nhsuk-tabs__list-item"
role="presentation"
>
<a
aria-controls="past-week"
aria-selected="false"
class="nhsuk-tabs__tab"
href="#past-week"
id="tab_past-week"
role="tab"
tabindex="-1"
>
Past week
</a>
</li>
<li
class="nhsuk-tabs__list-item"
role="presentation"
>
<a
aria-controls="past-month"
aria-selected="false"
class="nhsuk-tabs__tab"
href="#past-month"
id="tab_past-month"
role="tab"
tabindex="-1"
>
Past month
</a>
</li>
</ul>
<div
aria-labelledby="tab_past-day"
class="nhsuk-tabs__panel"
id="past-day"
role="tabpanel"
>
<div>
Past day contents go here
</div>
</div>
<div
aria-labelledby="tab_past-week"
class="nhsuk-tabs__panel nhsuk-tabs__panel--hidden"
id="past-week"
role="tabpanel"
>
<div>
Past week contents go here
</div>
</div>
<div
aria-labelledby="tab_past-month"
class="nhsuk-tabs__panel nhsuk-tabs__panel--hidden"
id="past-month"
role="tabpanel"
>
<div>
Past month contents go here
</div>
</div>
</div>
</div>
`;
3 changes: 3 additions & 0 deletions src/components/content-presentation/tabs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Tabs from './Tabs';

export default Tabs;
Loading
Loading