Files
documentation/node_modules/@docusaurus/theme-common/lib/utils/skipToContentUtils.js
2024-03-22 03:47:51 +05:30

75 lines
3.0 KiB
JavaScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, { useCallback, useRef } from 'react';
import { useHistory } from '@docusaurus/router';
import { translate } from '@docusaurus/Translate';
import { useLocationChange } from './useLocationChange';
/**
* The id of the element that should become focused on a page
* that does not have a <main> html tag.
* Focusing the Docusaurus Layout children is a reasonable fallback.
*
* __ prefix allows search crawlers (Algolia/DocSearch) to ignore anchors
* https://github.com/facebook/docusaurus/issues/8883#issuecomment-1516328368
*/
export const SkipToContentFallbackId = '__docusaurus_skipToContent_fallback';
/**
* Returns the skip to content element to focus when the link is clicked.
*/
function getSkipToContentTarget() {
return (
// Try to focus the <main> in priority
// Note: this will only work if JS is enabled
// See https://github.com/facebook/docusaurus/issues/6411#issuecomment-1284136069
document.querySelector('main:first-of-type') ??
// Then try to focus the fallback element (usually the Layout children)
document.getElementById(SkipToContentFallbackId));
}
function programmaticFocus(el) {
el.setAttribute('tabindex', '-1');
el.focus();
el.removeAttribute('tabindex');
}
/** This hook wires the logic for a skip-to-content link. */
function useSkipToContent() {
const containerRef = useRef(null);
const { action } = useHistory();
const onClick = useCallback((e) => {
e.preventDefault();
const targetElement = getSkipToContentTarget();
if (targetElement) {
programmaticFocus(targetElement);
}
}, []);
// "Reset" focus when navigating.
// See https://github.com/facebook/docusaurus/pull/8204#issuecomment-1276547558
useLocationChange(({ location }) => {
if (containerRef.current && !location.hash && action === 'PUSH') {
programmaticFocus(containerRef.current);
}
});
return { containerRef, onClick };
}
const DefaultSkipToContentLabel = translate({
id: 'theme.common.skipToMainContent',
description: 'The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation',
message: 'Skip to main content',
});
export function SkipToContentLink(props) {
const linkLabel = props.children ?? DefaultSkipToContentLabel;
const { containerRef, onClick } = useSkipToContent();
return (<div ref={containerRef} role="region" aria-label={DefaultSkipToContentLabel}>
{/* eslint-disable-next-line @docusaurus/no-html-links */}
<a {...props}
// Note this is a fallback href in case JS is disabled
// It has limitations, see https://github.com/facebook/docusaurus/issues/6411#issuecomment-1284136069
href={`#${SkipToContentFallbackId}`} onClick={onClick}>
{linkLabel}
</a>
</div>);
}
//# sourceMappingURL=skipToContentUtils.js.map