Notice
Persistent, inline messaging that stays on the surface — information, progress, confirmation, warning or error. Transient feedback is a toast; something the user must act on before continuing is a dialog.
Added 14 October 2026
React
Codecomponents/react/notice-demo.tsx
import {Button, Notice, NoticeAction, NoticeDescription, NoticeTitle} from '@stroeer-labs/design-library/react';
import {CircleAlert, CircleCheck, Info, Megaphone, TriangleAlert} from 'lucide-react';
// Section order is mirrored in ../angular/notice-demo.ts — the two panes sit side by side on the site,
// which is what makes a parity break visible instead of inferred.
export function NoticeDemo() {
return (
<div className="grid w-full max-w-xl items-start gap-6">
<div className="space-y-2">
<p className="text-xs font-medium text-muted-foreground">Five tones — the tone is the tint, the border and the icon, never the text</p>
<div className="grid gap-3">
<Notice>
<Megaphone />
<NoticeTitle>Declare what the advertising is about</NoticeTitle>
<NoticeDescription>You will see which sites accept the declared content.</NoticeDescription>
</Notice>
<Notice variant="info">
<Info />
<NoticeTitle>The plan saves automatically</NoticeTitle>
<NoticeDescription>Every line item edit is written through immediately.</NoticeDescription>
</Notice>
<Notice variant="success">
<CircleCheck />
<NoticeTitle>All 412 targeted sites accept the declared advertising</NoticeTitle>
<NoticeDescription>The compliance check finished with no blocks.</NoticeDescription>
</Notice>
<Notice variant="warning">
<TriangleAlert />
<NoticeTitle>Not saved — no hour selected</NoticeTitle>
<NoticeDescription>A line item must deliver in at least one hour, so this selection cannot be saved.</NoticeDescription>
</Notice>
<Notice variant="destructive">
<CircleAlert />
<NoticeTitle>The plan total is unavailable — no price came back.</NoticeTitle>
<NoticeDescription>Recalculate the plan, or adjust the line item budget.</NoticeDescription>
</Notice>
</div>
</div>
<div className="space-y-2">
<p className="text-xs font-medium text-muted-foreground">
<code className="font-mono">size="sm"</code> — for a notice inside a dense form section
</p>
<div className="grid gap-3">
<Notice size="sm" variant="info">
<Info />
<NoticeTitle>The plan saves automatically</NoticeTitle>
<NoticeDescription>Every line item edit is written through immediately.</NoticeDescription>
</Notice>
<Notice size="sm" variant="warning">
<TriangleAlert />
<NoticeTitle>Not saved — no hour selected</NoticeTitle>
<NoticeDescription>A line item must deliver in at least one hour, so this selection cannot be saved.</NoticeDescription>
</Notice>
<Notice size="sm" variant="destructive">
<CircleAlert />
<NoticeTitle>The plan total is unavailable — no price came back.</NoticeTitle>
<NoticeDescription>Recalculate the plan, or adjust the line item budget.</NoticeDescription>
</Notice>
</div>
</div>
<div className="space-y-2">
<p className="text-xs font-medium text-muted-foreground">One-liners — omit the description and the layout centres on a single row</p>
<div className="grid gap-3">
<Notice variant="success">
<CircleCheck />
<NoticeTitle>All 412 targeted sites accept the declared advertising</NoticeTitle>
</Notice>
<Notice size="sm" variant="info">
<Info />
<NoticeTitle>The plan saves automatically</NoticeTitle>
</Notice>
<Notice size="sm">
<NoticeTitle>No icon, single row</NoticeTitle>
</Notice>
</div>
</div>
<div className="space-y-2">
<p className="text-xs font-medium text-muted-foreground">
Action slot — <code className="font-mono">size="sm"</code> takes a <code className="font-mono">size="xs"</code> button
</p>
<div className="grid gap-3">
<Notice variant="warning">
<TriangleAlert />
<NoticeTitle>Sites removed</NoticeTitle>
<NoticeDescription>3 sites are not available on this network, so they were removed.</NoticeDescription>
<NoticeAction>
<Button variant="ghost" size="sm">
Dismiss
</Button>
</NoticeAction>
</Notice>
<Notice size="sm" variant="warning">
<TriangleAlert />
<NoticeTitle>Sites removed</NoticeTitle>
<NoticeAction>
<Button variant="ghost" size="xs">
Dismiss
</Button>
</NoticeAction>
</Notice>
</div>
</div>
<div className="space-y-2">
<p className="text-xs font-medium text-muted-foreground">Rich description — lists, paragraphs and links are styled by the slot</p>
<Notice variant="destructive">
<CircleAlert />
<NoticeTitle>Unable to process your payment.</NoticeTitle>
<NoticeDescription>
<p>Please verify your billing information and try again.</p>
<ul className="list-inside list-disc text-sm">
<li>Check your card details</li>
<li>Ensure sufficient funds</li>
<li>Verify billing address</li>
</ul>
</NoticeDescription>
</Notice>
</div>
</div>
);
}Angular
Codecomponents/angular/notice-demo.ts
import '@angular/compiler';
import {Component} from '@angular/core';
import {NgIcon, provideIcons} from '@ng-icons/core';
import {lucideCircleAlert, lucideCircleCheck, lucideInfo, lucideMegaphone, lucideTriangleAlert} from '@ng-icons/lucide';
import {HlmButtonImports, HlmNoticeImports} from '@stroeer-labs/design-library/angular';
// Section order is mirrored in ../react/notice-demo.tsx — the two panes sit side by side on the site,
// which is what makes a parity break visible instead of inferred.
@Component({
selector: 'dl-notice-demo',
standalone: true,
imports: [HlmNoticeImports, HlmButtonImports, NgIcon],
viewProviders: [provideIcons({lucideCircleAlert, lucideCircleCheck, lucideInfo, lucideMegaphone, lucideTriangleAlert})],
template: `
<div class="grid w-full max-w-xl items-start gap-6">
<div class="space-y-2">
<p class="text-xs font-medium text-muted-foreground">Five tones — the tone is the tint, the border and the icon, never the text</p>
<div class="grid gap-3">
<hlm-notice>
<ng-icon name="lucideMegaphone" />
<h4 hlmNoticeTitle>Declare what the advertising is about</h4>
<p hlmNoticeDescription>You will see which sites accept the declared content.</p>
</hlm-notice>
<hlm-notice variant="info">
<ng-icon name="lucideInfo" />
<h4 hlmNoticeTitle>The plan saves automatically</h4>
<p hlmNoticeDescription>Every line item edit is written through immediately.</p>
</hlm-notice>
<hlm-notice variant="success">
<ng-icon name="lucideCircleCheck" />
<h4 hlmNoticeTitle>All 412 targeted sites accept the declared advertising</h4>
<p hlmNoticeDescription>The compliance check finished with no blocks.</p>
</hlm-notice>
<hlm-notice variant="warning">
<ng-icon name="lucideTriangleAlert" />
<h4 hlmNoticeTitle>Not saved — no hour selected</h4>
<p hlmNoticeDescription>A line item must deliver in at least one hour, so this selection cannot be saved.</p>
</hlm-notice>
<hlm-notice variant="destructive">
<ng-icon name="lucideCircleAlert" />
<h4 hlmNoticeTitle>The plan total is unavailable — no price came back.</h4>
<p hlmNoticeDescription>Recalculate the plan, or adjust the line item budget.</p>
</hlm-notice>
</div>
</div>
<div class="space-y-2">
<p class="text-xs font-medium text-muted-foreground">
<code class="font-mono">size="sm"</code> — for a notice inside a dense form section
</p>
<div class="grid gap-3">
<hlm-notice size="sm" variant="info">
<ng-icon name="lucideInfo" />
<h4 hlmNoticeTitle>The plan saves automatically</h4>
<p hlmNoticeDescription>Every line item edit is written through immediately.</p>
</hlm-notice>
<hlm-notice size="sm" variant="warning">
<ng-icon name="lucideTriangleAlert" />
<h4 hlmNoticeTitle>Not saved — no hour selected</h4>
<p hlmNoticeDescription>A line item must deliver in at least one hour, so this selection cannot be saved.</p>
</hlm-notice>
<hlm-notice size="sm" variant="destructive">
<ng-icon name="lucideCircleAlert" />
<h4 hlmNoticeTitle>The plan total is unavailable — no price came back.</h4>
<p hlmNoticeDescription>Recalculate the plan, or adjust the line item budget.</p>
</hlm-notice>
</div>
</div>
<div class="space-y-2">
<p class="text-xs font-medium text-muted-foreground">One-liners — omit the description and the layout centres on a single row</p>
<div class="grid gap-3">
<hlm-notice variant="success">
<ng-icon name="lucideCircleCheck" />
<h4 hlmNoticeTitle>All 412 targeted sites accept the declared advertising</h4>
</hlm-notice>
<hlm-notice size="sm" variant="info">
<ng-icon name="lucideInfo" />
<h4 hlmNoticeTitle>The plan saves automatically</h4>
</hlm-notice>
<hlm-notice size="sm">
<h4 hlmNoticeTitle>No icon, single row</h4>
</hlm-notice>
</div>
</div>
<div class="space-y-2">
<p class="text-xs font-medium text-muted-foreground">
Action slot — <code class="font-mono">size="sm"</code> takes a <code class="font-mono">size="xs"</code> button
</p>
<div class="grid gap-3">
<hlm-notice variant="warning">
<ng-icon name="lucideTriangleAlert" />
<h4 hlmNoticeTitle>Sites removed</h4>
<p hlmNoticeDescription>3 sites are not available on this network, so they were removed.</p>
<div hlmNoticeAction>
<button hlmBtn variant="ghost" size="sm">Dismiss</button>
</div>
</hlm-notice>
<hlm-notice size="sm" variant="warning">
<ng-icon name="lucideTriangleAlert" />
<h4 hlmNoticeTitle>Sites removed</h4>
<div hlmNoticeAction>
<button hlmBtn variant="ghost" size="xs">Dismiss</button>
</div>
</hlm-notice>
</div>
</div>
<div class="space-y-2">
<p class="text-xs font-medium text-muted-foreground">Rich description — lists, paragraphs and links are styled by the slot</p>
<hlm-notice variant="destructive">
<ng-icon name="lucideCircleAlert" />
<h4 hlmNoticeTitle>Unable to process your payment.</h4>
<div hlmNoticeDescription>
<p>Please verify your billing information and try again.</p>
<ul class="list-inside list-disc text-sm">
<li>Check your card details</li>
<li>Ensure sufficient funds</li>
<li>Verify billing address</li>
</ul>
</div>
</hlm-notice>
</div>
</div>
`,
})
export class NoticeDemoComponent {}