Upload feature (c): atomic UI components (atoms/molecules/organisms) + stories

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 06:25:30 +02:00
parent c4bfe9d39b
commit 9521739ac1
18 changed files with 677 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
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()));
}

View File

@@ -0,0 +1,21 @@
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.' },
};