Compare commits

...

4 commits

5 changed files with 874 additions and 24 deletions

View file

@ -236,41 +236,41 @@ Always come back and update UI_UPDATE.MD once complete with task and task item.
- [x] Implement icon sprite system
#### 2.4.2: Icon Size Variants
- [ ] Define icon size scale (xs-xl)
- [ ] Create consistent icon sizing proportions
- [ ] Implement responsive icon scaling
- [x] Define icon size scale (xs-xl)
- [x] Create consistent icon sizing proportions
- [x] Implement responsive icon scaling
#### 2.4.3: Animated Icons
- [ ] Create loading spinners and progress indicators
- [ ] Implement micro-interaction animations
- [ ] Add hover state animations for interactive icons
- [x] Create loading spinners and progress indicators
- [x] Implement micro-interaction animations
- [x] Add hover state animations for interactive icons
#### 2.4.4: Accessibility Implementation
- [ ] Add screen reader labels for decorative icons
- [ ] Implement focus indicators for icon buttons
- [ ] Test keyboard navigation for icon controls
- [x] Add screen reader labels for decorative icons
- [x] Implement focus indicators for icon buttons
- [x] Test keyboard navigation for icon controls
### Sub-task 2.5: Component Visual Polish
#### 2.5.1: Button Style Redesign
- [ ] Create button component with multiple variants
- [ ] Implement consistent button sizing and padding
- [ ] Add button state variations (hover, active, disabled)
- [x] Create button component with multiple variants
- [x] Implement consistent button sizing and padding
- [x] Add button state variations (hover, active, disabled)
#### 2.5.2: Card Design Updates
- [ ] Redesign card components with modern styling
- [ ] Implement consistent card shadows and borders
- [ ] Add card interaction states
- [x] Redesign card components with modern styling
- [x] Implement consistent card shadows and borders
- [x] Add card interaction states
#### 2.5.3: Form Element Updates
- [ ] Enhance input field styling
- [ ] Create consistent form element design
- [ ] Implement form validation states
- [x] Enhance input field styling
- [x] Create consistent form element design
- [x] Implement form validation states
#### 2.5.4: Loading States
- [ ] Implement skeleton loading patterns
- [ ] Create smooth loading transitions
- [ ] Add stateful component styling
- [x] Implement skeleton loading patterns
- [x] Create smooth loading transitions
- [x] Add stateful component styling
---

View file

@ -326,7 +326,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
</div>
<div class="video-player__header-controls">
<button class="stream-stats__refresh-btn" data-action="manual-refresh" title="Manual Stream Refresh" aria-label="Refresh stream">
<span class="icon-refresh"></span> Refresh
<span class="icon-refresh icon-sm"></span> Refresh
</button>
<select class="video-player__quality-selector" id="qualitySelector" style="display:none;" aria-label="Video quality">
<option value="auto">Auto Quality</option>
@ -381,7 +381,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
</div>
<section class="chat__messages" id="chatMessages" aria-live="polite" aria-label="Chat messages" role="log" aria-atomic="false">
<div class="chat__empty-state">No messages yet. Be the first to say hello! <span class="icon-wave"></span></div>
<div class="chat__empty-state">No messages yet. Be the first to say hello! <span class="icon-wave icon-md"></span></div>
</section>
<div class="chat__typing-indicator" id="typingIndicator" aria-live="assertive">

View file

