From e388aee29541fd6a2a6af02cc29e740e20582172 Mon Sep 17 00:00:00 2001 From: Ivan Demchenko <1846484+ivan-demchenko@users.noreply.github.com> Date: Mon, 4 Dec 2023 23:29:42 +0100 Subject: [PATCH] feat: adding a skip to search anchor (#850) Co-authored-by: Luke Karrys --- gatsby-browser.js | 8 +++++ src/components/skip-nav.js | 65 +++++++++++++++++++------------------- src/constants.js | 4 +++ src/page.js | 8 +++-- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/gatsby-browser.js b/gatsby-browser.js index 68c1c92ad04..12118ae9a49 100644 --- a/gatsby-browser.js +++ b/gatsby-browser.js @@ -1,3 +1,5 @@ +import {SKIP_TO_SEARCH_ID} from './src/constants' + export {default as wrapPageElement} from './src/page' export {default as wrapRootElement} from './src/root' @@ -5,3 +7,9 @@ export const shouldUpdateScroll = ({routerProps}) => { const {scrollUpdate = true} = routerProps.location.state ?? {} return scrollUpdate } + +export const onRouteUpdate = ({location, prevLocation}) => { + if (location.hash === `#${SKIP_TO_SEARCH_ID}` && prevLocation?.hash !== `#${SKIP_TO_SEARCH_ID}`) { + document.getElementById(SKIP_TO_SEARCH_ID)?.focus() + } +} diff --git a/src/components/skip-nav.js b/src/components/skip-nav.js index 90c17cd368c..aad78519a5a 100644 --- a/src/components/skip-nav.js +++ b/src/components/skip-nav.js @@ -1,49 +1,50 @@ import React from 'react' -import {Box} from '@primer/react' +import {Box, themeGet} from '@primer/react' import styled from 'styled-components' import Link from './link' -import {SCROLL_MARGIN_TOP} from '../constants' +import {SCROLL_MARGIN_TOP, SKIP_TO_CONTENT_ID} from '../constants' -const ID = 'skip-nav' - -const SkipLinkBase = props => ( - - Skip to content - -) +export const SkipLink = styled(Link)` + color: ${themeGet('colors.accent.emphasis')}; + padding: ${themeGet('space.1')}; + &:focus { + text-decoration: underline; + } +` // The following rules are to ensure that the element is visually hidden, unless // it has focus. This is the recommended way to hide content from: // https://webaim.org/techniques/css/invisiblecontent/#techniques -export const SkipLink = styled(SkipLinkBase)` +export const SkipBox = styled.div` + display: inline-flex; z-index: 20; - width: auto; - height: auto; - clip: auto; - position: absolute; - overflow: hidden; left: 10px; + gap: 3px; + position: absolute; + transform: translateY(-100%); + transition: transform 0.3s; + padding: ${themeGet('space.2')}; + background-color: ${themeGet('colors.canvas.default')}; + border: 1px solid ${themeGet('colors.accent.emphasis')}; + border-top: 0; + font-size: ${themeGet('fontSizes.1')}; + border-radius: 0 0 ${themeGet('radii.2')} ${themeGet('radii.2')}; + + + &:focus-within { + transform: translateY(0%); + } + + & > * { + margin-right: ${themeGet('space.1')}; + } - &:not(:focus) { - clip: rect(1px, 1px, 1px, 1px); - clip-path: inset(50%); - height: 1px; - width: 1px; - margin: -1px; - padding: 0; + & > *:last-child { + margin-right: 0; } ` -const SkipNavBase = props => +const SkipNavBase = props => export const SkipNav = styled(SkipNavBase)` scroll-margin-top: ${SCROLL_MARGIN_TOP}px; diff --git a/src/constants.js b/src/constants.js index 48e2adb767f..70b9ad1adfb 100644 --- a/src/constants.js +++ b/src/constants.js @@ -6,4 +6,8 @@ export const FULL_HEADER_HEIGHT = HEADER_HEIGHT + HEADER_BAR export const SCROLL_MARGIN_TOP = FULL_HEADER_HEIGHT + 24 +export const SKIP_TO_CONTENT_ID = 'skip-to-content' + +export const SKIP_TO_SEARCH_ID = 'search-box-input' + export const CLI_PATH = '/cli' diff --git a/src/page.js b/src/page.js index ceded6c5839..d67e6c225ab 100644 --- a/src/page.js +++ b/src/page.js @@ -4,7 +4,8 @@ import {createGlobalStyle} from 'styled-components' import Slugger from 'github-slugger' import Header from './components/header' import Sidebar from './components/sidebar' -import {SkipLink} from './components/skip-nav' +import {SkipBox, SkipLink} from './components/skip-nav' +import {SKIP_TO_CONTENT_ID, SKIP_TO_SEARCH_ID} from './constants' import {PageProvider} from './hooks/use-page' import Layout from './layout' @@ -27,7 +28,10 @@ const PageElement = ({element, props}) => { return ( - + + Skip to search + Skip to content +