@graphcommerce/next-ui 8.0.0-canary.75 → 8.0.0-canary.77
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/CHANGELOG.md +9 -0
- package/LayoutDefault/components/LayoutDefault.tsx +6 -1
- package/LayoutParts/DesktopNavBar.tsx +2 -0
- package/Navigation/components/NavigationFab.tsx +9 -7
- package/Navigation/components/NavigationOverlay.tsx +12 -1
- package/SkipLink/SkipLink.tsx +38 -0
- package/TextInputNumber/TextInputNumber.tsx +1 -1
- package/index.ts +1 -0
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 8.0.0-canary.77
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`e33660f`](https://github.com/graphcommerce-org/graphcommerce/commit/e33660f172466dcfa0ab7262cee612d9a3e47776) - a11y improvements (see https://github.com/graphcommerce-org/graphcommerce/issues/1995 for more info)
|
|
8
|
+
([@FrankHarland](https://github.com/FrankHarland))
|
|
9
|
+
|
|
10
|
+
## 8.0.0-canary.76
|
|
11
|
+
|
|
3
12
|
## 8.0.0-canary.75
|
|
4
13
|
|
|
5
14
|
## 8.0.0-canary.74
|
|
@@ -3,6 +3,7 @@ import { dvh } from '@graphcommerce/framer-utils'
|
|
|
3
3
|
import { Box, SxProps, Theme } from '@mui/material'
|
|
4
4
|
import { useTransform, useScroll } from 'framer-motion'
|
|
5
5
|
import { LayoutProvider } from '../../Layout/components/LayoutProvider'
|
|
6
|
+
import { SkipLink } from '../../SkipLink/SkipLink'
|
|
6
7
|
import { extendableComponent } from '../../Styles'
|
|
7
8
|
import { useFabSize } from '../../Theme'
|
|
8
9
|
|
|
@@ -67,6 +68,7 @@ export function LayoutDefault(props: LayoutDefaultProps) {
|
|
|
67
68
|
...(Array.isArray(sx) ? sx : [sx]),
|
|
68
69
|
]}
|
|
69
70
|
>
|
|
71
|
+
<SkipLink />
|
|
70
72
|
<LayoutProvider scroll={scrollYOffset}>
|
|
71
73
|
{beforeHeader}
|
|
72
74
|
<Box
|
|
@@ -144,7 +146,10 @@ export function LayoutDefault(props: LayoutDefaultProps) {
|
|
|
144
146
|
) : (
|
|
145
147
|
<div />
|
|
146
148
|
)}
|
|
147
|
-
<div className={classes.children}>
|
|
149
|
+
<div className={classes.children}>
|
|
150
|
+
<div id='skip-nav' tabIndex={-1} />
|
|
151
|
+
{children}
|
|
152
|
+
</div>
|
|
148
153
|
<div className={classes.footer}>{footer}</div>
|
|
149
154
|
</LayoutProvider>
|
|
150
155
|
</Box>
|
|
@@ -69,6 +69,7 @@ export function DesktopNavBar(props: MenuTabsProps) {
|
|
|
69
69
|
}}
|
|
70
70
|
direction='left'
|
|
71
71
|
size='small'
|
|
72
|
+
tabIndex={-1}
|
|
72
73
|
className={`${classes.left} ${classes.button}`}
|
|
73
74
|
>
|
|
74
75
|
<IconSvg src={iconLeft ?? iconChevronLeft} />
|
|
@@ -94,6 +95,7 @@ export function DesktopNavBar(props: MenuTabsProps) {
|
|
|
94
95
|
}}
|
|
95
96
|
direction='right'
|
|
96
97
|
size='small'
|
|
98
|
+
tabIndex={-1}
|
|
97
99
|
className={`${classes.right} ${classes.button}`}
|
|
98
100
|
>
|
|
99
101
|
<IconSvg src={iconRight ?? iconChevronRight} />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
2
|
-
import { Fab, styled, Box, SxProps, Theme, FabProps } from '@mui/material'
|
|
2
|
+
import { Fab, styled, Box, SxProps, Theme, FabProps, useTheme } from '@mui/material'
|
|
3
3
|
import { m } from 'framer-motion'
|
|
4
4
|
import { useRouter } from 'next/router'
|
|
5
5
|
import React, { useEffect } from 'react'
|
|
@@ -35,6 +35,8 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
35
35
|
const scrollY = useScrollY()
|
|
36
36
|
const scrolled = useMotionValueValue(scrollY, (y) => y > 10)
|
|
37
37
|
|
|
38
|
+
const theme = useTheme()
|
|
39
|
+
|
|
38
40
|
useEffect(() => {
|
|
39
41
|
const clear = () => setOpenEl(null)
|
|
40
42
|
router.events.on('routeChangeStart', clear)
|
|
@@ -54,19 +56,19 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
54
56
|
>
|
|
55
57
|
<MotionDiv
|
|
56
58
|
className={classes.wrapper}
|
|
57
|
-
sx={
|
|
59
|
+
sx={{
|
|
58
60
|
[theme.breakpoints.down('md')]: {
|
|
59
61
|
opacity: '1 !important',
|
|
60
62
|
transform: 'none !important',
|
|
61
63
|
},
|
|
62
|
-
}
|
|
64
|
+
}}
|
|
63
65
|
style={{ opacity }}
|
|
64
66
|
>
|
|
65
67
|
<Fab
|
|
66
68
|
color='inherit'
|
|
67
69
|
aria-label='Open Menu'
|
|
68
70
|
size='responsive'
|
|
69
|
-
sx={
|
|
71
|
+
sx={{
|
|
70
72
|
boxShadow: 'none',
|
|
71
73
|
'&:hover, &:focus': {
|
|
72
74
|
boxShadow: 'none',
|
|
@@ -75,7 +77,7 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
75
77
|
background: theme.palette.text.primary,
|
|
76
78
|
pointerEvents: 'all',
|
|
77
79
|
color: theme.palette.background.paper,
|
|
78
|
-
}
|
|
80
|
+
}}
|
|
79
81
|
className={classes.fab}
|
|
80
82
|
{...fabProps}
|
|
81
83
|
>
|
|
@@ -87,7 +89,7 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
87
89
|
)}
|
|
88
90
|
</Fab>
|
|
89
91
|
<MotionDiv
|
|
90
|
-
sx={
|
|
92
|
+
sx={{
|
|
91
93
|
pointerEvents: 'none',
|
|
92
94
|
borderRadius: '99em',
|
|
93
95
|
position: 'absolute',
|
|
@@ -96,7 +98,7 @@ export function NavigationFab(props: NavigationFabProps) {
|
|
|
96
98
|
boxShadow: theme.shadows[6],
|
|
97
99
|
top: 0,
|
|
98
100
|
[theme.breakpoints.down('md')]: { opacity: '1 !important' },
|
|
99
|
-
}
|
|
101
|
+
}}
|
|
100
102
|
className={classes.shadow}
|
|
101
103
|
style={{ opacity: shadowOpacity }}
|
|
102
104
|
/>
|
|
@@ -2,7 +2,7 @@ import { useMotionValueValue, useMotionSelector, dvw } from '@graphcommerce/fram
|
|
|
2
2
|
import { i18n } from '@lingui/core'
|
|
3
3
|
import { useTheme, Box, Fab, SxProps, Theme, useEventCallback, styled } from '@mui/material'
|
|
4
4
|
import { m } from 'framer-motion'
|
|
5
|
-
import React, { useEffect } from 'react'
|
|
5
|
+
import React, { useEffect, useRef } from 'react'
|
|
6
6
|
import type { LiteralUnion } from 'type-fest'
|
|
7
7
|
import { IconSvg, useIconSvgSize } from '../../IconSvg'
|
|
8
8
|
import { LayoutHeaderContent } from '../../Layout/components/LayoutHeaderContent'
|
|
@@ -71,12 +71,22 @@ export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
|
71
71
|
} else selection.set([])
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
+
const a11yFocusRef = useRef<HTMLButtonElement | null>(null)
|
|
75
|
+
|
|
74
76
|
const selectedLevel = useMotionValueValue(selection, (s) => (s === false ? -1 : s.length))
|
|
75
77
|
const selectionValue = useMotionValueValue(selection, (s) => (s ? s.join('') : s))
|
|
76
78
|
const activeAndNotClosing = useMotionSelector([selection, closing], ([s, c]) =>
|
|
77
79
|
c ? false : s !== false,
|
|
78
80
|
)
|
|
79
81
|
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
animating.set(true)
|
|
84
|
+
|
|
85
|
+
if (activeAndNotClosing) {
|
|
86
|
+
a11yFocusRef.current?.focus()
|
|
87
|
+
}
|
|
88
|
+
}, [activeAndNotClosing, animating])
|
|
89
|
+
|
|
80
90
|
const afterClose = useEventCallback(() => {
|
|
81
91
|
if (!closing.get()) return
|
|
82
92
|
setTimeout(() => {
|
|
@@ -157,6 +167,7 @@ export const NavigationOverlay = React.memo((props: NavigationOverlayProps) => {
|
|
|
157
167
|
sx={{ boxShadow: 'none', my: fabMarginY }}
|
|
158
168
|
size='responsive'
|
|
159
169
|
aria-label={i18n._(/* i18n */ 'Close')}
|
|
170
|
+
ref={a11yFocusRef}
|
|
160
171
|
>
|
|
161
172
|
<IconSvg src={iconClose} size='large' aria-hidden />
|
|
162
173
|
</Fab>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Trans } from '@lingui/react'
|
|
2
|
+
import { Link } from '@mui/material'
|
|
3
|
+
|
|
4
|
+
export function SkipLink() {
|
|
5
|
+
const setFocus = (e) => {
|
|
6
|
+
e.preventDefault()
|
|
7
|
+
globalThis.document.querySelector<HTMLDivElement>('#skip-nav')?.focus()
|
|
8
|
+
globalThis.document.querySelector<HTMLDivElement>('#skip-nav')?.scrollIntoView()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<Link
|
|
13
|
+
href='#skip-nav'
|
|
14
|
+
tabIndex={0}
|
|
15
|
+
onClick={setFocus}
|
|
16
|
+
onKeyDown={(e) => {
|
|
17
|
+
if (e.key === 'Enter') {
|
|
18
|
+
setFocus(e)
|
|
19
|
+
}
|
|
20
|
+
}}
|
|
21
|
+
sx={(theme) => ({
|
|
22
|
+
position: 'absolute',
|
|
23
|
+
top: theme.page.vertical,
|
|
24
|
+
zIndex: '-1',
|
|
25
|
+
marginLeft: theme.page.horizontal,
|
|
26
|
+
padding: theme.spacings.xxs,
|
|
27
|
+
backgroundColor: theme.palette.background.paper,
|
|
28
|
+
border: theme.palette.text.primary,
|
|
29
|
+
borderRadius: theme.shape.borderRadius,
|
|
30
|
+
'&:focus': {
|
|
31
|
+
zIndex: 9999,
|
|
32
|
+
},
|
|
33
|
+
})}
|
|
34
|
+
>
|
|
35
|
+
<Trans id='Skip to main content' />
|
|
36
|
+
</Link>
|
|
37
|
+
)
|
|
38
|
+
}
|
package/index.ts
CHANGED
|
@@ -42,6 +42,7 @@ export * from './Row'
|
|
|
42
42
|
export * from './SectionContainer/SectionContainer'
|
|
43
43
|
export * from './SectionHeader/SectionHeader'
|
|
44
44
|
export * from './Separator/Separator'
|
|
45
|
+
export * from './SkipLink/SkipLink'
|
|
45
46
|
export * from './Snackbar/ErrorSnackbar'
|
|
46
47
|
export * from './Snackbar/MessageSnackbar'
|
|
47
48
|
export * from './Snackbar/MessageSnackbarImpl'
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/next-ui",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "8.0.0-canary.
|
|
5
|
+
"version": "8.0.0-canary.77",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"typescript": "5.3.3"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@graphcommerce/eslint-config-pwa": "^8.0.0-canary.
|
|
30
|
-
"@graphcommerce/framer-next-pages": "^8.0.0-canary.
|
|
31
|
-
"@graphcommerce/framer-scroller": "^8.0.0-canary.
|
|
32
|
-
"@graphcommerce/framer-utils": "^8.0.0-canary.
|
|
33
|
-
"@graphcommerce/image": "^8.0.0-canary.
|
|
34
|
-
"@graphcommerce/prettier-config-pwa": "^8.0.0-canary.
|
|
35
|
-
"@graphcommerce/typescript-config-pwa": "^8.0.0-canary.
|
|
29
|
+
"@graphcommerce/eslint-config-pwa": "^8.0.0-canary.77",
|
|
30
|
+
"@graphcommerce/framer-next-pages": "^8.0.0-canary.77",
|
|
31
|
+
"@graphcommerce/framer-scroller": "^8.0.0-canary.77",
|
|
32
|
+
"@graphcommerce/framer-utils": "^8.0.0-canary.77",
|
|
33
|
+
"@graphcommerce/image": "^8.0.0-canary.77",
|
|
34
|
+
"@graphcommerce/prettier-config-pwa": "^8.0.0-canary.77",
|
|
35
|
+
"@graphcommerce/typescript-config-pwa": "^8.0.0-canary.77",
|
|
36
36
|
"@lingui/core": "^4.2.1",
|
|
37
37
|
"@lingui/macro": "^4.2.1",
|
|
38
38
|
"@lingui/react": "^4.2.1",
|