Files
ui-essentials/projects/demo-ui-essentials/src/app/demos/avatar-demo/avatar-demo.component.ts
skyai_dev 6f0ab0cf5f Fix SCSS semantic token variable errors across components
- Replace incorrect semantic token names with correct ones:
  • $semantic-border-width-thin → $semantic-border-width-1
  • $semantic-color-border-default → $semantic-color-border-primary
  • $semantic-spacing-content-* → $semantic-spacing-component-*
  • $semantic-typography-body-* → $semantic-typography-font-size-*
  • $semantic-typography-caption-* → $semantic-typography-font-size-*
  • $semantic-motion-easing-standard → $semantic-easing-standard
  • $semantic-color-surface-tertiary → $semantic-color-surface-secondary
  • Various hover color tokens → base color tokens

- Fix typography map usage errors:
  • Replace heading map tokens with individual size tokens
  • $semantic-typography-heading-h* → $semantic-typography-heading-h*-size

- Update affected components:
  • tooltip, divider, progress-circle, range-slider components
  • Related demo components and SCSS files

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 07:50:34 +10:00

502 lines
19 KiB
TypeScript

import { Component, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AvatarComponent } from '../../../../../ui-essentials/src/lib/components/data-display/avatar/avatar.component';
interface Activity {
user: string;
action: string;
time: string;
status?: 'online' | 'offline' | 'away' | 'busy';
}
@Component({
selector: 'ui-avatar-demo',
standalone: true,
imports: [
CommonModule,
AvatarComponent
],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div style="padding: 2rem;">
<h2>Avatar Component Showcase</h2>
<!-- Size Variants -->
<section style="margin-bottom: 3rem;">
<h3>Size Variants</h3>
<div style="display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<div style="text-align: center;">
<ui-avatar size="xs" name="Extra Small"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">XS (24px)</p>
</div>
<div style="text-align: center;">
<ui-avatar size="sm" name="Small Avatar"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">SM (32px)</p>
</div>
<div style="text-align: center;">
<ui-avatar size="md" name="Medium Avatar"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">MD (40px)</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Large Avatar"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">LG (48px)</p>
</div>
<div style="text-align: center;">
<ui-avatar size="xl" name="Extra Large"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">XL (64px)</p>
</div>
<div style="text-align: center;">
<ui-avatar size="xxl" name="XX Large"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">XXL (80px)</p>
</div>
</div>
</section>
<!-- With Images -->
<section style="margin-bottom: 3rem;">
<h3>With Images</h3>
<div style="display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<div style="text-align: center;">
<ui-avatar
size="lg"
imageUrl="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=150&h=150&fit=crop&crop=face"
name="John Doe"
altText="John Doe's profile picture">
</ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">John Doe</p>
</div>
<div style="text-align: center;">
<ui-avatar
size="lg"
imageUrl="https://images.unsplash.com/photo-1494790108755-2616b612b786?w=150&h=150&fit=crop&crop=face"
name="Jane Smith"
altText="Jane Smith's profile picture">
</ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Jane Smith</p>
</div>
<div style="text-align: center;">
<ui-avatar
size="lg"
imageUrl="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&h=150&fit=crop&crop=face"
name="Alex Rodriguez"
altText="Alex Rodriguez's profile picture">
</ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Alex Rodriguez</p>
</div>
<div style="text-align: center;">
<ui-avatar
size="lg"
imageUrl="broken-url"
name="Fallback Test"
altText="This should show initials">
</ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Fallback (Broken URL)</p>
</div>
</div>
</section>
<!-- With Status -->
<section style="margin-bottom: 3rem;">
<h3>Status Indicators</h3>
<div style="display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<div style="text-align: center;">
<ui-avatar size="lg" name="Online User" status="online"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Online</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Offline User" status="offline"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Offline</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Away User" status="away"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Away</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Busy User" status="busy"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Busy</p>
</div>
</div>
</section>
<!-- With Badges -->
<section style="margin-bottom: 3rem;">
<h3>Notification Badges</h3>
<div style="display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<div style="text-align: center;">
<ui-avatar size="lg" name="Badge User" badge="3"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">3 notifications</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Badge User" badge="99+"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">99+ notifications</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Badge User" badge="5" status="online"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Online + Badge</p>
</div>
<div style="text-align: center;">
<ui-avatar
size="lg"
name="Premium User"
badge="⭐"
imageUrl="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=150&h=150&fit=crop&crop=face">
</ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Premium User</p>
</div>
</div>
</section>
<!-- Shape Variants -->
<section style="margin-bottom: 3rem;">
<h3>Shape Variants</h3>
<div style="display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<div style="text-align: center;">
<ui-avatar size="lg" name="Circle User" shape="circle"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Circle (Default)</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Square User" shape="square"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Square</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Rounded User" shape="rounded"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Rounded Square</p>
</div>
</div>
</section>
<!-- Color Variants -->
<section style="margin-bottom: 3rem;">
<h3>Color Variants</h3>
<div style="display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<div style="text-align: center;">
<ui-avatar size="lg" name="Primary User" color="primary"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Primary</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Secondary User" color="secondary"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Secondary</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Success User" color="success"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Success</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Warning User" color="warning"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Warning</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Danger User" color="danger"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Danger</p>
</div>
</div>
</section>
<!-- Activity List Example -->
<section style="margin-bottom: 3rem;">
<h3>Activity List Example</h3>
<div style="background: #f8f9fa; border-radius: 12px; padding: 1.5rem; max-width: 600px;">
<h4 style="margin: 0 0 1rem 0; font-size: 1.125rem;">Recent Activity</h4>
@for (activity of activities; track activity.user) {
<div style="display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 0; border-bottom: 1px solid #e9ecef;">
<ui-avatar
size="sm"
[name]="activity.user"
[status]="activity.status">
</ui-avatar>
<div style="flex: 1; min-width: 0;">
<div style="font-weight: 500; font-size: 14px; margin-bottom: 2px;">{{ activity.user }}</div>
<div style="color: #666; font-size: 12px; line-height: 1.3;">{{ activity.action }}</div>
</div>
<div style="color: #999; font-size: 11px; white-space: nowrap;">{{ activity.time }}</div>
</div>
}
</div>
</section>
<!-- User List Example -->
<section style="margin-bottom: 3rem;">
<h3>User List Example</h3>
<div style="background: #f8f9fa; border-radius: 12px; padding: 1.5rem; max-width: 800px;">
<div style="display: grid; gap: 1rem;">
@for (user of userProfiles; track user.id) {
<div style="display: flex; align-items: center; gap: 1rem; padding: 1rem; background: white; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
<ui-avatar
size="lg"
[name]="user.name"
[imageUrl]="user.avatar"
[status]="user.status"
[badge]="user.notifications > 0 ? user.notifications.toString() : ''">
</ui-avatar>
<div style="flex: 1; min-width: 0;">
<h4 style="margin: 0; font-size: 16px; font-weight: 600;">{{ user.name }}</h4>
<p style="margin: 2px 0; color: #666; font-size: 14px;">{{ user.role }}</p>
<p style="margin: 0; color: #999; font-size: 12px;">{{ user.email }}</p>
</div>
<div style="text-align: right;">
<div style="font-size: 12px; color: #999;">Last seen</div>
<div style="font-size: 12px; font-weight: 500;">{{ user.lastSeen }}</div>
</div>
</div>
}
</div>
</div>
</section>
<!-- Loading and Error States -->
<section style="margin-bottom: 3rem;">
<h3>Special States</h3>
<div style="display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<div style="text-align: center;">
<ui-avatar size="lg" [loading]="true"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Loading</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="" altText="Empty name fallback"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Empty Name</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" name="Single" altText="Single character name"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">Single Character</p>
</div>
<div style="text-align: center;">
<ui-avatar size="lg" altText="No name provided"></ui-avatar>
<p style="font-size: 12px; margin: 0.5rem 0;">No Name</p>
</div>
</div>
</section>
<!-- Avatar Group Example -->
<section style="margin-bottom: 3rem;">
<h3>Avatar Group Example</h3>
<div style="display: flex; align-items: center; gap: -0.5rem;">
@for (member of teamMembers; track member.name; let i = $index) {
<ui-avatar
size="md"
[name]="member.name"
[imageUrl]="member.avatar"
[status]="member.status"
[style.z-index]="teamMembers.length - i"
[style.margin-left]="i > 0 ? '-8px' : '0'">
</ui-avatar>
}
<div style="margin-left: 1rem; padding: 0.5rem 1rem; background: #e3f2fd; border-radius: 20px; font-size: 12px; font-weight: 500;">
+{{ teamMembers.length }} members
</div>
</div>
</section>
<!-- Usage Examples -->
<section style="margin-bottom: 3rem;">
<h3>Usage Examples</h3>
<div style="background: #f8f9fa; padding: 1.5rem; border-radius: 8px; border-left: 4px solid #007bff;">
<h4>Basic Avatar:</h4>
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>&lt;ui-avatar
size="md"
name="Current User"
status="online"&gt;
&lt;/ui-avatar&gt;</code></pre>
<h4>Avatar with Image:</h4>
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>&lt;ui-avatar
size="lg"
name="John Doe"
imageUrl="https://example.com/avatar.jpg"
altText="John's profile picture"
status="away"
badge="5"&gt;
&lt;/ui-avatar&gt;</code></pre>
<h4>Custom Styled Avatar:</h4>
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code>&lt;ui-avatar
size="xl"
name="Admin User"
color="primary"
shape="rounded"
badge="⭐"
[loading]="false"&gt;
&lt;/ui-avatar&gt;</code></pre>
</div>
</section>
<!-- Interactive Example -->
<section style="margin-bottom: 3rem;">
<h3>Interactive Example</h3>
<div style="display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin-bottom: 1rem;">
<button
(click)="cycleStatus()"
style="padding: 0.5rem 1rem; border: 1px solid #007bff; background: #007bff; color: white; border-radius: 4px; cursor: pointer;">
Toggle Status
</button>
<button
(click)="toggleBadge()"
style="padding: 0.5rem 1rem; border: 1px solid #28a745; background: #28a745; color: white; border-radius: 4px; cursor: pointer;">
Toggle Badge
</button>
<button
(click)="cycleSize()"
style="padding: 0.5rem 1rem; border: 1px solid #6c757d; background: #6c757d; color: white; border-radius: 4px; cursor: pointer;">
Cycle Size
</button>
</div>
<div style="display: flex; align-items: center; gap: 1rem;">
<ui-avatar
[size]="interactiveSize"
name="Interactive User"
[status]="interactiveStatus"
[badge]="interactiveBadge"
imageUrl="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=150&h=150&fit=crop&crop=face">
</ui-avatar>
<div>
<div><strong>Size:</strong> {{ interactiveSize }}</div>
<div><strong>Status:</strong> {{ interactiveStatus || 'none' }}</div>
<div><strong>Badge:</strong> {{ interactiveBadge || 'none' }}</div>
</div>
</div>
</section>
</div>
`,
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;
}
h4 {
color: hsl(287, 12%, 35%);
font-size: 1.125rem;
margin-bottom: 0.75rem;
}
section {
border: 1px solid hsl(289, 14%, 90%);
border-radius: 8px;
padding: 1.5rem;
background: hsl(286, 20%, 99%);
}
pre {
font-size: 0.875rem;
line-height: 1.5;
margin: 0.5rem 0;
}
code {
font-family: 'JetBrains Mono', monospace;
color: #d63384;
}
`]
})
export class AvatarDemoComponent {
activities: Activity[] = [
{
user: 'Alice Johnson',
action: 'Updated the project documentation and added new API endpoints',
time: '2 min ago',
status: 'online'
},
{
user: 'Bob Smith',
action: 'Completed code review for the authentication module',
time: '15 min ago',
status: 'away'
},
{
user: 'Carol Williams',
action: 'Created new user interface mockups for the dashboard',
time: '1 hour ago',
status: 'online'
},
{
user: 'David Brown',
action: 'Fixed critical bug in the payment processing system',
time: '2 hours ago',
status: 'busy'
},
{
user: 'Eve Davis',
action: 'Deployed version 2.1.0 to production environment',
time: '3 hours ago',
status: 'offline'
}
];
userProfiles = [
{
id: 1,
name: 'Alice Johnson',
role: 'Senior Developer',
email: 'alice@company.com',
status: 'online' as const,
notifications: 3,
lastSeen: '2 min ago',
avatar: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?w=150&h=150&fit=crop&crop=face'
},
{
id: 2,
name: 'Bob Smith',
role: 'Product Manager',
email: 'bob@company.com',
status: 'away' as const,
notifications: 0,
lastSeen: '15 min ago',
avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=150&h=150&fit=crop&crop=face'
},
{
id: 3,
name: 'Carol Williams',
role: 'UX Designer',
email: 'carol@company.com',
status: 'online' as const,
notifications: 12,
lastSeen: 'Just now',
avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=150&h=150&fit=crop&crop=face'
}
];
teamMembers = [
{ name: 'Alex Chen', status: 'online' as const, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&h=150&fit=crop&crop=face' },
{ name: 'Maria Garcia', status: 'away' as const, avatar: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=150&h=150&fit=crop&crop=face' },
{ name: 'James Wilson', status: 'busy' as const, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=150&h=150&fit=crop&crop=face' },
{ name: 'Sarah Kim', status: 'online' as const, avatar: 'https://images.unsplash.com/photo-1534751516642-a1af1ef26a56?w=150&h=150&fit=crop&crop=face' },
];
// Interactive demo properties
interactiveSize: any = 'lg';
interactiveStatus: any = 'online';
interactiveBadge = '3';
private statusCycle: any[] = ['online', 'away', 'busy', 'offline', null];
private statusIndex = 0;
private sizeCycle: any[] = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
private sizeIndex = 3; // Start with 'lg'
cycleStatus(): void {
this.statusIndex = (this.statusIndex + 1) % this.statusCycle.length;
this.interactiveStatus = this.statusCycle[this.statusIndex];
}
toggleBadge(): void {
if (this.interactiveBadge) {
this.interactiveBadge = '';
} else {
this.interactiveBadge = Math.floor(Math.random() * 99 + 1).toString();
}
}
cycleSize(): void {
this.sizeIndex = (this.sizeIndex + 1) % this.sizeCycle.length;
this.interactiveSize = this.sizeCycle[this.sizeIndex];
}
}