Hoppa till huvudinnehållet

Rapport / DEMO-01

Två hinder,
steg för steg.

Nordljus Demoaffär visar hur en avgränsad åtgärd kan beskrivas och lämnas över.

Fiktivt arbetsprov. Butiken och varan är påhittade. Inga kunduppgifter, verkliga köp eller betalningar används. Hindren i föreversionen är avsiktliga.

1. Vad arbetsprovet omfattar

Uppgiften är att välja en lykta, läsa varukorgen och välja leverans i en påhittad butik. Vi visar två ändringar: ett leveransval som bara reagerar på klick och en varukorg som är för bred på en smal skärm.

En sådan rapport är en del av överlämningen. I ett uppdrag får ni också den ändrade koden. Den som ansvarar för er butik granskar, för in och publicerar ändringarna.

Till översikten med alla före- och eftersidor.

2. Vilka delar går att ändra?

Produktsidan
Samma innehåll i båda versionerna. Inget av de två avsiktliga hindren finns här.
Varukorgen
Arbetsprovets egen kod. Bredd och ordning ändras i efterversionen.
Leveransvalet
Arbetsprovets egen kod. De klickbara valen ersätts med vanliga radioknappar.
Betalning och identifiering
Ingår inte. Ingen betalningskomponent finns i arbetsprovet.

En motsvarande karta i ett uppdrag behöver bekräftas av er. Att en del ligger utanför arbetet säger inget om dess tillgänglighet eller om vem som har rättsligt ansvar.

3. Vad har testats?

Det ursprungliga arbetsprovet har en automatisk Chromium-körning från den 2 september 2026 och en separat webbläsarkörning styrd av en AI-agent samma dag. De är äldre observationer av källmaterialet, inte resultat från en mänsklig testare eller från den här bearbetade webbplatsen.

Kontroller av den här webbplatsen dokumenteras separat vid varje bygg- och testtillfälle. De äldre observationerna får inte användas som bevis för att varje nuvarande sida fungerar.

Mänskliga manuella tester, skärmläsartester, användartester och tester i produktion har inte genomförts. Safari, Firefox och andra miljöer får inga resultat utifrån Chromium-körningen.

4. Leveransvalet kräver mus

Uppgift: Välj leveranssätt och fortsätt till det visade betalningssteget med tangentbord.

Före ändringen

Valen går att nå med Tab, men mellanslag, Enter och piltangenter väljer inget. Klick med mus fungerar. När inget är valt visar fortsättknappen ett meddelande och stannar i steget.

  1. Öppna kassan före ändring.
  2. Tryck Tab tills ni når Hemleverans.
  3. Prova mellanslag, Enter och piltangent ned. Kontrollera om något blir valt.
  4. Fortsätt med Tab till Fortsätt till betalning och tryck Enter.
  5. Jämför med att klicka på ett leveransval och fortsätta.

Ändringen

Leveranssätten blir vanliga radioknappar med tydliga etiketter i en gemensam grupp. Webbläsaren hanterar val med tangentbord. Ett felmeddelande kopplas till valen och fokus flyttas dit om ni fortsätter utan att välja.

Efter ändringen

Öppna kassan efter ändring. Prova samma steg. Mellanslag ska välja det fokuserade alternativet och piltangenterna ska flytta valet. Med ett valt alternativ ska fortsättknappen visa vilket som valts och flytta fokus till betalningsrubriken.

Detta är en avgränsad kontroll av leveransvalet. Betalning och identifiering går inte att testa här. WCAG 2.1.1 används som referens för tangentbordsfunktionen, inte som ett intyg för hela sidan.

5. Varukorgen är för bred

Uppgift: Läs varorna och sammanfattningen och nå Till kassan på en smal skärm.

Före ändringen

Två kolumner och fasta minsta bredder gör att sidan kräver rullning i sidled vid 320 bildpunkters bredd. Knappen till kassan hamnar utanför vyn.

  1. Öppna varukorgen före ändring.
  2. Gör fönstret 320 CSS-bildpunkter brett.
  3. Kontrollera om sidan måste rullas i sidled och om Till kassan syns.
  4. Jämför med varukorgen efter ändring vid samma bredd.

Ändringen

Varukorgen börjar med en kolumn. Två kolumner används först när det finns plats. Långa artikelnummer får brytas. Sammanfattningen och knappen följer efter artiklarna.

Efter ändringen

Vid 320 CSS-bildpunkter ska sidan rymmas utan rullning i sidled. Ordningen ska vara artiklar, sammanfattning och Till kassan. Vid bredare fönster ska två kolumner visas utan överlappning.

Layout kontrolleras vid 320 CSS-bildpunkters bredd. Kontrollerna testar inte webbläsarzoom eller ändrad textstorlek. WCAG 1.4.10 används som referens för just den här kontrollen.

6. Betalningen ligger utanför

I båda kassorna visas samma text om betalning. Ingen extern tjänst är ansluten. Det finns ingen betalning, identifiering eller beställning som kan genomföras.

