uikit-react-public 0.26.0 → 0.26.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/MenuNew/MenuBaseItem.d.ts +2 -2
- package/dist/index.js +4787 -4652
- package/lib/components/DrawerMenu/__tests__/DrawerMenu.test.tsx +93 -1
- package/lib/components/Dropdown/DropdownContent.tsx +139 -7
- package/lib/components/Footer/Footer.tsx +12 -0
- package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +36 -0
- package/lib/components/FooterNew/LegalAndCopyright.tsx +14 -0
- package/lib/components/FooterNew/__tests__/__snapshots__/Footer.test.tsx.snap +36 -0
- package/lib/components/HeaderNew/HeaderItem.tsx +7 -1
- package/lib/components/HeaderNew/__tests__/Header.test.tsx +30 -0
- package/lib/components/MenuNew/MenuAccordion/MenuAccordion.tsx +36 -2
- package/lib/components/MenuNew/MenuAccordion/MenuAccordionChevron.tsx +13 -11
- package/lib/components/MenuNew/MenuAccordion/MenuAccordionItem.tsx +5 -3
- package/lib/components/MenuNew/MenuBaseItem.tsx +20 -9
- package/lib/components/MenuNew/SecondaryMenuItem.tsx +1 -0
- package/lib/components/MenuNew/__tests__/Menu.test.tsx +42 -5
- package/package.json +1 -1
|
@@ -23,7 +23,13 @@ const HeaderItem = ({
|
|
|
23
23
|
min-height: 40px;
|
|
24
24
|
|
|
25
25
|
&:not(:first-of-type) {
|
|
26
|
-
margin-left: ${theme.margin.
|
|
26
|
+
margin-left: ${theme.margin.m16};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@media (min-width: ${theme.breakpoints.desktop}px) {
|
|
30
|
+
&:not(:first-of-type) {
|
|
31
|
+
margin-left: 0;
|
|
32
|
+
}
|
|
27
33
|
}
|
|
28
34
|
`;
|
|
29
35
|
|
|
@@ -39,4 +39,34 @@ describe('Header', () => {
|
|
|
39
39
|
expect(link).toBeInTheDocument();
|
|
40
40
|
expect(link.getAttribute('href')).toBe('/');
|
|
41
41
|
});
|
|
42
|
+
|
|
43
|
+
test('spaces subsequent header items on smaller screens and resets spacing on desktop', () => {
|
|
44
|
+
render(
|
|
45
|
+
<ThemeContextProvider>
|
|
46
|
+
<Header title='LIDS'>
|
|
47
|
+
<Header.MenuContainer>
|
|
48
|
+
<Header.Item testId='first-header-item'>First</Header.Item>
|
|
49
|
+
<Header.Item testId='second-header-item'>Second</Header.Item>
|
|
50
|
+
</Header.MenuContainer>
|
|
51
|
+
</Header>
|
|
52
|
+
</ThemeContextProvider>
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const firstItem = screen.getByTestId('first-header-item');
|
|
56
|
+
const secondItem = screen.getByTestId('second-header-item');
|
|
57
|
+
const generatedClass = [...secondItem.classList].find((className) =>
|
|
58
|
+
className.startsWith('css-')
|
|
59
|
+
);
|
|
60
|
+
const styles = document.head.textContent;
|
|
61
|
+
|
|
62
|
+
expect(firstItem).toHaveClass('ucl-uikit-header__item');
|
|
63
|
+
expect(secondItem).toHaveClass('ucl-uikit-header__item');
|
|
64
|
+
expect(generatedClass).toBeDefined();
|
|
65
|
+
expect(styles).toContain(
|
|
66
|
+
`.${generatedClass}:not(:first-of-type){margin-left:16px;}`
|
|
67
|
+
);
|
|
68
|
+
expect(styles).toContain(
|
|
69
|
+
`@media (min-width: 1056px){.${generatedClass}:not(:first-of-type){margin-left:0;}}`
|
|
70
|
+
);
|
|
71
|
+
});
|
|
42
72
|
});
|
|
@@ -14,6 +14,7 @@ import MenuAccordionChevron from './MenuAccordionChevron';
|
|
|
14
14
|
import MenuAccordionItem, { MenuAccordionItemProps } from './MenuAccordionItem';
|
|
15
15
|
|
|
16
16
|
export const NAME = 'ucl-uikit-menu__accordion';
|
|
17
|
+
const FOCUS_RING_GUTTER_PX = 6;
|
|
17
18
|
|
|
18
19
|
export interface MenuAccordionProps extends Omit<
|
|
19
20
|
MenuBaseItemProps,
|
|
@@ -60,8 +61,35 @@ const MenuAccordion = ({
|
|
|
60
61
|
`;
|
|
61
62
|
|
|
62
63
|
const bodyStyle = css`
|
|
64
|
+
display: grid;
|
|
65
|
+
grid-template-rows: 0fr;
|
|
63
66
|
width: 100%;
|
|
67
|
+
margin-top: 0;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
opacity: 0;
|
|
70
|
+
pointer-events: none;
|
|
71
|
+
transition:
|
|
72
|
+
grid-template-rows 200ms ease-in-out,
|
|
73
|
+
margin-top 200ms ease-in-out,
|
|
74
|
+
opacity 200ms ease-in-out;
|
|
75
|
+
`;
|
|
76
|
+
|
|
77
|
+
const bodyExpandedStyle = css`
|
|
78
|
+
grid-template-rows: 1fr;
|
|
64
79
|
margin-top: ${theme.margin.m8};
|
|
80
|
+
opacity: 1;
|
|
81
|
+
pointer-events: auto;
|
|
82
|
+
transition:
|
|
83
|
+
grid-template-rows 200ms ease-in-out,
|
|
84
|
+
margin-top 200ms ease-in-out,
|
|
85
|
+
opacity 200ms ease-in-out;
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
const bodyInnerStyle = css`
|
|
89
|
+
min-height: 0;
|
|
90
|
+
padding-top: ${FOCUS_RING_GUTTER_PX}px;
|
|
91
|
+
padding-bottom: ${FOCUS_RING_GUTTER_PX}px;
|
|
92
|
+
overflow: hidden;
|
|
65
93
|
`;
|
|
66
94
|
|
|
67
95
|
const handleClick = (event: MouseEvent<HTMLDivElement>) => {
|
|
@@ -74,7 +102,7 @@ const MenuAccordion = ({
|
|
|
74
102
|
<MenuBaseItem
|
|
75
103
|
className={style}
|
|
76
104
|
iconPosition='left'
|
|
77
|
-
|
|
105
|
+
hoverMode='background'
|
|
78
106
|
onClick={handleClick}
|
|
79
107
|
endAdornment={<MenuAccordionChevron expanded={expanded} />}
|
|
80
108
|
aria-expanded={expanded}
|
|
@@ -84,7 +112,13 @@ const MenuAccordion = ({
|
|
|
84
112
|
<MenuItemText className={textStyle}>{label}</MenuItemText>
|
|
85
113
|
</span>
|
|
86
114
|
</MenuBaseItem>
|
|
87
|
-
|
|
115
|
+
<div
|
|
116
|
+
className={cx(bodyStyle, expanded && bodyExpandedStyle)}
|
|
117
|
+
aria-hidden={!expanded}
|
|
118
|
+
inert={!expanded}
|
|
119
|
+
>
|
|
120
|
+
<div className={bodyInnerStyle}>{children}</div>
|
|
121
|
+
</div>
|
|
88
122
|
</>
|
|
89
123
|
);
|
|
90
124
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { css, cx } from '@emotion/css';
|
|
1
2
|
import Icon from '../../Icon';
|
|
2
3
|
|
|
3
4
|
export interface MenuAccordionChevronProps {
|
|
@@ -8,23 +9,24 @@ export interface MenuAccordionChevronProps {
|
|
|
8
9
|
const MenuAccordionChevron = ({
|
|
9
10
|
expanded,
|
|
10
11
|
className,
|
|
11
|
-
}: MenuAccordionChevronProps) =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
}: MenuAccordionChevronProps) => {
|
|
13
|
+
const baseStyle = css`
|
|
14
|
+
transition: transform 150ms ease-in-out;
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const expandedStyle = css`
|
|
18
|
+
transform: rotate(180deg);
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
return (
|
|
21
22
|
<Icon.ChevronDown
|
|
22
|
-
className={className}
|
|
23
|
+
className={cx(baseStyle, expanded && expandedStyle, className)}
|
|
23
24
|
size={24}
|
|
24
25
|
aria-hidden='true'
|
|
25
26
|
focusable='false'
|
|
26
27
|
testId='ucl-uikit-menu__accordion__icon--chevron-down'
|
|
27
28
|
/>
|
|
28
29
|
);
|
|
30
|
+
};
|
|
29
31
|
|
|
30
32
|
export default MenuAccordionChevron;
|
|
@@ -5,6 +5,7 @@ import MenuItemText from '../MenuItemText';
|
|
|
5
5
|
import { useTheme } from '../../../theme';
|
|
6
6
|
|
|
7
7
|
export const NAME = 'ucl-uikit-menu__accordion-item';
|
|
8
|
+
const FOCUS_RING_GUTTER_PX = 6;
|
|
8
9
|
|
|
9
10
|
export interface MenuAccordionItemProps extends HTMLAttributes<HTMLDivElement> {
|
|
10
11
|
asChild?: boolean;
|
|
@@ -21,11 +22,12 @@ const MenuAccordionItem = ({
|
|
|
21
22
|
const [theme] = useTheme();
|
|
22
23
|
|
|
23
24
|
const baseStyle = css`
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
width: calc(100% - ${FOCUS_RING_GUTTER_PX * 2}px);
|
|
26
|
+
margin: 0 ${FOCUS_RING_GUTTER_PX}px;
|
|
27
|
+
padding-left: calc(${theme.padding.p40} - ${FOCUS_RING_GUTTER_PX}px);
|
|
26
28
|
|
|
27
29
|
@media screen and (min-width: ${theme.breakpoints.tablet}px) {
|
|
28
|
-
padding: 0 ${theme.padding.p56};
|
|
30
|
+
padding: 0 calc(${theme.padding.p56} - ${FOCUS_RING_GUTTER_PX}px);
|
|
29
31
|
}
|
|
30
32
|
`;
|
|
31
33
|
|
|
@@ -6,7 +6,7 @@ export interface MenuBaseItemProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
6
6
|
icon?: ReactNode;
|
|
7
7
|
iconPosition?: 'left' | 'right';
|
|
8
8
|
endAdornment?: ReactNode;
|
|
9
|
-
|
|
9
|
+
hoverMode?: 'background' | 'underline';
|
|
10
10
|
asChild?: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -20,7 +20,7 @@ const MenuBaseItem = ({
|
|
|
20
20
|
onKeyDown,
|
|
21
21
|
role,
|
|
22
22
|
tabIndex,
|
|
23
|
-
|
|
23
|
+
hoverMode = 'background',
|
|
24
24
|
asChild = false,
|
|
25
25
|
...props
|
|
26
26
|
}: MenuBaseItemProps) => {
|
|
@@ -63,15 +63,26 @@ const MenuBaseItem = ({
|
|
|
63
63
|
&:focus-within {
|
|
64
64
|
box-shadow: ${theme.boxShadow.focus};
|
|
65
65
|
}
|
|
66
|
+
`;
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
`}
|
|
68
|
+
const backgroundOnHoverStyle = css`
|
|
69
|
+
&:hover {
|
|
70
|
+
background-color: ${theme.colour.fill.brandSubtleHover};
|
|
71
|
+
}
|
|
73
72
|
`;
|
|
74
|
-
|
|
73
|
+
|
|
74
|
+
const underlineStyleOnHoverStyle = css`
|
|
75
|
+
&:hover .ucl-uikit-menu__item-text {
|
|
76
|
+
text-decoration: underline;
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
const style = cx(
|
|
81
|
+
baseStyle,
|
|
82
|
+
hoverMode === 'underline' && underlineStyleOnHoverStyle,
|
|
83
|
+
hoverMode === 'background' && backgroundOnHoverStyle,
|
|
84
|
+
className
|
|
85
|
+
);
|
|
75
86
|
|
|
76
87
|
const endAdornmentStyle = css`
|
|
77
88
|
margin-left: auto;
|
|
@@ -86,7 +86,7 @@ describe('Menu', () => {
|
|
|
86
86
|
).toBeInTheDocument();
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
test('accordion toggles to expanded state with
|
|
89
|
+
test('accordion toggles to expanded state with rotated down chevron', () => {
|
|
90
90
|
wrap(
|
|
91
91
|
<Menu>
|
|
92
92
|
<Menu.Accordion
|
|
@@ -98,14 +98,51 @@ describe('Menu', () => {
|
|
|
98
98
|
</Menu>
|
|
99
99
|
);
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
const accordionContent = screen
|
|
102
|
+
.getByText('Library')
|
|
103
|
+
.closest('[aria-hidden]');
|
|
104
|
+
expect(accordionContent).toHaveAttribute('aria-hidden', 'true');
|
|
102
105
|
fireEvent.click(screen.getByText('Services'));
|
|
106
|
+
expect(accordionContent).toHaveAttribute('aria-hidden', 'false');
|
|
103
107
|
expect(
|
|
104
|
-
screen.getByTestId('ucl-uikit-menu__accordion__icon--chevron-
|
|
108
|
+
screen.getByTestId('ucl-uikit-menu__accordion__icon--chevron-down')
|
|
105
109
|
).toBeInTheDocument();
|
|
110
|
+
expect(
|
|
111
|
+
screen.queryByTestId('ucl-uikit-menu__accordion__icon--chevron-up')
|
|
112
|
+
).not.toBeInTheDocument();
|
|
106
113
|
expect(screen.getByText('Library')).toBeInTheDocument();
|
|
107
114
|
});
|
|
108
115
|
|
|
116
|
+
test('accordion items allow space for focus borders', () => {
|
|
117
|
+
wrap(
|
|
118
|
+
<Menu>
|
|
119
|
+
<Menu.Accordion
|
|
120
|
+
label='Services'
|
|
121
|
+
defaultExpanded
|
|
122
|
+
>
|
|
123
|
+
<Menu.Accordion.Item>Library</Menu.Accordion.Item>
|
|
124
|
+
</Menu.Accordion>
|
|
125
|
+
</Menu>
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const accordionItem = screen
|
|
129
|
+
.getByText('Library')
|
|
130
|
+
.closest('.ucl-uikit-menu__accordion-item');
|
|
131
|
+
const accordionContentInner = accordionItem?.parentElement;
|
|
132
|
+
|
|
133
|
+
expect(accordionItem).toHaveStyle({
|
|
134
|
+
marginTop: '0px',
|
|
135
|
+
marginLeft: '6px',
|
|
136
|
+
marginRight: '6px',
|
|
137
|
+
marginBottom: '0px',
|
|
138
|
+
width: 'calc(100% - 12px)',
|
|
139
|
+
});
|
|
140
|
+
expect(accordionContentInner).toHaveStyle({
|
|
141
|
+
paddingTop: '6px',
|
|
142
|
+
paddingBottom: '6px',
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
109
146
|
test('accordion item supports asChild link content', () => {
|
|
110
147
|
wrap(
|
|
111
148
|
<Menu>
|
|
@@ -220,10 +257,10 @@ describe('Menu', () => {
|
|
|
220
257
|
expect(item?.firstChild).toHaveAttribute('data-testid', 'left-icon');
|
|
221
258
|
});
|
|
222
259
|
|
|
223
|
-
test('
|
|
260
|
+
test('primary items use background hover instead of underline hover', () => {
|
|
224
261
|
wrap(
|
|
225
262
|
<Menu>
|
|
226
|
-
<Menu.PrimaryItem
|
|
263
|
+
<Menu.PrimaryItem>Home</Menu.PrimaryItem>
|
|
227
264
|
</Menu>
|
|
228
265
|
);
|
|
229
266
|
|