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

@ -13,10 +13,32 @@ Reference for alle genbrugelige komponenter. **LAV ALDRIG EN NY KOMPONENT HVIS D
| `swp-page-title` | Titel-wrapper med h1 og p | h1 + subtitle |
| `swp-page-actions` | Action buttons i header | Flex gap |
| `swp-card` | Standard card wrapper | Border, padding, rounded |
| `swp-card-header` | Card header | Flex, title + action |
| `swp-card-title` | Card titel med ikon | `<swp-card-title><i>...</i> Text</swp-card-title>` |
| `swp-section-label` | Card section label | Uppercase, 11px, border-bottom |
| `swp-section-header` | Wrapper for label + action | Flex, space-between |
| `swp-section-action` | Action link i section header | Teal, clickable |
| `swp-card-content` | Card indhold | Block |
### Card Header Eksempler
**Simpel label (uden action):**
```html
<swp-card>
<swp-section-label>Kontakter</swp-section-label>
<swp-card-content>...</swp-card-content>
</swp-card>
```
**Label med action:**
```html
<swp-card>
<swp-section-header>
<swp-section-label>Dagens bookinger</swp-section-label>
<swp-section-action>Se alle</swp-section-action>
</swp-section-header>
<swp-card-content>...</swp-card-content>
</swp-card>
```
---
## Stats Components (stats.css)

View file

