0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-27 22:19:04 -05:00

feat(audits): Add UI with list of audits (#10074)

* feat(audits): Add UI with list of audits

* style: slightly better UI

* requested design changes

* chore: changeset

* add test

* remove unwanted file
This commit is contained in:
Erika 2024-02-14 14:46:36 +01:00 committed by GitHub
parent 31de1ea8b8
commit 7443929381
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 155 additions and 3 deletions

View file

@ -0,0 +1,5 @@
---
"astro": minor
---
Add a UI showing the list of found problems when using the audit app in the dev toolbar

View file

@ -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'));

View file

@ -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",

View file

@ -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(
`
<style>
astro-dev-toolbar-window {
left: initial;
top: 8px;
right: 8px;
transform: none;
width: 320px;
max-height: 320px;
padding: 0;
overflow: hidden;
}
hr {
margin: 0;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 18px;
}
h1 {
font-size: 22px;
font-weight: 600;
color: #fff;
}
ul, li {
margin: 0;
padding: 0;
list-style: none;
}
h1, h2 {
margin: 0;
}
h3 {
margin: 0;
margin-bottom: 8px;
color: white;
white-space: nowrap;
}
.audit-title {
font-weight: bold;
color: white;
margin-right: 1ch;
}
#audit-list {
display: flex;
flex-direction: column;
overflow: auto;
}
</style>
<header>
<h1>Audits</h1>
<astro-dev-toolbar-badge size="large">${audits.length} problem${
audits.length > 1 ? 's' : ''
} found</astro-dev-toolbar-badge>
</header>
<hr />`
);
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 = `
<style>
:host>button {
text-align: left;
box-shadow: none !important;
${
index + 1 < audits.length
? 'border-radius: 0 !important;'
: 'border-radius: 0 0 8px 8px !important;'
}
}
:host>button:hover {
cursor: pointer;
}
</style>`;
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) {

View file

@ -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 += `
<style>
:host>a, :host>button, :host>div {
box-sizing: border-box;

7
pnpm-lock.yaml generated
View file

@ -524,6 +524,9 @@ importers:
'@babel/types':
specifier: ^7.23.3
version: 7.23.6
'@medv/finder':
specifier: ^3.1.0
version: 3.1.0
'@types/babel__core':
specifier: ^7.20.4
version: 7.20.5
@ -6831,6 +6834,10 @@ packages:
- supports-color
dev: false
/@medv/finder@3.1.0:
resolution: {integrity: sha512-ojkXjR3K0Zz3jnCR80tqPL+0yvbZk/lEodb6RIVjLz7W8RVA2wrw8ym/CzCpXO9SYVUIKHFUpc7jvf8UKfIM3w==}
dev: false
/@nanostores/preact@0.5.0(nanostores@0.9.5)(preact@10.19.3):
resolution: {integrity: sha512-Zq5DEAY+kIfwJ1NPd43D1mpsbISuiD6N/SuTHrt/8jUoifLwXaReaZMAnvkvbIGOgcB1Hy++A9jZix2taNNYxQ==}
engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}