Skip to content

Commit 6293a77

Browse files
committed
Merge branch 'master' of github.com:NHSDigital/nhsuk-react-components-extensions
2 parents d3f0dd6 + 8319bd3 commit 6293a77

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2811
-1746
lines changed

.storybook/_storybook.scss

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
%demo-centered {
2+
display: block;
3+
margin: auto;
4+
background-color: transparent;
5+
}
6+
17
.tag-demo {
28
display: grid;
39
grid-row-gap: 10px;
@@ -7,3 +13,25 @@
713
padding-bottom: 40px;
814
background-color: transparent;
915
}
16+
17+
.accordion-demo {
18+
@extend %demo-centered;
19+
width: 600px;
20+
padding-top: 40px;
21+
padding-bottom: 40px;
22+
}
23+
24+
.tooltip-demo {
25+
@extend %demo-centered;
26+
text-align: center;
27+
width: 250px;
28+
padding-top: 100px;
29+
padding-bottom: 100px;
30+
}
31+
32+
.masked-input-demo {
33+
@extend %demo-centered;
34+
width: 500px;
35+
padding-top: 100px;
36+
padding-bottom: 100px;
37+
}

package.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"@types/node": "^12.12.12",
2626
"@types/react": "^16.9.3",
2727
"@types/react-dom": "^16.9.3",
28-
"@types/storybook__react": "^4.0.2",
28+
"@types/react-input-mask": "^2.0.5",
29+
"@types/storybook__react": "^5.2.1",
2930
"@types/styled-components": "^4.1.19",
3031
"@typescript-eslint/eslint-plugin": "^2.3.1",
3132
"@typescript-eslint/parser": "^2.3.1",
@@ -46,6 +47,7 @@
4647
"eslint-plugin-react-hooks": "^1.7.0",
4748
"jest": "^24.9.0",
4849
"nhsuk-frontend": "^3.0.2",
50+
"nhsuk-react-components": "^1.0.1",
4951
"node-sass": "^4.12.0",
5052
"node-sass-tilde-importer": "^1.0.2",
5153
"prettier": "^1.18.2",
@@ -54,6 +56,7 @@
5456
"react-dom": "^16.9.3",
5557
"rollup": "^1.21.4",
5658
"rollup-plugin-sass": "^1.2.2",
59+
"rollup-plugin-typescript2": "^0.26.0",
5760
"sass-loader": "^8.0.0",
5861
"stylelint": "^13.2.0",
5962
"stylelint-config-sass-guidelines": "^7.0.0",
@@ -64,12 +67,13 @@
6467
"typescript": "^3.6.3"
6568
},
6669
"peerDependencies": {
67-
"react": "^16.9.0",
68-
"react-dom": "^16.9.0"
70+
"nhsuk-react-components": "^1.0.1",
71+
"react": "^16.9.3",
72+
"react-dom": "^16.9.3"
6973
},
7074
"dependencies": {
7175
"classnames": "^2.2.6",
72-
"rollup-plugin-typescript2": "^0.26.0"
76+
"react-input-mask": "^2.0.4"
7377
},
7478
"scripts": {
7579
"build": "yarn build:dist && yarn build:lib && yarn build:styles",

src/__tests__/index.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ import * as index from '../index';
22

33
describe('Index', () => {
44
it('contains all expected elements', () => {
5-
expect(Object.keys(index)).toEqual(['SubNavigation']);
5+
expect(Object.keys(index)).toEqual([
6+
'AccordionMenu',
7+
'MaskedInput',
8+
'SubNavigation',
9+
'TabSet',
10+
'Tag',
11+
'Tooltip',
12+
'WarningIcon',
13+
]);
614
});
715
});

src/all.scss

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,17 @@
44
// SubNavigation Component
55
@import './components/sub-navigation/SubNavigation';
66

7-
// Tag Styling
8-
@import './styles/tag';
7+
// Tag Component
8+
@import './components/tag/Tag';
9+
10+
// Mobile SCRa Components
11+
@import './components/accordion-menu/AccordionMenu';
12+
@import './components/tab-set/TabSet';
13+
@import './components/tooltip/Tooltip';
14+
15+
// Masked Input Depends on standard Input Styling - Include here and
16+
// not in the components.scss
17+
@import '~nhsuk-frontend/packages/components/error-message/error-message';
18+
@import '~nhsuk-frontend/packages/components/label/label';
19+
@import '~nhsuk-frontend/packages/components/hint/hint';
20+
@import '~nhsuk-frontend/packages/components/input/input';

src/components.scss

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
// SubNavigation Component
22
@import './components/sub-navigation/SubNavigation';
33

4-
// Tag Styling
5-
@import './styles/tag';
4+
// Tag Component
5+
@import './components/tag/Tag';
6+
7+
// Mobile SCRa Components
8+
@import './components/accordion-menu/AccordionMenu';
9+
@import './components/tab-set/TabSet';
10+
@import './components/tooltip/Tooltip';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React, { HTMLProps } from 'react';
2+
import classNames from 'classnames';
3+
import Section, { SectionProps } from './components/Section';
4+
import Link from './components/Link';
5+
6+
interface AccordionMenu extends React.FC<HTMLProps<HTMLDivElement>> {
7+
Section: React.FC<SectionProps>;
8+
Link: React.FC<HTMLProps<HTMLAnchorElement>>;
9+
}
10+
11+
const AccordionMenu: AccordionMenu = ({ className, ...rest }) => (
12+
<div className={classNames('nhsuk-accordion-menu', className)} {...rest} />
13+
);
14+
15+
AccordionMenu.Section = Section;
16+
AccordionMenu.Link = Link;
17+
18+
export default AccordionMenu;
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
@import '../../styles/variables';
2+
3+
.nhsuk-accordion-menu {
4+
display: block;
5+
background-color: $color_nhsuk-white;
6+
color: $color_nhsuk-white;
7+
8+
&__section {
9+
border-top: 1px solid $color_nhsuk-white;
10+
border-bottom: 1px solid $color_nhsuk-white;
11+
background-color: $color_nhsuk-white;
12+
padding: 0;
13+
14+
&:first-of-type + &:not(:focus-visible) {
15+
border-top: 4px solid $color_nhsuk-dark-blue;
16+
}
17+
18+
&:last-of-type + &:not(:focus-visible) {
19+
border-bottom: 4px solid $color_nhsuk-dark-blue;
20+
}
21+
22+
&-summary {
23+
@include nhsuk-responsive-padding(2, 'top');
24+
@include nhsuk-responsive-padding(2, 'bottom');
25+
@include nhsuk-responsive-padding(4, 'left');
26+
@include nhsuk-responsive-padding(4, 'right');
27+
list-style: none !important;
28+
background-color: $color_nhsuk-dark-blue;
29+
outline: none;
30+
border-bottom: 4px solid transparent;
31+
border-top: 4px solid transparent;
32+
display: flex;
33+
justify-content: space-between;
34+
align-items: center;
35+
cursor: pointer;
36+
37+
&::-webkit-details-marker {
38+
display: none !important;
39+
list-style: none !important;
40+
}
41+
42+
&::marker {
43+
display: none !important;
44+
list-style: none !important;
45+
}
46+
47+
&::before {
48+
display: none !important;
49+
list-style: none !important;
50+
}
51+
&:hover {
52+
text-decoration: underline;
53+
}
54+
55+
&:active,
56+
&:focus {
57+
background-color: $nhsuk-focus-color;
58+
color: $nhsuk-focus-text-color;
59+
border-bottom: 4px solid $color_nhsuk-black;
60+
}
61+
62+
&:active > .nhsuk-accordion-menu__icon,
63+
&:focus > .nhsuk-accordion-menu__icon {
64+
& > path {
65+
stroke: $color_nhsuk-white;
66+
}
67+
& > circle {
68+
fill: $color_nhsuk-black;
69+
}
70+
}
71+
72+
&-text {
73+
@include nhsuk-typography-responsive(22);
74+
display: block;
75+
position: relative;
76+
}
77+
}
78+
}
79+
80+
&__subsection {
81+
@include nhsuk-responsive-margin(2, 'top');
82+
@include nhsuk-responsive-margin(2, 'bottom');
83+
@include nhsuk-responsive-margin(2, 'right');
84+
@include nhsuk-responsive-margin(2, 'left');
85+
86+
display: block;
87+
cursor: pointer;
88+
89+
&-link {
90+
@include nhsuk-typography-responsive(19);
91+
@include nhsuk-responsive-padding(3, 'right');
92+
@include nhsuk-responsive-padding(3, 'left');
93+
94+
display: block;
95+
border-bottom: 3px solid transparent;
96+
border-top: 3px solid transparent;
97+
&:hover {
98+
color: $nhsuk-focus-text-color;
99+
background-color: $nhsuk-focus-color;
100+
}
101+
102+
&:active {
103+
color: $nhsuk-focus-text-color;
104+
background-color: $nhsuk-focus-color;
105+
padding-bottom: 0px;
106+
border-bottom: 3px solid $color_nhsuk-black;
107+
}
108+
}
109+
}
110+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import React from 'react';
2+
import { shallow } from 'enzyme';
3+
import AccordionMenu from '..';
4+
5+
describe('AccordionMenu', () => {
6+
it('matches snapshot', () => {
7+
const component = shallow(<AccordionMenu />);
8+
expect(component).toMatchSnapshot();
9+
component.unmount();
10+
});
11+
12+
describe('Section', () => {
13+
it('matches snapshot', () => {
14+
const component = shallow(<AccordionMenu.Section heading="TestHeading" />);
15+
expect(component).toMatchSnapshot();
16+
component.unmount();
17+
});
18+
19+
it('passes through text', () => {
20+
const component = shallow(<AccordionMenu.Section heading="TestHeading" />);
21+
expect(component.find('.nhsuk-accordion-menu__section-summary-text').text()).toBe(
22+
'TestHeading',
23+
);
24+
component.unmount();
25+
});
26+
27+
it('handles defaultOpen', () => {
28+
const component = shallow(
29+
<AccordionMenu.Section id="accordion" heading="Heading" defaultOpen />,
30+
);
31+
const event = {
32+
preventDefault: jest.fn(),
33+
};
34+
35+
expect(component.find('#accordion').getElement().props.open).toBe(true);
36+
component.find('summary').simulate('click', event);
37+
expect(event.preventDefault).toHaveBeenCalledTimes(1);
38+
expect(component.find('#accordion').getElement().props.open).toBe(false);
39+
component.find('summary').simulate('click', event);
40+
expect(event.preventDefault).toHaveBeenCalledTimes(2);
41+
expect(component.find('#accordion').getElement().props.open).toBe(true);
42+
component.unmount();
43+
});
44+
it('handles open={true}', () => {
45+
const component = shallow(<AccordionMenu.Section id="accordion" heading="Heading" open />);
46+
const event = {
47+
preventDefault: jest.fn(),
48+
};
49+
expect(component.find('#accordion').getElement().props.open).toBe(true);
50+
component.find('summary').simulate('click', event);
51+
expect(event.preventDefault).toHaveBeenCalledTimes(1);
52+
expect(component.find('#accordion').getElement().props.open).toBe(true);
53+
component.find('summary').simulate('click', event);
54+
expect(event.preventDefault).toHaveBeenCalledTimes(2);
55+
expect(component.find('#accordion').getElement().props.open).toBe(true);
56+
component.unmount();
57+
});
58+
59+
it('handles open={false}', () => {
60+
const component = shallow(
61+
<AccordionMenu.Section id="accordion" heading="Heading" open={false} />,
62+
);
63+
const event = {
64+
preventDefault: jest.fn(),
65+
};
66+
expect(component.find('#accordion').getElement().props.open).toBe(false);
67+
component.find('summary').simulate('click', event);
68+
expect(event.preventDefault).toHaveBeenCalledTimes(1);
69+
expect(component.find('#accordion').getElement().props.open).toBe(false);
70+
component.find('summary').simulate('click', event);
71+
expect(event.preventDefault).toHaveBeenCalledTimes(2);
72+
expect(component.find('#accordion').getElement().props.open).toBe(false);
73+
component.unmount();
74+
});
75+
});
76+
describe('Link', () => {
77+
it('matches snapshot', () => {
78+
const component = shallow(<AccordionMenu.Link>Test</AccordionMenu.Link>);
79+
expect(component).toMatchSnapshot();
80+
expect(component.text()).toBe('Test');
81+
component.unmount();
82+
});
83+
});
84+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`AccordionMenu Link matches snapshot 1`] = `
4+
<div
5+
className="nhsuk-accordion-menu__subsection"
6+
>
7+
<a
8+
className="nhsuk-accordion-menu__subsection-link"
9+
>
10+
Test
11+
</a>
12+
</div>
13+
`;
14+
15+
exports[`AccordionMenu Section matches snapshot 1`] = `
16+
<details
17+
className="nhsuk-accordion-menu__section"
18+
open={false}
19+
>
20+
<summary
21+
className="nhsuk-accordion-menu__section-summary"
22+
onClick={[Function]}
23+
role="tab"
24+
tabIndex={1}
25+
>
26+
<span
27+
className="nhsuk-accordion-menu__section-summary-text"
28+
>
29+
TestHeading
30+
</span>
31+
<ToggleIcon
32+
open={false}
33+
/>
34+
</summary>
35+
</details>
36+
`;
37+
38+
exports[`AccordionMenu matches snapshot 1`] = `
39+
<div
40+
className="nhsuk-accordion-menu"
41+
/>
42+
`;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React, { HTMLProps } from 'react';
2+
import classNames from 'classnames';
3+
4+
const Link: React.FC<HTMLProps<HTMLAnchorElement>> = ({ className, ...rest }) => (
5+
<div className="nhsuk-accordion-menu__subsection">
6+
<a className={classNames('nhsuk-accordion-menu__subsection-link', className)} {...rest} />
7+
</div>
8+
);
9+
10+
export default Link;

0 commit comments

Comments
 (0)