зеркало из https://github.com/github/docs.git
hovercard masc update (#52420)
This commit is contained in:
Родитель
ec66700365
Коммит
63e9b88c1f
|
@ -262,7 +262,6 @@ scroll_button:
|
|||
scroll_to_top: Scroll to top
|
||||
popovers:
|
||||
role_description: hovercard link
|
||||
keyboard_shortcut_description: Press alt+up to activate
|
||||
alerts:
|
||||
NOTE: Note
|
||||
IMPORTANT: Important
|
||||
|
|
|
@ -262,7 +262,6 @@ scroll_button:
|
|||
scroll_to_top: Scroll to top
|
||||
popovers:
|
||||
role_description: hovercard link
|
||||
keyboard_shortcut_description: Press alt+up to activate
|
||||
alerts:
|
||||
NOTE: Note
|
||||
IMPORTANT: Important
|
||||
|
|
|
@ -286,16 +286,27 @@ test.describe('hover cards', () => {
|
|||
).not.toBeVisible()
|
||||
})
|
||||
|
||||
test('internal links get a aria-roledescription and aria-describedby', async ({ page }) => {
|
||||
test('able to use Esc to close hovercard', async ({ page }) => {
|
||||
await page.goto('/pages/quickstart')
|
||||
const link = page.locator('#article-contents').getByRole('link', { name: 'Start your journey' })
|
||||
await expect(link).toHaveAttribute('aria-roledescription', 'hovercard link')
|
||||
|
||||
// The link gets a `aria-describedby="...ID..."` attribute that points to
|
||||
// another element in the DOM that has the description text.
|
||||
const id = 'popover-describedby'
|
||||
await expect(link).toHaveAttribute('aria-describedby', id)
|
||||
await expect(page.locator(`#${id}`)).toHaveText('Press alt+up to activate')
|
||||
// hover over a link and check for intro content from hovercard
|
||||
await page
|
||||
.locator('#article-contents')
|
||||
.getByRole('link', { name: 'Start your journey' })
|
||||
.hover()
|
||||
await expect(
|
||||
page.getByText(
|
||||
'Get started using HubGit to manage Git repositories and collaborate with others.',
|
||||
),
|
||||
).toBeVisible()
|
||||
|
||||
// click the Esc key to close the hovercard
|
||||
await page.keyboard.press('Escape')
|
||||
await expect(
|
||||
page.getByText(
|
||||
'Get started using GitHub to manage Git repositories and collaborate with others.',
|
||||
),
|
||||
).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { useEffect } from 'react'
|
||||
import { useTranslation } from 'src/languages/components/useTranslation'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
// We postpone the initial delay a bit in case the user didn't mean to
|
||||
// hover over the link. Perhaps they just dragged the mouse over on their
|
||||
|
@ -36,14 +34,6 @@ let currentlyOpen: HTMLLinkElement | null = null
|
|||
// change according to the popover's true height. But this can cause a flicker.
|
||||
const BOUNDING_TOP_MARGIN = 300
|
||||
|
||||
// All links that should have a hover card also get a
|
||||
// `aria-describedby="..."`. That ID is used to look up another DOM
|
||||
// element, that has a `visually-hidden` class. The value if the ID
|
||||
// isn't very important as long as it connects.
|
||||
// Note; at the moment this value is duplicated in the Playwright
|
||||
// tests because of trying to extract the value of `aria-describedby`.
|
||||
const DESCRIBEDBY_ELEMENT_ID = 'popover-describedby'
|
||||
|
||||
// used to identify the first focusable element in the hover card
|
||||
const FIRST_LINK_ID = '_hc_first_focusable'
|
||||
const TITLE_ID = '_hc_title'
|
||||
|
@ -70,7 +60,7 @@ function getOrCreatePopoverGlobal() {
|
|||
|
||||
// Semantics for the hovercard so SR users are aware they're about to be
|
||||
// focus trapped
|
||||
wrapper.setAttribute('role', 'dialog')
|
||||
wrapper.setAttribute('role', 'region')
|
||||
wrapper.setAttribute('aria-modal', 'true')
|
||||
wrapper.setAttribute('aria-label', 'user hovercard')
|
||||
wrapper.setAttribute('aria-labelledby', TITLE_ID)
|
||||
|
@ -202,28 +192,6 @@ function getOrCreatePopoverGlobal() {
|
|||
return popoverGlobal
|
||||
}
|
||||
|
||||
function getOrCreateDescribeByElement() {
|
||||
let element = document.querySelector<HTMLParagraphElement>(`#${DESCRIBEDBY_ELEMENT_ID}`)
|
||||
if (!element) {
|
||||
element = document.createElement('p')
|
||||
element.id = DESCRIBEDBY_ELEMENT_ID
|
||||
element.classList.add('visually-hidden')
|
||||
// "All page content should be contained by landmarks"
|
||||
// https://dequeuniversity.com/rules/axe/4.7/region
|
||||
// The element that we use for the `aria-describedby` attribute
|
||||
// needs to exist in the DOM inside a landmark. For example
|
||||
// `<div role="footer">`. In our case we use our
|
||||
// `<main id="main-content">` element.
|
||||
// We "know" that this querySelector() query will always find a
|
||||
// valid element, but it's theoretically not perfectly true, so we have to
|
||||
// use a fallback.
|
||||
const main = document.querySelector<HTMLDivElement>('main') || document.body
|
||||
main.appendChild(element)
|
||||
}
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
function popoverWrap(element: HTMLLinkElement, filledCallback?: (popover: HTMLDivElement) => void) {
|
||||
if (element.parentElement && element.parentElement.classList.contains('Popover')) {
|
||||
return
|
||||
|
@ -474,16 +442,6 @@ function popoverHide() {
|
|||
let lastFocussedLink: HTMLLinkElement | null = null
|
||||
|
||||
export function LinkPreviewPopover() {
|
||||
const { t } = useTranslation('popovers')
|
||||
const { locale } = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
const element = getOrCreateDescribeByElement()
|
||||
if (element) {
|
||||
element.textContent = t('keyboard_shortcut_description')
|
||||
}
|
||||
}, [locale])
|
||||
|
||||
// This is to track if the user entirely tabs out of the window.
|
||||
// For example if they go to the address bar.
|
||||
useEffect(() => {
|
||||
|
@ -587,13 +545,6 @@ export function LinkPreviewPopover() {
|
|||
link.addEventListener('mouseover', showPopover)
|
||||
link.addEventListener('mouseout', hidePopover)
|
||||
link.addEventListener('keydown', keyboardHandler)
|
||||
|
||||
if (!link.getAttribute('aria-roledescription')) {
|
||||
link.setAttribute('aria-roledescription', t('role_description'))
|
||||
}
|
||||
if (!link.getAttribute('aria-describedby')) {
|
||||
link.setAttribute('aria-describedby', DESCRIBEDBY_ELEMENT_ID)
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', escapeHandler)
|
||||
|
|
Загрузка…
Ссылка в новой задаче