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:
skyai_dev
2025-09-03 05:38:09 +10:00
parent c803831f60
commit 5983722793
246 changed files with 52845 additions and 25 deletions

View File

@@ -0,0 +1,175 @@
// Layout Container Component - Main application shell layout
.ui-layout-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
box-sizing: border-box;
overflow: hidden;
display: flex;
flex-wrap: nowrap;
flex-direction: column;
align-items: stretch;
flex-flow: column;
// Top navigation bar
&__top-bar {
order: 1;
flex: 0 0 64px; // Standard app bar height
box-sizing: border-box;
overflow: hidden;
transition: all 300ms cubic-bezier(0.2, 0.0, 0, 1.0);
position: relative;
}
// Main content wrapper
&__centre-wrapper {
width: 100%;
box-sizing: border-box;
position: relative;
order: 2;
flex: 1;
overflow: hidden;
min-height: 0;
display: flex;
flex-wrap: nowrap;
flex-direction: row;
align-items: stretch;
// Left sidebar navigation
.left-navigation {
order: 1;
flex: 0 0 64px; // Collapsed sidebar width
overflow: hidden;
position: relative;
box-sizing: border-box;
height: 100%;
transition: all 300ms cubic-bezier(0.2, 0.0, 0, 1.0);
// Navigation states
&--hide {
flex: 0 0 0;
}
&--rail {
flex: 0 0 80px; // Rail navigation width
}
&--full {
flex: 0 0 320px; // Expanded sidebar width
}
}
// Main content area
.main-body {
order: 2;
flex: 1;
overflow: hidden;
min-height: 0;
box-sizing: border-box;
position: relative;
display: flex;
flex-wrap: nowrap;
flex-direction: column;
align-items: stretch;
// Inner header section
&__header {
order: 1;
flex: 0 0 0;
box-sizing: border-box;
overflow: hidden;
transition: all 300ms cubic-bezier(0.2, 0.0, 0, 1.0);
width: 100%;
position: relative;
}
// Inner content body
&__body {
order: 2;
flex: 1;
overflow: hidden;
min-height: 0;
box-sizing: border-box;
}
// Inner footer section
&__footer {
order: 3;
flex: 0 0 0;
box-sizing: border-box;
overflow: hidden;
transition: all 300ms cubic-bezier(0.2, 0.0, 0, 1.0);
width: 100%;
position: relative;
}
}
// Right sidebar navigation
.right-navigation {
order: 3;
flex: 0 0 320px; // Right sidebar width
overflow: hidden;
position: relative;
box-sizing: border-box;
height: 100%;
transition: all 300ms cubic-bezier(0.2, 0.0, 0, 1.0);
// Right navigation states
&--hide {
flex: 0 0 0;
}
&--show {
flex: 0 0 320px; // Shown right sidebar width
}
}
}
// Bottom bar section
&__bottom-bar {
order: 3;
flex: 0 0 0;
overflow: hidden;
box-sizing: border-box;
transition: all 300ms cubic-bezier(0.2, 0.0, 0, 1.0);
}
// Responsive design for smaller screens
@media (max-width: 768px) {
&__centre-wrapper {
.left-navigation {
&--full {
flex: 0 0 280px; // Smaller full width on mobile
}
}
.right-navigation {
&--show {
flex: 0 0 280px; // Smaller right sidebar on mobile
}
}
}
}
// Mobile breakpoint - stack navigation vertically
@media (max-width: 640px) {
&__centre-wrapper {
flex-direction: column;
.left-navigation,
.right-navigation {
&--full,
&--show {
flex: 0 0 64px; // Navigation becomes horizontal bar on mobile
}
}
}
}
}

View File

