Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jakeb-nhs committed Mar 19, 2024
1 parent ff99a74 commit 3c482e4
Show file tree
Hide file tree
Showing 11 changed files with 232 additions and 134 deletions.
39 changes: 39 additions & 0 deletions docs/upgrade-to-4.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,45 @@ Usage:
</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`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import CharacterCount, { CharacterCountType } from '../CharacterCount';
import { Label, HintText, Textarea } from '../../../..';

describe('Character Count', () => {
it('Matches snapshot with character count type', () => {
it('Matches snapshot', () => {
const { container } = render(
<CharacterCount
maxLength={200}
Expand All @@ -28,43 +28,60 @@ describe('Character Count', () => {
expect(container).toMatchSnapshot();
});

it('Matches snapshot with word count type', () => {
it('Sets the data-maxlength attribute when counting characters', () => {
const { container } = render(
<CharacterCount
maxLength={150}
countType={CharacterCountType.Words}
textAreaId="job-description-detail"
maxLength={200}
countType={CharacterCountType.Characters}
textAreaId="more-detail"
>
<Label htmlFor="job-description-detail" size="l">
Enter a job description
</Label>
<Textarea
id="job-description-detail"
className="nhsuk-js-character-count"
name="job-description-detail"
rows={5}
/>
<div />
</CharacterCount>,
);

expect(container).toMatchSnapshot();
expect(container.querySelector('.nhsuk-character-count')?.getAttribute('data-maxlength')).toBe(
'200',
);
expect(
container.querySelector('.nhsuk-character-count')?.getAttribute('data-maxwords'),
).toBeNull();
expect(
container.querySelector('.nhsuk-character-count')?.getAttribute('data-threshold'),
).toBeNull();
});

it('Sets the data-maxwords attribute when counting words', () => {
const { container } = render(
<CharacterCount maxLength={200} countType={CharacterCountType.Words} textAreaId="more-detail">
<div />
</CharacterCount>,
);

expect(container.querySelector('.nhsuk-character-count')?.getAttribute('data-maxwords')).toBe(
'200',
);
expect(
container.querySelector('.nhsuk-character-count')?.getAttribute('data-maxlength'),
).toBeNull();
expect(
container.querySelector('.nhsuk-character-count')?.getAttribute('data-threshold'),
).toBeNull();
});

it('Matches snapshot with threshold percent set', () => {
it('Sets the data-threshold attribute when threshold is specified', () => {
const { container } = render(
<CharacterCount
maxLength={112}
maxLength={200}
countType={CharacterCountType.Characters}
textAreaId="threshold"
thresholdPercent={75}
thresholdPercent={50}
textAreaId="more-detail"
>
<Label htmlFor="threshold">Can you provide more detail?</Label>
<Textarea id="threshold" className="nhsuk-js-character-count" name="threshold" rows={5}>
Type another letter into this field after this message to see the threshold feature
</Textarea>
<div />
</CharacterCount>,
);

expect(container).toMatchSnapshot();
expect(container.querySelector('.nhsuk-character-count')?.getAttribute('data-threshold')).toBe(
'50',
);
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Character Count Matches snapshot with character count type 1`] = `
exports[`Character Count Matches snapshot 1`] = `
<div>
<div
class="nhsuk-character-count"
Expand Down Expand Up @@ -57,109 +57,3 @@ exports[`Character Count Matches snapshot with character count type 1`] = `
</div>
</div>
`;

exports[`Character Count Matches snapshot with threshold percent set 1`] = `
<div>
<div
class="nhsuk-character-count"
data-maxlength="112"
data-module="nhsuk-character-count"
data-threshold="75"
>
<div
class="nhsuk-form-group"
>
<label
class="nhsuk-label"
for="threshold"
>
Can you provide more detail?
</label>
<div
class="nhsuk-form-group"
>
<textarea
class="nhsuk-textarea nhsuk-js-character-count"
id="threshold"
name="threshold"
rows="5"
>
Type another letter into this field after this message to see the threshold feature
</textarea>
<div
class="nhsuk-hint nhsuk-character-count__message nhsuk-u-visually-hidden"
id="threshold-info"
>
You can enter up to
112
characters
</div>
<div
aria-hidden="true"
class="nhsuk-hint nhsuk-character-count__message nhsuk-character-count__status nhsuk-character-count__message--disabled"
>
You have 29 characters remaining
</div>
<div
aria-hidden="true"
aria-live="polite"
class="nhsuk-character-count__sr-status nhsuk-u-visually-hidden"
>
You have 29 characters remaining
</div>
</div>
</div>
</div>
</div>
`;

