Skip to content

Commit

Permalink
a11y: Standardize copy button announcement (#52229)
Browse files Browse the repository at this point in the history
  • Loading branch information
hectorsector authored Sep 5, 2024
1 parent e114494 commit 82923e2
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 14 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
"@octokit/request-error": "6.1.1",
"@primer/behaviors": "^1.7.0",
"@primer/css": "^21.3.1",
"@primer/live-region-element": "^0.7.0",
"@primer/octicons": "^19.11.0",
"@primer/octicons-react": "^19.11.0",
"@primer/react": "36.27.0",
Expand Down
4 changes: 4 additions & 0 deletions src/content-render/stylesheets/annotate.scss
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,7 @@
.subnav-item[aria-current]:not([aria-current="false"]) {
z-index: 0;
}

button.js-btn-copy.copied::after {
content: "Copied!";
}
2 changes: 1 addition & 1 deletion src/content-render/tests/__snapshots__/annotate.js.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`annotate > renders annotations 1`] = `
"<div class="annotate beside"><div class="annotate-header"><header class="d-flex flex-items-center flex-justify-between p-2 text-small rounded-top-1 border-top border-left border-right"><span class="flex-1">YAML</span><div class="annotate-toggle"><button name="annotate-display" value="beside" type="button" class="annotate-option">Beside</button><button name="annotate-display" value="inline" type="button" class="annotate-option">Inline</button></div><button class="js-btn-copy btn btn-sm tooltipped tooltipped-nw" aria-label="Copy YAML code to clipboard" data-clipboard="1746955726" aria-live="polite" aria-atomic="true"><svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-copy" aria-hidden="true"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><pre hidden data-clipboard="1746955726"># The name of the workflow as it will appear in the "Actions" tab of the GitHub repository.
"<div class="annotate beside"><div class="annotate-header"><header class="d-flex flex-items-center flex-justify-between p-2 text-small rounded-top-1 border-top border-left border-right"><span class="flex-1">YAML</span><div class="annotate-toggle"><button name="annotate-display" value="beside" type="button" class="annotate-option">Beside</button><button name="annotate-display" value="inline" type="button" class="annotate-option">Inline</button></div><button class="js-btn-copy btn btn-sm tooltipped tooltipped-nw" aria-label="Copy YAML code to clipboard" data-clipboard="1746955726"><svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-copy" aria-hidden="true"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><pre hidden data-clipboard="1746955726"># The name of the workflow as it will appear in the "Actions" tab of the GitHub repository.
name: Post welcome comment
# Add the \`pull_request\` event, so that the workflow runs automatically
Expand Down
2 changes: 0 additions & 2 deletions src/content-render/unified/code-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ export function header(lang, code, subnav) {
class: ['js-btn-copy', 'btn', 'btn-sm', 'tooltipped', 'tooltipped-nw'],
'aria-label': `Copy ${languages[lang]?.name} code to clipboard`,
'data-clipboard': codeId,
'aria-live': 'polite',
'aria-atomic': 'true',
},
btnIcon(),
),
Expand Down
9 changes: 6 additions & 3 deletions src/frame/components/lib/copy-code.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { announce } from '@primer/live-region-element'

export default function copyCode() {
const buttons = Array.from(document.querySelectorAll('button.js-btn-copy'))

Expand All @@ -13,11 +15,12 @@ export default function copyCode() {
if (!text) return
await navigator.clipboard.writeText(text)

const beforeTooltip = button.getAttribute('aria-label') || ''
button.setAttribute('aria-label', 'Copied!')
button.classList.add('copied')

announce('Copied!')

setTimeout(() => {
button.setAttribute('aria-label', beforeTooltip)
button.classList.remove('copied')
}, 2000)
}),
)
Expand Down
14 changes: 6 additions & 8 deletions src/rest/components/RestCodeSamples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState, useEffect, useRef, FormEvent } from 'react'
import { FormControl, Select, TabNav } from '@primer/react'
import { Tooltip } from '@primer/react/next'
import { CheckIcon, CopyIcon } from '@primer/octicons-react'
import { announce } from '@primer/live-region-element'
import Cookies from 'src/frame/components/lib/cookies'
import cx from 'classnames'

Expand Down Expand Up @@ -288,14 +289,11 @@ export function RestCodeSamples({ operation, slug, heading }: Props) {
>
<button
className="js-btn-copy btn-octicon"
aria-label={
isCopied
? t('button_text.copied')
: `${t('button_text.copy_to_clipboard')} ${selectedLanguage} request example`
}
aria-live="polite"
aria-atomic="true"
onClick={() => setCopied()}
aria-label={`${t('button_text.copy_to_clipboard')} ${selectedLanguage} request example`}
onClick={() => {
setCopied()
announce('Copied!')
}}
>
{isCopied ? <CheckIcon /> : <CopyIcon />}
</button>
Expand Down

0 comments on commit 82923e2

Please sign in to comment.