Skip to content

Commit f8ab6cb

Browse files
authored
fix(ui): reduce cls to 0 on package page (#1304)
1 parent e4c6642 commit f8ab6cb

File tree

7 files changed

+159
-155
lines changed

7 files changed

+159
-155
lines changed

.lighthouserc.cjs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,18 @@ module.exports = {
3535
chromePath: findChrome(),
3636
puppeteerScript: './lighthouse-setup.cjs',
3737
settings: {
38-
onlyCategories: ['accessibility'],
38+
onlyCategories: process.env.LH_PERF ? ['performance'] : ['accessibility'],
3939
skipAudits: ['valid-source-maps'],
4040
},
4141
},
4242
assert: {
43-
assertions: {
44-
'categories:accessibility': ['error', { minScore: 1 }],
45-
},
43+
assertions: process.env.LH_PERF
44+
? {
45+
'cumulative-layout-shift': ['error', { maxNumericValue: 0 }],
46+
}
47+
: {
48+
'categories:accessibility': ['error', { minScore: 1 }],
49+
},
4650
},
4751
upload: {
4852
target: 'temporary-public-storage',

CONTRIBUTING.md

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ This focus helps guide our project decisions as a community and what we choose t
5454
- [Unit tests](#unit-tests)
5555
- [Component accessibility tests](#component-accessibility-tests)
5656
- [Lighthouse accessibility tests](#lighthouse-accessibility-tests)
57+
- [Lighthouse performance tests](#lighthouse-performance-tests)
5758
- [End to end tests](#end-to-end-tests)
5859
- [Test fixtures (mocking external APIs)](#test-fixtures-mocking-external-apis)
5960
- [Submitting changes](#submitting-changes)
@@ -114,6 +115,7 @@ pnpm test:unit # Unit tests only
114115
pnpm test:nuxt # Nuxt component tests
115116
pnpm test:browser # Playwright E2E tests
116117
pnpm test:a11y # Lighthouse accessibility audits
118+
pnpm test:perf # Lighthouse performance audits (CLS)
117119
```
118120

119121
### Project structure
@@ -641,18 +643,38 @@ pnpm test:a11y:prebuilt
641643

642644
# Or run a single color mode manually
643645
pnpm build:test
644-
LIGHTHOUSE_COLOR_MODE=dark ./scripts/lighthouse-a11y.sh
646+
LIGHTHOUSE_COLOR_MODE=dark ./scripts/lighthouse.sh
645647
```
646648

647649
This requires Chrome or Chromium to be installed. The script will auto-detect common installation paths. Results are printed to the terminal and saved in `.lighthouseci/`.
648650

649651
#### Configuration
650652

651-
| File | Purpose |
652-
| ---------------------------- | --------------------------------------------------------- |
653-
| `.lighthouserc.cjs` | Lighthouse CI config (URLs, assertions, Chrome path) |
654-
| `lighthouse-setup.cjs` | Puppeteer script for color mode + client-side API mocking |
655-
| `scripts/lighthouse-a11y.sh` | Shell wrapper that runs the audit for a given color mode |
653+
| File | Purpose |
654+
| ----------------------- | --------------------------------------------------------- |
655+
| `.lighthouserc.cjs` | Lighthouse CI config (URLs, assertions, Chrome path) |
656+
| `lighthouse-setup.cjs` | Puppeteer script for color mode + client-side API mocking |
657+
| `scripts/lighthouse.sh` | Shell wrapper that runs the audit for a given color mode |
658+
659+
### Lighthouse performance tests
660+
661+
The project also runs Lighthouse performance audits to enforce zero Cumulative Layout Shift (CLS). These run separately from the accessibility audits and test the same set of URLs.
662+
663+
#### How it works
664+
665+
The same `.lighthouserc.cjs` config is shared between accessibility and performance audits. When the `LH_PERF` environment variable is set, the config switches from the `accessibility` category to the `performance` category and asserts that CLS is exactly 0.
666+
667+
#### Running locally
668+
669+
```bash
670+
# Build + run performance audit
671+
pnpm test:perf
672+
673+
# Or against an existing test build
674+
pnpm test:perf:prebuilt
675+
```
676+
677+
Unlike the accessibility audits, performance audits do not run in separate light/dark modes.
656678

657679
### End to end tests
658680

app/components/Package/WeeklyDownloadStats.vue

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ const config = computed(() => {
228228
>
229229
<span class="sr-only">{{ $t('package.downloads.analyze') }}</span>
230230
</ButtonBase>
231+
<span v-else-if="isLoadingWeeklyDownloads" class="min-w-6 min-h-6 -m-1 p-1" />
231232
</template>
232233

233234
<div class="w-full overflow-hidden">
@@ -240,26 +241,21 @@ const config = computed(() => {
240241
</template>
241242
</VueUiSparkline>
242243
<template #fallback>
243-
<!-- Skeleton matching sparkline layout: title row + chart with data label -->
244-
<div class="min-h-[75.195px]">
245-
<!-- Title row: date range (24px height) -->
244+
<!-- Skeleton matching VueUiSparkline layout (title 24px + SVG aspect 500:80) -->
245+
<div class="max-w-xs">
246+
<!-- Title row: fontSize * 2 = 24px -->
246247
<div class="h-6 flex items-center ps-3">
247248
<SkeletonInline class="h-3 w-36" />
248249
</div>
249-
<!-- Chart area: data label left, sparkline right -->
250+
<!-- Chart area: matches SVG viewBox 500:80 -->
250251
<div class="aspect-[500/80] flex items-center">
251-
<!-- Data label (covers ~42% width) -->
252+
<!-- Data label (covers ~42% width, matching dataLabel.offsetX) -->
252253
<div class="w-[42%] flex items-center ps-0.5">
253254
<SkeletonInline class="h-7 w-24" />
254255
</div>
255-
<!-- Sparkline area (~58% width) -->
256-
<div class="flex-1 flex items-end gap-0.5 h-4/5 pe-3">
257-
<SkeletonInline
258-
v-for="i in 16"
259-
:key="i"
260-
class="flex-1 rounded-sm"
261-
:style="{ height: `${25 + ((i * 7) % 50)}%` }"
262-
/>
256+
<!-- Sparkline line placeholder -->
257+
<div class="flex-1 flex items-end pe-3">
258+
<SkeletonInline class="h-px w-full" />
263259
</div>
264260
</div>
265261
</div>

app/pages/about.vue

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@
22
const router = useRouter()
33
const canGoBack = useCanGoBack()
44
5-
interface GitHubContributor {
6-
login: string
7-
id: number
8-
avatar_url: string
9-
html_url: string
10-
contributions: number
11-
}
12-
135
useSeoMeta({
146
title: () => `${$t('about.title')} - npmx`,
157
ogTitle: () => `${$t('about.title')} - npmx`,
@@ -34,12 +26,7 @@ const pmLinks = {
3426
vlt: 'https://www.vlt.sh/',
3527
}
3628
37-
const { data: contributors, status: contributorsStatus } = useFetch<GitHubContributor[]>(
38-
'/api/contributors',
39-
{
40-
lazy: true,
41-
},
42-
)
29+
const { data: contributors, status: contributorsStatus } = useLazyFetch('/api/contributors')
4330
</script>
4431

4532
<template>

0 commit comments

Comments
 (0)