feat(fp): WP-13 — CIBG-gap register + hygiene + MDX
Mark every hand-rolled shared/ui surface with a `// CIBG-GAP EXTENSION:` comment + `cibgGap` story parameter (skeleton, spinner, rich-text-editor, wizard-shell's error summary, application-link's non-navigating row, debug-state, status-badge, card, placeholder-chip) so deviations from the CIBG design system are auditable. Add the register MDX (Foundations/CIBG Gap Register), cross-linked from ADR-0003. Delete the near-identity upload-status-banner wrapper; its one consumer now uses <app-alert> directly (a story added to keep the info-banner state covered). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -48,3 +48,7 @@ layer — not a palette swap.
|
|||||||
alternative (adding the CSS to `angular.json` `styles`) would force-bundle the licensed fonts we
|
alternative (adding the CSS to `angular.json` `styles`) would force-bundle the licensed fonts we
|
||||||
intentionally dropped, so we accept the warning.
|
intentionally dropped, so we accept the warning.
|
||||||
- Renaming the internal token names from `--rhc-*` to `--app-*` is possible later but out of scope.
|
- Renaming the internal token names from `--rhc-*` to `--app-*` is possible later but out of scope.
|
||||||
|
- Hand-rolled components (point 4) are tracked in the **CIBG gap register**
|
||||||
|
(`src/docs/cibg-gaps.mdx`, Storybook "Foundations/CIBG Gap Register"): every deviation from the
|
||||||
|
design system carries a `// CIBG-GAP EXTENSION:` marker so it's auditable rather than silently
|
||||||
|
drifting.
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ for its existing violations, so every WP ends green.
|
|||||||
| [WP-07](WP-07-brief-idioms.md) | Brief on the shared idioms + RemoteData MDX | 1 · FP/DDD | done |
|
| [WP-07](WP-07-brief-idioms.md) | Brief on the shared idioms + RemoteData MDX | 1 · FP/DDD | done |
|
||||||
| [WP-08](WP-08-store-idiom.md) | One store idiom + machine naming + TEA MDX | 1 · FP/DDD | done |
|
| [WP-08](WP-08-store-idiom.md) | One store idiom + machine naming + TEA MDX | 1 · FP/DDD | done |
|
||||||
| [WP-09](WP-09-pure-logic.md) | Pure-logic closure: dates + missing command specs | 1 · FP/DDD | done |
|
| [WP-09](WP-09-pure-logic.md) | Pure-logic closure: dates + missing command specs | 1 · FP/DDD | done |
|
||||||
| [WP-10](WP-10-button-fidelity.md) | CIBG button fidelity | 2 · CIBG | todo |
|
| [WP-10](WP-10-button-fidelity.md) | CIBG button fidelity | 2 · CIBG | done |
|
||||||
| [WP-11](WP-11-markup-fidelity.md) | CIBG markup fidelity: application-link + absent-class triage | 2 · CIBG | done |
|
| [WP-11](WP-11-markup-fidelity.md) | CIBG markup fidelity: application-link + absent-class triage | 2 · CIBG | done |
|
||||||
| [WP-12](WP-12-datablock.md) | CIBG Datablock for application data | 2 · CIBG | done |
|
| [WP-12](WP-12-datablock.md) | CIBG Datablock for application data | 2 · CIBG | done |
|
||||||
| [WP-13](WP-13-cibg-gap-register.md) | CIBG-gap register + hygiene + MDX | 2 · CIBG | todo |
|
| [WP-13](WP-13-cibg-gap-register.md) | CIBG-gap register + hygiene + MDX | 2 · CIBG | done |
|
||||||
| [WP-14](WP-14-storybook-taxonomy.md) | Storybook taxonomy reorg + Layers MDX | 3 · Storybook | todo |
|
| [WP-14](WP-14-storybook-taxonomy.md) | Storybook taxonomy reorg + Layers MDX | 3 · Storybook | todo |
|
||||||
| [WP-15](WP-15-missing-stories.md) | Missing stories: shell + brief components | 3 · Storybook | todo |
|
| [WP-15](WP-15-missing-stories.md) | Missing stories: shell + brief components | 3 · Storybook | todo |
|
||||||
| [WP-16](WP-16-component-a11y.md) | Component a11y: description wiring + alert role | 4 · a11y | todo |
|
| [WP-16](WP-16-component-a11y.md) | Component a11y: description wiring + alert role | 4 · a11y | todo |
|
||||||
|
|||||||
@@ -1,8 +1,20 @@
|
|||||||
# WP-13 — CIBG-gap register + hygiene + MDX
|
# WP-13 — CIBG-gap register + hygiene + MDX
|
||||||
|
|
||||||
Status: todo
|
Status: done (<pending commit>)
|
||||||
Phase: 2 — CIBG fidelity
|
Phase: 2 — CIBG fidelity
|
||||||
|
|
||||||
|
> **Deviation:** WP-11/12 ran first but left no markers (deferred to this WP, as their own
|
||||||
|
> files note), so this WP defines the marker format fresh per its own Decisions block —
|
||||||
|
> not adopted from 11/12. The Decisions block's `task-list → Actieblok` mapping is stale:
|
||||||
|
> no `.actieblok`/`actie` class exists in the vendored CSS, and `task-list`'s own header
|
||||||
|
> comment already (accurately) documents it as composing `choice-list`'s Keuzelijst
|
||||||
|
> pattern rather than a distinct Actieblok one — left as-is rather than forced to claim a
|
||||||
|
> nonexistent mapping. `application-link`'s `.static-row` (flagged as a marked-gap
|
||||||
|
> candidate in this file's own correction note) got the marker too. The optional
|
||||||
|
> `check:cibg-gaps` script (step 4) is skipped: the register is nine rows, reviewed at PR
|
||||||
|
> time same as any other doc — a CI script to diff it against code markers is complexity
|
||||||
|
> the size of the problem doesn't warrant (noted, not built).
|
||||||
|
|
||||||
> **Correction (CIBG UI fidelity pass, b5c5d30):** this WP assumed the `upload/` suite
|
> **Correction (CIBG UI fidelity pass, b5c5d30):** this WP assumed the `upload/` suite
|
||||||
> had no vendored CIBG classes and would be marked as a CIBG-gap ("Bestand-upload").
|
> had no vendored CIBG classes and would be marked as a CIBG-gap ("Bestand-upload").
|
||||||
> The vendored build actually ships a full upload vocabulary (`.file-picker-drop-area`,
|
> The vendored build actually ships a full upload vocabulary (`.file-picker-drop-area`,
|
||||||
@@ -72,11 +84,11 @@ Components to mark (closest CIBG concept in parens):
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] Every component with hand-rolled surface CSS either wraps vendored classes or
|
- [x] Every component with hand-rolled surface CSS either wraps vendored classes or
|
||||||
carries the marker (spot-check with a grep for `styles: [` vs markers).
|
carries the marker (spot-check with a grep for `styles: [` vs markers).
|
||||||
- [ ] Register MDX complete, linked from ADR-0003.
|
- [x] Register MDX complete, linked from ADR-0003.
|
||||||
- [ ] `upload-status-banner` gone; consumer green; no story coverage lost.
|
- [x] `upload-status-banner` gone; consumer green; no story coverage lost.
|
||||||
- [ ] List trio documented.
|
- [x] List trio documented.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
|
|||||||
3201
documentation.json
3201
documentation.json
File diff suppressed because one or more lines are too long
@@ -32,6 +32,10 @@ export type WizardStatus = 'editing' | 'submitting' | 'submitted' | 'failed';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-wizard-shell',
|
selector: 'app-wizard-shell',
|
||||||
imports: [FormsModule, ButtonComponent, AlertComponent, SpinnerComponent, StepperComponent],
|
imports: [FormsModule, ButtonComponent, AlertComponent, SpinnerComponent, StepperComponent],
|
||||||
|
// CIBG-GAP EXTENSION: Foutmelding — the vendored build has no error-summary/
|
||||||
|
// Veldvalidatie list pattern (verified absent from huisstijl.min.css); the
|
||||||
|
// .es-title/.es-list rules below are the hand-rolled surface, see cibg-gaps.mdx.
|
||||||
|
// They render inside a vendored `.feedback-error` alert (app-alert).
|
||||||
styles: [
|
styles: [
|
||||||
`
|
`
|
||||||
.es-title {
|
.es-title {
|
||||||
|
|||||||
@@ -15,6 +15,15 @@ const meta: Meta<WizardShellComponent> = {
|
|||||||
<div wizardSuccess><p class="rhc-paragraph">Uw aanvraag is ontvangen.</p></div>
|
<div wizardSuccess><p class="rhc-paragraph">Uw aanvraag is ontvangen.</p></div>
|
||||||
</app-wizard-shell>`,
|
</app-wizard-shell>`,
|
||||||
}),
|
}),
|
||||||
|
parameters: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
component:
|
||||||
|
'CIBG-gap extension (error summary only) — see Foundations/CIBG Gap Register.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<WizardShellComponent>;
|
type Story = StoryObj<WizardShellComponent>;
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import { Component, input, output } from '@angular/core';
|
|||||||
import { NgTemplateOutlet } from '@angular/common';
|
import { NgTemplateOutlet } from '@angular/common';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
|
|
||||||
|
// CIBG-GAP EXTENSION: Aanvragen (non-navigating row) — the vendored
|
||||||
|
// `.dashboard-block.applications li a` chain only styles `<a>`; `.static-row`
|
||||||
|
// mirrors it from tokens for the non-navigating case, see cibg-gaps.mdx.
|
||||||
/** Molecule: one row in a CIBG Huisstijl "aanvragen" list
|
/** Molecule: one row in a CIBG Huisstijl "aanvragen" list
|
||||||
(designsystem.cibg.nl/componenten/aanvragen) — a white card-link styled by the
|
(designsystem.cibg.nl/componenten/aanvragen) — a white card-link styled by the
|
||||||
vendored `.dashboard-block.applications li a` chain (bg, chevron, link-blue `h3`),
|
vendored `.dashboard-block.applications li a` chain (bg, chevron, link-blue `h3`),
|
||||||
|
|||||||
@@ -12,6 +12,15 @@ const meta: Meta<ApplicationLinkComponent> = {
|
|||||||
// Rows are <li>s in the "aanvragen" list — a real <ul> gives them their layout.
|
// 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>`,
|
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: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
component:
|
||||||
|
'CIBG-gap extension (non-navigating row only, see NietInteractief) — see Foundations/CIBG Gap Register.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<ApplicationLinkComponent>;
|
type Story = StoryObj<ApplicationLinkComponent>;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { Component, input } from '@angular/core';
|
import { Component, input } from '@angular/core';
|
||||||
import { HeadingComponent } from '@shared/ui/heading/heading.component';
|
import { HeadingComponent } from '@shared/ui/heading/heading.component';
|
||||||
|
|
||||||
|
// CIBG-GAP EXTENSION: n/a — no vendored generic-card class; `.app-card` is a
|
||||||
|
// hand-rolled surface (NOT Bootstrap's `.card`), see cibg-gaps.mdx. Prefer the
|
||||||
|
// vendored Datablock (WP-12, `app-data-block`) for application/user data.
|
||||||
/** Molecule: a content card. Standardises the repeated card surface (white,
|
/** Molecule: a content card. Standardises the repeated card surface (white,
|
||||||
subtle border, rounded, padded) so pages compose cards instead of hand-rolling
|
subtle border, rounded, padded) so pages compose cards instead of hand-rolling
|
||||||
a hand-rolled card surface. Optional heading; the rest is projected.
|
a hand-rolled card surface. Optional heading; the rest is projected.
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ const meta: Meta<CardComponent> = {
|
|||||||
</app-card>`,
|
</app-card>`,
|
||||||
}),
|
}),
|
||||||
args: { heading: 'Persoonsgegevens (BRP)', level: 3 },
|
args: { heading: 'Persoonsgegevens (BRP)', level: 3 },
|
||||||
|
parameters: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: { description: { component: 'CIBG-gap extension — see Foundations/CIBG Gap Register.' } },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<CardComponent>;
|
type Story = StoryObj<CardComponent>;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { BigProfileStore } from '@registratie/application/big-profile.store';
|
|||||||
import { map } from '@shared/application/remote-data';
|
import { map } from '@shared/application/remote-data';
|
||||||
import { maskBsn, redactProfile } from './mask';
|
import { maskBsn, redactProfile } from './mask';
|
||||||
|
|
||||||
|
// CIBG-GAP EXTENSION: n/a — devtool, no corresponding CIBG concept; deliberately
|
||||||
|
// off-theme by design (see the ponytail note below), see cibg-gaps.mdx.
|
||||||
/**
|
/**
|
||||||
* Dev-only "show the current Model" panel (Elm-debugger style, read-only).
|
* Dev-only "show the current Model" panel (Elm-debugger style, read-only).
|
||||||
* Observes the root singletons and renders them via the json pipe. Never a
|
* Observes the root singletons and renders them via the json pipe. Never a
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import { DebugStateComponent } from './debug-state.component';
|
|||||||
const meta: Meta<DebugStateComponent> = {
|
const meta: Meta<DebugStateComponent> = {
|
||||||
title: 'Devtools/State debug',
|
title: 'Devtools/State debug',
|
||||||
component: DebugStateComponent,
|
component: DebugStateComponent,
|
||||||
|
parameters: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: { description: { component: 'CIBG-gap extension — see Foundations/CIBG Gap Register.' } },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<DebugStateComponent>;
|
type Story = StoryObj<DebugStateComponent>;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Component, computed, input } from '@angular/core';
|
import { Component, computed, input } from '@angular/core';
|
||||||
|
|
||||||
|
// CIBG-GAP EXTENSION: n/a — no vendored inline-chip/tag class; hand-rolled
|
||||||
|
// brace-wrapped chip, see cibg-gaps.mdx.
|
||||||
/** Atom: a highlighted, non-editable placeholder chip for READ-ONLY rendering
|
/** Atom: a highlighted, non-editable placeholder chip for READ-ONLY rendering
|
||||||
(preview, diagnostics). Distinct styling for auto-resolvable vs manual fields and
|
(preview, diagnostics). Distinct styling for auto-resolvable vs manual fields and
|
||||||
for linter error/warning states. Domain-free and presentational — the caller
|
for linter error/warning states. Domain-free and presentational — the caller
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ const meta: Meta<PlaceholderChipComponent> = {
|
|||||||
props: args,
|
props: args,
|
||||||
template: `<app-placeholder-chip [label]="label" [autoResolvable]="autoResolvable" [state]="state"></app-placeholder-chip>`,
|
template: `<app-placeholder-chip [label]="label" [autoResolvable]="autoResolvable" [state]="state"></app-placeholder-chip>`,
|
||||||
}),
|
}),
|
||||||
|
parameters: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: { description: { component: 'CIBG-gap extension — see Foundations/CIBG Gap Register.' } },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<PlaceholderChipComponent>;
|
type Story = StoryObj<PlaceholderChipComponent>;
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ export interface PlaceholderOption {
|
|||||||
readonly autoResolvable?: boolean;
|
readonly autoResolvable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CIBG-GAP EXTENSION: Tekstgebied — CIBG has no rich-text/WYSIWYG pattern (a
|
||||||
|
// contenteditable editor with formatting + placeholder chips); hand-rolled
|
||||||
|
// surface (toolbar + chip styling), see cibg-gaps.mdx. Buttons still use the
|
||||||
|
// vendored .btn-ghost class (WP-10).
|
||||||
/**
|
/**
|
||||||
* Molecule: a minimal no-dependency WYSIWYG editor over a `RichTextBlock`.
|
* Molecule: a minimal no-dependency WYSIWYG editor over a `RichTextBlock`.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ const meta: Meta<RichTextEditorComponent> = {
|
|||||||
props: args,
|
props: args,
|
||||||
template: `<app-rich-text-editor [content]="content" [placeholders]="placeholders" [editable]="editable"></app-rich-text-editor>`,
|
template: `<app-rich-text-editor [content]="content" [placeholders]="placeholders" [editable]="editable"></app-rich-text-editor>`,
|
||||||
}),
|
}),
|
||||||
|
parameters: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: { description: { component: 'CIBG-gap extension — see Foundations/CIBG Gap Register.' } },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<RichTextEditorComponent>;
|
type Story = StoryObj<RichTextEditorComponent>;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Component, OnDestroy, OnInit, computed, input, signal } from '@angular/core';
|
import { Component, OnDestroy, OnInit, computed, input, signal } from '@angular/core';
|
||||||
|
|
||||||
|
// CIBG-GAP EXTENSION: Laadindicatie — no vendored loading-skeleton class exists
|
||||||
|
// (verified absent from huisstijl.min.css); hand-rolled shimmer, see cibg-gaps.mdx.
|
||||||
/** Atom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes
|
/** Atom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes
|
||||||
on fast responses. Render `count` lines shaped roughly like the content. */
|
on fast responses. Render `count` lines shaped roughly like the content. */
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ const meta: Meta<SkeletonComponent> = {
|
|||||||
title: 'Atoms/Skeleton',
|
title: 'Atoms/Skeleton',
|
||||||
component: SkeletonComponent,
|
component: SkeletonComponent,
|
||||||
args: { delay: 0 },
|
args: { delay: 0 },
|
||||||
|
parameters: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: { description: { component: 'CIBG-gap extension — see Foundations/CIBG Gap Register.' } },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<SkeletonComponent>;
|
type Story = StoryObj<SkeletonComponent>;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Component, OnDestroy, OnInit, input, signal } from '@angular/core';
|
import { Component, OnDestroy, OnInit, input, signal } from '@angular/core';
|
||||||
|
|
||||||
|
// CIBG-GAP EXTENSION: Laadindicatie — no vendored loading-spinner class exists
|
||||||
|
// (verified absent from huisstijl.min.css); hand-rolled, see cibg-gaps.mdx.
|
||||||
/** Atom: spinner that only appears after `delay` ms — fast responses never
|
/** Atom: spinner that only appears after `delay` ms — fast responses never
|
||||||
flash a spinner, slow ones get feedback. */
|
flash a spinner, slow ones get feedback. */
|
||||||
@Component({
|
@Component({
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import { SpinnerComponent } from './spinner.component';
|
|||||||
const meta: Meta<SpinnerComponent> = {
|
const meta: Meta<SpinnerComponent> = {
|
||||||
title: 'Atoms/Spinner',
|
title: 'Atoms/Spinner',
|
||||||
component: SpinnerComponent,
|
component: SpinnerComponent,
|
||||||
|
parameters: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: { description: { component: 'CIBG-gap extension — see Foundations/CIBG Gap Register.' } },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<SpinnerComponent>;
|
type Story = StoryObj<SpinnerComponent>;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Component, input } from '@angular/core';
|
import { Component, input } from '@angular/core';
|
||||||
|
|
||||||
|
// CIBG-GAP EXTENSION: n/a — deliberate custom surface, not Bootstrap's `.badge`
|
||||||
|
// (whose pill padding/colour don't fit a status dot); see cibg-gaps.mdx.
|
||||||
/** Atom: a coloured dot + label. Purely presentational and domain-free — the
|
/** Atom: a coloured dot + label. Purely presentational and domain-free — the
|
||||||
caller decides what colour and label mean (e.g. via registration.policy).
|
caller decides what colour and label mean (e.g. via registration.policy).
|
||||||
This keeps the shared UI kernel free of any domain knowledge. */
|
This keeps the shared UI kernel free of any domain knowledge. */
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import { StatusBadgeComponent } from './status-badge.component';
|
|||||||
const meta: Meta<StatusBadgeComponent> = {
|
const meta: Meta<StatusBadgeComponent> = {
|
||||||
title: 'Shared UI/Status Badge',
|
title: 'Shared UI/Status Badge',
|
||||||
component: StatusBadgeComponent,
|
component: StatusBadgeComponent,
|
||||||
|
parameters: {
|
||||||
|
cibgGap: true,
|
||||||
|
docs: { description: { component: 'CIBG-gap extension — see Foundations/CIBG Gap Register.' } },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<StatusBadgeComponent>;
|
type Story = StoryObj<StatusBadgeComponent>;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { Component, input, output } from '@angular/core';
|
import { Component, input, output } from '@angular/core';
|
||||||
import type { DeliveryChannel, UploadState } from '@shared/upload/upload.machine';
|
import type { DeliveryChannel, UploadState } from '@shared/upload/upload.machine';
|
||||||
|
import { AlertComponent } from '@shared/ui/alert/alert.component';
|
||||||
import { DocumentCategoryComponent } from '../document-category/document-category.component';
|
import { DocumentCategoryComponent } from '../document-category/document-category.component';
|
||||||
import { UploadStatusBannerComponent } from '../upload-status-banner/upload-status-banner.component';
|
|
||||||
|
|
||||||
/** Organism: the full document-upload step — the category list, or a load-error
|
/** Organism: the full document-upload step — the category list, or a load-error
|
||||||
banner. Pure UI: re-exposes the category events, tagging each with its category
|
banner. Pure UI: re-exposes the category events, tagging each with its category
|
||||||
where the parent needs it. The container wires these to the upload reducer. */
|
where the parent needs it. The container wires these to the upload reducer. */
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-document-upload',
|
selector: 'app-document-upload',
|
||||||
imports: [DocumentCategoryComponent, UploadStatusBannerComponent],
|
imports: [DocumentCategoryComponent, AlertComponent],
|
||||||
styles: [
|
styles: [
|
||||||
`
|
`
|
||||||
:host {
|
:host {
|
||||||
@@ -20,10 +20,10 @@ import { UploadStatusBannerComponent } from '../upload-status-banner/upload-stat
|
|||||||
],
|
],
|
||||||
template: `
|
template: `
|
||||||
@if (state().categoriesError) {
|
@if (state().categoriesError) {
|
||||||
<app-upload-status-banner type="error" [message]="state().categoriesError!" />
|
<app-alert type="error">{{ state().categoriesError }}</app-alert>
|
||||||
} @else {
|
} @else {
|
||||||
@if (state().backgroundSyncAvailable === false && state().categories.length > 0) {
|
@if (state().backgroundSyncAvailable === false && state().categories.length > 0) {
|
||||||
<app-upload-status-banner type="info" [message]="foregroundOnlyMessage" />
|
<app-alert type="info">{{ foregroundOnlyMessage }}</app-alert>
|
||||||
}
|
}
|
||||||
@for (c of state().categories; track c.categoryId) {
|
@for (c of state().categories; track c.categoryId) {
|
||||||
<app-document-category
|
<app-document-category
|
||||||
|
|||||||
@@ -56,3 +56,7 @@ export const Default: Story = { args: { state } };
|
|||||||
export const LoadError: Story = {
|
export const LoadError: Story = {
|
||||||
args: { state: { ...state, categoriesError: 'De categorieën konden niet worden geladen.' } },
|
args: { state: { ...state, categoriesError: 'De categorieën konden niet worden geladen.' } },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ForegroundOnly: Story = {
|
||||||
|
args: { state: { ...state, backgroundSyncAvailable: false } },
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import { Component, computed, input } from '@angular/core';
|
|
||||||
import { AlertComponent } from '@shared/ui/alert/alert.component';
|
|
||||||
|
|
||||||
type BannerType = 'info' | 'warning' | 'error';
|
|
||||||
type AlertType = 'info' | 'ok' | 'warning' | 'error';
|
|
||||||
|
|
||||||
/** Molecule: a polite, announced status banner. Wraps the alert atom and maps the
|
|
||||||
banner type to an alert type. Pure UI: the container computes the message. */
|
|
||||||
@Component({
|
|
||||||
selector: 'app-upload-status-banner',
|
|
||||||
imports: [AlertComponent],
|
|
||||||
template: `
|
|
||||||
<div aria-live="polite">
|
|
||||||
<app-alert [type]="alertType()">{{ message() }}</app-alert>
|
|
||||||
</div>
|
|
||||||
`,
|
|
||||||
})
|
|
||||||
export class UploadStatusBannerComponent {
|
|
||||||
message = input.required<string>();
|
|
||||||
type = input<BannerType>('info');
|
|
||||||
|
|
||||||
protected readonly alertType = computed<AlertType>(() =>
|
|
||||||
this.type() === 'info' ? 'info' : this.type(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/angular';
|
|
||||||
import { UploadStatusBannerComponent } from './upload-status-banner.component';
|
|
||||||
|
|
||||||
const meta: Meta<UploadStatusBannerComponent> = {
|
|
||||||
title: 'Molecules/UploadStatusBanner',
|
|
||||||
component: UploadStatusBannerComponent,
|
|
||||||
render: (args) => ({
|
|
||||||
props: args,
|
|
||||||
template: `<app-upload-status-banner [message]="message" [type]="type" />`,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
export default meta;
|
|
||||||
type Story = StoryObj<UploadStatusBannerComponent>;
|
|
||||||
|
|
||||||
export const Info: Story = {
|
|
||||||
args: { type: 'info', message: 'Uw documenten worden geüpload.' },
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Error: Story = {
|
|
||||||
args: { type: 'error', message: 'De categorieën konden niet worden geladen.' },
|
|
||||||
};
|
|
||||||
52
src/docs/cibg-gaps.mdx
Normal file
52
src/docs/cibg-gaps.mdx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { Meta } from '@storybook/addon-docs/blocks';
|
||||||
|
|
||||||
|
<Meta title="Foundations/CIBG Gap Register" />
|
||||||
|
|
||||||
|
# CIBG gap register
|
||||||
|
|
||||||
|
CIBG Huisstijl (ADR-0003) is the design system of record — a component wraps a vendored class
|
||||||
|
before it hand-rolls anything. **Grep the vendored CSS
|
||||||
|
(`public/cibg-huisstijl/css/huisstijl.min.css`) before adding new surface CSS to a component.**
|
||||||
|
When no vendored pattern exists, the component is a **CIBG-gap extension**: allowed, but only
|
||||||
|
marked so every deviation from the design system is auditable.
|
||||||
|
|
||||||
|
## Marker format
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// CIBG-GAP EXTENSION: <closest CIBG concept, or "n/a"> — <why hand-rolled>
|
||||||
|
```
|
||||||
|
|
||||||
|
placed above the `@Component` decorator, plus `parameters: { cibgGap: true }` and a
|
||||||
|
"CIBG-gap extension" line in the story's `docs.description.component`.
|
||||||
|
|
||||||
|
## The register
|
||||||
|
|
||||||
|
| Component | Closest CIBG concept | Why hand-rolled |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `skeleton` | Laadindicatie | No loading-skeleton class in the vendored build. |
|
||||||
|
| `spinner` | Laadindicatie | No loading-spinner class in the vendored build. |
|
||||||
|
| `rich-text-editor` | Tekstgebied | No rich-text/WYSIWYG pattern; toolbar buttons still use vendored `.btn-ghost` (WP-10). |
|
||||||
|
| `wizard-shell` (error summary only) | Foutmelding | No error-summary/Veldvalidatie list class; renders inside a vendored `.feedback-error` alert. |
|
||||||
|
| `application-link` (non-navigating row) | Aanvragen | The vendored `.dashboard-block.applications li a` chain only styles `<a>`; `.static-row` mirrors it from tokens for the informational (non-link) case. |
|
||||||
|
| `debug-state` | n/a | Dev-only tool, deliberately off-theme — see the component's own `ponytail:` note. |
|
||||||
|
| `status-badge` | n/a | Deliberate custom status dot, not Bootstrap's `.badge` (pill padding/colour don't fit). |
|
||||||
|
| `card` (`.app-card`) | n/a | No vendored generic-card class; prefer the vendored **Datablock** (`app-data-block`, WP-12) for application/user data. |
|
||||||
|
| `placeholder-chip` | n/a | No vendored inline-chip/tag class. |
|
||||||
|
|
||||||
|
Not a gap: `confirmation` renders entirely with vendored `.confirmation*` classes (no `styles:
|
||||||
|
[...]` block) — its header comment names the pattern, no marker needed. The `upload/` suite
|
||||||
|
renders entirely with vendored classes (`.file-picker-drop-area`, `.btn-upload`, …) — reworked
|
||||||
|
onto them rather than marked (see WP-11's correction note). `task-list`, `application-list`, and
|
||||||
|
`choice-list` each wrap a distinct vendored pattern (Keuzelijst / Aanvragen / Keuzelijst) and name
|
||||||
|
it in their own header comment — no marker needed, they don't hand-roll surface CSS.
|
||||||
|
|
||||||
|
## Hygiene
|
||||||
|
|
||||||
|
`upload-status-banner` (a 23-line near-identity wrapper over `app-alert` with one consumer) was
|
||||||
|
deleted; its consumer (`document-upload`) now uses `<app-alert>` directly.
|
||||||
|
|
||||||
|
## Keeping this register honest
|
||||||
|
|
||||||
|
No automated check diffs this table against the markers in code (skipped as not worth a CI
|
||||||
|
script for a table this small — reviewed at PR time instead, same as any other doc). If markers
|
||||||
|
and this table drift, trust the code and fix the table.
|
||||||
Reference in New Issue
Block a user