Vi har därför inte testat eller ändrat en sådan komponent. I ett riktigt uppdrag behöver ni och leverantören ta ställning till eventuella hinder där.

7. Gör om kontrollerna

Vi använder Codex för återkörbara skriptade kontroller av utvalda tangentbordsinteraktioner, fokus, tillgänglighetsträd och layout samt axe-kontroller. Layout kontrolleras vid 320 CSS-bildpunkters bredd och andra angivna smala bredder. Kontrollerna testar inte webbläsarzoom eller ändrad textstorlek. Inga manuella tester, skärmläsartester eller användartester har genomförts.

Leveransvalet

  • Prova Tab, mellanslag och piltangenter i efterversionen.
  • Fortsätt utan val. Feltexten ska visas och fokus hamna vid första valet.
  • Välj ett alternativ. Feltexten ska försvinna.
  • Fortsätt igen. Det valda leveranssättet ska anges och fokus flyttas till betalningsrubriken.
  • Prova också klick på alternativets text.
  • Jämför alternativen, leveranstiderna och priserna med föreversionen.

Varukorgen

  • Kontrollera efterversionen vid 320 CSS-bildpunkters bredd.
  • Kontrollera att hela knappen till kassan ryms och går att nå med Tab.
  • Läs i ordningen artiklar, sammanfattning, Till kassan.
  • Öka bredden och kontrollera att kolumnerna inte överlappar.
  • Kontrollera att texter och priser är desamma i båda versionerna.

8. Om en ändring behöver återställas

Återställ ändringen i butikens versionshantering. Kontrollera sedan samma steg igen och se om det ursprungliga beteendet återkommer. I arbetsprovet påverkas inga sparade uppgifter eller externa system.

I ett kunduppdrag ska er utvecklare känna till återställningsstegen före publicering. Ni eller er byrå utför återställningen. Vi arbetar inte i produktion.

9. Se kodändringarna

Här är de delar som styr leveransvalet och varukorgens bredd i den här versionen. Kodexemplen kan användas för att följa skillnaden. De är inte instruktioner att klistra in i en annan butik utan granskning.

Före: leveransvalets funktion
import './delivery-options.css';

// Hinder 01 — FÖRE (avsiktligt seedat hinder).
// Leveransvalen är div-element med role="radio" och tabindex="0". De får fokus
// och fungerar med pekare (click), men det finns ingen hantering av mellanslag,
// Enter eller piltangenter. Ett div-element har ingen inbyggd aktivering, så
// tangentbordet ändrar aldrig valet och kassan kan inte fortsätta utan pekdon.

const continueButton = document.querySelector<HTMLButtonElement>('.kassa-fortsatt button');
const options = Array.from(document.querySelectorAll<HTMLElement>('.leveransval[role="radio"]'));
const warning = document.getElementById('leverans-varning');
const status = document.getElementById('kassa-status');
const paymentHeading = document.getElementById('betalning-rubrik');

let selected: HTMLElement | null = null;

function choose(option: HTMLElement): void {
  for (const candidate of options) {
    candidate.setAttribute('aria-checked', candidate === option ? 'true' : 'false');
  }
  selected = option;
  if (warning) {
    warning.hidden = true;
  }
}

for (const option of options) {
  option.addEventListener('click', () => choose(option));
}

continueButton?.addEventListener('click', (event) => {
  event.preventDefault();
  if (!selected) {
    if (warning) {
      warning.hidden = false;
    }
    if (status) {
      status.textContent = '';
    }
    return;
  }
  const name = selected.querySelector('.leveransval-namn')?.textContent?.trim() ?? 'okänt';
  if (status) {
    status.textContent = `Leveranssätt valt: ${name}. Nästa steg är betalning hos extern leverantör. Steget visas bara som exempel.`;
  }
  paymentHeading?.focus();
});
Före: varukorgens bredd
/* Hinder 02 — FÖRE (avsiktligt seedat hinder).
   Varukorgen har en fast tvåkolumnslayout med fasta minsta bredder, en
   sticky-summering med fast bredd och artikelnummer som inte får radbrytas.
   Vid 320 CSS-pixlars bredd (motsvarar 1280 px vid 400 % zoom) kräver
   sidan horisontell rullning och knappen ”Till kassan” ligger utanför vyn. */
.varukorg-layout {
  display: grid;
  grid-template-columns: minmax(440px, 1fr) 280px;
  gap: 1.5rem;
  min-width: 760px;
  align-items: start;
}

.varukorg-rad {
  display: grid;
  grid-template-columns: 96px minmax(300px, 1fr) 120px;
  gap: 1rem;
  align-items: start;
}

.rad-pris {
  text-align: right;
}

.artikelnummer {
  white-space: nowrap;
}

.varukorg-summering {
  position: sticky;
  top: 1rem;
  width: 280px;
}
Efter: leveransvalets funktion
import './delivery-options.css';

