import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
ListItemComponent,
ListContainerComponent,
ListItemData
} from '../../../../../ui-essentials/src/lib/components/data-display/list';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import {
faInbox,
faStar,
faPaperPlane,
faEdit,
faArchive,
faTrash,
faPhone,
faComment,
faPlay,
faDownload,
faCheck,
faChevronRight,
faPlus,
faMinus
} from '@fortawesome/free-solid-svg-icons';
@Component({
selector: 'ui-list-demo',
standalone: true,
imports: [
CommonModule,
ListItemComponent,
ListContainerComponent,
FontAwesomeModule
],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
List Component Showcase
Basic Lists - Size Variants
Small (sm)
@for (item of navigationItems; track item.primary) {
}
Medium (md)
@for (item of navigationItems; track item.primary) {
}
Large (lg)
@for (item of navigationItems; track item.primary) {
}
Multi-line Lists
Two Lines
@for (item of twoLineItems; track item.primary) {
}
Three Lines
@for (item of threeLineItems; track item.primary) {
}
Lists with Avatars
Contacts - Avatar + One Line
@for (item of contactItems; track item.primary) {
}
Messages - Avatar + Two Lines
@for (item of messageItems; track item.primary) {
2h
}
Lists with Media
Music - Media + Two Lines
@for (item of musicItems; track item.primary) {
3:42
}
Videos - Media + Three Lines
@for (item of videoItems; track item.primary) {
}
Interactive Demo
Click items to interact with them:
@for (item of interactiveItems(); track item.primary) {
@if (item.selected) {
Enabled
} @else if (item.disabled) {
Disabled
} @else {
Click to enable
}
}
Usage Examples
Basic List with Icons:
<ui-list-container elevation="sm" spacing="xs" [rounded]="true">
<ui-list-item
[data]="{primary: 'Inbox'}"
size="md"
lines="one"
variant="text">
<fa-icon [icon]="faInbox" slot="trailing"></fa-icon>
</ui-list-item>
</ui-list-container>
List with Avatar and Actions:
<ui-list-container elevation="md" spacing="sm" [rounded]="true">
<ui-list-item
[data]="{
primary: 'John Doe',
secondary: 'john@example.com',
avatarSrc: 'avatar.jpg'
}"
size="lg"
lines="two"
variant="avatar">
<button slot="trailing" (click)="call()">
<fa-icon [icon]="faPhone"></fa-icon>
</button>
</ui-list-item>
</ui-list-container>
@if (lastAction()) {
Action: {{ lastAction() }}
}
`,
styles: [`
h2 {
color: hsl(279, 14%, 11%);
font-size: 2rem;
margin-bottom: 2rem;
border-bottom: 2px solid hsl(258, 100%, 47%);
padding-bottom: 0.5rem;
}
h3 {
color: hsl(279, 14%, 25%);
font-size: 1.5rem;
margin-bottom: 1rem;
margin-top: 2rem;
}
h4 {
color: hsl(287, 12%, 35%);
font-size: 1.125rem;
margin-bottom: 0.75rem;
margin-top: 1rem;
}
section {
border: 1px solid hsl(289, 14%, 90%);
border-radius: 12px;
padding: 1.5rem;
background: hsl(286, 20%, 99%);
margin-bottom: 2rem;
}
pre {
font-size: 0.875rem;
line-height: 1.5;
margin: 0.5rem 0;
white-space: pre-wrap;
}
code {
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Courier New', monospace;
color: #d63384;
}
button {
transition: all 0.15s ease;
}
button:hover {
transform: translateY(-1px);
}
button:active {
transform: translateY(0);
}
fa-icon {
transition: color 0.2s ease;
}
`]
})
export class ListDemoComponent {
// State signals
lastAction = signal('');
// Demo data
navigationItems: ListItemData[] = [
{ primary: 'Inbox' },
{ primary: 'Starred' },
{ primary: 'Sent' },
{ primary: 'Drafts' },
{ primary: 'Archive' },
{ primary: 'Trash' }
];
twoLineItems: ListItemData[] = [
{
primary: 'Review Design System Updates',
secondary: 'Check new component specifications and design tokens'
},
{
primary: 'Team Standup Meeting',
secondary: 'Daily sync with development and design teams'
},
{
primary: 'Code Review - Authentication',
secondary: 'Review pull request #247 for OAuth integration'
}
];
threeLineItems: ListItemData[] = [
{
primary: 'Angular 19 Migration',
secondary: 'Upgrade project to latest Angular version with control flow',
tertiary: 'Estimated completion: Next Sprint • Priority: High'
},
{
primary: 'Design System Documentation',
secondary: 'Create comprehensive documentation for all components',
tertiary: 'Status: In Progress • Assigned: Design Team'
}
];
contactItems: ListItemData[] = [
{
primary: 'Sarah Wilson',
avatarSrc: 'https://api.dicebear.com/7.x/avataaars/svg?seed=sarah',
avatarAlt: 'Sarah Wilson avatar'
},
{
primary: 'Alex Chen',
avatarSrc: 'https://api.dicebear.com/7.x/avataaars/svg?seed=alex',
avatarAlt: 'Alex Chen avatar'
},
{
primary: 'Mike Rodriguez',
avatarSrc: 'https://api.dicebear.com/7.x/avataaars/svg?seed=mike',
avatarAlt: 'Mike Rodriguez avatar'
}
];
messageItems: ListItemData[] = [
{
primary: 'John Doe',
secondary: 'Hey! How\'s the new component library coming along?',
avatarSrc: 'https://api.dicebear.com/7.x/avataaars/svg?seed=john',
avatarAlt: 'John Doe avatar'
},
{
primary: 'Jane Smith',
secondary: 'The design tokens look great. Ready for review when you are.',
avatarSrc: 'https://api.dicebear.com/7.x/avataaars/svg?seed=jane',
avatarAlt: 'Jane Smith avatar'
}
];
musicItems: ListItemData[] = [
{
primary: 'Bohemian Rhapsody',
secondary: 'Queen • A Night at the Opera',
mediaSrc: 'https://picsum.photos/80/80?random=1',
mediaAlt: 'Album cover'
},
{
primary: 'Hotel California',
secondary: 'Eagles • Hotel California',
mediaSrc: 'https://picsum.photos/80/80?random=2',
mediaAlt: 'Album cover'
}
];
videoItems: ListItemData[] = [
{
primary: 'Angular Fundamentals',
secondary: 'Complete guide to modern Angular development',
tertiary: 'Duration: 2h 30m • Updated: Today • 1.2M views',
mediaSrc: 'https://picsum.photos/80/80?random=5',
mediaAlt: 'Video thumbnail'
}
];
interactiveItems = signal([
{
primary: 'Email Notifications',
secondary: 'Receive emails about important updates',
avatarSrc: 'https://api.dicebear.com/7.x/avataaars/svg?seed=email',
selected: false,
disabled: false
},
{
primary: 'SMS Alerts',
secondary: 'Get text messages for urgent notifications',
avatarSrc: 'https://api.dicebear.com/7.x/avataaars/svg?seed=sms',
selected: true,
disabled: false
},
{
primary: 'Marketing Communications',
secondary: 'Promotional offers and product updates',
avatarSrc: 'https://api.dicebear.com/7.x/avataaars/svg?seed=marketing',
selected: false,
disabled: true
}
]);
// Font Awesome icons
faInbox = faInbox;
faStar = faStar;
faPaperPlane = faPaperPlane;
faEdit = faEdit;
faArchive = faArchive;
faTrash = faTrash;
faPhone = faPhone;
faComment = faComment;
faPlay = faPlay;
faDownload = faDownload;
faCheck = faCheck;
faChevronRight = faChevronRight;
faPlus = faPlus;
faMinus = faMinus;
// Helper methods
getIconForItem(itemName: string): any {
const iconMap: { [key: string]: any } = {
'Inbox': faInbox,
'Starred': faStar,
'Sent': faPaperPlane,
'Drafts': faEdit,
'Archive': faArchive,
'Trash': faTrash
};
return iconMap[itemName] || faInbox;
}
// Event handlers
handleAction(action: string, item?: string): void {
const message = item
? `${action} action on "${item}" at ${new Date().toLocaleTimeString()}`
: `${action} action at ${new Date().toLocaleTimeString()}`;
this.lastAction.set(message);
console.log(`List action: ${action}`, item);
// Clear the message after 3 seconds
setTimeout(() => this.lastAction.set(''), 3000);
}
toggleInteractiveItem(itemName: string): void {
this.interactiveItems.update(items =>
items.map(item => {
if (item.primary === itemName && !item.disabled) {
return { ...item, selected: !item.selected };
}
return item;
})
);
this.handleAction('toggle', itemName);
}
}