diff --git a/packages/__docs__/src/App/index.tsx b/packages/__docs__/src/App/index.tsx index a33eee196f..17d55e2c4d 100644 --- a/packages/__docs__/src/App/index.tsx +++ b/packages/__docs__/src/App/index.tsx @@ -80,6 +80,7 @@ import type { ParsedDocSummary } from '../../buildScripts/DataTypes.mjs' import { logError } from '@instructure/console' +import React from 'react' type AppContextType = { themeKey: keyof MainDocsData['themes'] @@ -106,6 +107,7 @@ class App extends Component { _mediaQueryListener?: ReturnType _defaultDocumentTitle?: string _controller?: AbortController + _heroRef: React.RefObject constructor(props: AppProps) { super(props) @@ -127,6 +129,8 @@ class App extends Component { versionsData: undefined, iconsData: null } + + this._heroRef = React.createRef() } fetchDocumentData = async (docId: string) => { @@ -487,6 +491,7 @@ class App extends Component { repository={library.repository} version={library.version} layout={layout} + ref={this._heroRef} /> ) @@ -691,6 +696,10 @@ class App extends Component { ) : null } + focusMainContent = () => { + this._heroRef.current?.focusMainContentHeading() + } + render() { const key = this.state.key const { showMenu, layout, docsData, iconsData } = this.state @@ -717,6 +726,18 @@ class App extends Component { aria-label={key || docsData.library.name} ref={this.handleContentRef} > + + Skip to main content + {!showMenu && (
diff --git a/packages/__docs__/src/App/props.ts b/packages/__docs__/src/App/props.ts index 55923403e3..c3de7202b2 100644 --- a/packages/__docs__/src/App/props.ts +++ b/packages/__docs__/src/App/props.ts @@ -51,6 +51,7 @@ type AppStyle = ComponentStyle< | 'hamburger' | 'inlineNavigation' | 'globalStyles' + | 'skipToMainButton' > type AppTheme = { diff --git a/packages/__docs__/src/App/styles.ts b/packages/__docs__/src/App/styles.ts index 1a04a3be9d..eb1eb09191 100644 --- a/packages/__docs__/src/App/styles.ts +++ b/packages/__docs__/src/App/styles.ts @@ -76,6 +76,21 @@ const generateStyle = (componentTheme: AppTheme): AppStyle => { borderInlineEndWidth: componentTheme.navBorderWidth, borderInlineEndStyle: 'solid' }, + skipToMainButton: { + label: 'skipToMainButton', + position: 'absolute', + left: '-9999px', + zIndex: 999, + marginTop: '6px', + opacity: 0, + height: '60px', + fontSize: '150%', + '&:focus': { + left: '11.5rem', + transform: 'translateX(-50%)', + opacity: 1 + } + }, globalStyles: { html: { height: '100%', diff --git a/packages/__docs__/src/Hero/index.tsx b/packages/__docs__/src/Hero/index.tsx index ba936edfe0..03f7b1949f 100644 --- a/packages/__docs__/src/Hero/index.tsx +++ b/packages/__docs__/src/Hero/index.tsx @@ -52,6 +52,7 @@ import { Heading } from '../Heading' import type { HeroProps } from './props' import { propTypes, allowedProps } from './props' +import React from 'react' @withStyle(generateStyle, generateComponentTheme) class Hero extends Component { @@ -61,6 +62,8 @@ class Hero extends Component { docs: null } + _mainContentHeading?: HTMLElement + componentDidMount() { this.props.makeStyles?.() } @@ -69,6 +72,16 @@ class Hero extends Component { this.props.makeStyles?.() } + mainContentHeadingRef = (el: Element | null) => { + this._mainContentHeading = el as HTMLElement + } + + focusMainContentHeading = () => { + if (this._mainContentHeading) { + this._mainContentHeading.focus() + } + } + render() { const { version, layout, styles } = this.props @@ -192,7 +205,13 @@ class Hero extends Component { const heroBodyContent = ( - + Components everyone can count on