diff --git a/src/app/registratie/ui/address-fields/address-fields.component.ts b/src/app/registratie/ui/address-fields/address-fields.component.ts index c4bbc64..98cc28d 100644 --- a/src/app/registratie/ui/address-fields/address-fields.component.ts +++ b/src/app/registratie/ui/address-fields/address-fields.component.ts @@ -19,14 +19,11 @@ export type AdresErrors = Partial>; @Component({ selector: 'app-address-fields', imports: [FormsModule, FormFieldComponent, TextInputComponent], + // No scoped `fieldset` reset here: the fieldset must keep CIBG's + // `.form-horizontal fieldset` grey-box padding/margin. A local `fieldset{padding:0}` + // would tie on specificity and (injected later) win, flattening the padding. styles: [ ` - fieldset { - border: 0; - margin: 0; - padding: 0; - min-inline-size: 0; - } legend { padding: 0; font-weight: var(--rhc-text-font-weight-semi-bold); diff --git a/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts b/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts index 714b298..aa2b60a 100644 --- a/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts +++ b/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts @@ -7,6 +7,7 @@ import { ButtonComponent } from '@shared/ui/button/button.component'; import { AlertComponent } from '@shared/ui/alert/alert.component'; import { SkeletonComponent } from '@shared/ui/skeleton/skeleton.component'; import { DataRowComponent } from '@shared/ui/data-row/data-row.component'; +import { DataBlockComponent } from '@shared/ui/data-block/data-block.component'; import { ReviewSectionComponent } from '@shared/ui/review-section/review-section.component'; import { ConfirmationComponent } from '@shared/ui/confirmation/confirmation.component'; import { @@ -67,6 +68,7 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid'; AlertComponent, SkeletonComponent, DataRowComponent, + DataBlockComponent, ReviewSectionComponent, ConfirmationComponent, WizardShellComponent, @@ -216,14 +218,14 @@ const NL_TAALVAARDIGHEID_VRAAG = 'nl-taalvaardigheid'; } @else if (draft().beroep) { -
+
-
+ } @if (actieveVragen(data).length) { diff --git a/src/app/shared/ui/application-link/application-link.component.ts b/src/app/shared/ui/application-link/application-link.component.ts index 2b52f7e..47b6082 100644 --- a/src/app/shared/ui/application-link/application-link.component.ts +++ b/src/app/shared/ui/application-link/application-link.component.ts @@ -48,6 +48,9 @@ import { RouterLink } from '@angular/router';
+

{{ heading() }}

@if (subtitle()) {
{{ subtitle() }}
diff --git a/src/app/shared/ui/card/card.component.ts b/src/app/shared/ui/card/card.component.ts deleted file mode 100644 index 2e413fb..0000000 --- a/src/app/shared/ui/card/card.component.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Component, input } from '@angular/core'; -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, - subtle border, rounded, padded) so pages compose cards instead of hand-rolling - a hand-rolled card surface. Optional heading; the rest is projected. - Local class is .app-card (NOT Bootstrap's .card, whose padding-on-body layout differs). */ -@Component({ - selector: 'app-card', - imports: [HeadingComponent], - styles: [ - ` - :host { - display: block; - block-size: 100%; - } - .app-card { - background: var(--rhc-color-wit); - border: var(--rhc-border-width-sm) solid var(--rhc-color-border-subtle); - border-radius: var(--rhc-border-radius-md); - padding: var(--rhc-space-max-xl); - block-size: 100%; - box-sizing: border-box; - } - .app-card > * + * { - margin-block-start: var(--rhc-space-max-md); - } - `, - ], - template: ` -
- @if (heading()) { - {{ heading() }} - } - -
- `, -}) -export class CardComponent { - heading = input(); - level = input<1 | 2 | 3 | 4 | 5>(3); -} diff --git a/src/app/shared/ui/card/card.stories.ts b/src/app/shared/ui/card/card.stories.ts deleted file mode 100644 index ef26bdc..0000000 --- a/src/app/shared/ui/card/card.stories.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/angular'; -import { CardComponent } from './card.component'; - -const meta: Meta = { - title: 'Design System/Molecules/Card', - component: CardComponent, - render: (args) => ({ - props: args, - template: ` - -

Een kaart groepeert samenhangende inhoud op een schone, omkaderde vlak.

-
`, - }), - args: { heading: 'Persoonsgegevens (BRP)', level: 3 }, - parameters: { - cibgGap: true, - docs: { description: { component: 'CIBG-gap extension — see Foundations/CIBG Gap Register.' } }, - }, -}; -export default meta; -type Story = StoryObj; - -export const Default: Story = {}; -export const ZonderKop: Story = { args: { heading: undefined } }; diff --git a/src/app/shared/ui/data-block/data-block.component.ts b/src/app/shared/ui/data-block/data-block.component.ts index 92796ab..2726bb9 100644 --- a/src/app/shared/ui/data-block/data-block.component.ts +++ b/src/app/shared/ui/data-block/data-block.component.ts @@ -4,10 +4,11 @@ import { HeadingComponent } from '@shared/ui/heading/heading.component'; /** Molecule: CIBG Huisstijl **Datablock** (designsystem.cibg.nl/componenten/datablock) — THE way to show user/application data. A grey `.data-block` surface holds a white `.block-wrapper` panel with a `
` of projected ``s. Use `stacked` - (`.data-block--stacked`) when labels/values are long and should stack. Replaces the - `app-card + dl` idiom for data views (the datablock carries its own surface, so it is - NOT wrapped in an `app-card` — see WP-12). When there is no visible `heading`, pass an - `ariaLabel` so the definition list is announced. */ + (`.data-block--stacked`) when labels/values are long and should stack. This is the + single data surface (a generic white `app-card` used to exist but was unused and + removed — see WP-12); the datablock carries its own surface, so it is not nested in + another one. When there is no visible `heading`, pass an `ariaLabel` so the definition + list is announced. */ @Component({ selector: 'app-data-block', imports: [HeadingComponent], @@ -26,7 +27,7 @@ import { HeadingComponent } from '@shared/ui/heading/heading.component'; }) export class DataBlockComponent { heading = input(''); - /** Heading level when `heading` is set (default h3, matching `app-card`). */ + /** Heading level when `heading` is set (default h3). */ level = input<1 | 2 | 3 | 4 | 5>(3); /** Stacks label above value (`.data-block--stacked`) for long content. */ stacked = input(false); diff --git a/src/app/shared/ui/review-section/review-section.component.ts b/src/app/shared/ui/review-section/review-section.component.ts index 6c31063..7cb4067 100644 --- a/src/app/shared/ui/review-section/review-section.component.ts +++ b/src/app/shared/ui/review-section/review-section.component.ts @@ -1,5 +1,6 @@ import { Component, input, output } from '@angular/core'; import { DataBlockComponent } from '@shared/ui/data-block/data-block.component'; +import { HeadingComponent } from '@shared/ui/heading/heading.component'; /** Molecule: one section of a CIBG Huisstijl "controlestap" (wizard review step) — a heading with a "Wijzigen" link, and the section's ``s in a CIBG @@ -7,10 +8,10 @@ import { DataBlockComponent } from '@shared/ui/data-block/data-block.component'; heading and decides what "Wijzigen" does (typically jump back to a step). */ @Component({ selector: 'app-review-section', - imports: [DataBlockComponent], + imports: [DataBlockComponent, HeadingComponent], template: `
-

{{ heading() }}

+ {{ heading() }} @if (showEdit()) {
{{ diff --git a/src/docs/atomic-design.mdx b/src/docs/atomic-design.mdx index fe4f5f9..4e3dd22 100644 --- a/src/docs/atomic-design.mdx +++ b/src/docs/atomic-design.mdx @@ -99,3 +99,27 @@ A new page should be **composition of existing blocks**. Adding a new building b exception, not the reflex — if you reach for one, that is a signal to check whether an existing atom/molecule already covers it. Fewer primitives → less to test, less to learn, one place to fix a bug. + +## Convergence decisions — pairs that look duplicated but stay separate + +Periodically we audit for near-duplicate blocks. Some collapse into one; a few **look** +similar but earn their separation. This table records the "don't merge these" verdicts so +the next person doesn't spend an afternoon re-deciding. (Deliberate CIBG-specific deviations +live in [CIBG gaps](?path=/docs/foundations-cibg-gaps--docs); the FE⇄DS "same shape, different +context" cases in [Layers](?path=/docs/foundations-layers--docs).) + +| Pair | Why kept separate | +| --- | --- | +| `choice-link` vs `application-link` | Share the same `to`/`clickable`/`activate` navigation triad, but bind **different vendored patterns** — CIBG _Keuzelijst_ (`.keuzelijst__link`, `.stretched-link`) vs _Aanvragen_ (`.dashboard-block.applications li a`) — with different list/host semantics (`app-choice-link` renders an inner `
  • `; `application-link` **is** the `
  • `). Merging would fight the vendored CSS. Extract the shared triad into a mixin only if it grows. | +| `text-input` / `radio-group` / `checkbox` | Share only the standard Angular **ControlValueAccessor** boilerplate (the `writeValue`/`registerOn*`/`setDisabledState` block). They render genuinely different controls, so they stay three atoms. A base CVA class is the only DRY move — a refactor, not a component merge, and not worth it at three. | +| `button variant="subtle"` (`.btn-link`) vs `app-link` | A subtle button _looks_ like a link but is an **action** (`