@ -3,6 +3,8 @@
*
* For logged-in users to manage their subscription plan,
* payment method, and view invoice history.
*
* Reuses: swp-btn, swp-plan-card, swp-plan-badge, swp-plan-action (components.css)
*/
/* ===========================================
@ -49,46 +51,7 @@ swp-plan-grid {
}
}
/* Plan card current state (extends auth.css) */
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-badge.current {
background: color-mix(in srgb, var(--color-teal) 15%, transparent);
color: var(--color-teal);
}
/* 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;
}
/* Enterprise plan styling */
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);
}
swp-plan-badge.popular {
background: color-mix(in srgb, var(--color-amber) 15%, transparent);
color: var(--color-amber);
}
/* Plan action buttons */
swp-plan-action {
margin-top: auto;
padding-top: var(--card-padding);
}
swp-plan-action swp-btn {
width: 100%;
justify-content: center;
}
/* Plan card/badge/action styles in components.css */
/* ===========================================
BILLING GRID (2 columns)
@ -343,37 +306,7 @@ swp-download-btn i {
font-size: 14px;
}
/* ===========================================
BUTTONS (account-specific)
=========================================== */
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);
}
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.sm {
padding: var(--spacing-2) var(--spacing-3);
font-size: var(--font-size-xs);
}
swp-btn.sm i {
font-size: 14px;
}
/* Button styles in components.css */
/* ===========================================
RESPONSIVE

View file

@ -3,6 +3,8 @@
*
* Login, Signup, Password Reset etc.
* Split-screen SaaS layout pattern
*
* Reuses: swp-btn, swp-plan-card, swp-plan-badge (components.css)
*/
/* ===========================================
@ -124,46 +126,13 @@ swp-selected-plan-header {
}
/* ===========================================
PLAN CARD (Selected Plan)
PLAN CONTENT (Auth-specific layout)
Plan card/badge base styles in components.css
=========================================== */
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 {
border-color: var(--color-teal);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-teal) 15%, transparent);
}
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;
margin-bottom: var(--spacing-4);
}
swp-plan-badge.selected {
background: color-mix(in srgb, var(--color-teal) 15%, transparent);
color: var(--color-teal);
}
swp-plan-badge i {
font-size: 14px;
}
swp-plan-name {
display: block;
font-size: var(--font-size-2xl);
@ -589,52 +558,7 @@ swp-form-checkbox a:hover {
text-decoration: underline;
}
/* ===========================================
BUTTONS
=========================================== */
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(--border-radius);
border: 1px solid transparent;
cursor: pointer;
transition: all var(--transition-fast);
text-decoration: none;
}
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.full-width {
width: 100%;
}
swp-btn.lg {
padding: var(--spacing-4) var(--spacing-8);
font-size: var(--font-size-lg);
}
swp-btn i {
font-size: 18px;
}
/* Button base styles in components.css */
/* ===========================================
AUTH FOOTER
@ -692,21 +616,7 @@ swp-social-buttons {
gap: var(--spacing-3);
}
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;
}
/* Social button styles in components.css */
/* ===========================================
FORM MESSAGES
@ -819,72 +729,12 @@ swp-pricing-grid swp-plan-card.popular {
transform: scale(1.02);
}
swp-pricing-grid 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);
}
swp-plan-badge.popular {
background: color-mix(in srgb, var(--color-teal) 15%, transparent);
color: var(--color-teal);
}
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);
}
/* Plan badge/button styles in components.css */
swp-pricing-grid swp-plan-action {
margin-top: var(--spacing-6);
}
/* Button styles for pricing */
.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(--border-radius);
border: 1px solid transparent;
cursor: pointer;
transition: all var(--transition-fast);
text-decoration: none;
}
.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.outline {
background: transparent;
color: var(--color-purple);
border-color: var(--color-purple);
}
.swp-btn.outline:hover {
background: color-mix(in srgb, var(--color-purple) 10%, transparent);
}
.swp-btn.full-width {
width: 100%;
}
swp-pricing-footer {
margin-top: var(--spacing-12);
text-align: center;

View file

@ -96,6 +96,7 @@ swp-booking-employee {
gap: var(--spacing-3);
}
/* TODO: Consider using swp-avatar.size-xs from components.css instead */
swp-booking-employee swp-avatar-small {
width: 24px;
height: 24px;

View file

@ -3,6 +3,7 @@
*
* Filter bar, stats, table, forms, and difference box
* Reuses: swp-sticky-header, swp-header-content (page.css)
* Reuses: swp-btn, swp-status-badge, swp-card-footer (components.css)
*/
/* ===========================================
@ -321,67 +322,14 @@ swp-cash-table-footer {
color: var(--color-text-secondary);
}
/* ===========================================
STATUS BADGE
=========================================== */
/* Status badge styles in components.css */
/* Center status column */
swp-cash-th:nth-child(9),
swp-cash-td:nth-child(9) {
text-align: center;
}
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);
}
/* ===========================================
TWO-COLUMN GRID (Detail View)
=========================================== */
@ -774,78 +722,14 @@ swp-checkbox-field label {
line-height: var(--line-height-normal);
}
/* ===========================================
CARD FOOTER (Actions)
=========================================== */
swp-card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-8) var(--spacing-10);
background: var(--color-background-alt);
border-top: 1px solid var(--color-border);
margin: var(--spacing-10) calc(-1 * var(--spacing-5)) calc(-1 * var(--spacing-5));
border-radius: 0 0 var(--border-radius-lg) var(--border-radius-lg);
}
/* Card footer base styles in components.css */
swp-actions-right {
display: flex;
gap: var(--spacing-5);
}
/* ===========================================
BUTTONS
=========================================== */
swp-btn {
display: inline-flex;
align-items: center;
gap: var(--spacing-3);
padding: var(--spacing-5) var(--spacing-8);
font-size: var(--font-size-md);
font-weight: var(--font-weight-medium);
font-family: var(--font-family);
border-radius: var(--radius-md);
cursor: pointer;
transition: all var(--transition-fast);
border: none;
}
swp-btn i {
font-size: var(--font-size-lg);
}
swp-btn.primary {
background: var(--color-teal);
color: white;
}
swp-btn.primary:hover {
opacity: 0.9;
}
swp-btn.primary:disabled {
background: var(--color-border);
cursor: not-allowed;
}
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);
}
swp-btn.ghost {
background: transparent;
color: var(--color-text-secondary);
}
swp-btn.ghost:hover {
color: var(--color-text);
}
/* Button styles in components.css */
/* ===========================================
SYSTEM NOTE

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);
}

View file

@ -3,7 +3,8 @@
*
* Employees-specific styling only.
* Reuses: swp-stat-card (stats.css), swp-stats-row (stats.css), swp-tab-bar (tabs.css),
* swp-btn (cash.css), swp-status-badge (cash.css), swp-row-toggle (cash.css),
* swp-btn, swp-status-badge, swp-icon-btn, swp-card, swp-section-label (components.css),
* swp-row-toggle (cash.css),
* swp-sticky-header, swp-header-content (page.css),
* swp-toggle-slider, swp-checkbox-list (controls.css)
*
@ -57,8 +58,8 @@ swp-users-progress-bar {
swp-employee-table-card {
display: block;
background: var(--color-surface);
border-radius: var(--radius-lg);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-lg);
overflow: hidden;
}
@ -195,33 +196,7 @@ swp-table-actions {
justify-content: flex-end;
}
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;
}
/* Icon button styles in components.css */
/* ===========================================
PERMISSIONS MATRIX
@ -452,7 +427,7 @@ swp-edit-row {
}
swp-edit-label {
font-size: var(--font-size-sm);
font-size: var(--font-size-md);
color: var(--color-text-secondary);
}
@ -477,16 +452,7 @@ swp-edit-value:focus {
border-color: var(--color-teal);
}
/* Section label in cards */
swp-section-label {
display: block;
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
color: var(--color-text);
margin-bottom: var(--spacing-6);
padding-bottom: var(--spacing-4);
border-bottom: 1px solid var(--color-border);
}
/* swp-section-label is now in components.css */
/* ===========================================
VIEW CONTAINERS (List/Detail swap)
@ -532,12 +498,7 @@ swp-detail-grid > div {
gap: var(--spacing-8);
}
swp-detail-grid swp-card {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
padding: var(--card-padding);
}
/* swp-card base styles in components.css */
@media (max-width: 900px) {
swp-detail-grid {

View file

@ -78,54 +78,9 @@ swp-page-actions {
}
/* ===========================================
CARDS
CARD CONTENT GRIDS (Page-specific)
Base card styles in components.css
=========================================== */
swp-card {
display: block;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-lg);
padding: var(--card-padding);
}
swp-card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin: calc(-1 * var(--card-padding)) calc(-1 * var(--card-padding)) var(--spacing-5) calc(-1 * var(--card-padding));
padding: var(--spacing-4) var(--card-padding);
border-bottom: 1px solid var(--color-border);
}
swp-card-title {
display: flex;
align-items: center;
gap: var(--spacing-2);
font-size: var(--font-size-base);
font-weight: var(--font-weight-semibold);
color: var(--color-text);
}
swp-card-title i {
font-size: var(--font-size-xl);
color: var(--color-text-secondary);
}
swp-card-action {
font-size: var(--font-size-md);
color: var(--color-teal);
cursor: pointer;
transition: opacity var(--transition-fast);
}
swp-card-action:hover {
opacity: 0.8;
}
swp-card-content {
display: block;
}
/* Card content with grid lists - auto-detect via :has() */
swp-card-content:has(> swp-booking-list),
swp-card-content:has(> swp-notification-list),

