ae6db7e16f
Onboarding asks explicitly for one or two parents and shows one card per parent for balances; the balance form is per parent with inline validation; the partner can be filled from the FK deduction or added from it. Settings and Dashboard reuse the same form. CSS: bare buttons carry no colour any more; buttons, cards, choice cards, fields, alerts, badges, eyebrow and modal chrome are defined once in primitives.css. Media queries live only in responsive.css. A style guard test blocks hex, !important and stray media queries. Bilingual fixes: calendar selects size by content, header no longer wraps. Vitest is capped at four workers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
49 lines
2.1 KiB
TypeScript
49 lines
2.1 KiB
TypeScript
/**
|
|
* Regression for a specificity bug: `.header__nav-link:hover` (a class +
|
|
* pseudo-class, specificity (0,2,0)) outranked `.header__nav-link--active`
|
|
* (a single class, (0,1,0)), so hovering the *active* tab kept the active
|
|
* rule's white (`--c-surface`) text but reverted the background to the
|
|
* hover rule's `--c-bg` — near-white text on a near-white background.
|
|
* `.header__nav-link[aria-current='page']:hover` now wins on specificity
|
|
* (attribute selector + pseudo-class, (0,2,0)) over the plain hover rule,
|
|
* and repaints the background with `--c-accent-hover` so the surface-coloured
|
|
* text stays readable. The active state is marked by `aria-current="page"`
|
|
* (set automatically by react-router-dom when the route matches). See `header.css`.
|
|
*/
|
|
import { test, expect, type Page } from '@playwright/test'
|
|
|
|
/**
|
|
* Resolves a CSS custom property (declared on :root in styles/global.css) to
|
|
* the computed `rgb(...)` string the browser would report for an element
|
|
* actually painted with it — see the identical helper (and its rationale)
|
|
* in `red-days.spec.ts`.
|
|
*/
|
|
async function resolveCssVar(page: Page, varName: string): Promise<string> {
|
|
return page.evaluate((name) => {
|
|
const probe = document.createElement('div')
|
|
probe.style.backgroundColor = `var(${name})`
|
|
probe.style.color = `var(${name})`
|
|
document.body.appendChild(probe)
|
|
const style = getComputedStyle(probe)
|
|
const resolved = style.backgroundColor
|
|
probe.remove()
|
|
return resolved
|
|
}, varName)
|
|
}
|
|
|
|
test.describe('header nav — active tab stays readable on hover', () => {
|
|
test('hovering the active nav link keeps the text readable', async ({ page }) => {
|
|
await page.goto('/')
|
|
const activeLink = page.getByTestId('header-nav').getByRole('link', { name: 'Översikt' })
|
|
await expect(activeLink).toHaveAttribute('aria-current', 'page')
|
|
|
|
const accentHover = await resolveCssVar(page, '--c-accent-hover')
|
|
const surface = await resolveCssVar(page, '--c-surface')
|
|
|
|
await activeLink.hover()
|
|
|
|
await expect(activeLink).toHaveCSS('background-color', accentHover)
|
|
await expect(activeLink).toHaveCSS('color', surface)
|
|
})
|
|
})
|