Reorganizes and optimizes shared CSS components

Consolidates UI components into a centralized components.css file
Removes duplicate styles across multiple CSS files
Adds utility classes in a new utilities.css file
Reduces overall CSS complexity and improves maintainability

Removes quick-stats.css and redistributes its styles
Updates layout and stylesheet references accordingly
This commit is contained in:
Janus C. H. Knudsen 2026-01-13 00:09:46 +01:00
parent 15579acba8
commit 2e6207bb0b
33 changed files with 971 additions and 796 deletions

View file

@ -0,0 +1,434 @@
/**
* UI Components - Shared reusable components
*
* This file contains all shared UI components used across the application.
* Feature files should NOT define these components - only use them.
*
* Components:
* - swp-btn (buttons)
* - swp-status-badge (status/role badges)
* - swp-plan-card (subscription plan cards)
* - swp-avatar (user avatars with size variants)
* - swp-icon-btn (icon-only buttons)
* - swp-card (content cards with section-label/footer)
* - swp-section-label (card section headers)
* - swp-section-header (section header with action link)
* - swp-section-action (action link in section header)
*/
/* ===========================================
BUTTONS (swp-btn)
=========================================== */
swp-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--spacing-2);
padding: var(--spacing-3) var(--spacing-6);
font-size: var(--font-size-base);
font-weight: var(--font-weight-medium);
font-family: var(--font-family);
border-radius: var(--radius-md);
border: 1px solid transparent;
cursor: pointer;
transition: all var(--transition-fast);
text-decoration: none;
}
swp-btn i {
font-size: 18px;
}
/* Primary button */
swp-btn.primary {
background: var(--color-teal);
color: white;
border-color: var(--color-teal);
}
swp-btn.primary:hover {
background: #00796b;
border-color: #00796b;
}
swp-btn.primary:active {
transform: translateY(1px);
}
swp-btn.primary:disabled {
background: var(--color-border);
border-color: var(--color-border);
cursor: not-allowed;
}
/* Secondary button */
swp-btn.secondary {
background: var(--color-surface);
border: 1px solid var(--color-border);
color: var(--color-text);
}
swp-btn.secondary:hover {
background: var(--color-background-hover);
}
/* Ghost button */
swp-btn.ghost {
background: transparent;
color: var(--color-text-secondary);
}
swp-btn.ghost:hover {
color: var(--color-text);
}
/* Outline button */
swp-btn.outline {
background: transparent;
border: 1px solid var(--color-teal);
color: var(--color-teal);
}
swp-btn.outline:hover {
background: color-mix(in srgb, var(--color-teal) 10%, transparent);
}
swp-btn.outline.purple {
border-color: var(--color-purple);
color: var(--color-purple);
}
swp-btn.outline.purple:hover {
background: color-mix(in srgb, var(--color-purple) 10%, transparent);
}
/* Social button */
swp-btn.social {
background: var(--color-background);
color: var(--color-text);
border-color: var(--color-border);
}
swp-btn.social:hover {
background: var(--color-background-hover);
border-color: var(--color-text-muted);
}
swp-btn.social img {
width: 20px;
height: 20px;
}
/* Size variants */
swp-btn.sm {
padding: var(--spacing-2) var(--spacing-3);
font-size: var(--font-size-xs);
}
swp-btn.sm i {
font-size: 14px;
}
swp-btn.lg {
padding: var(--spacing-4) var(--spacing-8);
font-size: var(--font-size-lg);
}
/* Full width */
swp-btn.full-width {
width: 100%;
}
/* ===========================================
STATUS BADGES (swp-status-badge)
=========================================== */
swp-status-badge {
display: inline-flex;
align-items: center;
gap: var(--spacing-3);
padding: var(--spacing-2) var(--spacing-5);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-medium);
border-radius: var(--radius-pill);
}
swp-status-badge::before {
content: '';
width: 6px;
height: 6px;
border-radius: var(--radius-full);
background: currentColor;
}
/* Status variants */
swp-status-badge.approved,
swp-status-badge.active {
background: color-mix(in srgb, var(--color-green) 15%, transparent);
color: var(--color-green);
}
swp-status-badge.draft,
swp-status-badge.invited {
background: color-mix(in srgb, var(--color-amber) 15%, transparent);
color: #b45309;
}
/* Role variants */
swp-status-badge.owner {
background: color-mix(in srgb, var(--color-teal) 15%, transparent);
color: var(--color-teal);
}
swp-status-badge.admin {
background: color-mix(in srgb, var(--color-purple) 15%, transparent);
color: var(--color-purple);
}
swp-status-badge.leader {
background: color-mix(in srgb, var(--color-blue) 15%, transparent);
color: var(--color-blue);
}
swp-status-badge.employee {
background: var(--color-background-alt);
color: var(--color-text-secondary);
}
/* ===========================================
PLAN CARDS (swp-plan-card)
=========================================== */
swp-plan-card {
display: flex;
flex-direction: column;
background: var(--color-surface);
border: 2px solid var(--color-border);
border-radius: var(--radius-xl);
padding: var(--spacing-10);
transition: all var(--transition-normal);
}
swp-plan-card.selected,
swp-plan-card.current {
border-color: var(--color-teal);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-teal) 15%, transparent);
}
swp-plan-card.popular {
border-color: var(--color-amber);
}
swp-plan-card.enterprise {
background: linear-gradient(135deg, var(--color-surface) 0%, color-mix(in srgb, var(--color-purple) 5%, var(--color-surface)) 100%);
border-color: var(--color-purple);
}
/* Disabled button for current plan */
swp-plan-card.current swp-btn.secondary {
background: var(--color-background-alt);
color: var(--color-text-secondary);
cursor: default;
pointer-events: none;
}
/* Plan badge */
swp-plan-badge {
display: inline-flex;
align-items: center;
gap: var(--spacing-2);
padding: var(--spacing-2) var(--spacing-3);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-semibold);
text-transform: uppercase;
letter-spacing: 0.5px;
border-radius: var(--radius-pill);
width: fit-content;
}
swp-plan-badge.current,
swp-plan-badge.selected {
background: color-mix(in srgb, var(--color-teal) 15%, transparent);
color: var(--color-teal);
}
swp-plan-badge.popular {
background: color-mix(in srgb, var(--color-amber) 15%, transparent);
color: var(--color-amber);
}
swp-plan-badge.enterprise {
background: color-mix(in srgb, var(--color-purple) 15%, transparent);
color: var(--color-purple);
}
swp-plan-badge.free {
background: color-mix(in srgb, var(--color-green) 15%, transparent);
color: var(--color-green);
}
swp-plan-badge i {
font-size: 14px;
}
/* Plan action */
swp-plan-action {
margin-top: auto;
padding-top: var(--card-padding);
}
swp-plan-action swp-btn {
width: 100%;
}
/* ===========================================
AVATARS (swp-avatar)
=========================================== */
swp-avatar {
border-radius: 50%;
background: var(--color-teal);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: var(--font-weight-semibold);
flex-shrink: 0;
}
/* Default size (md = 40px) */
swp-avatar {
width: 40px;
height: 40px;
font-size: var(--font-size-sm);
}
/* Size variants */
swp-avatar.size-xs {
width: 24px;
height: 24px;
font-size: 10px;
}
swp-avatar.size-sm {
width: 36px;
height: 36px;
font-size: var(--font-size-xs);
}
swp-avatar.size-lg {
width: 80px;
height: 80px;
font-size: var(--font-size-2xl);
}
/* Color variants */
swp-avatar.purple {
background: var(--color-purple);
}
swp-avatar.blue {
background: var(--color-blue);
}
swp-avatar.amber {
background: var(--color-amber);
}
swp-avatar.teal {
background: var(--color-teal);
}
/* ===========================================
ICON BUTTONS (swp-icon-btn)
=========================================== */
swp-icon-btn {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-md);
background: transparent;
border: none;
color: var(--color-text-secondary);
cursor: pointer;
transition: all var(--transition-fast);
}
swp-icon-btn:hover {
background: var(--color-background-alt);
color: var(--color-text);
}
swp-icon-btn.danger:hover {
background: color-mix(in srgb, var(--color-red) 10%, transparent);
color: var(--color-red);
}
swp-icon-btn i {
font-size: 18px;
}
/* ===========================================
CARDS (swp-card)
=========================================== */
swp-card {
display: block;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-lg);
padding: var(--card-padding);
}
/* Section label - simple card header */
swp-section-label {
display: block;
font-size: var(--font-size-xs);
font-weight: var(--font-weight-semibold);
color: var(--color-text);
text-transform: uppercase;
letter-spacing: 0.5px;
padding-bottom: var(--spacing-4);
border-bottom: 1px solid var(--color-border);
margin-bottom: var(--spacing-6);
}
/* Section header - wrapper when action link is needed */
swp-section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: var(--spacing-4);
border-bottom: 1px solid var(--color-border);
margin-bottom: var(--spacing-6);
}
swp-section-header swp-section-label {
padding-bottom: 0;
border-bottom: none;
margin-bottom: 0;
}
swp-section-action {
font-size: var(--font-size-sm);
color: var(--color-teal);
cursor: pointer;
transition: opacity var(--transition-fast);
}
swp-section-action:hover {
opacity: 0.8;
}
swp-card-content {
display: block;
}
swp-card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-6) var(--card-padding);
background: var(--color-background-alt);
border-top: 1px solid var(--color-border);
margin: var(--spacing-6) calc(-1 * var(--card-padding)) calc(-1 * var(--card-padding));
border-radius: 0 0 var(--border-radius-lg) var(--border-radius-lg);
}