View file

@ -1,38 +0,0 @@
/**
* Quick Stats CSS
*
* Styling for quick stats components in sidebar
*/
/* ===========================================
QUICK STATS CONTAINER
=========================================== */
swp-quick-stats {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--card-gap);
}
/* ===========================================
QUICK STAT ITEM
=========================================== */
swp-quick-stat {
display: flex;
flex-direction: column;
gap: var(--spacing-2);
padding: var(--card-padding);
background: var(--color-background-alt);
border-radius: var(--radius-md);
}
swp-quick-stat swp-stat-value {
font-size: var(--font-size-xl);
font-weight: var(--font-weight-semibold);
font-family: var(--font-mono);
color: var(--color-text);
}
swp-quick-stat swp-stat-label {
font-size: var(--font-size-xs);
color: var(--color-text-secondary);
}

View file

@ -208,6 +208,36 @@ swp-stat-item swp-stat-label {
margin-top: 0;
}
/* ===========================================
QUICK STATS (Sidebar Variant)
=========================================== */
swp-quick-stats {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--card-gap);
}
swp-quick-stat {
display: flex;
flex-direction: column;
gap: var(--spacing-2);
padding: var(--card-padding);
background: var(--color-background-alt);
border-radius: var(--radius-md);
}
swp-quick-stat swp-stat-value {
font-size: var(--font-size-xl);
font-weight: var(--font-weight-semibold);
font-family: var(--font-mono);
color: var(--color-text);
}
swp-quick-stat swp-stat-label {
font-size: var(--font-size-xs);
color: var(--color-text-secondary);
}
/* ===========================================
RESPONSIVE
=========================================== */

