fix(cibg): wizard fields render as grey fieldset groups

Wizard steps rendered bare .form-group divs, so CIBG's
".form-horizontal fieldset { background:#f1f5f9; margin-bottom:1.25em }"
never matched and inputs showed on white instead of the grey CIBG surface.

Wrap each logical field group per step in a <fieldset> (intake, herregistratie
and registratie wizards); CIBG then gives every group its grey surface with a
1.25em gap between groups. The shell stays group-agnostic (no outer fieldset,
which would hide the white gaps). address-fields already used a <fieldset>.

Adds intake-wizard.component.spec.ts asserting the buitenland step renders its
groups as separate fieldsets (guards against the wrapping being dropped again).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-20 13:39:13 +02:00
co-authored by Claude Opus 4.8
parent f6c837f281
commit 950fb5f0b2
5 changed files with 292 additions and 226 deletions
@@ -64,6 +64,7 @@ import { UploadState, initialUpload, deliveryRefs } from '@shared/upload/upload.
>
@switch (step()) {
@case (1) {
<fieldset>
<app-form-field
i18n-label="@@herregWizard.urenLabel"
label="Gewerkte uren (afgelopen 5 jaar)"
@@ -98,8 +99,10 @@ import { UploadState, initialUpload, deliveryRefs } from '@shared/upload/upload.
placeholder="bijv. 5"
/>
</app-form-field>
</fieldset>
}
@case (2) {
<fieldset>
<app-form-field
i18n-label="@@herregWizard.puntenLabel"
label="Behaalde nascholingspunten"
@@ -117,6 +120,7 @@ import { UploadState, initialUpload, deliveryRefs } from '@shared/upload/upload.
placeholder="bijv. 200"
/>
</app-form-field>
</fieldset>
}
@case (3) {
<app-document-upload
@@ -0,0 +1,36 @@
import { provideHttpClient } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { describe, expect, it } from 'vitest';
import { provideApiClient } from '@shared/infrastructure/api-client.provider';
import { IntakeWizardComponent } from './intake-wizard.component';
import { IntakeState } from '@herregistratie/domain/intake.machine';
// Regression: wizard steps must render their logical field groups as separate CIBG grey
// <fieldset> blocks (`.form-horizontal fieldset` ⇒ #f1f5f9, 1.25em gap). If the fieldset
// wrapping is dropped, the inputs revert to bare white. The buitenland step with
// buitenlandGewerkt='ja' has two groups (the question + the land/uren follow-up), so it
// must render ≥2 fieldsets, each holding a form-group.
const buitenlandJa: IntakeState = {
tag: 'Answering',
answers: { buitenlandGewerkt: 'ja' },
cursor: 0,
errors: {},
scholingThreshold: 1000,
};
describe('IntakeWizardComponent', () => {
it('renders each field group as its own grey <fieldset>', () => {
TestBed.configureTestingModule({
providers: [provideHttpClient(), provideApiClient()],
});
const fixture = TestBed.createComponent(IntakeWizardComponent);
fixture.componentInstance.dispatch({ tag: 'Seed', state: buitenlandJa });
fixture.detectChanges();
const fieldsets: HTMLElement[] = Array.from(
fixture.nativeElement.querySelectorAll('form.form-horizontal fieldset'),
);
expect(fieldsets.length).toBeGreaterThanOrEqual(2);
fieldsets.forEach((fs) => expect(fs.querySelector('.form-group')).toBeTruthy());
});
});
@@ -71,6 +71,7 @@ import { IntakePolicyStore } from '@herregistratie/application/intake-policy.sto
>
@switch (step()) {
@case ('buitenland') {
<fieldset>
<app-form-field
i18n-label="@@intake.q.buitenland"
label="Heeft u de afgelopen 5 jaar buiten Nederland gewerkt?"
@@ -85,7 +86,9 @@ import { IntakePolicyStore } from '@herregistratie/application/intake-policy.sto
(ngModelChange)="set('buitenlandGewerkt', $event)"
/>
</app-form-field>
</fieldset>
@if (answers().buitenlandGewerkt === 'ja') {
<fieldset>
<app-form-field
i18n-label="@@intake.q.land"
label="In welk land?"
@@ -118,9 +121,11 @@ import { IntakePolicyStore } from '@herregistratie/application/intake-policy.sto
placeholder="bijv. 800"
/>
</app-form-field>
</fieldset>
}
}
@case ('werk') {
<fieldset>
<app-form-field
i18n-label="@@intake.q.urenNl"
label="Gewerkte uren in Nederland (afgelopen 5 jaar)"
@@ -137,7 +142,9 @@ import { IntakePolicyStore } from '@herregistratie/application/intake-policy.sto
placeholder="bijv. 4160"
/>
</app-form-field>
</fieldset>
@if (scholingZichtbaar()) {
<fieldset>
<app-form-field
i18n-label="@@intake.q.scholing"
label="U werkte relatief weinig uren. Heeft u aanvullende scholing gevolgd?"
@@ -152,8 +159,10 @@ import { IntakePolicyStore } from '@herregistratie/application/intake-policy.sto
(ngModelChange)="set('scholingGevolgd', $event)"
/>
</app-form-field>
</fieldset>
}
@if (answers().scholingGevolgd === 'ja') {
<fieldset>
<app-form-field
i18n-label="@@intake.q.punten"
label="Behaalde nascholingspunten"
@@ -170,6 +179,7 @@ import { IntakePolicyStore } from '@herregistratie/application/intake-policy.sto
placeholder="bijv. 200"
/>
</app-form-field>
</fieldset>
}
}
@case ('review') {
@@ -130,6 +130,7 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
}"
(fieldChange)="set($event.key, $event.value)"
/>
<fieldset>
<app-form-field
i18n-label="@@regWizard.correspondentieLabel"
label="Hoe wilt u correspondentie ontvangen?"
@@ -145,7 +146,9 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
(ngModelChange)="setKanaal($event)"
/>
</app-form-field>
</fieldset>
@if (draft().correspondentie === 'email') {
<fieldset>
<app-form-field
i18n-label="@@regWizard.emailLabel"
label="E-mailadres"
@@ -164,6 +167,7 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
placeholder="naam@voorbeeld.nl"
/>
</app-form-field>
</fieldset>
}
}
}
@@ -171,6 +175,7 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
<app-async [data]="lookupRd()">
<ng-template appAsyncLoaded>
@if (duoData(); as data) {
<fieldset>
<app-form-field
i18n-label="@@regWizard.diplomaLabel"
label="Kies het diploma waarmee u zich wilt registreren"
@@ -186,6 +191,7 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
(ngModelChange)="onDiplomaKeuze(data, $event)"
/>
</app-form-field>
</fieldset>
@if (handmatigActief()) {
<app-alert type="warning" i18n="@@regWizard.handmatigWaarschuwing"
@@ -193,6 +199,7 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
uw beroep en beantwoord de aanvullende vragen; uw aanvraag wordt daarna
handmatig beoordeeld.</app-alert
>
<fieldset>
<app-form-field
i18n-label="@@regWizard.beroepLabel"
label="Voor welk beroep wilt u zich registreren?"
@@ -207,6 +214,7 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
(ngModelChange)="dispatch({ tag: 'DeclareerBeroep', beroep: $event })"
/>
</app-form-field>
</fieldset>
} @else if (draft().beroep) {
<dl class="mb-0 app-section">
<div
@@ -218,6 +226,8 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
</dl>
}
@if (actieveVragen(data).length) {
<fieldset>
@for (q of actieveVragen(data); track q.id) {
<app-form-field
[label]="q.vraag"
@@ -248,6 +258,8 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid';
}
</app-form-field>
}
</fieldset>
}
}
</ng-template>
<ng-template appAsyncLoading>
@@ -90,6 +90,10 @@ export type WizardStatus = 'editing' | 'submitting' | 'submitted' | 'failed';
<span class="meta" i18n="@@form.verplichteVelden">* verplichte velden</span>
</div>
</div>
<!-- Wizard pages wrap their field groups in <fieldset>s; CIBG's
".form-horizontal fieldset" gives each a grey #f1f5f9 surface with a 1.25em
gap. The shell stays group-agnostic and does NOT add its own fieldset (an
outer grey fieldset would hide the white gaps between the page groups). -->
<ng-content />
<hr />
<div class="d-flex flex-column flex-sm-row-reverse">