Rijkshuisstijl restyle + wizard fixes

Chrome: two-tier Rijksoverheid header (white brand bar + lint-blue
breadcrumb bar, route-driven), dark multi-column footer, white page
surface. Session shown via a shared SESSION_PORT token (keeps shared/
free of the auth context).

Overview ("Mijn overzicht") rebuilt to the NL Design System #392 pattern:
side-nav + "Wat moet ik regelen" task list (derived) + "Mijn registratie"
cards. New shared components: card, task-list, side-nav; pure
tasksFromProfile (+spec).

Wizards: grey form panel, connected numbered stepper, form-field
"(verplicht)" markers + styled description/error, full-width inputs.
Propagated to login, detail, change-request, address-fields.

Bug fixes:
- wizard-shell: add FormsModule so NgForm intercepts submit (wizards now
  advance; no native GET leaking choices into the URL).
- wizard-shell: error-summary links focus the field instead of navigating
  (a fragment href resolved against <base href="/"> reloaded to "/" and
  bounced to login).
- wizard-shell: error-summary focus only on the rising edge, so typing
  while errors are shown no longer scrolls the page up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 13:21:54 +02:00
parent d08f3877f7
commit 7a582ae2fa
30 changed files with 677 additions and 149 deletions

View File

@@ -0,0 +1,51 @@
import { Component, input } from '@angular/core';
import { LinkComponent } from '@shared/ui/link/link.component';
/** Presentational task shape — what "Wat moet ik regelen" renders. Domain-free so
shared/ stays independent of any context (a context's task type that has these
fields is structurally assignable). */
export interface TaskItem {
readonly title: string;
readonly description: string;
readonly to: string;
readonly actionLabel: string;
}
/** Molecule: the "Wat moet ik regelen" action list (NL Design System "Mijn
omgeving" pattern). Each task is a titled row with a call to action. */
@Component({
selector: 'app-task-list',
imports: [LinkComponent],
styles: [`
:host{display:block}
.tasks{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--rhc-space-max-md)}
.task{
display:flex;flex-wrap:wrap;gap:var(--rhc-space-max-md) var(--rhc-space-max-xl);
align-items:center;justify-content:space-between;
background:var(--rhc-color-wit);
border:var(--rhc-border-width-sm) solid var(--rhc-color-border-subtle);
border-inline-start:var(--rhc-border-width-md) solid var(--rhc-color-lintblauw-700);
border-radius:var(--rhc-border-radius-md);
padding:var(--rhc-space-max-lg) var(--rhc-space-max-xl);
}
.title{margin:0 0 var(--rhc-space-max-xs);font-weight:var(--rhc-text-font-weight-semi-bold)}
.desc{margin:0;color:var(--rhc-color-foreground-subtle);font-size:var(--rhc-text-font-size-sm)}
.cta{flex:0 0 auto}
`],
template: `
<ul class="tasks">
@for (t of tasks(); track t.title) {
<li class="task">
<div>
<p class="title">{{ t.title }}</p>
<p class="desc">{{ t.description }}</p>
</div>
<span class="cta"><app-link [to]="t.to">{{ t.actionLabel }} →</app-link></span>
</li>
}
</ul>
`,
})
export class TaskListComponent {
tasks = input.required<readonly TaskItem[]>();
}

View File

@@ -0,0 +1,22 @@
import type { Meta, StoryObj } from '@storybook/angular';
import { applicationConfig } from '@storybook/angular';
import { provideRouter } from '@angular/router';
import { TaskListComponent } from './task-list.component';
const meta: Meta<TaskListComponent> = {
title: 'Molecules/Task List',
component: TaskListComponent,
decorators: [applicationConfig({ providers: [provideRouter([])] })],
render: (args) => ({ props: args, template: `<app-task-list [tasks]="tasks" />` }),
};
export default meta;
type Story = StoryObj<TaskListComponent>;
export const Default: Story = {
args: {
tasks: [
{ title: 'Vraag uw herregistratie aan', description: 'Verleng uw registratie vóór 31 december 2026.', to: '/herregistratie', actionLabel: 'Herregistratie aanvragen' },
{ title: 'Controleer uw adresgegevens', description: 'Uw adres is langer dan een jaar niet bevestigd.', to: '/registratie', actionLabel: 'Bekijk uw gegevens' },
],
},
};