@ -1,5 +1,529 @@
/* Component styles - Reusable UI components */
/* =================================================================
BUTTON COMPONENT SYSTEM
================================================================= */
/* Base button styles */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--spacing-2);
padding: var(--spacing-3) var(--spacing-5);
border: 2px solid transparent;
border-radius: var(--border-radius-lg);
font-family: var(--font-family-base);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
text-align: center;
text-decoration: none;
cursor: pointer;
transition: all var(--transition-fast);
user-select: none;
position: relative;
overflow: hidden;
min-height: var(--min-tap-target-size, 44px);
box-sizing: border-box;
}
/* Button sizes */
.btn-sm {
padding: var(--spacing-2) var(--spacing-4);
font-size: var(--font-size-xs);
min-height: var(--min-tap-target-size-sm, 36px);
}
.btn-lg {
padding: var(--spacing-4) var(--spacing-6);
font-size: var(--font-size-base);
min-height: var(--min-tap-target-size-lg, 52px);
}
/* Button variants */
.btn-primary {
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-darker));
color: var(--color-on-primary);
box-shadow: var(--elevation-3);
border-color: var(--color-primary);
}
.btn-secondary {
background: var(--color-secondary);
color: var(--color-on-secondary);
border-color: var(--color-secondary);
}
.btn-accent {
background: linear-gradient(135deg, var(--color-accent), var(--color-accent-darker));
color: var(--color-on-accent);
box-shadow: var(--elevation-3);
border-color: var(--color-accent);
}
.btn-outline {
background: transparent;
border-color: var(--color-outline);
color: var(--color-on-surface);
}
.btn-outline-primary {
background: transparent;
border-color: var(--color-primary);
color: var(--color-primary);
}
.btn-text {
background: transparent;
border-color: transparent;
color: var(--color-primary);
padding: var(--spacing-2) var(--spacing-3);
box-shadow: none;
}
/* Button states */
.btn:hover {
/* Transform handled by state variants */
}
.btn:active {
transform: translateY(0);
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none !important;
}
.btn-primary:hover {
background: linear-gradient(135deg, var(--color-primary-light), var(--color-primary));
transform: translateY(-1px);
box-shadow: var(--elevation-4);
}
.btn-secondary:hover {
transform: translateY(-1px);
box-shadow: var(--elevation-2);
}
.btn-accent:hover {
background: linear-gradient(135deg, var(--color-accent-light), var(--color-accent));
transform: translateY(-1px);
box-shadow: var(--elevation-4);
}
.btn-outline:hover {
background: var(--color-surface-variant);
}
.btn-outline-primary:hover {
background: var(--color-primary);
color: var(--color-on-primary);
}
.btn-text:hover {
background: rgba(var(--color-primary-rgb), 0.1);
}
/* Focus states for accessibility */
.btn:focus-visible {
outline: 2px solid var(--color-focus);
outline-offset: 2px;
}
/* Loading state */
.btn-loading {
position: relative;
color: transparent;
}
.btn-loading::after {
position: absolute;
content: '';
width: 1em;
height: 1em;
border: 2px solid rgba(255,255,255,0.3);
border-top: 2px solid white;
border-radius: 50%;
animation: spin 1s linear infinite;
}
/* Full width button */
.btn-full {
width: 100%;
}
/* Icon buttons */
.btn-icon {
padding: var(--spacing-2);
width: auto;
aspect-ratio: 1;
}
.btn-icon-only {
width: var(--min-tap-target-size, 44px);
height: var(--min-tap-target-size, 44px);
padding: 0;
}
/* =================================================================
CARD COMPONENT SYSTEM
================================================================= */
/* Base card styles */
.card {
background: var(--color-surface);
border-radius: var(--border-radius-lg);
box-shadow: var(--elevation-1);
border: 1px solid var(--color-outline-variant);
transition: all var(--transition-fast);
overflow: hidden;
position: relative;
}
.card-elevated {
box-shadow: var(--elevation-2);
}
.card-outlined {
border-width: 2px;
background: var(--color-surface);
}
.card-header {
padding: var(--spacing-4);
border-bottom: 1px solid var(--color-outline-variant);
background: var(--color-surface-variant);
}
.card-body {
padding: var(--spacing-4);
}
.card-footer {
padding: var(--spacing-4);
border-top: 1px solid var(--color-outline-variant);
background: var(--color-surface-variant);
}
/* Card interaction states */
.card:hover {
transform: translateY(-2px);
box-shadow: var(--elevation-3);
}
.card-interactive {
cursor: pointer;
}
.card-interactive:hover {
transform: translateY(-2px);
box-shadow: var(--elevation-3);
}
.card-interactive:active {
transform: translateY(0);
box-shadow: var(--elevation-1);
}
.card:focus-visible {
outline: 2px solid var(--color-focus);
outline-offset: 2px;
}
/* Card variants */
.card-compact .card-body {
padding: var(--spacing-3);
}
.card-compact .card-header,
.card-compact .card-footer {
padding: var(--spacing-3);
}
/* =================================================================
FORM ELEMENT SYSTEM
================================================================= */
/* Base input styles */
.form-control {
width: 100%;
padding: var(--spacing-3) var(--spacing-4);
border: 2px solid var(--color-outline);
border-radius: var(--border-radius-md);
background: var(--color-surface);
color: var(--color-on-surface);
font-family: inherit;
font-size: var(--font-size-sm);
transition: all var(--transition-fast);
box-sizing: border-box;
}
.form-control:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 3px var(--focus-ring);
}
.form-label {
display: block;
margin-bottom: var(--spacing-2);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
color: var(--color-on-surface);
}
.form-input,
.form-textarea,
.form-select {
/* Inherit from form-control */
width: 100%;
padding: var(--spacing-3) var(--spacing-4);
border: 2px solid var(--color-outline);
border-radius: var(--border-radius-md);
background: var(--color-surface);
color: var(--color-on-surface);
font-family: inherit;
font-size: var(--font-size-sm);
transition: all var(--transition-fast);
box-sizing: border-box;
}
.form-input:focus,
.form-textarea:focus,
.form-select:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 3px var(--focus-ring);
}
/* Form row for horizontal layouts */
.form-row {
display: flex;
gap: var(--spacing-4);
align-items: flex-start;
}
.form-row .form-control {
flex: 1;
}
/* Validation states */
.form-group {
margin-bottom: var(--spacing-4);
position: relative;
}
.form-group--error .form-control {
border-color: var(--color-error);
}
.form-group--error .form-control:focus {
box-shadow: 0 0 0 3px rgba(var(--color-error-rgb), 0.2);
}
.form-group--success .form-control {
border-color: var(--color-success);
}
.form-group--success .form-control:focus {
box-shadow: 0 0 0 3px rgba(var(--color-success-rgb), 0.2);
}
.form-error,
.form-success {
font-size: var(--font-size-xs);
margin-top: var(--spacing-1);
display: block;
}
.form-error {
color: var(--color-error);
}
.form-success {
color: var(--color-success);
}
/* =================================================================
LOADING STATES - SKELETONS AND TRANSITIONS
================================================================= */
/* Skeleton loading animations */
@keyframes skeleton-pulse {
0% { opacity: 1; }
50% { opacity: 0.6; }
100% { opacity: 1; }
}
/* Base skeleton styles */
.skeleton {
background: linear-gradient(90deg, var(--color-surface-variant) 25%, var(--color-surface) 50%, var(--color-surface-variant) 75%);
background-size: 200% 100%;
animation: skeleton-pulse 1.5s ease-in-out infinite, skeleton-shimmer 1.5s ease-in-out infinite;
border-radius: var(--border-radius-sm);
}
@keyframes skeleton-shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
/* Specific skeleton types */
.skeleton-text {
height: var(--font-size-base);
width: 100%;
margin-bottom: var(--spacing-2);
}
.skeleton-text:last-child {
margin-bottom: 0;
}
.skeleton-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
}
.skeleton-button {
height: var(--min-tap-target-size, 44px);
width: 120px;
border-radius: var(--border-radius-lg);
}
.skeleton-card {
padding: var(--spacing-4);
margin-bottom: var(--spacing-4);
}
.skeleton-card .skeleton-header {
height: var(--font-size-lg);
width: 60%;
margin-bottom: var(--spacing-3);
}
.skeleton-card .skeleton-content {
height: var(--font-size-sm);
width: 100%;
margin-bottom: var(--spacing-1);
}
.skeleton-card .skeleton-content:nth-child(2) {
width: 80%;
}
.skeleton-card .skeleton-content:nth-child(3) {
width: 90%;
}
/* Loading overlay */
.loading-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(var(--color-surface-rgb), 0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
opacity: 0;
transition: opacity var(--transition-fast);
pointer-events: none;
}
.loading-overlay.active {
opacity: 1;
pointer-events: auto;
}
/* Loading spinner */
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid var(--color-surface-variant);
border-top: 3px solid var(--color-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
}
/* Loading bar */
.loading-bar {
width: 100%;
height: 3px;
background: var(--color-surface-variant);
border-radius: 2px;
overflow: hidden;
position: relative;
}
.loading-bar::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, var(--color-primary), transparent);
animation: loading-bar-anim 1.5s ease-in-out infinite;
}
@keyframes loading-bar-anim {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
/* =================================================================
STATEFUL COMPONENTS - Interactive States
================================================================= */
/* State utilities for dynamic components */
.state-loading {
position: relative;
overflow: hidden;
}
.state-loading::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.1) 50%, transparent 100%);
animation: state-loading-shimmer 2s infinite;
z-index: 1;
}
@keyframes state-loading-shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.state-disabled {
opacity: 0.6;
pointer-events: none;
}
.state-expanded {
transform: rotate(180deg);
}
.state-collapsed {
transform: rotate(0deg);
}
.state-active {
background: var(--color-primary);
color: var(--color-on-primary);
}
.state-inactive {
background: var(--color-surface-variant);
color: var(--color-on-surface);
}
/* =================================================================
VIDEO HEADER - Top section of video area
================================================================= */

