feat(design-system): add reusable EmptyState primitive
Standalone, OnPush. title required input (caller supplies translated text), optional description, icon/actions content-projection slots. Colors via existing tenant CSS vars with fallbacks.
This commit is contained in:
12
src/app/shared/ui/empty-state/empty-state.component.html
Normal file
12
src/app/shared/ui/empty-state/empty-state.component.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<div class="app-empty-state">
|
||||
<div class="app-empty-state__icon">
|
||||
<ng-content select="[slot=icon]" />
|
||||
</div>
|
||||
<h3 class="app-empty-state__title">{{ title() }}</h3>
|
||||
@if (description()) {
|
||||
<p class="app-empty-state__description">{{ description() }}</p>
|
||||
}
|
||||
<div class="app-empty-state__actions">
|
||||
<ng-content select="[slot=actions]" />
|
||||
</div>
|
||||
</div>
|
||||
44
src/app/shared/ui/empty-state/empty-state.component.scss
Normal file
44
src/app/shared/ui/empty-state/empty-state.component.scss
Normal file
@@ -0,0 +1,44 @@
|
||||
.app-empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
gap: var(--space-sm, 0.5rem);
|
||||
padding: var(--space-xl, 2rem) var(--space-lg, 1.5rem);
|
||||
color: var(--text-secondary, #6b7280);
|
||||
}
|
||||
|
||||
.app-empty-state__icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--text-secondary, #6b7280);
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.app-empty-state__title {
|
||||
margin: 0;
|
||||
font-size: 1.0625rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary, #1f322d);
|
||||
}
|
||||
|
||||
.app-empty-state__description {
|
||||
margin: 0;
|
||||
max-width: 32rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.app-empty-state__actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm, 0.5rem);
|
||||
margin-top: var(--space-xs, 0.25rem);
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
13
src/app/shared/ui/empty-state/empty-state.component.ts
Normal file
13
src/app/shared/ui/empty-state/empty-state.component.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-empty-state',
|
||||
standalone: true,
|
||||
templateUrl: './empty-state.component.html',
|
||||
styleUrl: './empty-state.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class EmptyStateComponent {
|
||||
readonly title = input.required<string>();
|
||||
readonly description = input<string | null>(null);
|
||||
}
|
||||
Reference in New Issue
Block a user