View file

@ -0,0 +1,118 @@
/**
* Utilities - Common utility classes
*
* Reusable utility classes for common patterns.
* Use sparingly - prefer semantic component styles.
*/
/* ===========================================
FLEXBOX UTILITIES
=========================================== */
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex-start {
display: flex;
align-items: center;
justify-content: flex-start;
}
.flex-end {
display: flex;
align-items: center;
justify-content: flex-end;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-1 {
flex: 1;
}
.flex-shrink-0 {
flex-shrink: 0;
}
/* ===========================================
TEXT UTILITIES
=========================================== */
.text-truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
.text-secondary {
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
}
.text-muted {
color: var(--color-text-muted);
}
.text-mono {
font-family: var(--font-mono);
}
/* ===========================================
SPACING UTILITIES
=========================================== */
.gap-2 { gap: var(--spacing-2); }
.gap-3 { gap: var(--spacing-3); }
.gap-4 { gap: var(--spacing-4); }
.gap-6 { gap: var(--spacing-6); }
.gap-8 { gap: var(--spacing-8); }
.mt-auto { margin-top: auto; }
.mb-0 { margin-bottom: 0; }
/* ===========================================
VISIBILITY UTILITIES
=========================================== */
.hidden {
display: none !important;
}
.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;
}
/* ===========================================
WIDTH UTILITIES
=========================================== */
.w-full {
width: 100%;
}
.min-w-0 {
min-width: 0;
}

View file

@ -2,6 +2,8 @@
* Waitlist CSS
*
* Styling for waitlist mini card and drawer items
*
* Reuses: swp-btn, swp-avatar (components.css)
*/
/* ===========================================
@ -84,19 +86,7 @@ swp-waitlist-customer {
gap: var(--spacing-6);
}
swp-waitlist-customer swp-avatar {
width: 40px;
height: 40px;
border-radius: var(--radius-full);
background: var(--color-teal);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-size-base);
font-weight: var(--font-weight-semibold);
flex-shrink: 0;
}
/* Avatar base styles in components.css */
swp-waitlist-customer-info {
flex: 1;
@ -191,39 +181,9 @@ swp-waitlist-actions {
border-top: 1px solid var(--color-border);
}
/* Button base styles in components.css */
swp-waitlist-actions swp-btn {
flex: 1;
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--spacing-2);
padding: var(--spacing-4) var(--spacing-6);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
font-family: var(--font-family);
border-radius: var(--radius-md);
cursor: pointer;
transition: all var(--transition-fast);
border: none;
}
swp-waitlist-actions swp-btn.secondary {
background: var(--color-surface);
border: 1px solid var(--color-border);
color: var(--color-text);
}
swp-waitlist-actions swp-btn.secondary:hover {
background: var(--color-background-hover);
}
swp-waitlist-actions swp-btn.primary {
background: var(--color-teal);
color: white;
}
swp-waitlist-actions swp-btn.primary:hover {
opacity: 0.9;
}
/* ===========================================