exports[`Character Count Matches snapshot with word count type 1`] = `
<div>
<div
class="nhsuk-character-count"
data-maxwords="150"
data-module="nhsuk-character-count"
>
<div
class="nhsuk-form-group"
>
<label
class="nhsuk-label nhsuk-label--l"
for="job-description-detail"
>
Enter a job description
</label>
<div
class="nhsuk-form-group"
>
<textarea
class="nhsuk-textarea nhsuk-js-character-count"
id="job-description-detail"
name="job-description-detail"
rows="5"
/>
<div
class="nhsuk-hint nhsuk-character-count__message nhsuk-u-visually-hidden"
id="job-description-detail-info"
>
You can enter up to
150
characters
</div>
<div
aria-hidden="true"
class="nhsuk-hint nhsuk-character-count__message nhsuk-character-count__status"
>
You have 150 words remaining
</div>
<div
aria-live="polite"
class="nhsuk-character-count__sr-status nhsuk-u-visually-hidden"
>
You have 150 words remaining
</div>
</div>
</div>
</div>
</div>
`;
36 changes: 36 additions & 0 deletions src/components/icons/__tests__/__snapshots__/Icons.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,42 @@ exports[`Icons all icons match snapshots: ChevronRight 1`] = `
</div>
`;

exports[`Icons all icons match snapshots: ChevronRightCircle 1`] = `
<div>
<svg
aria-hidden="true"
class="nhsuk-icon nhsuk-icon nhsuk-icon__chevron-right-circle"
focusable="false"
height="27"
width="27"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="13.333"
cy="13.333"
fill=""
r="13.333"
/>
<g
data-name="Group 1"
fill="none"
stroke="#fff"
stroke-linecap="round"
stroke-miterlimit="10"
stroke-width="2.667"
>
<path
d="M15.438 13l-3.771 3.771"
/>
<path
d="M11.667 9.229L15.438 13"
data-name="Path"
/>
</g>
</svg>
</div>
`;

exports[`Icons all icons match snapshots: Close 1`] = `
<div>
<svg
Expand Down
1 change: 1 addition & 0 deletions src/components/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { ArrowRightCircle } from './individual/ArrowRightCircle';
export { ChevronDown } from './individual/ChevronDown';
export { ChevronLeft } from './individual/ChevronLeft';
export { ChevronRight } from './individual/ChevronRight';
export { ChevronRightCircle } from './individual/ChevronRightCircle';
export { Close } from './individual/Close';
export { Cross } from './individual/Cross';
export { SmallEmdash } from './individual/SmallEmdash';
Expand Down
25 changes: 25 additions & 0 deletions src/components/icons/individual/ChevronRightCircle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';

export const ChevronRightCircle: React.FC = () => (
<svg
className="nhsuk-icon nhsuk-icon nhsuk-icon__chevron-right-circle"
xmlns="http://www.w3.org/2000/svg"
width="27"
height="27"
aria-hidden="true"
focusable="false"
>
<circle cx="13.333" cy="13.333" r="13.333" fill="" />
<g
data-name="Group 1"
fill="none"
stroke="#fff"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="2.667"
>
<path d="M15.438 13l-3.771 3.771" />
<path data-name="Path" d="M11.667 9.229L15.438 13" />
</g>
</svg>
);
21 changes: 19 additions & 2 deletions src/components/navigation/card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import CardGroupItem from './components/CardGroupItem';
interface CardProps extends HTMLProps<HTMLDivElement> {
clickable?: boolean;
feature?: boolean;
primary?: boolean;
secondary?: boolean;
}

interface ICard extends React.FC<CardProps> {
Expand All @@ -25,18 +27,33 @@ interface ICard extends React.FC<CardProps> {
}

const Card: ICard = ({
className, clickable, children, feature = false, ...rest
className,
clickable,
children,
feature = false,
primary = false,
secondary = false,
...rest
}) => (
<div
className={classNames(
'nhsuk-card',
{ 'nhsuk-card--clickable': clickable },
{ 'nhsuk-card--feature': feature },
{ 'nhsuk-card--secondary': secondary },
className,
)}
{...rest}
>
<CardContext.Provider value={{ feature: Boolean(feature) }}>{children}</CardContext.Provider>
<CardContext.Provider
value={{
feature: Boolean(feature),
primary: Boolean(primary),
secondary: Boolean(secondary),
}}
>
{children}
</CardContext.Provider>
</div>
);

Expand Down
4 changes: 4 additions & 0 deletions src/components/navigation/card/CardContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import React from 'react';

export interface ICardContext {
feature: boolean;
primary: boolean;
secondary: boolean;
}

const CardContext = React.createContext<ICardContext>({
feature: false,
primary: false,
secondary: false,
});

export default CardContext;
Loading

0 comments on commit 3c482e4

Please sign in to comment.