View file

@ -1,4 +1,37 @@
/* SVG Icon System */
/* =================================================================
ANIMATIONS
================================================================= */
/* Keyframe definitions */
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.8; transform: scale(1.05); }
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
40% { transform: translateY(-4px); }
60% { transform: translateY(-2px); }
}
@keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes progress-fill {
0% { width: 0%; }
100% { width: var(--progress-fill-percent, 100%); }
}
/* =================================================================
SVG Icon System
================================================================= */
.icon {
display: inline-flex;
@ -6,12 +39,15 @@
justify-content: center;
width: 1em;
height: 1em;
/* Smooth transitions for hover effects */
transition: transform 0.2s ease, color 0.2s ease, opacity 0.2s ease;
}
.icon svg {
width: 100%;
height: 100%;
fill: currentColor;
transition: inherit;
}
/* Icon Definitions */
@ -89,3 +125,275 @@
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='currentColor'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M7 16l-4-4m0 0l4-4m-4 4h18'%3E%3C/svg%3E") no-repeat center center;
background-size: contain;
}
/* =================================================================
ICON SIZE MODIFIERS
================================================================= */
/* Extra small icons (12px) */
.icon-xs {
width: var(--icon-size-xs);
height: var(--icon-size-xs);
}
/* Small icons (16px) - Default fallback */
.icon-sm {
width: var(--icon-size-sm);
height: var(--icon-size-sm);
}
/* Medium icons (20px) */
.icon-md {
width: var(--icon-size-md);
height: var(--icon-size-md);
}
/* Large icons (24px) */
.icon-lg {
width: var(--icon-size-lg);
height: var(--icon-size-lg);
}
/* Extra large icons (32px) */
.icon-xl {
width: var(--icon-size-xl);
height: var(--icon-size-xl);
}
/* =================================================================
RESPONSIVE ICON SCALING
================================================================= */
/* Responsive size variants that scale with viewport */
.icon-responsive {
--current-icon-size: var(--icon-size-sm);
width: var(--current-icon-size);
height: var(--current-icon-size);
}
.icon-responsive-xs {
--current-icon-size: var(--icon-size-responsive-xs);
width: var(--current-icon-size);
height: var(--current-icon-size);
}
.icon-responsive-sm {
--current-icon-size: var(--icon-size-responsive-sm);
width: var(--current-icon-size);
height: var(--current-icon-size);
}
.icon-responsive-md {
--current-icon-size: var(--icon-size-responsive-md);
width: var(--current-icon-size);
height: var(--current-icon-size);
}
.icon-responsive-lg {
--current-icon-size: var(--icon-size-responsive-lg);
width: var(--current-icon-size);
height: var(--current-icon-size);
}
.icon-responsive-xl {
--current-icon-size: var(--icon-size-responsive-xl);
width: var(--current-icon-size);
height: var(--current-icon-size);
}
/* =================================================================
ACCESSIBILITY - Screen Reader Support
================================================================= */
/* Screen reader only text - hide visually but available to assistive tech */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Screen reader only - but show when focused for keyboard users */
.sr-only:focus {
position: static;
width: auto;
height: auto;
padding: 0.5rem;
margin: 0;
overflow: visible;
clip: auto;
white-space: normal;
background: var(--color-surface);
color: var(--color-on-surface);
border-radius: var(--border-radius-md);
box-shadow: var(--elevation-3);
z-index: var(--z-tooltip);
}
/* =================================================================
FOCUS INDICATORS FOR ICON CONTROLS
================================================================= */
/* Base focus styles for interactive icons */
.icon-interactive:focus {
outline: 2px solid var(--color-focus);
outline-offset: 2px;
border-radius: var(--border-radius-sm);
}
/* Enhanced focus ring that matches design system */
.icon-focus-ring {
position: relative;
}
.icon-focus-ring:focus::after {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border: 2px solid var(--color-focus);
border-radius: var(--border-radius-md);
z-index: 1;
pointer-events: none;
}
/* =================================================================
ANIMATED ICONS
================================================================= */
/* Loading States and Spinners */
.icon-loading,
.icon-refresh.icon-loading {
animation: spin 1s linear infinite;
}
.icon-spinner {
display: inline-block;
width: 1em;
height: 1em;
animation: spin 1s linear infinite;
}
.icon-spinner::before {
content: '';
display: inline-block;
width: 100%;
height: 100%;
border: 2px solid var(--color-primary-light);
border-top: 2px solid var(--color-primary);
border-radius: 50%;
}
/* Micro-interaction Animations */
.icon-pulse {
animation: pulse 2s ease-in-out infinite;
}
/* Applied when element is being updated or refreshed */
.icon-bounce {
animation: bounce 1s ease-in-out infinite;
}
/* Smooth fade in for new icons */
.icon-fade-in {
animation: fadeIn 0.3s ease-in;
}
/* =================================================================
PROGRESS INDICATORS
================================================================= */
.progress-indicator {
display: inline-block;
position: relative;
width: 100%;
height: 4px;
background-color: var(--color-surface-variant);
border-radius: 2px;
overflow: hidden;
}
.progress-indicator::after {
content: '';
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 0%;
background-color: var(--color-primary);
border-radius: 2px;
animation: progress-fill 2s ease-out;
}
/* Customizable progress with CSS variable */
.progress-indicator-custom {
--progress-fill-percent: 75%;
}
.progress-indicator-custom::after {
animation: progress-fill var(--progress-duration, 1s) ease-out;
}
/* =================================================================
HOVER STATE ANIMATIONS
================================================================= */
/* Base hover effects for interactive icons */
.icon:hover,
.icon-interactive:hover {
transform: scale(1.1);
}
/* Specific hover effects for different icon types */
.icon-refresh:hover {
color: var(--color-accent);
animation: spin 0.5s ease-in;
}
.icon-chat:hover {
transform: scale(1.1) translateY(-1px);
color: var(--color-accent);
}
.icon-baseball:hover {
animation: bounce 0.6s ease-in-out;
}
.icon-users:hover {
transform: scale(1.05) translateY(-1px);
color: var(--color-secondary);
}
.icon-wave:hover {
transform: translateX(2px);
color: var(--color-accent);
}
/* Interactive button icons - more pronounced effects */
.icon-button:hover {
transform: scale(1.15);
filter: brightness(1.2);
transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Icon sets with coordinated hover effects */
.icon-group .icon:hover {
z-index: 1;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
/* Override defaults for specific icon types if needed */
/* Add icon-specific overrides here as needed */

View file

@ -277,6 +277,24 @@
--z-tooltip: 1070;
--z-toast: 1080;
/* =================================================================
ICON SIZE SCALE
================================================================= */
/* Icon Size Scale - Consistent scaling for SVG icons */
--icon-size-xs: 0.75rem; /* 12px - Small indicators */
--icon-size-sm: 1rem; /* 16px - Default size */
--icon-size-md: 1.25rem; /* 20px - Button icons */
--icon-size-lg: 1.5rem; /* 24px - Navigation elements */
--icon-size-xl: 2rem; /* 32px - Hero elements */
/* Responsive icon sizes based on viewport */
--icon-size-responsive-xs: clamp(0.625rem, 2vw, var(--icon-size-xs));
--icon-size-responsive-sm: clamp(0.875rem, 2.5vw, var(--icon-size-sm));
--icon-size-responsive-md: clamp(1rem, 3vw, var(--icon-size-md));
--icon-size-responsive-lg: clamp(1.25rem, 3.5vw, var(--icon-size-lg));
--icon-size-responsive-xl: clamp(1.5rem, 4vw, var(--icon-size-xl));
/* =================================================================
TRANSITIONS & ANIMATIONS
================================================================= */