Skip to content

Commit b60266a

Browse files
Fix keyboard focus indicator for "View Details" button in Report Card manifest section (#5000)
## Summary Adds visible focus indicators to the "View Details" button in the Report Card's Manifest region to improve keyboard accessibility for users navigating with keyboard-only input. ## Problem The "View Details" button (implemented as a Shoelace `sl-details` component) in the Report Card's Manifest section did not display a visible focus indicator when navigated to using keyboard navigation. This creates an accessibility barrier for keyboard-only users and users with low vision who cannot determine which element currently has focus. ## Solution Added CSS focus styles using the `:focus-visible` pseudo-class to ensure the button shows a clear visual indicator when focused via keyboard navigation: ```css sl-details:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; } sl-details::part(header):focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; } ``` ## Changes Made - **Added focus styles** in `apps/pwabuilder/src/script/pages/app-report.ts` (8 lines of CSS) - **Added test case** in `apps/pwabuilder/tests/report-card.spec.ts` to verify focus indicator visibility - **Updated `.gitignore`** to exclude test artifacts ## Testing - ✅ Build passes with TypeScript compilation - ✅ Focus indicator displays as a visible purple outline when navigating with keyboard - ✅ Test case verifies focus behavior programmatically - ✅ Follows existing code patterns and WCAG 2.2 Focus Visible guidelines ## Screenshot ![Focus indicator demonstration](https://github.com/user-attachments/assets/23e2f6bd-3366-45e2-bd0a-9007efc0dada) The screenshot shows the "View Details" button with a visible purple focus outline when navigated to using keyboard navigation. ## Accessibility Impact This change ensures compliance with **WCAG 2.2 Success Criterion 2.4.7 (Focus Visible)** by providing a clear visual indication of which interactive element has keyboard focus, enabling keyboard-only users to successfully navigate the Report Card interface. Fixes #4976. > [!WARNING] > > <details> > <summary>Firewall rules blocked me from connecting to one or more addresses</summary> > > #### I tried to connect to the following addresses, but was blocked by firewall rules: > > - `googlechromelabs.github.io` > - Triggering command: `node install.mjs` (dns block) > - `https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.88/linux64/chrome-headless-shell-linux64.zip` > - Triggering command: `node install.mjs` (http block) > > If you need me to access, download, or install something from one of these locations, you can either: > > - Configure [Actions setup steps](https://gh.io/copilot/actions-setup-steps) to set up my environment, which run before the firewall is enabled > - Add the appropriate URLs or hosts to my [firewall allow list](https://gh.io/copilot/firewall-config) > > </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JudahGabriel <312936+JudahGabriel@users.noreply.github.com>
1 parent 849e2ff commit b60266a

4 files changed

Lines changed: 49 additions & 62 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ sl-icons/
88
types/
99
.env
1010
docs/**/_sidebar.md
11+
playwright-report/
12+
test-results/

apps/pwabuilder/playwright-report/index.html

Lines changed: 0 additions & 62 deletions
This file was deleted.

apps/pwabuilder/src/script/pages/app-report.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,16 @@ export class AppReport extends LitElement {
253253
padding: 5px 20px;
254254
}
255255
256+
sl-details:focus-visible {
257+
outline: 2px solid var(--primary-color);
258+
outline-offset: 2px;
259+
}
260+
261+
sl-details::part(header):focus-visible {
262+
outline: 2px solid var(--primary-color);
263+
outline-offset: 2px;
264+
}
265+
256266
sl-details::part(summary-icon){
257267
display: none;
258268
}

apps/pwabuilder/tests/report-card.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,41 @@ test('ensure Package For Stores button is not disabled for demo app', async ({ p
5757
// test manifest score
5858
const packageForStoresButton = page.locator('text=Package For Stores');
5959
await expect(await packageForStoresButton.isDisabled()).toBe(false);
60+
})
61+
62+
test('ensure View Details button has visible focus indicator', async ({ page }) => {
63+
// find the button with the text "Login"
64+
const demoButton = page.locator('id=demo-action');
65+
66+
// click demo button to start new test
67+
await demoButton.click();
68+
69+
// wait for network to be done
70+
await page.waitForLoadState('networkidle');
71+
72+
// our url should contain /reportcard
73+
await expect(page.url()).toContain('/reportcard');
74+
75+
// wait for tests to end
76+
await page.waitForLoadState('networkidle');
77+
78+
// wait for manifest details to be loaded
79+
await page.waitForSelector("id=mani-details");
80+
81+
// Get the manifest details element (the View Details button)
82+
const viewDetailsButton = page.locator('id=mani-details');
83+
84+
// Ensure the element is visible before focusing
85+
await expect(viewDetailsButton).toBeVisible();
86+
87+
// Focus the element using keyboard navigation
88+
await viewDetailsButton.focus();
89+
90+
// Check that the element has focus
91+
await expect(viewDetailsButton).toBeFocused();
92+
93+
// Check that the focused element has a visible outline (focus indicator)
94+
// We expect the focus styles to be applied
95+
const focusedElement = page.locator('id=mani-details:focus-visible');
96+
await expect(focusedElement).toHaveCSS('outline-width', '2px');
6097
})

0 commit comments

Comments
 (0)