@@ -0,0 +1,138 @@
import { Component, ChangeDetectionStrategy, input, computed } from '@angular/core';
export type NavigationState = 'hide' | 'rail' | 'full';
export type SidebarState = 'hide' | 'show';
@Component({
selector: 'ui-layout-container',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
styleUrl: './layout-container.component.scss',
template: `
<div class="ui-layout-container">
<!-- Top navigation bar -->
<div class="ui-layout-container__top-bar"
[style.flex-basis.px]="effectiveTopBarHeight()">
<ng-content select="[slot=top-bar]"></ng-content>
</div>
<!-- Main content wrapper -->
<div class="ui-layout-container__centre-wrapper">
<!-- Left sidebar navigation -->
<div class="left-navigation"
[class]="leftNavigationClasses()"
[style.flex-basis.px]="leftNavigationWidth()">
<ng-content select="[slot=left-navigation]"></ng-content>
</div>
<!-- Main content area -->
<div class="main-body">
<!-- Inner header -->
<div class="main-body__header"
[style.flex-basis.px]="effectiveInnerHeaderHeight()">
<ng-content select="[slot=inner-header]"></ng-content>
</div>
<!-- Inner content body -->
<div class="main-body__body">
<ng-content select="[slot=content]"></ng-content>
</div>
<!-- Inner footer -->
<div class="main-body__footer"
[style.flex-basis.px]="effectiveInnerFooterHeight()">
<ng-content select="[slot=inner-footer]"></ng-content>
</div>
</div>
<!-- Right sidebar navigation -->
<div class="right-navigation"
[class]="rightNavigationClasses()"
[style.flex-basis.px]="rightNavigationWidth()">
<ng-content select="[slot=right-navigation]"></ng-content>
</div>
</div>
<!-- Bottom bar -->
<div class="ui-layout-container__bottom-bar"
[style.flex-basis.px]="effectiveBottomBarHeight()">
<ng-content select="[slot=bottom-bar]"></ng-content>
</div>
</div>
`
})
export class LayoutContainerComponent {
// Input signals for layout configuration
leftNavigationState = input<NavigationState>('rail');
rightNavigationState = input<SidebarState>('hide');
// Show/hide inputs
showTopBar = input<boolean>(false);
showInnerHeader = input<boolean>(false);
showInnerFooter = input<boolean>(false);
showBottomBar = input<boolean>(false);
// Size inputs (in pixels) - with sensible defaults
topBarHeight = input<number>(64);
innerHeaderHeight = input<number>(56);
innerFooterHeight = input<number>(48);
bottomBarHeight = input<number>(56);
// Custom width overrides
customLeftWidth = input<number | null>(null);
customRightWidth = input<number | null>(null);
// Computed CSS classes for navigation states
leftNavigationClasses = computed(() => {
const state = this.leftNavigationState();
return `left-navigation--${state}`;
});
rightNavigationClasses = computed(() => {
const state = this.rightNavigationState();
return `right-navigation--${state}`;
});
// Computed widths based on state and custom overrides
leftNavigationWidth = computed(() => {
const customWidth = this.customLeftWidth();
if (customWidth !== null) return customWidth;
const state = this.leftNavigationState();
switch (state) {
case 'hide': return 0;
case 'rail': return 81;
case 'full': return 320;
default: return 64;
}
});
rightNavigationWidth = computed(() => {
const customWidth = this.customRightWidth();
if (customWidth !== null) return customWidth;
const state = this.rightNavigationState();
switch (state) {
case 'hide': return 0;
case 'show': return 320;
default: return 0;
}
});
// Computed effective heights (0 when hidden, configured height when shown)
effectiveTopBarHeight = computed(() => {
return this.showTopBar() ? this.topBarHeight() : 0;
});
effectiveInnerHeaderHeight = computed(() => {
return this.showInnerHeader() ? this.innerHeaderHeight() : 0;
});
effectiveInnerFooterHeight = computed(() => {
return this.showInnerFooter() ? this.innerFooterHeight() : 0;
});
effectiveBottomBarHeight = computed(() => {
return this.showBottomBar() ? this.bottomBarHeight() : 0;
});
}