diff --git a/.changeset/lovely-yaks-obey.md b/.changeset/lovely-yaks-obey.md new file mode 100644 index 0000000000..ce72c1c722 --- /dev/null +++ b/.changeset/lovely-yaks-obey.md @@ -0,0 +1,5 @@ +--- +"astro": minor +--- + +Add a UI showing the list of found problems when using the audit app in the dev toolbar diff --git a/packages/astro/e2e/dev-toolbar.test.js b/packages/astro/e2e/dev-toolbar.test.js index 798e734618..3060b6050d 100644 --- a/packages/astro/e2e/dev-toolbar.test.js +++ b/packages/astro/e2e/dev-toolbar.test.js @@ -130,6 +130,23 @@ test.describe('Dev Toolbar', () => { await expect(auditWindow.locator('astro-dev-toolbar-icon[icon=check-circle]')).toBeVisible(); }); + test('audit shows a window with list of problems', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const toolbar = page.locator('astro-dev-toolbar'); + const appButton = toolbar.locator('button[data-app-id="astro:audit"]'); + await appButton.click(); + + const auditCanvas = toolbar.locator('astro-dev-toolbar-app-canvas[data-app-id="astro:audit"]'); + const auditWindow = auditCanvas.locator('astro-dev-toolbar-window'); + await expect(auditWindow).toHaveCount(1); + await expect(auditWindow).toBeVisible(); + + // Toggle app off + await appButton.click(); + await expect(auditWindow).not.toBeVisible(); + }); + test('adjusts tooltip position if off-screen', async ({ page, astro }) => { await page.goto(astro.resolveUrl('/tooltip-position')); diff --git a/packages/astro/package.json b/packages/astro/package.json index 71ae3e310d..ed65b99cff 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -124,6 +124,7 @@ "@babel/plugin-transform-react-jsx": "^7.22.5", "@babel/traverse": "^7.23.3", "@babel/types": "^7.23.3", + "@medv/finder": "^3.1.0", "@types/babel__core": "^7.20.4", "acorn": "^8.11.2", "aria-query": "^5.3.0", diff --git a/packages/astro/src/runtime/client/dev-toolbar/apps/audit/index.ts b/packages/astro/src/runtime/client/dev-toolbar/apps/audit/index.ts index 7ece328502..dfaa7dc88d 100644 --- a/packages/astro/src/runtime/client/dev-toolbar/apps/audit/index.ts +++ b/packages/astro/src/runtime/client/dev-toolbar/apps/audit/index.ts @@ -8,6 +8,7 @@ import { } from '../utils/highlight.js'; import { createWindowElement } from '../utils/window.js'; import { a11y } from './a11y.js'; +import { finder } from '@medv/finder'; import { perf } from './perf.js'; const icon = @@ -60,7 +61,11 @@ export default { name: 'Audit', icon: icon, async init(canvas, eventTarget) { - let audits: { highlightElement: DevToolbarHighlight; auditedElement: HTMLElement }[] = []; + let audits: { + highlightElement: DevToolbarHighlight; + auditedElement: HTMLElement; + rule: AuditRule; + }[] = []; await lint(); @@ -126,6 +131,119 @@ export default { }, }) ); + + const auditListWindow = createWindowElement( + ` + + +
+

Audits

+ ${audits.length} problem${ + audits.length > 1 ? 's' : '' + } found +
+
` + ); + + const auditListUl = document.createElement('ul'); + auditListUl.id = 'audit-list'; + audits.forEach((audit, index) => { + const resolvedRule = resolveAuditRule(audit.rule, audit.auditedElement); + const card = document.createElement('astro-dev-toolbar-card'); + + card.shadowRoot.innerHTML = ` + `; + + card.clickAction = () => { + audit.highlightElement.scrollIntoView(); + audit.highlightElement.focus(); + }; + const h3 = document.createElement('h3'); + h3.innerText = finder(audit.auditedElement); + card.appendChild(h3); + const div = document.createElement('div'); + const title = document.createElement('span'); + title.classList.add('audit-title'); + title.innerHTML = resolvedRule.title; + div.appendChild(title); + card.appendChild(div); + auditListUl.appendChild(card); + }); + + auditListWindow.appendChild(auditListUl); + + canvas.append(auditListWindow); } else { eventTarget.dispatchEvent( new CustomEvent('toggle-notification', { @@ -229,7 +347,11 @@ export default { attachTooltipToHighlight(highlight, tooltip, originalElement); canvas.append(highlight); - audits.push({ highlightElement: highlight, auditedElement: originalElement as HTMLElement }); + audits.push({ + highlightElement: highlight, + auditedElement: originalElement as HTMLElement, + rule: rule, + }); } function buildAuditTooltip(rule: AuditRule, element: Element) { diff --git a/packages/astro/src/runtime/client/dev-toolbar/ui-library/card.ts b/packages/astro/src/runtime/client/dev-toolbar/ui-library/card.ts index 7331a88b2a..6d1d5c381b 100644 --- a/packages/astro/src/runtime/client/dev-toolbar/ui-library/card.ts +++ b/packages/astro/src/runtime/client/dev-toolbar/ui-library/card.ts @@ -13,7 +13,7 @@ export class DevToolbarCard extends HTMLElement { connectedCallback() { const element = this.link ? 'a' : this.clickAction ? 'button' : 'div'; - this.shadowRoot.innerHTML = ` + this.shadowRoot.innerHTML += `