feat(design-system): add reusable Card primitive

Standalone, OnPush, content-projection container. Padding none/sm/md/lg,
bordered and interactive variants. Colors/radius/shadow/spacing consumed
via existing tenant CSS vars with fallbacks.
This commit is contained in:
sdarbinyan
2026-07-15 03:31:31 +04:00
parent 2fc9051f86
commit b309afbe8e
3 changed files with 72 additions and 0 deletions

View File

@@ -0,0 +1 @@
<ng-content />

View File

@@ -0,0 +1,47 @@
:host {
display: block;
background: var(--bg-primary, #fff);
border-radius: var(--radius-lg, 10px);
box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.06));
transition: box-shadow var(--transition-fast, 120ms ease),
border-color var(--transition-fast, 120ms ease);
}
:host.app-card--bordered {
border: 1px solid var(--border-color, #e4e4e7);
}
:host.app-card--interactive {
cursor: pointer;
&:hover {
box-shadow: var(--shadow-md, 0 4px 12px rgba(0, 0, 0, 0.08));
}
&:focus-visible {
outline: 2px solid var(--primary-color, #2f6e5d);
outline-offset: 2px;
}
}
:host.app-card--pad-none {
padding: 0;
}
:host.app-card--pad-sm {
padding: var(--space-sm, 0.5rem);
}
:host.app-card--pad-md {
padding: var(--space-md, 1rem);
}
:host.app-card--pad-lg {
padding: var(--space-lg, 1.5rem);
}
@media (prefers-reduced-motion: reduce) {
:host {
transition: none;
}
}

View File

@@ -0,0 +1,24 @@
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
export type CardPadding = 'none' | 'sm' | 'md' | 'lg';
@Component({
selector: 'app-card',
standalone: true,
templateUrl: './card.component.html',
styleUrl: './card.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[class.app-card--bordered]': 'bordered()',
'[class.app-card--interactive]': 'interactive()',
'[class.app-card--pad-none]': "padding() === 'none'",
'[class.app-card--pad-sm]': "padding() === 'sm'",
'[class.app-card--pad-md]': "padding() === 'md'",
'[class.app-card--pad-lg]': "padding() === 'lg'"
}
})
export class CardComponent {
readonly padding = input<CardPadding>('md');
readonly bordered = input(true);
readonly interactive = input(false);
}