Skip to content

Commit 7ba47f3

Browse files
committed
chore: add 'Skip to main content' button to the main page
Closes: INSTUI-4240
1 parent 56308de commit 7ba47f3

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

packages/__docs__/src/App/index.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import type {
8080
ParsedDocSummary
8181
} from '../../buildScripts/DataTypes.mjs'
8282
import { logError } from '@instructure/console'
83+
import React from 'react'
8384

8485
type AppContextType = {
8586
themeKey: keyof MainDocsData['themes']
@@ -106,6 +107,7 @@ class App extends Component<AppProps, AppState> {
106107
_mediaQueryListener?: ReturnType<typeof addMediaQueryMatchListener>
107108
_defaultDocumentTitle?: string
108109
_controller?: AbortController
110+
_heroRef: React.RefObject<Hero>
109111

110112
constructor(props: AppProps) {
111113
super(props)
@@ -127,6 +129,8 @@ class App extends Component<AppProps, AppState> {
127129
versionsData: undefined,
128130
iconsData: null
129131
}
132+
133+
this._heroRef = React.createRef()
130134
}
131135

132136
fetchDocumentData = async (docId: string) => {
@@ -487,6 +491,7 @@ class App extends Component<AppProps, AppState> {
487491
repository={library.repository}
488492
version={library.version}
489493
layout={layout}
494+
ref={this._heroRef}
490495
/>
491496
</InstUISettingsProvider>
492497
)
@@ -691,6 +696,10 @@ class App extends Component<AppProps, AppState> {
691696
) : null
692697
}
693698

699+
focusMainContent = () => {
700+
this._heroRef.current?.focusMainContentHeading()
701+
}
702+
694703
render() {
695704
const key = this.state.key
696705
const { showMenu, layout, docsData, iconsData } = this.state
@@ -717,6 +726,18 @@ class App extends Component<AppProps, AppState> {
717726
aria-label={key || docsData.library.name}
718727
ref={this.handleContentRef}
719728
>
729+
<View
730+
as={'button'}
731+
onClick={this.focusMainContent}
732+
tabIndex={0}
733+
css={this.props.styles?.skipToMainButton}
734+
borderRadius="small"
735+
display="inline-block"
736+
padding="small"
737+
background="primary"
738+
>
739+
Skip to main content
740+
</View>
720741
{!showMenu && (
721742
<div css={this.props.styles?.hamburger}>
722743
<InstUISettingsProvider>

packages/__docs__/src/App/props.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type AppStyle = ComponentStyle<
5151
| 'hamburger'
5252
| 'inlineNavigation'
5353
| 'globalStyles'
54+
| 'skipToMainButton'
5455
>
5556

5657
type AppTheme = {

packages/__docs__/src/App/styles.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ const generateStyle = (componentTheme: AppTheme): AppStyle => {
7676
borderInlineEndWidth: componentTheme.navBorderWidth,
7777
borderInlineEndStyle: 'solid'
7878
},
79+
skipToMainButton: {
80+
label: 'skipToMainButton',
81+
position: 'absolute',
82+
left: '-9999px',
83+
zIndex: 999,
84+
marginTop: '6px',
85+
opacity: 0,
86+
height: '60px',
87+
fontSize: '150%',
88+
'&:focus': {
89+
left: '8rem',
90+
transform: 'translateX(-50%)',
91+
opacity: 1
92+
}
93+
},
7994
globalStyles: {
8095
html: {
8196
height: '100%',

packages/__docs__/src/Hero/index.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import { Heading } from '../Heading'
5252

5353
import type { HeroProps } from './props'
5454
import { propTypes, allowedProps } from './props'
55+
import React from 'react'
5556

5657
@withStyle(generateStyle, generateComponentTheme)
5758
class Hero extends Component<HeroProps> {
@@ -61,6 +62,8 @@ class Hero extends Component<HeroProps> {
6162
docs: null
6263
}
6364

65+
_mainContentHeading?: HTMLElement
66+
6467
componentDidMount() {
6568
this.props.makeStyles?.()
6669
}
@@ -69,6 +72,16 @@ class Hero extends Component<HeroProps> {
6972
this.props.makeStyles?.()
7073
}
7174

75+
mainContentHeadingRef = (el: Element | null) => {
76+
this._mainContentHeading = el as HTMLElement
77+
}
78+
79+
focusMainContentHeading = () => {
80+
if (this._mainContentHeading) {
81+
this._mainContentHeading.focus()
82+
}
83+
}
84+
7285
render() {
7386
const { version, layout, styles } = this.props
7487

@@ -192,7 +205,13 @@ class Hero extends Component<HeroProps> {
192205

193206
const heroBodyContent = (
194207
<View as="div">
195-
<Heading as="h3" level="h2" margin="none none medium">
208+
<Heading
209+
as="h3"
210+
level="h2"
211+
margin="none none medium"
212+
elementRef={this.mainContentHeadingRef}
213+
tabIndex={0}
214+
>
196215
Components everyone can count on
197216
</Heading>
198217
<View as="div" margin="medium none">

0 commit comments

Comments
 (0)