// Hinder 01 — EFTER (ändring).
// Leveransvalen är native radioknappar i ett fieldset med legend och label.
// Webbläsaren sköter mellanslag, piltangenter och pekare. Skriptet kopplar bara
// feltexten programmatiskt (aria-describedby/aria-invalid), flyttar fokus vid fel
// och ger statustext när kassan går vidare.

const continueButton = document.querySelector<HTMLButtonElement>('.kassa-fortsatt button');
const radios = Array.from(document.querySelectorAll<HTMLInputElement>('input[name="leverans"]'));
const error = document.getElementById('leverans-fel');
const status = document.getElementById('kassa-status');
const paymentHeading = document.getElementById('betalning-rubrik');

function selectedRadio(): HTMLInputElement | null {
  return radios.find((radio) => radio.checked) ?? null;
}

function clearError(): void {
  if (error) {
    error.hidden = true;
  }
  for (const radio of radios) {
    radio.removeAttribute('aria-invalid');
    radio.removeAttribute('aria-describedby');
  }
}

function showError(): void {
  if (error) {
    error.hidden = false;
    for (const radio of radios) {
      radio.setAttribute('aria-invalid', 'true');
      radio.setAttribute('aria-describedby', error.id);
    }
  }
  if (status) {
    status.textContent = '';
  }
  radios[0]?.focus();
}

for (const radio of radios) {
  radio.addEventListener('change', clearError);
}

continueButton?.addEventListener('click', (event) => {
  event.preventDefault();
  const choice = selectedRadio();
  if (!choice) {
    showError();
    return;
  }
  clearError();
  const label = document.querySelector(`label[for="${choice.id}"] .leveransval-namn`);
  const name = label?.textContent?.trim() ?? choice.value;
  if (status) {
    status.textContent = `Leveranssätt valt: ${name}. Nästa steg är betalning hos extern leverantör. Steget visas bara som exempel.`;
  }
  paymentHeading?.focus();
});
Efter: varukorgens bredd
/* Hinder 02 — EFTER (ändring).
   Enkolumnslayout som standard, tvåkolumnslayout först från 48 rem.
   Inga fasta minsta bredder, min-width: 0 på grid-barn, radbrytning
   tillåten för långa artikelnummer och sticky-summering endast vid
   bredare fönster. Ingen horisontell rullning på sidnivå vid 320 CSS-px. */
.varukorg-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}

.varukorg-layout > * {
  min-width: 0;
}

@media (min-width: 48rem) {
  .varukorg-layout {
    grid-template-columns: minmax(0, 1fr) minmax(16rem, 20rem);
  }

  .varukorg-summering {
    position: sticky;
    top: 1rem;
  }
}

.varukorg-rad {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.75rem;
  align-items: start;
}

.varukorg-rad > * {
  min-width: 0;
}

@media (min-width: 30rem) {
  .varukorg-rad {
    grid-template-columns: 6rem minmax(0, 1fr) auto;
    gap: 1rem;
  }

  .rad-pris {
    text-align: right;
  }
}

.artikelnummer {
  overflow-wrap: anywhere;
}

10. Det äldre automatiska underlaget

Den ursprungliga körningen gjordes med Playwright 1.61.1 och Chromium 149.0.7827.55 på macOS 27.0 den 2 september 2026 klockan 23.10.44. Den startades av Fable 5.1 Max, en AI-agent. Inget hjälpmedel användes.

Körningen visade det avsiktliga tangentbordshindret före ändring och det förväntade valet efter ändring. Den uppmätte också en för bred varukorg före ändring och en varukorg som rymdes vid 320 CSS-bildpunkter efter ändring.

Den automatiska regelkontrollen med axe-core 4.13.0 rapporterade inga fynd från de valda reglerna på arbetsprovets eftersidor i den körningen. En automatisk kontroll kan missa hinder. Den är inte ett intyg eller ett användartest.

Körningens referens: PW-CHROMIUM-20260902-2310440200. Ursprungliga källor och körningsuppgifter bevaras med projektets dokumentation.

11. Agentstyrda och mänskliga kontroller

Den separata agentstyrda webbläsarkörningen den 2 september 2026 jämförde varukorgens bredd och provade leveransvalen med pekare. Den kunde inte utföra tangentbordskontrollen på den då tillgängliga ytan. Det är inte en mänsklig manuell körning.

Körningens referens: AGENT-CURSOR-BROWSER-2026-09-02-2224.

VoiceOver, NVDA, JAWS och TalkBack: Ej testat. Användartester med personer med funktionsnedsättning: Ej testat. Mänsklig kontroll av utskrift och 400 procent webbläsarzoom: Ej testat.

12. Vad underlaget inte visar

Arbetsprovet visar ett arbetssätt i en liten, påhittad butik. Det visar inte kundresultat, efterfrågan på tjänsten, att en hel butik uppfyller en standard eller att lagkrav är uppfyllda.

Inga resultat anges för produktion, verkliga betalningar eller miljöer som inte har körts. Rapportens utskriftsvy är HTML. En PDF som ni själva sparar från webbläsaren har inte granskats som en tillgänglig, taggad PDF.

Tillbaka till arbetsprovet · Mejla om er webbutik