Overview
The Card component provides a flexible container for displaying related content in a visually distinct panel. Cards can include headers, footers, images, and actions, making them ideal for presenting information in a structured and scannable format.
Basic usage
Import the Card component and use it in your Angular templates:
import { CardComponent } from '@flowx/angular-ui-toolkit' ;
@ Component ({
selector: 'app-example' ,
standalone: true ,
imports: [ CardComponent ],
template: `
<flx-card
[title]="'Card Title'"
[subtitle]="'Card subtitle'">
<p>Your card content goes here</p>
</flx-card>
`
})
export class ExampleComponent {}
Component selector
Properties
The main title displayed in the card header.
Secondary text displayed below the title in the card header.
Shadow depth of the card. Valid values are 0 (no shadow) through 5 (maximum shadow).
variant
'default' | 'outlined' | 'elevated'
default: "'default'"
Visual style variant of the card:
default: Standard card with subtle border
outlined: Card with prominent border
elevated: Card with shadow elevation
When true, applies hover effects and cursor pointer to indicate the card is interactive.
When true, applies a disabled visual state and prevents interaction.
When true, displays a loading skeleton or spinner overlay.
padding
'none' | 'small' | 'medium' | 'large'
default: "'medium'"
Controls the internal padding of the card content area.
Events
Emitted when the card is clicked. Only fires when clickable is true.
Content projection
The Card component supports multiple content projection slots:
Default content slot
< flx-card [title] = "'Simple Card'" >
<!-- This content goes in the main content area -->
< p > Main card content </ p >
</ flx-card >
Named slots
Header slot
Footer slot
Media slot
< flx-card >
< div slot = "header" >
< h3 > Custom Header </ h3 >
< button > Action </ button >
</ div >
< p > Card content </ p >
</ flx-card >
Examples
Basic card
Clickable card
Card with media
Loading state
Card grid layout
Simple card with title, content, and actions: @ Component ({
template: `
<flx-card
[title]="'User Profile'"
[subtitle]="'Member since 2024'"
[elevation]="2">
<div class="profile-content">
<p><strong>Email:</strong> user@example.com</p>
<p><strong>Role:</strong> Administrator</p>
</div>
<div slot="footer">
<button (click)="editProfile()">Edit</button>
<button (click)="deleteProfile()">Delete</button>
</div>
</flx-card>
`
})
export class ProfileCardComponent {
editProfile () {
console . log ( 'Edit profile' );
}
deleteProfile () {
console . log ( 'Delete profile' );
}
}
Interactive card that responds to clicks: @ Component ({
template: `
<div class="card-grid">
<flx-card
*ngFor="let item of items"
[title]="item.title"
[subtitle]="item.category"
[clickable]="true"
(cardClick)="onCardClick(item)">
<p>{{ item.description }}</p>
</flx-card>
</div>
`
})
export class ProductGridComponent {
items = [
{
id: 1 ,
title: 'Product A' ,
category: 'Electronics' ,
description: 'High-quality electronic device'
},
{
id: 2 ,
title: 'Product B' ,
category: 'Accessories' ,
description: 'Premium accessories'
}
];
onCardClick ( item : any ) {
console . log ( 'Navigating to:' , item . id );
// Navigate to detail page
}
}
Card featuring an image or media content: @ Component ({
template: `
<flx-card [variant]="'elevated'" [elevation]="3">
<img
slot="media"
[src]="product.imageUrl"
[alt]="product.name"
class="card-image" />
<div slot="content">
<h3>{{ product.name }}</h3>
<p class="price">{{ product.price | currency }}</p>
<p>{{ product.description }}</p>
</div>
<div slot="footer">
<button (click)="addToCart(product)">Add to Cart</button>
<button (click)="viewDetails(product)">View Details</button>
</div>
</flx-card>
` ,
styles: [ `
.card-image {
width: 100%;
height: 200px;
object-fit: cover;
}
.price {
font-size: 1.5rem;
font-weight: bold;
color: var(--primary-color);
}
` ]
})
export class ProductCardComponent {
product = {
name: 'Premium Widget' ,
price: 99.99 ,
description: 'A high-quality widget for all your needs' ,
imageUrl: '/assets/product.jpg'
};
addToCart ( product : any ) {
console . log ( 'Added to cart:' , product );
}
viewDetails ( product : any ) {
console . log ( 'View details:' , product );
}
}
Display a loading skeleton while data is being fetched: @ Component ({
template: `
<flx-card
[title]="data ? data.title : 'Loading...'"
[loading]="isLoading">
<div *ngIf="data">
<p>{{ data.content }}</p>
</div>
</flx-card>
`
})
export class DataCardComponent implements OnInit {
isLoading = true ;
data : any = null ;
ngOnInit () {
this . loadData ();
}
async loadData () {
this . isLoading = true ;
try {
// Simulate API call
await new Promise ( resolve => setTimeout ( resolve , 2000 ));
this . data = {
title: 'Data Loaded' ,
content: 'Content from API'
};
} finally {
this . isLoading = false ;
}
}
}
Arrange multiple cards in a responsive grid: @ Component ({
template: `
<div class="card-grid">
<flx-card
*ngFor="let stat of statistics"
[variant]="'elevated'"
[padding]="'large'">
<div class="stat-card">
<div class="stat-icon">
<flx-icon [name]="stat.icon"></flx-icon>
</div>
<h3>{{ stat.value }}</h3>
<p>{{ stat.label }}</p>
<span class="trend" [class.positive]="stat.trend > 0">
{{ stat.trend > 0 ? '↑' : '↓' }} {{ stat.trend }}%
</span>
</div>
</flx-card>
</div>
` ,
styles: [ `
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.stat-card {
text-align: center;
}
.stat-icon {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.trend {
color: var(--error-color);
}
.trend.positive {
color: var(--success-color);
}
` ]
})
export class DashboardComponent {
statistics = [
{ icon: 'users' , value: '1,234' , label: 'Total Users' , trend: 12 },
{ icon: 'revenue' , value: '$45,678' , label: 'Revenue' , trend: 8 },
{ icon: 'orders' , value: '567' , label: 'Orders' , trend: - 3 },
{ icon: 'growth' , value: '23%' , label: 'Growth' , trend: 15 }
];
}
When using the clickable property, ensure you provide appropriate visual feedback and handle keyboard navigation for accessibility.
Accessibility
The Card component includes accessibility features:
Semantic HTML structure with proper heading hierarchy
Keyboard navigation support for clickable cards
ARIA attributes for interactive states
Screen reader announcements for loading states
Avoid using cards for critical navigation elements. While clickable cards are convenient, important navigation should use proper link or button elements.
Styling
Customize card appearance using CSS custom properties:
flx-card {
--card-background : #ffffff ;
--card-border-color : #e0e0e0 ;
--card-border-radius : 8 px ;
--card-padding : 16 px ;
--card-shadow : 0 2 px 4 px rgba ( 0 , 0 , 0 , 0.1 );
--card-header-color : #333333 ;
--card-subtitle-color : #666666 ;
}
Common use cases
Product listings : Display products with images, descriptions, and actions
Dashboard widgets : Show statistics and metrics in card format
User profiles : Present user information in organized cards
Content previews : Provide summaries with links to full content
Settings panels : Group related settings in separate cards
Notification cards : Display notifications or alerts with actions