g/** * 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) * - swp-add-button (dashed border add button) * - BASE PATTERNS: table, list-item, icon-container (Grid+Subgrid reusable patterns) */ /* =========================================== BASE PATTERNS - Grid + Subgrid Tables =========================================== */ /* Base table structure - use with feature-specific column definitions */ swp-table-header-base { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; background: var(--color-background-alt); border-bottom: 1px solid var(--color-border); } swp-table-body-base { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; } swp-table-row-base { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; border-bottom: 1px solid var(--color-border); transition: background var(--transition-fast); } swp-table-row-base:last-child { border-bottom: none; } swp-table-row-base:hover { background: var(--color-background-hover); } /* Header cells base styling */ swp-table-header-base swp-table-cell-base { font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); text-transform: uppercase; letter-spacing: 0.5px; color: var(--color-text-secondary); } /* =========================================== BASE PATTERNS - List Items (Grid+Subgrid) =========================================== */ swp-list-base { display: contents; } swp-list-item-base { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; padding: var(--card-padding); background: var(--color-background-alt); border-radius: var(--radius-lg); cursor: pointer; transition: background var(--transition-fast); } swp-list-item-base:hover { background: var(--color-background-hover); } /* =========================================== BASE PATTERNS - Icon Container =========================================== */ swp-icon-container { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; background: var(--color-background-hover); border-radius: var(--radius-xl); color: var(--color-text-secondary); font-size: var(--font-size-xl); flex-shrink: 0; } /* =========================================== 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; & 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: var(--bg-teal-medium); } swp-btn.outline.purple { border-color: var(--color-purple); color: var(--color-purple); } swp-btn.outline.purple:hover { background: var(--bg-purple-medium); } /* 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: var(--bg-green-strong); color: var(--color-green); } swp-status-badge.draft, swp-status-badge.invited { background: var(--bg-amber-strong); color: #b45309; } /* Role variants */ swp-status-badge.owner { background: var(--bg-teal-strong); color: var(--color-teal); } swp-status-badge.admin { background: var(--bg-purple-strong); color: var(--color-purple); } swp-status-badge.leader { background: var(--bg-blue-strong); color: var(--color-blue); } swp-status-badge.employee { background: var(--color-background-alt); color: var(--color-text-secondary); } /* Additional status variants */ swp-status-badge.valid { background: var(--bg-green-strong); color: var(--color-green); } swp-status-badge.expiring, swp-status-badge.warning { background: var(--bg-amber-strong); color: #b45309; } swp-status-badge.enrolled, swp-status-badge.ferie { background: var(--bg-teal-strong); color: var(--color-teal); } swp-status-badge.fri, swp-status-badge.info { background: var(--bg-blue-strong); color: var(--color-blue); } swp-status-badge.sygdom, swp-status-badge.danger { background: var(--bg-red-strong); color: var(--color-red); } /* Booking/scheduling specific variants */ swp-status-badge.confirmed { background: var(--bg-green-strong); color: var(--color-green); } swp-status-badge.pending { background: var(--bg-amber-strong); color: var(--color-amber); } swp-status-badge.inprogress, swp-status-badge.in-progress { background: var(--bg-blue-strong); color: var(--color-blue); } swp-status-badge.completed { background: var(--color-background-hover); 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 var(--bg-teal-strong); } 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: var(--bg-teal-strong); color: var(--color-teal); } swp-plan-badge.popular { background: var(--bg-amber-strong); color: var(--color-amber); } swp-plan-badge.enterprise { background: var(--bg-purple-strong); color: var(--color-purple); } swp-plan-badge.free { background: var(--bg-green-strong); 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); & i { font-size: 18px; } &:hover { background: var(--color-background-alt); color: var(--color-text); } &.danger:hover { background: var(--bg-red-medium); color: var(--color-red); } } /* =========================================== 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); &: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); } /* =========================================== ADD BUTTON (dashed border style) =========================================== */ swp-add-button { display: flex; align-items: center; justify-content: center; gap: var(--spacing-2); padding: var(--spacing-5); margin-top: var(--spacing-5); border: 2px dashed var(--color-border); border-radius: var(--radius-md); color: var(--color-text-secondary); font-size: var(--font-size-md); cursor: pointer; transition: all var(--transition-fast); &:hover { border-color: var(--color-teal); color: var(--color-teal); background: var(--bg-teal-subtle); } } /* =========================================== USER INFO PATTERN (shared across auth, waitlist, employees, drawers) =========================================== */ swp-user-info { display: flex; align-items: center; gap: var(--spacing-4); } swp-user-info-card { display: flex; align-items: center; gap: var(--spacing-4); padding: var(--spacing-4); background: var(--color-background); border: 1px solid var(--color-border); border-radius: var(--radius-lg); } swp-user-details { display: flex; flex-direction: column; gap: var(--spacing-1); flex: 1; min-width: 0; } swp-user-name { display: block; font-size: var(--font-size-base); font-weight: var(--font-weight-medium); color: var(--color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } swp-user-email { display: block; font-size: var(--font-size-sm); color: var(--color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* =========================================== FORM INPUTS (shared base styling) =========================================== */ swp-form-group { display: flex; flex-direction: column; gap: var(--spacing-2); } swp-form-label { display: block; font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-text); } swp-form-input { position: relative; } swp-form-input input, swp-form-input select, swp-form-input textarea { width: 100%; padding: var(--spacing-3) var(--spacing-4); font-size: var(--font-size-base); font-family: var(--font-family); color: var(--color-text); background: var(--color-background); border: 1px solid var(--color-border); border-radius: var(--border-radius); transition: border-color var(--transition-fast), box-shadow var(--transition-fast); } swp-form-input input::placeholder, swp-form-input textarea::placeholder { color: var(--color-text-muted); } swp-form-input input:focus, swp-form-input select:focus, swp-form-input textarea:focus { outline: none; border-color: var(--color-teal); box-shadow: var(--shadow-focus-ring); } swp-form-input select { cursor: pointer; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; padding-right: 40px; } swp-form-input textarea { resize: vertical; min-height: 80px; } /* =========================================== EMPTY STATE PATTERN =========================================== */ swp-empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--spacing-10) var(--spacing-6); text-align: center; & i { font-size: 48px; color: var(--color-border); margin-bottom: var(--spacing-4); } & span { font-size: var(--font-size-base); color: var(--color-text-secondary); } }