feat(cibg): WP-11 — render "Mijn aanvragen" as the CIBG Aanvragen component

- application-link switches to a `li[app-application-link]` attribute selector
  (native <li> child of the <ul> — axe-clean list) and drops the invented,
  dead `.application` / `.application-title` classes for the real vendored
  `.dashboard-block.applications li a` chain (h3.h3 / .subtitle / .status / .cta).
  Content stacks in a flex column; a non-navigating row mirrors the card surface
  from tokens. Re-enables a11y on the application-link/list stories.
- Dashboard "Mijn aanvragen" now renders through app-application-list +
  <li app-application-link> rows (was a keuzelijst), mapped by a new pure
  submittedRow() view helper (+ spec). Concepts stay the resumable melding.
- aanvraag-block is now concept-only (submitted mapping moved to aanvraag-view).

WP-11 grep gate clean. GREEN: lint, tokens, 181 tests, build, 136 axe stories.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-02 21:34:21 +02:00
parent 82fc3c493d
commit 98fd7e4bcd
8 changed files with 410 additions and 203 deletions

View File

@@ -2,33 +2,40 @@ import { Component, input, output } from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';
import { RouterLink } from '@angular/router';
/** Molecule: one row in a CIBG Huisstijl "aanvragen" list — `<li><a class="application">`
with a title, optional subtitle/status/cta (see application-list.component.ts).
Renders a plain (non-interactive) row when there's nothing to navigate to — the
chevron/hover styling only applies to the `<a>`. A `[applicationActions]` slot
projects a sibling action (e.g. "Annuleren") after the anchor — a button can't
nest inside the anchor itself. */
/** Molecule: one row in a CIBG Huisstijl "aanvragen" list
(designsystem.cibg.nl/componenten/aanvragen) — a white card-link styled by the
vendored `.dashboard-block.applications li a` chain (bg, chevron, link-blue `h3`),
with an optional `.subtitle`/`.status`/`.cta`. Used on an `<li>` so the `<ul>`'s
direct child is a native `<li>` (keeps the list axe-clean — a bare custom element
between `<ul>` and its `<li>` trips axe's list rule regardless of `display:contents`).
A non-navigating row renders a `<div>` (the vendored chain only styles `<a>`, so
that surface is mirrored from tokens). A `[applicationActions]` slot projects a
sibling action after the anchor — a button can't nest inside the anchor itself. */
@Component({
selector: 'app-application-link',
selector: 'li[app-application-link]',
imports: [RouterLink, NgTemplateOutlet],
// display:contents so the <li> becomes a real DOM/accessibility-tree child of the
// parent <ul> — a wrapper host between them can break list semantics for AT.
styles: [`:host{display:contents}`],
styles: [`
/* The vendored .applications li a surface only styles <a>; mirror it from tokens
for a non-navigating (informational) row so the card looks consistent. */
.static-row{display:flex;background:var(--rhc-color-wit);border-block-end:.065rem solid var(--rhc-color-border-subtle);padding:.75rem 2rem .75rem 1rem}
.content{flex:1 1 auto;min-inline-size:0}
.cta{margin-inline-start:auto;align-self:center}
`],
template: `
<li>
@if (to()) {
<a class="application" [routerLink]="to()"><ng-container [ngTemplateOutlet]="body" /></a>
} @else if (clickable()) {
<a href="#" class="application" (click)="onActivate($event)"><ng-container [ngTemplateOutlet]="body" /></a>
} @else {
<div><ng-container [ngTemplateOutlet]="body" /></div>
}
<ng-content select="[applicationActions]" />
</li>
@if (to()) {
<a [routerLink]="to()"><ng-container [ngTemplateOutlet]="body" /></a>
} @else if (clickable()) {
<a href="#" (click)="onActivate($event)"><ng-container [ngTemplateOutlet]="body" /></a>
} @else {
<div class="static-row"><ng-container [ngTemplateOutlet]="body" /></div>
}
<ng-content select="[applicationActions]" />
<ng-template #body>
<h3 class="application-title">{{ heading() }}</h3>
@if (subtitle()) { <div class="subtitle">{{ subtitle() }}</div> }
@if (status()) { <div class="status">{{ status() }}</div> }
<div class="content">
<h3 class="h3">{{ heading() }}</h3>
@if (subtitle()) { <div class="subtitle">{{ subtitle() }}</div> }
@if (status()) { <div class="status">{{ status() }}</div> }
</div>
@if (cta()) { <div class="cta">{{ cta() }}</div> }
</ng-template>
`,

View File

@@ -9,15 +9,9 @@ const meta: Meta<ApplicationLinkComponent> = {
decorators: [applicationConfig({ providers: [provideRouter([])] })],
render: (args) => ({
props: args,
// Rows are <li>s — a real list gives them their normal layout in the story.
template: `<ul class="list-unstyled"><app-application-link [heading]="heading" [subtitle]="subtitle" [status]="status" [cta]="cta" [to]="to" [clickable]="clickable" /></ul>`,
// Rows are <li>s in the "aanvragen" list — a real <ul> gives them their layout.
template: `<div class="dashboard-block applications"><ul class="list-unstyled"><li app-application-link [heading]="heading" [subtitle]="subtitle" [status]="status" [cta]="cta" [to]="to" [clickable]="clickable"></li></ul></div>`,
}),
parameters: {
// Structural: app-application-link's host sits between the <ul> and its <li> —
// axe's list/listitem rule requires them adjacent regardless of `display:contents`.
// WP-11 (CIBG markup fidelity) reworks this markup; see docs/backlog/WP-11-markup-fidelity.md.
a11y: { disable: true },
},
};
export default meta;
type Story = StoryObj<ApplicationLinkComponent>;

View File

@@ -14,16 +14,11 @@ const meta: Meta<ApplicationListComponent> = {
render: () => ({
template: `
<app-application-list>
<app-application-link heading="Inschrijving" status="Stap 2 van 3" cta="Verder gaan" clickable="true" />
<app-application-link heading="Herregistratie" status="Referentie 2024-00123 · ingediend op 12 mei 2024" />
<app-application-link heading="Inschrijven" subtitle="Schrijf u in in het BIG-register." to="/registreren" />
<li app-application-link heading="Inschrijving" status="Stap 2 van 3" cta="Verder gaan" clickable="true"></li>
<li app-application-link heading="Herregistratie" status="Referentie 2024-00123 · ingediend op 12 mei 2024"></li>
<li app-application-link heading="Inschrijven" subtitle="Schrijf u in in het BIG-register." to="/registreren"></li>
</app-application-list>`,
}),
parameters: {
// Structural: app-application-link's host sits between the <ul> and its <li> —
// fixed by the WP-11 markup rework. See docs/backlog/WP-11-markup-fidelity.md.
a11y: { disable: true },
},
};
export default meta;
type Story = StoryObj<ApplicationListComponent>;