feat: image variants per image

This commit is contained in:
fsylvain committed 2026-10-08 19:57:51 +02:00
1 parent f567866161
commit 951fef18ba
92 files changed
+8695 -413

No files matched your search

+44 -4
View File
@@ -6,7 +6,7 @@ import { build, preview } from 'vite'
import { chromium, type Browser, type BrowserContext, type Page } from 'playwright'
import { icons as lucide } from '@iconify-json/lucide'
import { getIconData, getIcons, iconToHTML, iconToSVG, replaceIDs } from '@iconify/utils'
import { visualStates, type ApiMock, type VisualState } from './states'
import { visualStates, type ApiMock, type DiffException, type VisualState } from './states'
type Viewport = 'desktop' | 'mobile'
type Theme = 'light' | 'dark'
@@ -151,6 +151,17 @@ const settleMs = 400
const diffThreshold = 24
const maxDiffPercent = 10
function budgetFor(cap: DiffException['maxPercent'] | undefined, viewport: Viewport) {
if (cap === undefined) {
return maxDiffPercent
}
return typeof cap === 'number' ? cap : cap[viewport]
}
function describeCap(cap: DiffException['maxPercent']) {
return typeof cap === 'number' ? `${cap}%` : `${cap.desktop}% desktop, ${cap.mobile}% mobile`
}
function slug(text: string) {
return text
.toLowerCase()
@@ -239,11 +250,40 @@ function variantsScreen(): Screen {
alias: numberedStates('2', formNames),
},
]
const libraryNames = [
'3a · Grid with badges',
'3b · Sort menu',
'3c · Filter: With variants, sorted by total size',
'3d · Filter: Without variants',
'3e · Filter: nothing to show',
'3f · Delete confirm',
]
const detailNames = [
'4a · Partly generated',
'4b · Nothing generated yet',
'4c · Generating',
'4d · Generation failed',
'4e · No variants defined',
'4f · Source is an SVG',
'4h · Preview dialog',
]
const editorNames = [
'6a · Variant select',
'6b · Select open',
'6c · No variants defined',
'6d · Variant deleted',
'6e · Variant disabled',
]
sources.push(
{ board: variantsBoard, group: 'Media library', states: libraryNames, alias: {} },
{ board: variantsBoard, group: 'Image detail', states: detailNames, alias: {} },
{ board: variantsBoard, group: 'Editor picker', states: editorNames, alias: {} },
)
return {
name: 'image-variants',
board: variantsBoard,
group: 'Variants list',
states: [...listNames, ...formNames],
states: [...listNames, ...formNames, ...libraryNames, ...detailNames, ...editorNames],
sources,
}
}
@@ -686,7 +726,7 @@ async function main() {
)
const result = await diff(browser, designPath, appPath, diffPath)
const percent = result.ratio * 100
const budget = setup.exception?.maxPercent ?? maxDiffPercent
const budget = budgetFor(setup.exception?.maxPercent, viewport)
const problems = [
...(percent > budget
? [`${percent.toFixed(2)}% exceeds ${budget}% budget`]
@@ -700,7 +740,7 @@ async function main() {
failures++
}
const exception = setup.exception
? ` [exception ${setup.exception.maxPercent}% approved by ${setup.exception.approvedBy}: ${setup.exception.reason}]`
? ` [exception ${describeCap(setup.exception.maxPercent)} approved by ${setup.exception.approvedBy}: ${setup.exception.reason}]`
: ''
lines.push(
`${problems.length ? 'FAIL' : 'PASS'} ${state} · ${viewport} · ${theme}: ${percent.toFixed(2)}% pixels differ → ${relative(repoRoot, directory)}${problems.length ? ` (${problems.join('; ')})` : ''}${exception}`,