diff --git a/docs/redesign/phase-2/TRACEABILITY.md b/docs/redesign/phase-2/TRACEABILITY.md index 97b960b..f7e4373 100644 --- a/docs/redesign/phase-2/TRACEABILITY.md +++ b/docs/redesign/phase-2/TRACEABILITY.md @@ -1,6 +1,6 @@ # Redesign traceability -Successor planning checkpoint: [Phase 3 impact matrix and architecture](../phase-3/PRESERVATION_IMPACT_MATRIX.md). It maps all 57 contracts to proposed destinations/validation, without changing their requirements or claiming implemented/visual parity. The subsequent [P4-01 trace sheet](../phase-4/p4-01/TRACEABILITY.md), [P4-02 named-control/modal record](../phase-4/p4-02/README.md), [P4-03 preview keyboard record](../phase-4/p4-03/README.md) and [P4-04 Settings layout/typography record](../phase-4/p4-04/README.md) link shared foundation changes to regression and representative visual evidence. P4-05 remains unstarted. +Successor planning checkpoint: [Phase 3 impact matrix and architecture](../phase-3/PRESERVATION_IMPACT_MATRIX.md). It maps all 57 contracts to proposed destinations/validation, without changing their requirements or claiming implemented/visual parity. The subsequent [P4-01 trace sheet](../phase-4/p4-01/TRACEABILITY.md), [P4-02 named-control/modal record](../phase-4/p4-02/README.md), [P4-03 preview keyboard record](../phase-4/p4-03/README.md), [P4-04 Settings layout/typography record](../phase-4/p4-04/README.md) and [P4-05 table/list density record](../phase-4/p4-05/README.md) link shared foundation changes to regression and representative visual evidence. P4-06 remains unstarted. Phase 2 starts at `2d0f131`. The [preservation matrix](PRESERVATION_MATRIX.md) is the stable baseline: **PRES-E01…PRES-A03**, in the original ledger's groups (not one contiguous numeric range). Old references such as C07 remain valid aliases. Subdivide a later workflow with a suffix, for example `PRES-C07.override-reset`; do not reuse an ID or silently change its meaning. diff --git a/docs/redesign/phase-4/README.md b/docs/redesign/phase-4/README.md index bd0980f..44f33bb 100644 --- a/docs/redesign/phase-4/README.md +++ b/docs/redesign/phase-4/README.md @@ -7,5 +7,6 @@ Phase 4 starts from `f696f23` on `codex/ui-redesign-phase4`. The 57 preservation - [P4-02 named controls and modal state](p4-02/README.md) - [P4-03 builder preview keyboard boundary](p4-03/README.md) - [P4-04 page layout and typography primitives](p4-04/README.md) +- [P4-05 table/list density contract](p4-05/README.md) -P4-02 is locally validated after `115441a` and the separate documentation restructure `682a302` on the same Phase 4 branch. P4-03 follows the P4-02 checkpoint `ebd4a3e`, adding preview keyboard access and preserving focused panes through viewport transitions. P4-04 follows `806eee4e`, introducing opt-in shared page/section typography and layout with Settings as the sole consumer. Its baseline is 916 backend / 348 frontend / 47 actual browser passes plus unchanged P2-D01 expected failure. P4-05 remains unstarted. No broader page migration, CV margin/template rendering correction, B07, backend/schema behaviour change or production deployment is included. F04 remains open pending actual production ingress evidence. +P4-02 is locally validated after `115441a` and the separate documentation restructure `682a302` on the same Phase 4 branch. P4-03 follows the P4-02 checkpoint `ebd4a3e`, adding preview keyboard access and preserving focused panes through viewport transitions. P4-04 follows `806eee4e`, introducing opt-in shared page/section typography and layout with Settings as the sole consumer. P4-05 follows `2cdcab9e`, adding opt-in Comfortable/Compact spacing to the existing Jobs/Trash table and phone cards. Its baseline is 916 backend / 354 frontend / 51 actual browser passes plus unchanged P2-D01 expected failure. P4-06 remains unstarted. No broader page migration, CV margin/template rendering correction, B07, backend/schema behaviour change or production deployment is included. F04 remains open pending actual production ingress evidence. diff --git a/docs/redesign/phase-4/p4-05/README.md b/docs/redesign/phase-4/p4-05/README.md new file mode 100644 index 0000000..21f535d --- /dev/null +++ b/docs/redesign/phase-4/p4-05/README.md @@ -0,0 +1,168 @@ +# P4-05 — Table/list density contract + +Implemented from `2cdcab9e2152f171a19cd0c9dd955bd16f5cc424` on `codex/ui-redesign-phase4`; final verification is recorded below. Scope: the [approved P4-05 slice](../../phase-3/PHASE4_IMPLEMENTATION_PLAN.md), not the Phase 5 Jobs redesign. F04 remains open; P4-06 and B07 are not started. + +## Consumer and preservation analysis before implementation + +Retain the existing `JobTable`: it already owns server sorting/paging/filtering, optional columns, selection, bulk and row actions, dedicated-workspace navigation and phone cards. Its existing Trash mode shares the same rendering and will receive the same density treatment, with restore semantics protected. No separate table framework, navigation or workflow change is required. + +Density is absent from existing account preferences and saved-view contracts. Introduce a typed, component-local Comfortable/Compact choice with Comfortable as default. It survives filtering, selection, paging and viewport changes while mounted; it resets on unmount/reload. It is deliberately not saved to storage, URLs, saved views or the API. Existing page-size/column preferences and account-scoped saved views remain independent. CV document density is a different contract. + +| PRES ID | Existing behavior retained | P4-05 change | Existing regression evidence | Added evidence | +|---|---|---|---|---| +| PRES-J05 | Search/filter, sort, page, columns, saved views, rows/cards | Opt-in shared spacing; local density selector | application-workspace-overlay, account-scoped-state, daily-control-loop; backend listing tests | Density changes retain query/selection/columns/page; both modes/locales/viewports | +| PRES-J06 | Status, edit, confirm delete, bulk, Trash/restore | Same controls with density-independent targets | confirm-flow; backend lifecycle/authorization tests | Row-action isolation, bulk/restore, native browser mutations | +| PRES-W01, PRES-W02 | Dedicated workspace and contextual workflow entry, return context | Preserve click/keyboard handlers; localize accessible row name | application-workspace-overlay, workflow-trust-signals, browser preservation | Link/action isolation; keyboard entry and focus | +| PRES-S03 | Independent page-size/column preferences | Density excluded from these settings | settings-view, page-layout preference case | Existing callbacks/paging unchanged | +| PRES-E08 | Language/theme/focus/error behavior | MUI semantic styling, EN/NB names | semantic-foundations, loaded-state and named-controls browser cases | Light/dark density/reflow/axe/focus evidence | +| PRES-E09 | Owner data and account-switch boundary | No storage or identity changes | account-scoped-state; B02 integration/browser regressions | Full inherited security regression | + +PRES-E07 shell and PRES-J07 board behavior are regression-only dependencies; their implementation is not changed. Unknown/custom status strings retain existing labels/tones; no new status configuration is introduced. Quick preview is a future requirement, not a currently mounted workflow to rebuild here. + +The existing App keeps the list mounted behind its dedicated workspace. Actual browser verification confirmed density survives opening a job and returning, along with the existing return focus and query. No route, router or application-shell code was changed to achieve this. Component unmount/reload still resets the provisional preference; the unit test explicitly proves the unmount boundary. + +## Implementation and files + +| File/component | Change | +|---|---| +| [theme.ts](../../../../job-tracker-ui/src/theme.ts) | Export the two-value `ContentDensity` type; opt-in spacing/target aliases under MUI `MuiCssBaseline`; existing `MuiTableCell` consumes cell padding with its original 10px fallback | +| [JobTable.tsx](../../../../job-tracker-ui/src/components/JobTable.tsx) | Local translated density select; opt-in table/card container; card spacing; MUI selected-row/surface treatment; accessible mobile/column checkboxes, localized row/paging names and focusable horizontal-scroll region; bounded long-content reflow | +| [translations.ts](../../../../job-tracker-ui/src/i18n/translations.ts) | Eleven EN/NB pairs for density, row/scroll/workflow names and pagination | +| [job-table-density.test.tsx](../../../../job-tracker-ui/src/job-table-density.test.tsx) | Six behavioral component tests, using existing providers and API mocks; only the unrelated edit-dialog body is stubbed | +| [table-density.spec.ts](../../../../job-tracker-ui/e2e/table-density.spec.ts) | Four real-API browser workflows, one per theme/language combination; synthetic owner data, dimensions, keyboard, mutations, axe and screenshots | +| This record, Phase 4 index, Phase 2 traceability and current TODO | Preservation links, verification, visual evidence and stop boundary | + +Retained: MUI Table, TableSortLabel, TablePagination, cards, filter controls, SavedViewsMenu, lifecycle handlers, EditJobDialog, API queries and owner/session enforcement. Refactored: spacing, presentation/naming and a literal table-container shadow to the existing MUI semantic shadow. Added: one local preference/control and opt-in theme aliases. No library, package, CI, infrastructure, schema, backend, navigation or workflow architecture was added. + +## Density contract + +Opt in a MUI table/list container with `data-content-density` using the exported type. `MuiCssBaseline` owns the spacing values; consumers use the aliases through MUI `sx`/Stack. There is no parallel palette, table engine or generic DataTable wrapper. + +| Property | Comfortable (default) | Compact | +|---|---|---| +| Table-cell vertical padding | 12px | 8px | +| Phone card padding | 16px | 12px | +| Phone inter-card/inner-stack gap | 12px | 8px | +| Text/font/icon sizes | Existing sizes | Identical | +| Fine-pointer table checkbox/icon targets | At least 32×32px | Identical | +| Phone/coarse-pointer checkbox/icon targets | At least 44×44px | Identical | +| Sort labels, clickable chips, buttons and links | Density-independent minimum height; 44px on phones/coarse pointers | Identical | +| Columns, values, actions, status labels and workflow signals | Existing content and user column choices | Identical | + +Unmarked tables retain their original cell padding and control styles. Density does not enter fetch dependencies, route parameters, page-size callbacks, storage, saved-view fields or API requests. It therefore does not clear selection, refetch jobs or reset page/sort/filter state. Browser page-size/column persistence and workspace return remain independent. + +Row height is content-driven rather than fixed: long text and wrapped actions can grow. The normal fixture row measures **59px Comfortable / 51px Compact** in all four theme/locale combinations; see [SCAN_RESULTS.json](SCAN_RESULTS.json). Typography, palette, focus tokens and status meanings remain those of P4-01/04. Selection uses existing MUI selection semantics plus the checked control, not color alone. + +## Responsive and accessibility work + +- Desktop/tablet retain the existing scrollable table, including all selected columns. The horizontal region now has an EN/NB name and native keyboard focus/scrolling; its inherited 3px focus outline is inset to survive the existing clipped Paper boundary. No page-wide overflow rule was introduced. +- Below the existing 768px boundary, the same records and selected IDs use existing cards. Comfortable/Compact changes spacing, not card fields or actions. Row checkbox names now match the desktop selection contract. No new mobile sorting workflow or filter architecture is introduced. +- Actual 320px visual review caught a custom status forcing the adjacent title into almost one-character lines. The bounded fix lets the card header wrap and its status label wrap without truncation. A minimum readable title-width assertion prevents geometry-only overflow checks from falsely passing this state. Desktop role cells receive a 260px minimum so long titles do not become similarly narrow columns; excess width remains deliberately scrollable. +- Column-menu checkboxes are named, without changing toggle callbacks. Native table headers/sort state, selection, row/action click isolation and Enter/Space row activation are retained. Row/workflow accessible names and page controls now use the existing localization system. No non-interactive card was made focusable. +- The new select uses P4-01 outlined-field focus and MUI keyboard choice/focus return. No animation or reduced-motion behavior was added; fixtures exercise the inherited reduced-motion path. + +The limited header/column adjustment is owned by this slice's long-text/readability requirement. It does not reorganize Jobs filters, workspace tabs, table/board navigation, mobile cards, status configuration or business logic. + +## Regression evidence + +Three new behavior tests were run successfully against the original implementation before adding density: row-action isolation with edit/cancel/status; sort/page-size/columns; Trash selection/restore. The seven inherited workspace-overlay tests also passed during pre-change checking. Three further tests cover selected/query/page/column/custom-status preservation without refetch, no storage/API writes plus unmount reset, and failed-refresh/retry/empty compatibility. + +The four native browser cases each create an ordinary synthetic user and 18 owned jobs, with Norwegian characters, a long title and a custom status. They prove: + +- Comfortable default, keyboard density choice/focus return, unchanged visible row data/columns/query/selection and zero listing requests solely from density changes. +- Native sortable header semantics; table at 1440/1024/768px and cards at 390/320px; selected IDs and status labels survive resizing; card targets stay at least 44px in both densities, with containment and minimum title-width assertions. +- Keyboard horizontal scrolling and visible focus on the selection, scroll region and row-action button; desktop checkbox/icon targets at least 32px; native external-link isolation and keyboard workspace entry/back with focus restoration. +- Real status PATCH, paging 15→20, persisted column choice, confirm/soft-delete and Trash bulk restore. All writes await and require the actual success response before readback/continuation; existing B02 request headers remain required. +- Real empty Trash plus a deliberately held/503 list GET, followed by the existing retry and a successful native reload while keeping Compact. No mutation is mocked. Remote browser traffic is blocked; no provider or production load test is performed. + +The new unit bulk tests use one selected record. Arbitrary multi-record partial-failure UI, saved-view CRUD browser coverage and dirty nested page-size changes remain explicit Phase 2 gaps. Existing account-scoped saved-view, server lifecycle/authorization and full workspace regression evidence is retained; this slice does not claim to close every gap in PRES-J05/J06/W02/S03. + +## Rendered evidence + +Actual screenshots were inspected, not only axe results. The long-status phone correction was prompted by that inspection. The final fixture produces **32 synthetic screenshots and 24 full tagged axe scans with zero violations**, across the two themes/locales/densities, empty and error states. Detailed scan results and incomplete checks are retained in [SCAN_RESULTS.json](SCAN_RESULTS.json): contrast is incomplete in 24 scans, `aria-hidden-focus` in four and `th-has-data-cells` in four. Incomplete checks are not passes. + +| PRES → change → validation | Rendered evidence | +|---|---| +| J05/E08 → Comfortable/Compact spacing, identical data and semantic surfaces → row measurement and full axe | [Comfortable dark/NB](visual/desktop-comfortable-dark-nb.png), [Compact dark/NB](visual/desktop-compact-dark-nb.png), [Comfortable light/EN](visual/desktop-comfortable-light-en.png), [Compact light/EN](visual/desktop-compact-light-en.png) | +| J05/J06/E08 → unchanged phone actions, readable long custom status/title → target/width/containment checks | [320px Comfortable light/EN](visual/phone-320-comfortable-light-en.png), [320px Compact dark/NB](visual/phone-320-compact-dark-nb.png), [390px Comfortable dark/EN](visual/phone-390-comfortable-dark-en.png), [390px Compact light/NB](visual/phone-390-compact-light-nb.png) | +| J06/W01/W02 → visible row actions/focus and retained entry/status/delete/restore → native API and keyboard | [Focused action dark/EN](visual/row-action-focus-dark-en.png), [focused action light/NB](visual/row-action-focus-light-nb.png) | +| E08/J05 → existing loading/error/retry independent of density → held GET, failed GET, native retry | [Error light/NB](visual/list-error-light-nb.png), [error dark/EN](visual/list-error-dark-en.png) | + +Horizontal clipping in a scrolled table screenshot represents its intentional viewport, not hidden/deleted columns: keyboard scroll and action focus expose the remaining columns. Card title/status wrapping, checkbox/action alignment, secondary text and selection are readable in the inspected phone renders. Existing bold typography, rounded cards and dense filter toolbar are retained for Phase 5 rather than redesigned here. + +## Final validation + +| Check | P4-04 inherited | P4-05 | +|---|---|---| +| Backend Release suite | 916 | **916 passed**, zero failed/skipped, including the rerun after the final application change | +| Frontend Jest | 348 in 74 suites | **354 passed in 75 suites**; six added tests, none removed | +| Full Chromium browser suite | 47 actual passes + P2-D01 expected failure | **51 actual passes + unchanged P2-D01 expected failure**: all 47 inherited passes plus four new cases | +| Focused new browser cases | — | **4 passed**, same four cases included in the full suite, not extra counts | +| Rate-limit HTTP | 9 | **9 passed** | +| Production-mode ingress HTTP | 6 | **6 passed**; local evidence cannot close deployed F04 | +| PDF admission HTTP | 1 | **1 passed** | +| Effective Compose/config checks | 3 | **3 passed** | +| Standalone frontend and scoped E2E TypeScript | Pass | **Pass** | +| Lint | Pass | **Pass**, zero warnings allowed | +| Frontend static production build | Pass | **Pass**, used by the browser tests | +| API Release build | Pass | **Pass**, zero warnings/errors, `-warnaserror` | +| Supply-chain / Ollama harness / extension tests | 3 / 5 / 3 | **3 / 5 / 3 passed** | +| Secret / whitespace / local Markdown-target checks | Pass | **Pass**, including staged files; **121** current/root Markdown documents, zero missing local targets, historical archive excluded | + +No existing test or expected failure is renamed, suppressed or reclassified. The full backend suite retains B01–B05 protections. Complete frontend/browser/security counts are recorded independently; a reporter's expected-failure success outcome is not a successful P2-D01 workflow. + +Final diff review confirmed that `App.tsx`/AppShell, navigation, backend code, dependencies and CI are unchanged. Density affects only opt-in presentation and does not alter requests or status values. All validation above ran after the final application change; subsequent changes only recorded the evidence. P4-05's bounded implementation and local validation are complete. + +### Commands and reproducibility + +From repository root unless noted. Existing installed runtimes/dependencies were used. Logs/TRX/Playwright JSON are under ignored `.artifacts/`; authentication traces are not committed. The committed scans/screenshots contain synthetic test data only. + +```powershell +$env:DOTNET_ROOT='C:/Users/Connor/.dotnet' +& C:/Users/Connor/.dotnet/dotnet.exe test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --configuration Release --no-restore --logger 'trx;LogFileName=p4-05.trx' --results-directory .artifacts/redesign-p4-05 -- xUnit.parallelizeTestCollections=false xUnit.maxParallelThreads=1 +# After the final application change, unchanged backend binaries: +& C:/Users/Connor/.dotnet/dotnet.exe test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --configuration Release --no-build --no-restore --logger 'trx;LogFileName=p4-05-final.trx' --results-directory .artifacts/redesign-p4-05 -- xUnit.parallelizeTestCollections=false xUnit.maxParallelThreads=1 +& C:/Users/Connor/.dotnet/dotnet.exe build JobTrackerApi/JobTrackerApi.csproj --configuration Release --no-restore -warnaserror +python scripts/test-ingress.py +python scripts/test-supply-chain.py +python scripts/test-ollama-evaluation.py +node --test browser-extension/tests/*.test.mjs +Set-Location job-tracker-ui +npm test -- --watchAll=false --runInBand --runTestsByPath src/job-table-density.test.tsx src/application-workspace-overlay.test.tsx +npm test -- --watchAll=false --runInBand --json --outputFile=../.artifacts/p4-05-jest.json +npm run typecheck +node node_modules/typescript/bin/tsc --project ../.artifacts/p4-05-e2e-tsconfig.json +npm run lint +$env:NEXT_PUBLIC_API_BASE_URL='http://localhost:5302/api' +$env:NEXT_TELEMETRY_DISABLED='1' +npm run build +$env:DOTNET_HOST_PATH='C:/Users/Connor/.dotnet/dotnet.exe' +$env:PLAYWRIGHT_STATIC_EXPORT='true' +$env:PLAYWRIGHT_PREBUILT_EXPORT='true' +$env:P4_05_CAPTURE='true' +$env:PLAYWRIGHT_JSON_OUTPUT_FILE='../.artifacts/p4-05-browser-focused.json' +node node_modules/@playwright/test/cli.js test e2e/table-density.spec.ts --reporter=list,json +$env:PLAYWRIGHT_JSON_OUTPUT_FILE='../.artifacts/p4-05-browser.json' +node node_modules/@playwright/test/cli.js test --reporter=list,json +# Separate configurations run sequentially against their own disposable API instance. +node node_modules/@playwright/test/cli.js test --config=playwright.rate-limits.config.ts +node node_modules/@playwright/test/cli.js test --config=playwright.ingress.config.ts +node node_modules/@playwright/test/cli.js test --config=playwright.pdf.config.ts +Set-Location .. +python scripts/supply-chain.py scan-secrets +git diff --check +git diff --cached --check +``` + +The ignored scoped E2E type config extends the frontend tsconfig, includes `table-density.spec.ts` and existing MUI augmentation, resolves frontend Node types and disables incremental caching. There is no compiler exclusion, package or CI change. + +## Deferred issues and Phase 5 implications + +- P2-D01 remains the documented submitted-package expected failure. P4-04-O02 SQLite contention, P4-04-O01 toast overlap, P4-03-D01 Tooltip contrast, earlier modal/command defects and CV margin/template rendering work remain separately scoped. The new axe states do not certify transient tooltip contrast; row-action screenshots can still show the inherited tooltip. No accessibility rule is disabled in the new scans. +- **P4-05-O01:** existing status action menus/bulk buttons contain raw English status keys in Bokmål, and applied dates use the existing browser locale rather than the chosen application language. These are baseline localization issues; new density/pagination/accessible-name text is localized. Do not change lifecycle values or date semantics as density work. +- Existing mobile cards lack a sort picker; desktop/query ordering is retained across resize. Current status filters are a fixed list, while custom status labels still display. Custom-status management, new filters, saved-filter expansion and integrated Table/Board/preview architecture are Phase 5 requirements, not delivered here. +- Browser checks prove the stated Chromium dimensions and keyboard behavior, not physical touch, a coarse-pointer tablet hardware run, Narrator/NVDA, 200%/400% zoom, forced colors or every long input. Those manual gaps remain. Only this table/list is opted in; future consumers need their own data/action/responsive fixtures. +- Density is deliberately local/provisional. Cross-device or account-persisted density needs an explicit preferences decision; do not silently add it to CV document density or existing saved-view payloads. +- F04 remains open pending deployed Traefik/nginx/API, firewall, DNS and TLS evidence. No production environment was inspected or deployed by this slice. + +Phase 5 can reuse the opt-in MUI density contract while separately reorganizing Jobs and other consumers. Preserve the current capabilities, own each migration's missing tests and keep touch/focus targets independent of density. Rollback is a presentation/test revert; no migration or stored-data transformation is required. Stop before P4-06. diff --git a/docs/redesign/phase-4/p4-05/SCAN_RESULTS.json b/docs/redesign/phase-4/p4-05/SCAN_RESULTS.json new file mode 100644 index 0000000..a7d0a2b --- /dev/null +++ b/docs/redesign/phase-4/p4-05/SCAN_RESULTS.json @@ -0,0 +1,4778 @@ +{ + "slice": "P4-05", + "source": "Complete Chromium run against final static export and disposable real API", + "outcomes": { + "passed -> passed": 51, + "failed -> failed": 1 + }, + "inheritedActualPasses": 47, + "newActualPasses": 4, + "expectedFailures": [ + { + "file": "redesign-preservation.spec.ts", + "title": "[PRES-W01 PRES-W05 PRES-W06 PRES-W07 PRES-W08] legacy workspace preserves frozen documents after current sources change", + "expected": "failed", + "actual": "failed" + } + ], + "screenshots": 32, + "axeScanCount": 24, + "axeViolationCount": 0, + "incompleteRuleCounts": { + "color-contrast": 24, + "aria-hidden-focus": 4, + "th-has-data-cells": 4 + }, + "rowHeights": [ + { + "name": "row-heights-light-en", + "comfortable": 59, + "compact": 51 + }, + { + "name": "row-heights-light-nb", + "comfortable": 59, + "compact": 51 + }, + { + "name": "row-heights-dark-en", + "comfortable": 59, + "compact": 51 + }, + { + "name": "row-heights-dark-nb", + "comfortable": 59, + "compact": 51 + } + ], + "scans": [ + { + "name": "desktop-comfortable-light-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All readiness
", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
Comfortable
", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "9.8pt (13px)", + "fontWeight": "bold", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "Follow up", + "target": [ + "tr[data-job-row-id=\"23\"] > .css-1laywfi > .css-ubcfx2.MuiBox-root > .MuiChip-colorWarning.MuiChip-clickableColorWarning.MuiChip-filledWarning > .css-4y436t.MuiChip-label.MuiChip-labelSmall" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "desktop-compact-light-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All readiness
", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
Compact
", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "9.8pt (13px)", + "fontWeight": "bold", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "Follow up", + "target": [ + "tr[data-job-row-id=\"23\"] > .css-1laywfi > .css-ubcfx2.MuiBox-root > .MuiChip-colorWarning.MuiChip-clickableColorWarning.MuiChip-filledWarning > .css-4y436t.MuiChip-label.MuiChip-labelSmall" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "phone-comfortable-light-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_4b_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_4e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All readiness
", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
Comfortable
", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "phone-compact-light-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_9m_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_9p_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All readiness
", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
Compact
", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "empty-trash-light-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_d_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
All
", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_g_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
Compact
", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "list-error-light-en-axe", + "violations": [], + "incomplete": [ + { + "id": "aria-hidden-focus", + "impact": "serious", + "tags": [ + "cat.name-role-value", + "wcag2a", + "wcag412", + "TTv5", + "TT6.a", + "EN-301-549", + "EN-9.4.1.2", + "RGAAv4", + "RGAA-10.8.1" + ], + "description": "Ensure aria-hidden elements are not focusable nor contain focusable elements", + "help": "ARIA hidden element must not be focusable or contain focusable elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/aria-hidden-focus?application=playwright", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "focusable-modal-open", + "data": null, + "relatedNodes": [ + { + "html": "
  • Compact
  • ", + "target": [ + "li[data-value=\"compact\"]" + ] + } + ], + "impact": "serious", + "message": "Check that focusable elements are not tabbable in the current state" + } + ], + "none": [], + "impact": "serious", + "html": "
    ", + "target": [ + "#menu-" + ], + "failureSummary": "Fix all of the following:\n Check that focusable elements are not tabbable in the current state" + } + ] + }, + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All readiness
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Compact
    ", + "target": [ + ".MuiSelect-outlined.css-1ehla7j[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + }, + { + "id": "th-has-data-cells", + "impact": "serious", + "tags": [ + "cat.tables", + "wcag2a", + "wcag131", + "section508", + "section508.22.g", + "TTv5", + "TT14.b", + "EN-301-549", + "EN-9.1.3.1", + "RGAAv4", + "RGAA-5.7.1" + ], + "description": "Ensure that elements and elements with role=columnheader/rowheader have data cells they describe", + "help": "Table headers in a data table must refer to data cells", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/th-has-data-cells?application=playwright", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "th-has-data-cells", + "data": null, + "relatedNodes": [ + { + "html": "Actions", + "target": [ + ".MuiTableCell-alignRight" + ] + } + ], + "impact": "serious", + "message": "Table data cells are missing or empty" + } + ], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "table" + ], + "failureSummary": "Fix all of the following:\n Table data cells are missing or empty" + } + ] + } + ] + }, + { + "name": "desktop-comfortable-light-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Komfortabel
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "9.8pt (13px)", + "fontWeight": "bold", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "Følg opp", + "target": [ + "tr[data-job-row-id=\"41\"] > .css-1laywfi > .css-ubcfx2.MuiBox-root > .MuiChip-colorWarning.MuiChip-clickableColorWarning.MuiChip-filledWarning > .css-4y436t.MuiChip-label.MuiChip-labelSmall" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "desktop-compact-light-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Kompakt
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "9.8pt (13px)", + "fontWeight": "bold", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "Følg opp", + "target": [ + "tr[data-job-row-id=\"41\"] > .css-1laywfi > .css-ubcfx2.MuiBox-root > .MuiChip-colorWarning.MuiChip-clickableColorWarning.MuiChip-filledWarning > .css-4y436t.MuiChip-label.MuiChip-labelSmall" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "phone-comfortable-light-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_4b_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_4e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Komfortabel
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "phone-compact-light-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_9m_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_9p_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Kompakt
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "empty-trash-light-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_d_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_g_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Kompakt
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "list-error-light-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "aria-hidden-focus", + "impact": "serious", + "tags": [ + "cat.name-role-value", + "wcag2a", + "wcag412", + "TTv5", + "TT6.a", + "EN-301-549", + "EN-9.4.1.2", + "RGAAv4", + "RGAA-10.8.1" + ], + "description": "Ensure aria-hidden elements are not focusable nor contain focusable elements", + "help": "ARIA hidden element must not be focusable or contain focusable elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/aria-hidden-focus?application=playwright", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "focusable-modal-open", + "data": null, + "relatedNodes": [ + { + "html": "
  • Kompakt
  • ", + "target": [ + "li[data-value=\"compact\"]" + ] + } + ], + "impact": "serious", + "message": "Check that focusable elements are not tabbable in the current state" + } + ], + "none": [], + "impact": "serious", + "html": "
    ", + "target": [ + "#menu-" + ], + "failureSummary": "Fix all of the following:\n Check that focusable elements are not tabbable in the current state" + } + ] + }, + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Kompakt
    ", + "target": [ + ".MuiSelect-outlined.css-1ehla7j[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + }, + { + "id": "th-has-data-cells", + "impact": "serious", + "tags": [ + "cat.tables", + "wcag2a", + "wcag131", + "section508", + "section508.22.g", + "TTv5", + "TT14.b", + "EN-301-549", + "EN-9.1.3.1", + "RGAAv4", + "RGAA-5.7.1" + ], + "description": "Ensure that
    ", + "target": [ + ".MuiTableCell-alignRight" + ] + } + ], + "impact": "serious", + "message": "Table data cells are missing or empty" + } + ], + "none": [], + "impact": "serious", + "html": "
    elements and elements with role=columnheader/rowheader have data cells they describe", + "help": "Table headers in a data table must refer to data cells", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/th-has-data-cells?application=playwright", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "th-has-data-cells", + "data": null, + "relatedNodes": [ + { + "html": "Handlinger
    ", + "target": [ + "table" + ], + "failureSummary": "Fix all of the following:\n Table data cells are missing or empty" + } + ] + } + ] + }, + { + "name": "desktop-comfortable-dark-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All readiness
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Comfortable
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "9.8pt (13px)", + "fontWeight": "bold", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "Follow up", + "target": [ + "tr[data-job-row-id=\"59\"] > .css-1laywfi > .css-ubcfx2.MuiBox-root > .MuiChip-colorWarning.MuiChip-clickableColorWarning.MuiChip-filledWarning > .css-4y436t.MuiChip-label.MuiChip-labelSmall" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "desktop-compact-dark-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All readiness
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Compact
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "9.8pt (13px)", + "fontWeight": "bold", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "Follow up", + "target": [ + "tr[data-job-row-id=\"59\"] > .css-1laywfi > .css-ubcfx2.MuiBox-root > .MuiChip-colorWarning.MuiChip-clickableColorWarning.MuiChip-filledWarning > .css-4y436t.MuiChip-label.MuiChip-labelSmall" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "phone-comfortable-dark-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_4b_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_4e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All readiness
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Comfortable
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "phone-compact-dark-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_9m_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_9p_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All readiness
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Compact
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "empty-trash-dark-en-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_d_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_g_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Compact
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "list-error-dark-en-axe", + "violations": [], + "incomplete": [ + { + "id": "aria-hidden-focus", + "impact": "serious", + "tags": [ + "cat.name-role-value", + "wcag2a", + "wcag412", + "TTv5", + "TT6.a", + "EN-301-549", + "EN-9.4.1.2", + "RGAAv4", + "RGAA-10.8.1" + ], + "description": "Ensure aria-hidden elements are not focusable nor contain focusable elements", + "help": "ARIA hidden element must not be focusable or contain focusable elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/aria-hidden-focus?application=playwright", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "focusable-modal-open", + "data": null, + "relatedNodes": [ + { + "html": "
  • Compact
  • ", + "target": [ + "li[data-value=\"compact\"]" + ] + } + ], + "impact": "serious", + "message": "Check that focusable elements are not tabbable in the current state" + } + ], + "none": [], + "impact": "serious", + "html": "
    ", + "target": [ + "#menu-" + ], + "failureSummary": "Fix all of the following:\n Check that focusable elements are not tabbable in the current state" + } + ] + }, + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All readiness
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Compact
    ", + "target": [ + ".MuiSelect-outlined.css-1ehla7j[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + }, + { + "id": "th-has-data-cells", + "impact": "serious", + "tags": [ + "cat.tables", + "wcag2a", + "wcag131", + "section508", + "section508.22.g", + "TTv5", + "TT14.b", + "EN-301-549", + "EN-9.1.3.1", + "RGAAv4", + "RGAA-5.7.1" + ], + "description": "Ensure that
    ", + "target": [ + ".MuiTableCell-alignRight" + ] + } + ], + "impact": "serious", + "message": "Table data cells are missing or empty" + } + ], + "none": [], + "impact": "serious", + "html": "
    elements and elements with role=columnheader/rowheader have data cells they describe", + "help": "Table headers in a data table must refer to data cells", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/th-has-data-cells?application=playwright", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "th-has-data-cells", + "data": null, + "relatedNodes": [ + { + "html": "Actions
    ", + "target": [ + "table" + ], + "failureSummary": "Fix all of the following:\n Table data cells are missing or empty" + } + ] + } + ] + }, + { + "name": "desktop-comfortable-dark-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Komfortabel
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "9.8pt (13px)", + "fontWeight": "bold", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "Følg opp", + "target": [ + "tr[data-job-row-id=\"77\"] > .css-1laywfi > .css-ubcfx2.MuiBox-root > .MuiChip-colorWarning.MuiChip-clickableColorWarning.MuiChip-filledWarning > .css-4y436t.MuiChip-label.MuiChip-labelSmall" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "desktop-compact-dark-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Kompakt
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "9.8pt (13px)", + "fontWeight": "bold", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "Følg opp", + "target": [ + "tr[data-job-row-id=\"77\"] > .css-1laywfi > .css-ubcfx2.MuiBox-root > .MuiChip-colorWarning.MuiChip-clickableColorWarning.MuiChip-filledWarning > .css-4y436t.MuiChip-label.MuiChip-labelSmall" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "phone-comfortable-dark-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_4b_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_4e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Komfortabel
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "phone-compact-dark-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_9m_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_9p_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Kompakt
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "empty-trash-dark-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_d_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_g_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Kompakt
    ", + "target": [ + "div[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + } + ] + }, + { + "name": "list-error-dark-nb-axe", + "violations": [], + "incomplete": [ + { + "id": "aria-hidden-focus", + "impact": "serious", + "tags": [ + "cat.name-role-value", + "wcag2a", + "wcag412", + "TTv5", + "TT6.a", + "EN-301-549", + "EN-9.4.1.2", + "RGAAv4", + "RGAA-10.8.1" + ], + "description": "Ensure aria-hidden elements are not focusable nor contain focusable elements", + "help": "ARIA hidden element must not be focusable or contain focusable elements", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/aria-hidden-focus?application=playwright", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "focusable-modal-open", + "data": null, + "relatedNodes": [ + { + "html": "
  • Kompakt
  • ", + "target": [ + "li[data-value=\"compact\"]" + ] + } + ], + "impact": "serious", + "message": "Check that focusable elements are not tabbable in the current state" + } + ], + "none": [], + "impact": "serious", + "html": "
    ", + "target": [ + "#menu-" + ], + "failureSummary": "Fix all of the following:\n Check that focusable elements are not tabbable in the current state" + } + ] + }, + { + "id": "color-contrast", + "impact": "serious", + "tags": [ + "cat.color", + "wcag2aa", + "wcag143", + "TTv5", + "TT13.c", + "EN-301-549", + "EN-9.1.4.3", + "ACT", + "RGAAv4", + "RGAA-3.2.1" + ], + "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds", + "help": "Elements must meet minimum color contrast ratio thresholds", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/color-contrast?application=playwright", + "nodes": [ + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_e_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-status-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Alle
    ", + "target": [ + "div[aria-labelledby=\"job-table-company-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "", + "target": [ + "#_r_h_" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    All beredskap
    ", + "target": [ + "div[aria-labelledby=\"job-table-readiness-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + }, + { + "any": [ + { + "id": "color-contrast", + "data": { + "contrastRatio": 0, + "fontSize": "10.5pt (14px)", + "fontWeight": "normal", + "messageKey": "bgOverlap", + "expectedContrastRatio": "4.5:1" + }, + "relatedNodes": [], + "impact": "serious", + "message": "Element's background color could not be determined because it is overlapped by another element" + } + ], + "all": [], + "none": [], + "impact": "serious", + "html": "
    Kompakt
    ", + "target": [ + ".MuiSelect-outlined.css-1ehla7j[aria-labelledby=\"job-table-density-label\"]" + ], + "failureSummary": "Fix any of the following:\n Element's background color could not be determined because it is overlapped by another element" + } + ] + }, + { + "id": "th-has-data-cells", + "impact": "serious", + "tags": [ + "cat.tables", + "wcag2a", + "wcag131", + "section508", + "section508.22.g", + "TTv5", + "TT14.b", + "EN-301-549", + "EN-9.1.3.1", + "RGAAv4", + "RGAA-5.7.1" + ], + "description": "Ensure that
    ", + "target": [ + ".MuiTableCell-alignRight" + ] + } + ], + "impact": "serious", + "message": "Table data cells are missing or empty" + } + ], + "none": [], + "impact": "serious", + "html": "
    elements and elements with role=columnheader/rowheader have data cells they describe", + "help": "Table headers in a data table must refer to data cells", + "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/th-has-data-cells?application=playwright", + "nodes": [ + { + "any": [], + "all": [ + { + "id": "th-has-data-cells", + "data": null, + "relatedNodes": [ + { + "html": "Handlinger
    ", + "target": [ + "table" + ], + "failureSummary": "Fix all of the following:\n Table data cells are missing or empty" + } + ] + } + ] + } + ], + "limitations": [ + "Incomplete axe results need human review.", + "No screen-reader, physical touch, coarse-pointer tablet hardware, zoom or production ingress certification." + ] +} diff --git a/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-dark-en.png b/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-dark-en.png new file mode 100644 index 0000000..00a4d41 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-dark-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-dark-nb.png b/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-dark-nb.png new file mode 100644 index 0000000..5f5e4f7 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-dark-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-light-en.png b/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-light-en.png new file mode 100644 index 0000000..ef618bb Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-light-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-light-nb.png b/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-light-nb.png new file mode 100644 index 0000000..0bff952 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/desktop-comfortable-light-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/desktop-compact-dark-en.png b/docs/redesign/phase-4/p4-05/visual/desktop-compact-dark-en.png new file mode 100644 index 0000000..c1825d8 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/desktop-compact-dark-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/desktop-compact-dark-nb.png b/docs/redesign/phase-4/p4-05/visual/desktop-compact-dark-nb.png new file mode 100644 index 0000000..49beacd Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/desktop-compact-dark-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/desktop-compact-light-en.png b/docs/redesign/phase-4/p4-05/visual/desktop-compact-light-en.png new file mode 100644 index 0000000..b70a40c Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/desktop-compact-light-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/desktop-compact-light-nb.png b/docs/redesign/phase-4/p4-05/visual/desktop-compact-light-nb.png new file mode 100644 index 0000000..dca117d Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/desktop-compact-light-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/list-error-dark-en.png b/docs/redesign/phase-4/p4-05/visual/list-error-dark-en.png new file mode 100644 index 0000000..a01c427 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/list-error-dark-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/list-error-dark-nb.png b/docs/redesign/phase-4/p4-05/visual/list-error-dark-nb.png new file mode 100644 index 0000000..a0d4161 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/list-error-dark-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/list-error-light-en.png b/docs/redesign/phase-4/p4-05/visual/list-error-light-en.png new file mode 100644 index 0000000..72bc82c Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/list-error-light-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/list-error-light-nb.png b/docs/redesign/phase-4/p4-05/visual/list-error-light-nb.png new file mode 100644 index 0000000..fb83602 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/list-error-light-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-dark-en.png b/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-dark-en.png new file mode 100644 index 0000000..9cd4ee6 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-dark-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-dark-nb.png b/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-dark-nb.png new file mode 100644 index 0000000..56d9171 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-dark-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-light-en.png b/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-light-en.png new file mode 100644 index 0000000..82defc5 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-light-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-light-nb.png b/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-light-nb.png new file mode 100644 index 0000000..143898f Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-320-comfortable-light-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-320-compact-dark-en.png b/docs/redesign/phase-4/p4-05/visual/phone-320-compact-dark-en.png new file mode 100644 index 0000000..48629de Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-320-compact-dark-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-320-compact-dark-nb.png b/docs/redesign/phase-4/p4-05/visual/phone-320-compact-dark-nb.png new file mode 100644 index 0000000..d59eb84 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-320-compact-dark-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-320-compact-light-en.png b/docs/redesign/phase-4/p4-05/visual/phone-320-compact-light-en.png new file mode 100644 index 0000000..e0f54b3 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-320-compact-light-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-320-compact-light-nb.png b/docs/redesign/phase-4/p4-05/visual/phone-320-compact-light-nb.png new file mode 100644 index 0000000..0d80518 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-320-compact-light-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-dark-en.png b/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-dark-en.png new file mode 100644 index 0000000..c606403 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-dark-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-dark-nb.png b/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-dark-nb.png new file mode 100644 index 0000000..421da5b Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-dark-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-light-en.png b/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-light-en.png new file mode 100644 index 0000000..6e5a7db Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-light-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-light-nb.png b/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-light-nb.png new file mode 100644 index 0000000..7e0c6d2 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-390-comfortable-light-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-390-compact-dark-en.png b/docs/redesign/phase-4/p4-05/visual/phone-390-compact-dark-en.png new file mode 100644 index 0000000..ce2c845 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-390-compact-dark-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-390-compact-dark-nb.png b/docs/redesign/phase-4/p4-05/visual/phone-390-compact-dark-nb.png new file mode 100644 index 0000000..1921faa Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-390-compact-dark-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-390-compact-light-en.png b/docs/redesign/phase-4/p4-05/visual/phone-390-compact-light-en.png new file mode 100644 index 0000000..5799edd Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-390-compact-light-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/phone-390-compact-light-nb.png b/docs/redesign/phase-4/p4-05/visual/phone-390-compact-light-nb.png new file mode 100644 index 0000000..31e45e3 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/phone-390-compact-light-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/row-action-focus-dark-en.png b/docs/redesign/phase-4/p4-05/visual/row-action-focus-dark-en.png new file mode 100644 index 0000000..4623dcf Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/row-action-focus-dark-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/row-action-focus-dark-nb.png b/docs/redesign/phase-4/p4-05/visual/row-action-focus-dark-nb.png new file mode 100644 index 0000000..aec34c4 Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/row-action-focus-dark-nb.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/row-action-focus-light-en.png b/docs/redesign/phase-4/p4-05/visual/row-action-focus-light-en.png new file mode 100644 index 0000000..6abf40e Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/row-action-focus-light-en.png differ diff --git a/docs/redesign/phase-4/p4-05/visual/row-action-focus-light-nb.png b/docs/redesign/phase-4/p4-05/visual/row-action-focus-light-nb.png new file mode 100644 index 0000000..45e634d Binary files /dev/null and b/docs/redesign/phase-4/p4-05/visual/row-action-focus-light-nb.png differ diff --git a/docs/roadmap/todo.md b/docs/roadmap/todo.md index 35e56cb..ae7d0a6 100644 --- a/docs/roadmap/todo.md +++ b/docs/roadmap/todo.md @@ -1,6 +1,6 @@ # TODO -Status reconciled: 2026-09-12. +Status reconciled: 2026-09-13. ## Current repository work @@ -10,6 +10,7 @@ Status reconciled: 2026-09-12. - **P4-03-D01 — existing shared Tooltip contrast debt:** the light Redo tooltip fails the text contrast target. Evidence and the narrow regression exception are in the [P4-03 record](../redesign/phase-4/p4-03/README.md); repair in a scoped shared-theme follow-up. - **P4-04-O01 — existing fixed-toast overlap:** export-success feedback can temporarily obscure a bottom-of-page action. Review shared feedback placement with later shell work; P4-04 leaves timing/placement unchanged and verifies the action after normal dismissal. [Evidence](../redesign/phase-4/p4-04/README.md). - **P4-04-O02 — existing SQLite notification-save contention:** overlapping native preference read/write requests reproduced HTTP 500 with SQLite error 5 in two of ten local runs. The sequential UI test now awaits and requires the save response before readback; server concurrency remains unresolved. Investigate separately from page-layout/density work. [Evidence](../redesign/phase-4/p4-04/README.md). +- **P4-05-O01 — existing table localization debt:** status menu/bulk actions expose raw English status keys in Bokmål, and applied dates follow the browser locale. Keep status values/date semantics intact until the Phase 5 Jobs localization work; P4-05 localizes its new density/paging/accessible names only. [Evidence](../redesign/phase-4/p4-05/README.md). - **F04/B06 — open:** complete the authorized main release and production ingress/runtime verification; the browser gate and runner diagnostics remain unresolved. No gate should be bypassed. ## Delivery and feature gates diff --git a/job-tracker-ui/e2e/table-density.spec.ts b/job-tracker-ui/e2e/table-density.spec.ts new file mode 100644 index 0000000..6939904 --- /dev/null +++ b/job-tracker-ui/e2e/table-density.spec.ts @@ -0,0 +1,225 @@ +import AxeBuilder from "@axe-core/playwright"; +import { expect, test as base, type APIRequestContext, type Locator, type Page, type TestInfo } from "@playwright/test"; +import { translations } from "../src/i18n/translations"; + +const apiUrl = "http://localhost:5302/api"; +const password = "E2ePassword123!"; +async function login(api: APIRequestContext, email: string) { + expect((await api.post(`${apiUrl}/auth/login`, { data: { email, password } })).status()).toBe(200); + const me = await (await api.get(`${apiUrl}/auth/me`)).json(); + const csrf = (await api.storageState()).cookies.find(c => c.name === "XSRF-TOKEN")!.value; + return { "X-CSRF-TOKEN": csrf, "X-Session-Context": me.sessionContext as string }; +} +const test = base.extend<{ owner: { headers: Record; ids: number[] } }>({ + owner: async ({ playwright, page, context }, provide) => { + const admin = await playwright.request.newContext(); + try { + const adminHeaders = await login(admin, "e2e@example.test"); + const email = `p405-${Date.now()}-${Math.random().toString(36).slice(2)}@example.test`; + expect((await admin.post(`${apiUrl}/users`, { headers: adminHeaders, data: { email, password, roles: [] } })).status()).toBe(200); + const headers = await login(page.request, email); + await context.route("**/*", route => { + const url = new URL(route.request().url()); + return ["localhost", "127.0.0.1"].includes(url.hostname) || ["data:", "blob:", "about:"].includes(url.protocol) ? route.continue() : route.abort(); + }); + const company = await page.request.post(`${apiUrl}/companies`, { headers, data: { name: "Nordlys æøå AS", location: "Tromsø" } }); + expect(company.status()).toBe(201); + const companyId = (await company.json()).id; + const ids: number[] = []; + for (let index = 0; index < 18; index++) { + const result = await page.request.post(`${apiUrl}/jobapplications`, { headers, data: { + companyId, jobTitle: `Density ${String(index).padStart(2, "0")}${index === 0 ? " — Seniorrådgiver for plattformutvikling og digitale fellestjenester" : " Engineer"}`, + status: index === 0 ? "Avventer faglig vurdering" : index % 3 === 0 ? "Interview" : "Saved", + dateApplied: "2026-08-01", location: "Tromsø / hjemmekontor", jobUrl: "https://example.test/listing", + } }); + expect(result.status()).toBe(201); + ids.push((await result.json()).id); + } + await provide({ headers, ids }); + } finally { await admin.dispose(); } + }, +}); + +async function capture(page: Page, info: TestInfo, name: string) { + const path = process.env.P4_05_CAPTURE === "true" ? `../docs/redesign/phase-4/p4-05/visual/${name}.png` : info.outputPath(`${name}.png`); + await page.screenshot({ path, fullPage: false }); + await info.attach(name, { path, contentType: "image/png" }); +} +async function scan(page: Page, info: TestInfo, name: string) { + const result = await new AxeBuilder({ page }).withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"]).analyze(); + await info.attach(`${name}-axe`, { body: JSON.stringify({ violations: result.violations, incomplete: result.incomplete }), contentType: "application/json" }); + expect(result.violations).toEqual([]); +} +async function keyboardFocus(page: Page, target: Locator) { + await target.focus(); + await page.keyboard.press("Tab"); + await page.keyboard.press("Shift+Tab"); + await expect(target).toBeFocused(); + const ring = await target.evaluate(node => { + const control = node.closest(".MuiInputBase-root, .MuiCheckbox-root") ?? node; + const notch = control.querySelector(".MuiOutlinedInput-notchedOutline"); + const css = getComputedStyle(notch ?? control); + return { width: notch ? css.borderTopWidth : css.outlineWidth, style: notch ? css.borderTopStyle : css.outlineStyle }; + }); + expect(ring).toEqual({ width: "3px", style: "solid" }); +} + +for (const mode of ["light", "dark"] as const) for (const language of ["en", "nb"] as const) { + test(`[PRES-J05 J06 W01 W02 S03 E08 E09] ${mode}/${language} table and cards preserve behavior at both densities`, async ({ page, owner }, info) => { + test.setTimeout(180_000); + const t = translations[language]; + const suffix = `${mode}-${language}`; + await page.emulateMedia({ reducedMotion: "reduce" }); + expect((await page.request.put(`${apiUrl}/auth/preferences/language`, { headers: owner.headers, data: { language: language === "nb" ? "nb-NO" : "en" } })).status()).toBe(204); + await page.addInitScript(({ mode, language }) => { + localStorage.setItem("jobtracker.themeMode", mode); localStorage.setItem("uiLanguage", language); + localStorage.setItem("jobColumns", JSON.stringify({ status: true, dateApplied: true, daysSince: true, jobUrl: true })); + localStorage.setItem("jobPageSize", "15"); + }, { mode, language }); + await page.setViewportSize({ width: 1440, height: 960 }); + await page.goto("/jobs?q=Density&sortBy=jobTitle&sortDir=asc"); + const main = page.getByRole("main"); + const density = main.getByRole("combobox", { name: t.listDensity, exact: true }); + const first = main.locator(`[data-job-row-id='${owner.ids[0]}']`); + const ordinary = main.locator(`[data-job-row-id='${owner.ids[1]}']`); + const region = main.getByRole("region", { name: t.jobTableScrollRegion }); + await expect(first).toBeVisible(); + await expect(page.locator("html")).toHaveAttribute("data-color-scheme", mode); + await expect(density).toHaveText(t.densityComfortable); + await expect(main.getByRole("columnheader", { name: t.jobTableRole, exact: true })).toHaveAttribute("aria-sort", "ascending"); + const rowText = await first.innerText(); + const headers = await main.getByRole("columnheader").allTextContents(); + const select = first.getByRole("checkbox"); + await select.check(); + const query = new URL(page.url()).search; + const rowHeights: number[] = []; + let listingReads = 0; + page.on("request", request => { if (new URL(request.url()).pathname === "/api/jobapplications" && request.method() === "GET") listingReads++; }); + const chooseDensity = async (value: string) => { + await density.focus(); await density.press("Enter"); + await page.getByRole("option", { name: value, exact: true }).focus(); await page.keyboard.press("Enter"); + await expect(density).toBeFocused(); + }; + for (const value of ["comfortable", "compact"] as const) { + if (value === "compact") await chooseDensity(t.densityCompact); + await expect(select).toBeChecked(); + expect(await first.innerText()).toBe(rowText); + expect(await main.getByRole("columnheader").allTextContents()).toEqual(headers); + expect(new URL(page.url()).search).toBe(query); + expect(listingReads).toBe(0); + rowHeights.push((await ordinary.boundingBox())!.height); + await keyboardFocus(page, select); + await keyboardFocus(page, region); + await page.keyboard.press("ArrowRight"); + await expect.poll(() => region.evaluate(node => node.scrollLeft)).toBeGreaterThan(0); + await region.evaluate(node => { node.scrollLeft = 0; }); + await density.scrollIntoViewIfNeeded(); + await capture(page, info, `desktop-${value}-${suffix}`); + await scan(page, info, `desktop-${value}-${suffix}`); + } + expect(rowHeights[0] - rowHeights[1]).toBeCloseTo(8, 0); + await info.attach(`row-heights-${suffix}`, { body: JSON.stringify({ comfortable: rowHeights[0], compact: rowHeights[1] }), contentType: "application/json" }); + + // Responsive cards retain selected IDs; targets do not shrink with density. + for (const value of ["comfortable", "compact"] as const) { + await chooseDensity(value === "compact" ? t.densityCompact : t.densityComfortable); + for (const width of [1024, 768, 390, 320]) { + await page.setViewportSize({ width, height: 960 }); + await expect(first.getByRole("checkbox")).toBeChecked(); + await expect(first.getByText("Avventer faglig vurdering", { exact: true })).toBeVisible(); + if (width >= 768) { await expect(main.getByRole("table")).toBeVisible(); continue; } + await expect(main.getByRole("table")).toHaveCount(0); + // Geometric containment alone misses a title squeezed into one-letter lines. + expect((await first.getByText(/^Density 00/).boundingBox())!.width).toBeGreaterThanOrEqual(150); + const metrics = await first.evaluate(card => Array.from(card.querySelectorAll("button,a,.MuiCheckbox-root")).map(node => { + const rect = node.getBoundingClientRect(); return { text: node.textContent, width: rect.width, height: rect.height, left: rect.left, right: rect.right }; + })); + expect(metrics.every(rect => rect.height >= 44 && rect.width >= 44 && rect.left >= 0 && rect.right <= width)).toBe(true); + const overflow = await first.evaluate(card => Array.from(card.querySelectorAll("p,span,button,a")).filter(node => node.getClientRects().length).map(node => node.getBoundingClientRect()).some(rect => rect.left < 0 || rect.right > innerWidth + 1)); + expect(overflow).toBe(false); + await first.scrollIntoViewIfNeeded(); + await capture(page, info, `phone-${width}-${value}-${suffix}`); + if (width === 390) await scan(page, info, `phone-${value}-${suffix}`); + } + await page.setViewportSize({ width: 1440, height: 960 }); + } + + // Native row status request, listing-link isolation and workspace navigation. + await select.uncheck(); + // Match by the translated action prefix; the long title remains in its accessible name. + const statusAction = first.getByRole("button", { name: new RegExp(`^${t.jobTableQuickStatus}:`) }); + await keyboardFocus(page, statusAction); + await page.keyboard.press("Escape"); // Dismiss the existing tooltip, preserving focus. + const targets = await first.locator(".MuiIconButton-root,.MuiCheckbox-root").evaluateAll(nodes => nodes.map(node => ({ width: node.getBoundingClientRect().width, height: node.getBoundingClientRect().height }))); + expect(targets.every(target => target.width >= 32 && target.height >= 32)).toBe(true); + await capture(page, info, `row-action-focus-${suffix}`); + await statusAction.press("Enter"); + const changed = page.waitForResponse(r => r.url() === `${apiUrl}/jobapplications/${owner.ids[0]}/status` && r.request().method() === "PATCH"); + await page.getByRole("menuitem", { name: t.jobTableSetStatus.replace("{status}", "Interview"), exact: true }).click(); + expect((await changed).status()).toBe(204); + await expect(first.getByText(t.statusInterview, { exact: true })).toBeVisible(); + expect(new URL(page.url()).pathname).toBe("/jobs"); + const listing = first.getByRole("link", { name: t.jobTableLink, exact: true }); + const popup = page.waitForEvent("popup"); + await listing.click(); + await (await popup).close(); + expect(new URL(page.url()).pathname).toBe("/jobs"); + await first.focus(); await first.press("Enter"); + await expect(page).toHaveURL(new RegExp(`/jobs/${owner.ids[0]}$`)); + await page.goBack(); + // Existing App keeps the list mounted behind the dedicated workspace. + await expect(density).toHaveText(t.densityCompact); + await expect(first).toBeFocused(); + + await main.getByRole("button", { name: t.tableNextPage }).click(); + await expect(main.locator("[data-job-row-id]")).toHaveCount(3); + await chooseDensity(t.densityCompact); + expect(new URL(page.url()).searchParams.get("page")).toBe("2"); + await main.getByRole("combobox", { name: t.settingsRowsPerPage }).click(); + await page.getByRole("option", { name: "20", exact: true }).click(); + await expect(main.locator("[data-job-row-id]")).toHaveCount(18); + await expect(density).toHaveText(t.densityCompact); + expect(await page.evaluate(() => localStorage.getItem("jobPageSize"))).toBe("20"); + + await main.getByRole("button", { name: t.jobTableColumns, exact: true }).click(); + await page.getByRole("menuitem", { name: t.settingsColumnJobUrl, exact: true }).click(); + await page.keyboard.press("Escape"); + await expect(first.getByRole("link", { name: t.jobTableLink, exact: true })).toHaveCount(0); + expect(JSON.parse((await page.evaluate(() => localStorage.getItem("jobColumns")))!).jobUrl).toBe(false); + + // Real confirm/soft-delete and the same renderer's existing Trash restore path. + await first.getByRole("button", { name: new RegExp(`^${t.jobTableSoftDelete}:`) }).click(); + const deleted = page.waitForResponse(r => r.url() === `${apiUrl}/jobapplications/${owner.ids[0]}` && r.request().method() === "DELETE"); + await page.getByRole("dialog").getByRole("button", { name: t.jobTableMove, exact: true }).click(); + expect((await deleted).status()).toBe(204); + await expect(first).toHaveCount(0); + await page.goto("/trash"); + await expect(first).toBeVisible(); + await chooseDensity(t.densityCompact); + await first.getByRole("checkbox").check(); + const restored = page.waitForResponse(r => r.url() === `${apiUrl}/jobapplications/${owner.ids[0]}/restore` && r.request().method() === "POST"); + await main.getByRole("button", { name: t.jobTableRestoreSelected, exact: true }).click(); + expect((await restored).status()).toBe(204); + await expect(first).toHaveCount(0); + await expect(density).toHaveText(t.densityCompact); + await scan(page, info, `empty-trash-${suffix}`); + + // Only this GET is held/failed; loaded data, actions and all mutations above + // use the real owner API. Retry keeps the existing error contract. + let release!: () => void; + const held = new Promise(resolve => { release = resolve; }); + await page.route(`${apiUrl}/jobapplications?*`, async route => { await held; await route.fulfill({ status: 503, contentType: "application/json", body: JSON.stringify({ message: "Synthetic list unavailable" }) }); }); + await page.goto("/jobs?q=Density"); + await expect(main.getByText(t.loading, { exact: true })).toBeVisible(); + await chooseDensity(t.densityCompact); + release(); + await expect(main.getByRole("alert")).toBeVisible(); + await capture(page, info, `list-error-${suffix}`); + await scan(page, info, `list-error-${suffix}`); + await page.unroute(`${apiUrl}/jobapplications?*`); + await main.getByRole("button", { name: t.retry, exact: true }).click(); + await expect(first).toBeVisible(); + await expect(main.getByRole("alert")).toHaveCount(0); + await expect(density).toHaveText(t.densityCompact); + }); +} diff --git a/job-tracker-ui/src/components/JobTable.tsx b/job-tracker-ui/src/components/JobTable.tsx index f992bdb..1001544 100644 --- a/job-tracker-ui/src/components/JobTable.tsx +++ b/job-tracker-ui/src/components/JobTable.tsx @@ -51,6 +51,7 @@ import { useI18n } from "../i18n/I18nProvider"; import { JobApplication } from "../types"; import { useViewResource } from "../hooks/useViewResource"; import { getWorkflowAction } from "../jobWorkflowSignals"; +import type { ContentDensity } from "../theme"; interface PagedResult { items: T[]; @@ -179,6 +180,8 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col const [jobs, setJobs] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(() => queryPage(location.search)); + // Presentation only: not an account preference, saved-view field or API input. + const [density, setDensity] = useState("comfortable"); const [selectedIds, setSelectedIds] = useState([]); const [search, setSearch] = useState(() => new URLSearchParams(location.search).get("q") ?? ""); const debouncedSearch = useDebouncedValue(search, 250); @@ -456,6 +459,15 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col const statusOptions = ["Waiting", "Interview", "Offer", "Rejected", "Ghosted"] as const; const visibleDesktopColumns = 6 + Number(columns.status) + Number(columns.dateApplied) + Number(columns.daysSince) + Number(columns.jobUrl); const selectedCompanyIsLoading = companyFilterId !== "All" && !companies.some((company) => company.id === companyFilterId); + const densityControl = ( + + {t("listDensity")} + + + ); return ( @@ -537,6 +549,7 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col {t("jobTableColumns")} + {densityControl} ) : ( @@ -589,6 +602,7 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col {mode === "jobs" ? changeIncludeDeleted(e.target.checked)} />} label={t("jobTableShowDeleted")} sx={{ mr: 0 }} /> : null} {!isMobile ? setColumnsAnchor(e.currentTarget)}> : null} + {densityControl} )} @@ -605,8 +619,8 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col setColumnsAnchor(null)}> {([ ["status", t("settingsColumnStatus")], ["dateApplied", t("settingsColumnDateApplied")], ["daysSince", t("settingsColumnDays")], ["jobUrl", t("settingsColumnJobUrl")] ] as const).map(([key, label]) => ( - onColumnsChange({ ...columns, [key]: !columns[key] })}> - + onColumnsChange({ ...columns, [key]: !columns[key] })}> + {label} ))} @@ -629,16 +643,17 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col ) : null} {isMobile ? ( - + 0 && !selectedAllOnPage} onChange={(e) => toggleSelectAll(e.target.checked)} />} label={t("jobTableSelectAll")} sx={{ mr: 0 }} /> @@ -652,7 +667,7 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col data-job-row-id={job.id} role={mode === "jobs" && !job.isDeleted ? "link" : undefined} tabIndex={mode === "jobs" && !job.isDeleted ? 0 : undefined} - aria-label={mode === "jobs" && !job.isDeleted ? `Open ${job.jobTitle} at ${job.company?.name ?? "company"}` : undefined} + aria-label={mode === "jobs" && !job.isDeleted ? t("jobTableOpenJob", { title: job.jobTitle, company: job.company?.name ?? t("jobTableCompany") }) : undefined} onClick={(event) => { if (mode === "jobs" && !job.isDeleted && !isInteractiveTarget(event.target)) openJob(job.id); }} @@ -663,20 +678,20 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col } }} sx={{ - p: 1.5, + p: "var(--app-list-item-padding)", borderRadius: 3.5, cursor: mode === "jobs" && !job.isDeleted ? "pointer" : "default", - backgroundColor: alpha(theme.palette.primary.main, 0.03), + backgroundColor: isSelected ? "action.selected" : alpha(theme.palette.primary.main, 0.03), borderColor: alpha(theme.palette.primary.main, 0.08), boxShadow: `0 10px 24px ${alpha(theme.palette.common.black, theme.palette.mode === "dark" ? 0.18 : 0.06)}`, "&:hover": mode === "jobs" && !job.isDeleted ? { backgroundColor: "action.hover" } : undefined, "&:focus-visible": { outline: "3px solid", outlineColor: "primary.main", outlineOffset: 2 }, }} > - - - - toggleSelected(job.id, e.target.checked)} sx={{ mt: -0.5, ml: -1 }} /> + + + + toggleSelected(job.id, e.target.checked)} sx={{ mt: -0.5, ml: -1 }} /> {job.company?.name ?? t("jobTableCompany")} @@ -686,7 +701,7 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col - {columns.status ? : null} + {columns.status ? : null} @@ -767,8 +782,8 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col ) : null} ) : ( - -
    + +
    0 && !selectedAllOnPage} onChange={(e) => toggleSelectAll(e.target.checked)} /> @@ -792,8 +807,9 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col key={job.id} data-job-row-id={job.id} hover={mode === "jobs" && !job.isDeleted} + selected={isSelected} tabIndex={mode === "jobs" && !job.isDeleted ? 0 : undefined} - aria-label={mode === "jobs" && !job.isDeleted ? `Open ${job.jobTitle} at ${job.company?.name ?? "company"}` : undefined} + aria-label={mode === "jobs" && !job.isDeleted ? t("jobTableOpenJob", { title: job.jobTitle, company: job.company?.name ?? t("jobTableCompany") }) : undefined} onClick={(event) => { if (mode === "jobs" && !job.isDeleted && !isInteractiveTarget(event.target)) openJob(job.id); }} @@ -811,7 +827,7 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col > toggleSelected(job.id, e.target.checked)} /> {job.company?.name ?? ""} - + {job.jobTitle} {actionSignals.map((signal) => ( @@ -825,7 +841,7 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col sx={{ fontWeight: 800, cursor: "pointer" }} clickable onClick={signal.onClick} - aria-label={`${job.jobTitle} — ${signal.label} signal`} + aria-label={t("jobTableWorkflowSignal", { title: job.jobTitle, signal: signal.label })} /> ))} @@ -853,7 +869,7 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col
    )} - { setPage(next); updateListRoute({ page: next > 0 ? String(next + 1) : null }); }} rowsPerPage={pageSize} onRowsPerPageChange={(e) => { onPageSizeChange(Number(e.target.value) as 15 | 20 | 25); setPage(0); updateListRoute({ page: null }); }} rowsPerPageOptions={[15, 20, 25]} /> + t("tableDisplayedRows", { from, to, count })} getItemAriaLabel={(type) => t(type === "next" ? "tableNextPage" : type === "previous" ? "tablePreviousPage" : type === "first" ? "tableFirstPage" : "tableLastPage")} count={total} page={page} onPageChange={(_, next) => { setPage(next); updateListRoute({ page: next > 0 ? String(next + 1) : null }); }} rowsPerPage={pageSize} onRowsPerPageChange={(e) => { onPageSizeChange(Number(e.target.value) as 15 | 20 | 25); setPage(0); updateListRoute({ page: null }); }} rowsPerPageOptions={[15, 20, 25]} /> setEditJobId(null)} onSaved={() => setReloadToken((token) => token + 1)} /> diff --git a/job-tracker-ui/src/i18n/translations.ts b/job-tracker-ui/src/i18n/translations.ts index 38a7bff..97711c5 100644 --- a/job-tracker-ui/src/i18n/translations.ts +++ b/job-tracker-ui/src/i18n/translations.ts @@ -1003,6 +1003,17 @@ export const translations = { securityCheck: "Security check", dashboardTotalCount: "{count} total", jobTableSelectJob: "Select {title}", + listDensity: "List density", + densityComfortable: "Comfortable", + densityCompact: "Compact", + jobTableScrollRegion: "Job table — scroll for more columns", + jobTableOpenJob: "Open {title} at {company}", + jobTableWorkflowSignal: "{title} — {signal} signal", + tableDisplayedRows: "{from}–{to} of {count}", + tableNextPage: "Go to next page", + tablePreviousPage: "Go to previous page", + tableFirstPage: "Go to first page", + tableLastPage: "Go to last page", characterCount: "{count} characters", back: "Back", continue: "Continue", @@ -3443,6 +3454,17 @@ export const translations = { securityCheck: "Sikkerhetskontroll", dashboardTotalCount: "{count} totalt", jobTableSelectJob: "Velg {title}", + listDensity: "Listetetthet", + densityComfortable: "Komfortabel", + densityCompact: "Kompakt", + jobTableScrollRegion: "Jobbtabell — rull for å se flere kolonner", + jobTableOpenJob: "Åpne {title} hos {company}", + jobTableWorkflowSignal: "{title} — {signal}", + tableDisplayedRows: "{from}–{to} av {count}", + tableNextPage: "Gå til neste side", + tablePreviousPage: "Gå til forrige side", + tableFirstPage: "Gå til første side", + tableLastPage: "Gå til siste side", characterCount: "{count} tegn", back: "Tilbake", continue: "Fortsett", diff --git a/job-tracker-ui/src/job-table-density.test.tsx b/job-tracker-ui/src/job-table-density.test.tsx new file mode 100644 index 0000000..384b53d --- /dev/null +++ b/job-tracker-ui/src/job-table-density.test.tsx @@ -0,0 +1,127 @@ +import React, { useState } from "react"; +import "@testing-library/jest-dom"; +import { fireEvent, render, screen, waitFor, within } from "@testing-library/react"; +import { MemoryRouter, useLocation } from "react-router-dom"; +import { api } from "./api"; +import JobTable, { type JobTableColumns } from "./components/JobTable"; +import { ConfirmProvider } from "./confirm"; +import { PromptProvider } from "./prompt"; +import { ToastProvider } from "./toast"; +import { I18nProvider } from "./i18n/I18nProvider"; +import { translations } from "./i18n/translations"; + +jest.mock("./components/EditJobDialog", () => ({ open, onClose }: { open: boolean; onClose: () => void }) => open ?
    : null); + +const mockedApi = api as jest.Mocked; +const job = { id: 42, companyId: 1, company: { id: 1, name: "Østlandet" }, jobTitle: "Platform engineer", status: "Custom review", dateApplied: "2026-08-01", daysSince: 2, location: "Tromsø", jobUrl: "https://example.test/listing", isDeleted: false }; +const t = translations.en; + +function Consumer({ mode }: { mode: "jobs" | "trash" }) { + const location = useLocation(); + const [pageSize, setPageSize] = useState<15 | 20 | 25>(15); + const [columns, setColumns] = useState({ status: true, dateApplied: true, daysSince: true, jobUrl: true }); + return <>{location.pathname}{location.search}; +} +function show(mode: "jobs" | "trash" = "jobs", query = "") { + return render(); +} +const calls = () => mockedApi.get.mock.calls.filter(([url]) => url === "/jobapplications"); +const lastParams = () => calls().at(-1)?.[1]?.params as Record; +beforeEach(() => { + localStorage.clear(); + jest.clearAllMocks(); + mockedApi.get.mockImplementation((url: string) => Promise.resolve({ data: url === "/companies" ? [job.company] : url === "/jobapplications" ? { items: [job], total: 31, page: 1, pageSize: 15 } : [] } as any)); +}); + +test("row status/edit/delete controls retain selection and do not open the workspace", async () => { + show(); + const row = await screen.findByRole("row", { name: /open platform engineer/i }); + fireEvent.click(within(row).getByRole("checkbox")); + fireEvent.click(within(row).getByRole("button", { name: `${t.jobTableEdit}: ${job.jobTitle}` })); + expect(screen.getByRole("dialog", { name: "Edit job" })).toBeVisible(); + fireEvent.click(screen.getByText("Close editor")); + expect(within(row).getByRole("checkbox")).toBeChecked(); + fireEvent.click(within(row).getByRole("button", { name: `${t.jobTableSoftDelete}: ${job.jobTitle}` })); + fireEvent.click(within(await screen.findByRole("dialog")).getByRole("button", { name: /cancel/i })); + expect(mockedApi.delete).not.toHaveBeenCalled(); + fireEvent.click(await within(row).findByRole("button", { name: `${t.jobTableQuickStatus}: ${job.jobTitle}` })); + fireEvent.click(await screen.findByRole("menuitem", { name: /Interview/ })); + await waitFor(() => expect(mockedApi.patch).toHaveBeenCalledWith("/jobapplications/42/status", { status: "Interview" })); + expect(screen.getByLabelText("Current route")).toHaveTextContent(/^\/jobs$/); +}); + +test("table sort, page-size and optional columns keep their existing independent contracts", async () => { + show("jobs", "?q=platform&location=Troms%C3%B8"); + await screen.findByRole("row", { name: /open platform engineer/i }); + fireEvent.click(screen.getByRole("button", { name: t.jobTableCompany })); + await waitFor(() => expect(lastParams()).toMatchObject({ q: "platform", location: "Tromsø", sortBy: "company", sortDir: "asc" })); + fireEvent.click(screen.getByRole("button", { name: "Go to next page" })); + await waitFor(() => expect(lastParams().page).toBe(2)); + fireEvent.mouseDown(screen.getByRole("combobox", { name: /rows per page/i })); + fireEvent.click(await screen.findByRole("option", { name: "20" })); + await waitFor(() => expect(lastParams()).toMatchObject({ page: 1, pageSize: 20 })); + fireEvent.click(screen.getByRole("button", { name: t.jobTableColumns })); + fireEvent.click(await screen.findByRole("menuitem", { name: t.settingsColumnJobUrl })); + expect(screen.queryByRole("link", { name: t.jobTableLink })).not.toBeInTheDocument(); +}); + +test("Trash select-all and bulk restore use the original IDs without workspace navigation", async () => { + show("trash"); + await screen.findByText(job.jobTitle); + fireEvent.click(screen.getByRole("checkbox", { name: t.jobTableSelectAll })); + fireEvent.click(screen.getByRole("button", { name: t.jobTableRestoreSelected })); + await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith("/jobapplications/42/restore")); + expect(screen.getByLabelText("Current route")).toHaveTextContent(/^\/trash$/); +}); + +async function compact() { + fireEvent.mouseDown(screen.getByRole("combobox", { name: t.listDensity })); + fireEvent.click(await screen.findByRole("option", { name: t.densityCompact })); +} + +test("density preserves selected rows, query, page, custom status, columns and listing link without refetch", async () => { + show("jobs", "?q=platform&page=2&sortBy=company&sortDir=asc"); + const row = await screen.findByRole("row", { name: /open platform engineer/i }); + const columns = within(row).getAllByRole("cell").length; + fireEvent.click(within(row).getByRole("checkbox")); + const before = calls().length; + expect(screen.getByRole("combobox", { name: t.listDensity })).toHaveTextContent(t.densityComfortable); + await compact(); + expect(within(row).getByRole("checkbox")).toBeChecked(); + expect(within(row).getAllByRole("cell")).toHaveLength(columns); + expect(within(row).getByText("Custom review")).toBeVisible(); + expect(within(row).getByRole("link", { name: t.jobTableLink })).toHaveAttribute("href", job.jobUrl); + expect(screen.getByText("16–30 of 31")).toBeVisible(); + expect(screen.getByLabelText("Current route")).toHaveTextContent("/jobs?q=platform&page=2&sortBy=company&sortDir=asc"); + expect(calls()).toHaveLength(before); + fireEvent.click(screen.getByRole("button", { name: "Offer" })); + await waitFor(() => expect(mockedApi.patch).toHaveBeenCalledWith("/jobapplications/42/status", { status: "Offer" })); +}); + +test("density is local and resets on unmount without writing settings or a saved view", async () => { + const view = show(); + await screen.findByText(job.jobTitle); + const stored = { ...localStorage }; + await compact(); + expect({ ...localStorage }).toEqual(stored); + expect(mockedApi.put).not.toHaveBeenCalled(); + view.unmount(); + show(); + await screen.findByText(job.jobTitle); + expect(screen.getByRole("combobox", { name: t.listDensity })).toHaveTextContent(t.densityComfortable); +}); + +test("density survives an empty result and a failed refresh with the existing retry action", async () => { + show(); + await screen.findByText(job.jobTitle); + await compact(); + mockedApi.get.mockImplementation((url: string) => url === "/jobapplications" ? Promise.reject({ message: "Synthetic unavailable", response: { status: 503 } }) : Promise.resolve({ data: [] } as any)); + fireEvent.click(screen.getByRole("button", { name: t.tableNextPage })); + expect(await screen.findByRole("alert")).toHaveTextContent("Synthetic unavailable"); + expect(screen.getByRole("combobox", { name: t.listDensity })).toHaveTextContent(t.densityCompact); + mockedApi.get.mockResolvedValue({ data: { items: [], total: 0, page: 1, pageSize: 15 } } as any); + fireEvent.click(screen.getByRole("button", { name: /retry/i })); + await waitFor(() => expect(screen.queryByRole("alert")).not.toBeInTheDocument()); + expect(screen.getByRole("combobox", { name: t.listDensity })).toHaveTextContent(t.densityCompact); + expect(screen.queryByText(job.jobTitle)).not.toBeInTheDocument(); +}); diff --git a/job-tracker-ui/src/theme.ts b/job-tracker-ui/src/theme.ts index d588cc2..c684dac 100644 --- a/job-tracker-ui/src/theme.ts +++ b/job-tracker-ui/src/theme.ts @@ -2,6 +2,8 @@ import { alpha, createTheme, darken, lighten } from "@mui/material/styles"; type PaletteLike = Record; +export type ContentDensity = "comfortable" | "compact"; + // Existing provisional brand hue. Dark mode uses a lighter tone for readable text; // this does not settle the Phase 3 brand/identity decision. const ACCENT = "#5B5BD6"; @@ -300,6 +302,31 @@ export const getTheme = (_mode: "light" | "dark") => { "@media (min-width: 1440px)": { ":root": { "--app-page-gutter": "32px" }, }, + // Opt-in MUI table/list spacing. Unmigrated consumers keep their defaults. + "[data-content-density]": { + "--app-table-cell-py": "12px", + "--app-list-item-padding": "16px", + "--app-list-gap": "12px", + "--app-data-target": "32px", + }, + '[data-content-density="compact"]': { + "--app-table-cell-py": "8px", + "--app-list-item-padding": "12px", + "--app-list-gap": "8px", + }, + // Density never shrinks hit regions. Coarse pointers and phone cards get + // 44px targets in either mode; desktop controls keep at least 32px. + "@media (pointer: coarse), (max-width: 767.95px)": { + "[data-content-density]": { "--app-data-target": "44px" }, + }, + "[data-content-density] .MuiIconButton-root, [data-content-density] .MuiCheckbox-root": { + minWidth: "var(--app-data-target)", minHeight: "var(--app-data-target)", + }, + "[data-content-density] .MuiTableSortLabel-root, [data-content-density] .MuiChip-clickable, [data-content-density] .MuiButton-root, [data-content-density] a": { + minHeight: "var(--app-data-target)", + }, + "[data-content-density] a": { display: "inline-flex", alignItems: "center" }, + "[data-content-density] .MuiTableCell-paddingCheckbox": { width: "auto" }, body: { WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale", @@ -525,8 +552,8 @@ export const getTheme = (_mode: "light" | "dark") => { background: theme.vars.palette.grey[100], }), root: { - paddingTop: 10, - paddingBottom: 10, + paddingTop: "var(--app-table-cell-py, 10px)", + paddingBottom: "var(--app-table-cell-py, 10px)", }, }, },