Add comprehensive component library and demo application
Added extensive component library with feedback components (empty state, loading spinner, skeleton loader), enhanced form components (autocomplete, date picker, file upload, form field, time picker), navigation components (pagination), and overlay components (backdrop, drawer, modal, overlay container). Updated demo application with comprehensive showcase components and enhanced styling throughout the project. Excluded font files from repository to reduce size. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,389 @@
|
||||
import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormControl, FormGroup, ReactiveFormsModule, Validators, FormsModule } from '@angular/forms';
|
||||
import { SwitchComponent } from '../../../../../ui-essentials/src/lib/components/forms/switch';
|
||||
|
||||
@Component({
|
||||
selector: 'ui-switch-demo',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
SwitchComponent
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<div style="padding: 2rem;">
|
||||
<h2>Switch Component Showcase</h2>
|
||||
|
||||
<!-- Basic Switches -->
|
||||
<section style="margin-bottom: 3rem;">
|
||||
<h3>Basic Switches</h3>
|
||||
<div style="display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; margin-bottom: 1rem;">
|
||||
<ui-switch size="sm" label="Small" (switchChange)="handleToggle('small', $event)"></ui-switch>
|
||||
<ui-switch size="md" label="Medium" (switchChange)="handleToggle('medium', $event)"></ui-switch>
|
||||
<ui-switch size="lg" label="Large" (switchChange)="handleToggle('large', $event)"></ui-switch>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Switch Variants -->
|
||||
<section style="margin-bottom: 3rem;">
|
||||
<h3>Variants</h3>
|
||||
<div style="display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; margin-bottom: 1rem;">
|
||||
<ui-switch variant="primary" label="Primary" (switchChange)="handleToggle('primary', $event)"></ui-switch>
|
||||
<ui-switch variant="secondary" label="Secondary" (switchChange)="handleToggle('secondary', $event)"></ui-switch>
|
||||
<ui-switch variant="success" label="Success" (switchChange)="handleToggle('success', $event)"></ui-switch>
|
||||
<ui-switch variant="warning" label="Warning" (switchChange)="handleToggle('warning', $event)"></ui-switch>
|
||||
<ui-switch variant="danger" label="Danger" (switchChange)="handleToggle('danger', $event)"></ui-switch>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Switch States -->
|
||||
<section style="margin-bottom: 3rem;">
|
||||
<h3>States</h3>
|
||||
<div style="display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; margin-bottom: 1rem;">
|
||||
<ui-switch label="Enabled" (switchChange)="handleToggle('enabled', $event)"></ui-switch>
|
||||
<ui-switch label="Disabled" [disabled]="true" (switchChange)="handleToggle('disabled', $event)"></ui-switch>
|
||||
<ui-switch label="Pre-checked" [(ngModel)]="preCheckedValue" (switchChange)="handleToggle('pre-checked', $event)"></ui-switch>
|
||||
<ui-switch label="Required" [required]="true" (switchChange)="handleToggle('required', $event)"></ui-switch>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Size Comparison -->
|
||||
<section style="margin-bottom: 3rem;">
|
||||
<h3>Size Comparison</h3>
|
||||
<div style="display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; margin-bottom: 2rem;">
|
||||
<div style="display: flex; flex-direction: column; gap: 1rem; align-items: center;">
|
||||
<ui-switch size="sm" variant="primary" label="Small Primary" (switchChange)="handleToggle('sm-primary', $event)"></ui-switch>
|
||||
<ui-switch size="md" variant="primary" label="Medium Primary" (switchChange)="handleToggle('md-primary', $event)"></ui-switch>
|
||||
<ui-switch size="lg" variant="primary" label="Large Primary" (switchChange)="handleToggle('lg-primary', $event)"></ui-switch>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 1rem; align-items: center;">
|
||||
<ui-switch size="sm" variant="success" label="Small Success" (switchChange)="handleToggle('sm-success', $event)"></ui-switch>
|
||||
<ui-switch size="md" variant="success" label="Medium Success" (switchChange)="handleToggle('md-success', $event)"></ui-switch>
|
||||
<ui-switch size="lg" variant="success" label="Large Success" (switchChange)="handleToggle('lg-success', $event)"></ui-switch>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 1rem; align-items: center;">
|
||||
<ui-switch size="sm" variant="danger" label="Small Danger" (switchChange)="handleToggle('sm-danger', $event)"></ui-switch>
|
||||
<ui-switch size="md" variant="danger" label="Medium Danger" (switchChange)="handleToggle('md-danger', $event)"></ui-switch>
|
||||
<ui-switch size="lg" variant="danger" label="Large Danger" (switchChange)="handleToggle('lg-danger', $event)"></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Switches without Labels -->
|
||||
<section style="margin-bottom: 3rem;">
|
||||
<h3>Switches without Labels</h3>
|
||||
<div style="display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; margin-bottom: 1rem;">
|
||||
<div style="display: flex; flex-direction: column; gap: 0.5rem; align-items: center;">
|
||||
<ui-switch size="sm" variant="primary" ariaLabel="Small toggle" (switchChange)="handleToggle('no-label-sm', $event)"></ui-switch>
|
||||
<span style="font-size: 12px; color: #666;">Small</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 0.5rem; align-items: center;">
|
||||
<ui-switch size="md" variant="secondary" ariaLabel="Medium toggle" (switchChange)="handleToggle('no-label-md', $event)"></ui-switch>
|
||||
<span style="font-size: 12px; color: #666;">Medium</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 0.5rem; align-items: center;">
|
||||
<ui-switch size="lg" variant="success" ariaLabel="Large toggle" (switchChange)="handleToggle('no-label-lg', $event)"></ui-switch>
|
||||
<span style="font-size: 12px; color: #666;">Large</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Switches with Helper Text -->
|
||||
<section style="margin-bottom: 3rem;">
|
||||
<h3>With Helper Text</h3>
|
||||
<div style="display: flex; flex-direction: column; gap: 1.5rem;">
|
||||
<ui-switch
|
||||
label="Email Notifications"
|
||||
helperText="Receive email updates about your account activity"
|
||||
(switchChange)="handleToggle('email-notifications', $event)">
|
||||
</ui-switch>
|
||||
<ui-switch
|
||||
label="Dark Mode"
|
||||
helperText="Switch to dark theme for better viewing in low light"
|
||||
variant="secondary"
|
||||
(switchChange)="handleToggle('dark-mode', $event)">
|
||||
</ui-switch>
|
||||
<ui-switch
|
||||
label="Auto-save"
|
||||
helperText="Automatically save your work every 30 seconds"
|
||||
variant="success"
|
||||
[(ngModel)]="autoSaveValue"
|
||||
(switchChange)="handleToggle('auto-save', $event)">
|
||||
</ui-switch>
|
||||
<ui-switch
|
||||
label="Data Sharing"
|
||||
helperText="Share anonymous usage data to help improve our services"
|
||||
variant="warning"
|
||||
(switchChange)="handleToggle('data-sharing', $event)">
|
||||
</ui-switch>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Reactive Forms Integration -->
|
||||
<section style="margin-bottom: 3rem;">
|
||||
<h3>Reactive Forms Integration</h3>
|
||||
<form [formGroup]="settingsForm" style="display: flex; flex-direction: column; gap: 1.5rem; max-width: 400px;">
|
||||
<ui-switch
|
||||
formControlName="notifications"
|
||||
label="Push Notifications"
|
||||
helperText="Receive push notifications on your device">
|
||||
</ui-switch>
|
||||
<ui-switch
|
||||
formControlName="newsletter"
|
||||
label="Newsletter Subscription"
|
||||
variant="secondary"
|
||||
helperText="Subscribe to our weekly newsletter">
|
||||
</ui-switch>
|
||||
<ui-switch
|
||||
formControlName="analytics"
|
||||
label="Analytics Tracking"
|
||||
variant="warning"
|
||||
[required]="true"
|
||||
helperText="Required for core functionality">
|
||||
</ui-switch>
|
||||
<ui-switch
|
||||
formControlName="marketing"
|
||||
label="Marketing Emails"
|
||||
variant="danger"
|
||||
helperText="Receive promotional offers and updates">
|
||||
</ui-switch>
|
||||
|
||||
<div style="margin-top: 1rem; padding: 1rem; background: #f8f9fa; border-radius: 4px;">
|
||||
<h4>Form Values:</h4>
|
||||
<pre style="font-size: 0.875rem; margin: 0;">{{ getFormValues() }}</pre>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 1rem;">
|
||||
<button type="button" (click)="resetForm()" style="padding: 0.5rem 1rem; border: 1px solid #ccc; border-radius: 4px; background: white; cursor: pointer;">
|
||||
Reset Form
|
||||
</button>
|
||||
<button type="button" (click)="toggleAllSwitches()" style="padding: 0.5rem 1rem; border: 1px solid #007bff; border-radius: 4px; background: #007bff; color: white; cursor: pointer;">
|
||||
Toggle All
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</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 Switch:</h4>
|
||||
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code><ui-switch
|
||||
label="Enable feature"
|
||||
size="md"
|
||||
variant="primary"
|
||||
(switchChange)="onToggle($event)">
|
||||
</ui-switch></code></pre>
|
||||
|
||||
<h4>Switch with Helper Text:</h4>
|
||||
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code><ui-switch
|
||||
label="Email Notifications"
|
||||
helperText="Receive updates via email"
|
||||
variant="success"
|
||||
[ngModel]="emailEnabled"
|
||||
(switchChange)="toggleEmail($event)">
|
||||
</ui-switch></code></pre>
|
||||
|
||||
<h4>Reactive Form Switch:</h4>
|
||||
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code><ui-switch
|
||||
formControlName="agreement"
|
||||
label="I agree to terms"
|
||||
variant="primary"
|
||||
[required]="true">
|
||||
</ui-switch></code></pre>
|
||||
|
||||
<h4>Switch without Label:</h4>
|
||||
<pre style="background: #fff; padding: 1rem; border-radius: 4px; overflow-x: auto;"><code><ui-switch
|
||||
size="lg"
|
||||
variant="secondary"
|
||||
ariaLabel="Toggle feature"
|
||||
(switchChange)="handleToggle($event)">
|
||||
</ui-switch></code></pre>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Interactive Demo -->
|
||||
<section style="margin-bottom: 3rem;">
|
||||
<h3>Interactive Demo</h3>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 2rem; margin-bottom: 2rem;">
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Size:</label>
|
||||
<select [(ngModel)]="demoSizeValue" style="padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px;">
|
||||
<option value="sm">Small</option>
|
||||
<option value="md">Medium</option>
|
||||
<option value="lg">Large</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Variant:</label>
|
||||
<select [(ngModel)]="demoVariantValue" style="padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px;">
|
||||
<option value="primary">Primary</option>
|
||||
<option value="secondary">Secondary</option>
|
||||
<option value="success">Success</option>
|
||||
<option value="warning">Warning</option>
|
||||
<option value="danger">Danger</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 0.5rem; font-weight: bold;">Options:</label>
|
||||
<div style="display: flex; flex-direction: column; gap: 0.25rem;">
|
||||
<label style="font-size: 0.875rem;">
|
||||
<input type="checkbox" [(ngModel)]="demoDisabledValue" style="margin-right: 0.5rem;">
|
||||
Disabled
|
||||
</label>
|
||||
<label style="font-size: 0.875rem;">
|
||||
<input type="checkbox" [(ngModel)]="demoRequiredValue" style="margin-right: 0.5rem;">
|
||||
Required
|
||||
</label>
|
||||
<label style="font-size: 0.875rem;">
|
||||
<input type="checkbox" [(ngModel)]="demoWithHelperValue" style="margin-right: 0.5rem;">
|
||||
With Helper Text
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="padding: 2rem; border: 2px dashed #ccc; border-radius: 8px; background: #fafafa;">
|
||||
<h4>Live Preview:</h4>
|
||||
<ui-switch
|
||||
[size]="demoSizeValue"
|
||||
[variant]="demoVariantValue"
|
||||
[disabled]="demoDisabledValue"
|
||||
[required]="demoRequiredValue"
|
||||
[helperText]="demoWithHelperValue ? 'This is example helper text for the switch component.' : ''"
|
||||
label="Interactive Demo Switch"
|
||||
[(ngModel)]="demoCheckedValue"
|
||||
(switchChange)="handleDemoToggle($event)">
|
||||
</ui-switch>
|
||||
|
||||
<div style="margin-top: 1rem; font-size: 0.875rem; color: #666;">
|
||||
<strong>Current state:</strong> {{ demoCheckedValue ? 'ON' : 'OFF' }}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Last Action Display -->
|
||||
@if (lastAction()) {
|
||||
<section style="margin-bottom: 2rem;">
|
||||
<div style="padding: 1rem; background: #e3f2fd; border-radius: 4px; border-left: 4px solid #2196f3;">
|
||||
<strong>Last Action:</strong> {{ lastAction() }}
|
||||
</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;
|
||||
}
|
||||
|
||||
select, input[type="checkbox"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class SwitchDemoComponent {
|
||||
lastAction = signal<string>('');
|
||||
|
||||
// Template values for ngModel binding
|
||||
preCheckedValue = true;
|
||||
autoSaveValue = true;
|
||||
|
||||
// Interactive demo properties
|
||||
demoSizeValue: 'sm' | 'md' | 'lg' = 'md';
|
||||
demoVariantValue: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' = 'primary';
|
||||
demoDisabledValue = false;
|
||||
demoRequiredValue = false;
|
||||
demoWithHelperValue = false;
|
||||
demoCheckedValue = false;
|
||||
|
||||
// Reactive form
|
||||
settingsForm = new FormGroup({
|
||||
notifications: new FormControl(false),
|
||||
newsletter: new FormControl(true),
|
||||
analytics: new FormControl(false, [Validators.requiredTrue]),
|
||||
marketing: new FormControl(false)
|
||||
});
|
||||
|
||||
handleToggle(switchName: string, checked: boolean): void {
|
||||
const action = `${switchName}: ${checked ? 'ON' : 'OFF'}`;
|
||||
this.lastAction.set(action);
|
||||
console.log(`Switch toggled - ${action}`);
|
||||
}
|
||||
|
||||
handleDemoToggle(checked: boolean): void {
|
||||
this.demoCheckedValue = checked;
|
||||
this.handleToggle('Interactive Demo', checked);
|
||||
}
|
||||
|
||||
getFormValues(): string {
|
||||
const values = this.settingsForm.value;
|
||||
return JSON.stringify(values, null, 2);
|
||||
}
|
||||
|
||||
resetForm(): void {
|
||||
this.settingsForm.reset({
|
||||
notifications: false,
|
||||
newsletter: false,
|
||||
analytics: false,
|
||||
marketing: false
|
||||
});
|
||||
this.lastAction.set('Form reset to default values');
|
||||
}
|
||||
|
||||
toggleAllSwitches(): void {
|
||||
const allEnabled = Object.values(this.settingsForm.value).every(val => val === true);
|
||||
const newState = !allEnabled;
|
||||
|
||||
this.settingsForm.patchValue({
|
||||
notifications: newState,
|
||||
newsletter: newState,
|
||||
analytics: newState,
|
||||
marketing: newState
|
||||
});
|
||||
|
||||
this.lastAction.set(`All switches turned ${newState ? 'ON' : 'OFF'}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user