refactor(frontend): consolidate shared styles into centralized style system
- Create comprehensive shared.ts with design tokens and categorized styles: - layoutStyles: main, loader, content variants - cardStyles: card, tableCard, cardHeader - tableStyles: complete table styling - paginationStyles: pagination controls - formStyles: inputs, labels, errors - buttonStyles: primary, secondary, accent, danger variants - badgeStyles: status badges with color variants - bannerStyles: error/success banners - modalStyles: modal overlay and content - toastStyles: toast notifications - utilityStyles: divider, emptyState, etc. - Refactor all page components to use shared styles: - page.tsx (counter) - audit/page.tsx - booking/page.tsx - appointments/page.tsx - profile/page.tsx - invites/page.tsx - admin/invites/page.tsx - admin/availability/page.tsx - Reduce code duplication significantly (each page now has only truly page-specific styles) - Maintain backwards compatibility with sharedStyles export
This commit is contained in:
parent
4d9edd7fd4
commit
81cd34b0e7
9 changed files with 1148 additions and 1173 deletions
|
|
@ -1,28 +1,113 @@
|
|||
import React from "react";
|
||||
|
||||
/**
|
||||
* Shared styles used across multiple pages.
|
||||
* These styles define the common layout and theming for the app.
|
||||
* Design tokens - centralized values for consistency.
|
||||
*/
|
||||
export const sharedStyles: Record<string, React.CSSProperties> = {
|
||||
const tokens = {
|
||||
// Font families
|
||||
fontSans: "'DM Sans', system-ui, sans-serif",
|
||||
fontSerif: "'Instrument Serif', Georgia, serif",
|
||||
fontMono: "'DM Mono', monospace",
|
||||
|
||||
// Colors
|
||||
white: "#fff",
|
||||
textPrimary: "#fff",
|
||||
textSecondary: "rgba(255, 255, 255, 0.7)",
|
||||
textMuted: "rgba(255, 255, 255, 0.5)",
|
||||
textDim: "rgba(255, 255, 255, 0.4)",
|
||||
textDisabled: "rgba(255, 255, 255, 0.3)",
|
||||
|
||||
// Accent colors
|
||||
accent: "#a78bfa",
|
||||
accentIndigo: "rgba(99, 102, 241, 0.9)",
|
||||
accentIndigoMuted: "rgba(129, 140, 248, 0.9)",
|
||||
|
||||
// Status colors
|
||||
success: "rgba(34, 197, 94, 0.9)",
|
||||
successBg: "rgba(34, 197, 94, 0.2)",
|
||||
successBorder: "rgba(34, 197, 94, 0.3)",
|
||||
error: "#f87171",
|
||||
errorBg: "rgba(239, 68, 68, 0.15)",
|
||||
errorBorder: "rgba(239, 68, 68, 0.3)",
|
||||
|
||||
// Surfaces
|
||||
surfaceBg: "rgba(255, 255, 255, 0.03)",
|
||||
surfaceBorder: "rgba(255, 255, 255, 0.08)",
|
||||
surfaceHover: "rgba(255, 255, 255, 0.05)",
|
||||
inputBg: "rgba(255, 255, 255, 0.05)",
|
||||
inputBorder: "rgba(255, 255, 255, 0.1)",
|
||||
|
||||
// Gradients
|
||||
pageGradient: "linear-gradient(135deg, #0f0f23 0%, #1a1a3e 50%, #2d1b4e 100%)",
|
||||
primaryGradient: "linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)",
|
||||
|
||||
// Shadows
|
||||
cardShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5)",
|
||||
buttonShadow: "0 4px 14px rgba(99, 102, 241, 0.4)",
|
||||
|
||||
// Border radius
|
||||
radiusSm: "6px",
|
||||
radiusMd: "8px",
|
||||
radiusLg: "12px",
|
||||
radiusXl: "16px",
|
||||
radius2xl: "20px",
|
||||
radius3xl: "24px",
|
||||
} as const;
|
||||
|
||||
type StyleRecord = Record<string, React.CSSProperties>;
|
||||
|
||||
// =============================================================================
|
||||
// Layout Styles
|
||||
// =============================================================================
|
||||
|
||||
export const layoutStyles: StyleRecord = {
|
||||
/** Full-page main container with gradient background */
|
||||
main: {
|
||||
minHeight: "100vh",
|
||||
background: "linear-gradient(135deg, #0f0f23 0%, #1a1a3e 50%, #2d1b4e 100%)",
|
||||
background: tokens.pageGradient,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
},
|
||||
/** Centered loading indicator */
|
||||
loader: {
|
||||
flex: 1,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
color: "rgba(255, 255, 255, 0.5)",
|
||||
fontFamily: tokens.fontSans,
|
||||
color: tokens.textMuted,
|
||||
fontSize: "1.125rem",
|
||||
},
|
||||
/** Content area - centered (for cards/forms) */
|
||||
contentCentered: {
|
||||
flex: 1,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "2rem",
|
||||
},
|
||||
/** Content area - scrollable (for tables/lists) */
|
||||
contentScrollable: {
|
||||
flex: 1,
|
||||
padding: "2rem",
|
||||
overflowY: "auto",
|
||||
},
|
||||
/** Max-width container for page content */
|
||||
pageContainer: {
|
||||
maxWidth: "1200px",
|
||||
margin: "0 auto",
|
||||
width: "100%",
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Header Styles (for nav/app header - used by Header component)
|
||||
// =============================================================================
|
||||
|
||||
export const headerStyles: StyleRecord = {
|
||||
header: {
|
||||
padding: "1.5rem 2rem",
|
||||
borderBottom: "1px solid rgba(255, 255, 255, 0.06)",
|
||||
borderBottom: `1px solid ${tokens.surfaceBorder}`,
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
|
|
@ -33,8 +118,8 @@ export const sharedStyles: Record<string, React.CSSProperties> = {
|
|||
gap: "0.75rem",
|
||||
},
|
||||
navLink: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
color: "rgba(255, 255, 255, 0.5)",
|
||||
fontFamily: tokens.fontSans,
|
||||
color: tokens.textMuted,
|
||||
fontSize: "0.875rem",
|
||||
textDecoration: "none",
|
||||
transition: "color 0.2s",
|
||||
|
|
@ -44,8 +129,8 @@ export const sharedStyles: Record<string, React.CSSProperties> = {
|
|||
fontSize: "0.75rem",
|
||||
},
|
||||
navCurrent: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
color: "#a78bfa",
|
||||
fontFamily: tokens.fontSans,
|
||||
color: tokens.accent,
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 600,
|
||||
},
|
||||
|
|
@ -55,55 +140,593 @@ export const sharedStyles: Record<string, React.CSSProperties> = {
|
|||
gap: "1rem",
|
||||
},
|
||||
userEmail: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
fontFamily: tokens.fontSans,
|
||||
color: "rgba(255, 255, 255, 0.6)",
|
||||
fontSize: "0.875rem",
|
||||
},
|
||||
logoutBtn: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
fontFamily: tokens.fontSans,
|
||||
padding: "0.5rem 1rem",
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 500,
|
||||
background: "rgba(255, 255, 255, 0.05)",
|
||||
color: "rgba(255, 255, 255, 0.7)",
|
||||
border: "1px solid rgba(255, 255, 255, 0.1)",
|
||||
borderRadius: "8px",
|
||||
background: tokens.surfaceHover,
|
||||
color: tokens.textSecondary,
|
||||
border: `1px solid ${tokens.inputBorder}`,
|
||||
borderRadius: tokens.radiusMd,
|
||||
cursor: "pointer",
|
||||
transition: "all 0.2s",
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Typography Styles
|
||||
// =============================================================================
|
||||
|
||||
export const typographyStyles: StyleRecord = {
|
||||
/** Large page title - serif font */
|
||||
pageTitle: {
|
||||
fontFamily: tokens.fontSerif,
|
||||
fontSize: "2rem",
|
||||
fontWeight: 400,
|
||||
color: tokens.white,
|
||||
margin: 0,
|
||||
letterSpacing: "-0.02em",
|
||||
},
|
||||
/** Page subtitle text */
|
||||
pageSubtitle: {
|
||||
fontFamily: tokens.fontSans,
|
||||
color: tokens.textMuted,
|
||||
marginTop: "0.5rem",
|
||||
fontSize: "0.95rem",
|
||||
},
|
||||
/** Section title - uppercase, smaller */
|
||||
sectionTitle: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 600,
|
||||
color: "rgba(255, 255, 255, 0.8)",
|
||||
margin: 0,
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.05em",
|
||||
},
|
||||
/** Section title - muted variant */
|
||||
sectionTitleMuted: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "1.1rem",
|
||||
fontWeight: 500,
|
||||
color: tokens.textMuted,
|
||||
marginBottom: "1rem",
|
||||
},
|
||||
/** Section hint text */
|
||||
sectionHint: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.8rem",
|
||||
color: tokens.textDim,
|
||||
margin: 0,
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Card Styles
|
||||
// =============================================================================
|
||||
|
||||
export const cardStyles: StyleRecord = {
|
||||
/** Standard card container */
|
||||
card: {
|
||||
background: tokens.surfaceBg,
|
||||
backdropFilter: "blur(10px)",
|
||||
border: `1px solid ${tokens.surfaceBorder}`,
|
||||
borderRadius: tokens.radius3xl,
|
||||
padding: "2.5rem",
|
||||
boxShadow: tokens.cardShadow,
|
||||
},
|
||||
/** Card header section */
|
||||
cardHeader: {
|
||||
marginBottom: "2rem",
|
||||
},
|
||||
/** Card title - serif, large */
|
||||
cardTitle: {
|
||||
fontFamily: tokens.fontSerif,
|
||||
fontSize: "2rem",
|
||||
fontWeight: 400,
|
||||
color: tokens.white,
|
||||
margin: 0,
|
||||
letterSpacing: "-0.02em",
|
||||
},
|
||||
/** Card subtitle */
|
||||
cardSubtitle: {
|
||||
fontFamily: tokens.fontSans,
|
||||
color: tokens.textMuted,
|
||||
marginTop: "0.5rem",
|
||||
fontSize: "0.95rem",
|
||||
},
|
||||
/** Smaller table/section card */
|
||||
tableCard: {
|
||||
background: tokens.surfaceBg,
|
||||
backdropFilter: "blur(10px)",
|
||||
border: `1px solid ${tokens.surfaceBorder}`,
|
||||
borderRadius: tokens.radius2xl,
|
||||
padding: "1.5rem",
|
||||
boxShadow: tokens.cardShadow,
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Table Styles
|
||||
// =============================================================================
|
||||
|
||||
export const tableStyles: StyleRecord = {
|
||||
tableHeader: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: "1rem",
|
||||
flexWrap: "wrap",
|
||||
gap: "1rem",
|
||||
},
|
||||
tableTitle: {
|
||||
fontFamily: tokens.fontSerif,
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: 400,
|
||||
color: tokens.white,
|
||||
margin: 0,
|
||||
},
|
||||
totalCount: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.875rem",
|
||||
color: tokens.textDim,
|
||||
},
|
||||
tableWrapper: {
|
||||
overflowX: "auto",
|
||||
},
|
||||
table: {
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
fontFamily: tokens.fontSans,
|
||||
},
|
||||
th: {
|
||||
textAlign: "left",
|
||||
padding: "0.75rem 1rem",
|
||||
fontSize: "0.75rem",
|
||||
fontWeight: 600,
|
||||
color: tokens.textDim,
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.05em",
|
||||
borderBottom: `1px solid ${tokens.surfaceBorder}`,
|
||||
},
|
||||
tr: {
|
||||
borderBottom: "1px solid rgba(255, 255, 255, 0.04)",
|
||||
},
|
||||
td: {
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "0.875rem",
|
||||
color: tokens.textSecondary,
|
||||
},
|
||||
tdMono: {
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "0.875rem",
|
||||
color: tokens.white,
|
||||
fontFamily: tokens.fontMono,
|
||||
},
|
||||
tdNum: {
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "0.875rem",
|
||||
color: "rgba(255, 255, 255, 0.9)",
|
||||
fontFamily: tokens.fontMono,
|
||||
},
|
||||
tdDate: {
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "0.75rem",
|
||||
color: tokens.textDim,
|
||||
},
|
||||
emptyRow: {
|
||||
padding: "2rem 1rem",
|
||||
textAlign: "center",
|
||||
color: tokens.textDisabled,
|
||||
fontSize: "0.875rem",
|
||||
},
|
||||
errorRow: {
|
||||
padding: "2rem 1rem",
|
||||
textAlign: "center",
|
||||
color: tokens.error,
|
||||
fontSize: "0.875rem",
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Pagination Styles
|
||||
// =============================================================================
|
||||
|
||||
export const paginationStyles: StyleRecord = {
|
||||
pagination: {
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "1rem",
|
||||
marginTop: "1rem",
|
||||
paddingTop: "1rem",
|
||||
borderTop: "1px solid rgba(255, 255, 255, 0.06)",
|
||||
},
|
||||
pageBtn: {
|
||||
fontFamily: tokens.fontSans,
|
||||
padding: "0.5rem 1rem",
|
||||
fontSize: "1rem",
|
||||
background: tokens.surfaceHover,
|
||||
color: tokens.textSecondary,
|
||||
border: `1px solid ${tokens.inputBorder}`,
|
||||
borderRadius: tokens.radiusMd,
|
||||
cursor: "pointer",
|
||||
transition: "all 0.2s",
|
||||
},
|
||||
pageInfo: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.875rem",
|
||||
color: tokens.textMuted,
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Form/Input Styles
|
||||
// =============================================================================
|
||||
|
||||
export const formStyles: StyleRecord = {
|
||||
form: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "1.25rem",
|
||||
},
|
||||
field: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "0.5rem",
|
||||
},
|
||||
label: {
|
||||
fontFamily: tokens.fontSans,
|
||||
color: tokens.textSecondary,
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 500,
|
||||
},
|
||||
input: {
|
||||
fontFamily: tokens.fontSans,
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "1rem",
|
||||
background: tokens.inputBg,
|
||||
border: `1px solid ${tokens.inputBorder}`,
|
||||
borderRadius: tokens.radiusLg,
|
||||
color: tokens.white,
|
||||
outline: "none",
|
||||
transition: "border-color 0.2s, box-shadow 0.2s",
|
||||
},
|
||||
inputError: {
|
||||
border: `1px solid ${tokens.errorBorder}`,
|
||||
boxShadow: `0 0 0 2px ${tokens.errorBg}`,
|
||||
},
|
||||
inputReadOnly: {
|
||||
background: "rgba(255, 255, 255, 0.02)",
|
||||
color: tokens.textMuted,
|
||||
cursor: "not-allowed",
|
||||
},
|
||||
textarea: {
|
||||
fontFamily: tokens.fontSans,
|
||||
width: "100%",
|
||||
padding: "0.75rem",
|
||||
background: tokens.inputBg,
|
||||
border: `1px solid ${tokens.inputBorder}`,
|
||||
borderRadius: tokens.radiusMd,
|
||||
color: tokens.white,
|
||||
fontSize: "0.875rem",
|
||||
minHeight: "80px",
|
||||
resize: "vertical" as const,
|
||||
},
|
||||
select: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.9rem",
|
||||
padding: "0.75rem",
|
||||
background: tokens.inputBg,
|
||||
border: `1px solid ${tokens.inputBorder}`,
|
||||
borderRadius: tokens.radiusMd,
|
||||
color: tokens.white,
|
||||
cursor: "pointer",
|
||||
},
|
||||
hint: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.75rem",
|
||||
color: tokens.textDim,
|
||||
fontStyle: "italic",
|
||||
},
|
||||
errorText: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.75rem",
|
||||
color: "#fca5a5",
|
||||
},
|
||||
charCount: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.75rem",
|
||||
color: tokens.textDim,
|
||||
textAlign: "right" as const,
|
||||
marginTop: "0.25rem",
|
||||
},
|
||||
charCountWarning: {
|
||||
color: tokens.error,
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Button Styles
|
||||
// =============================================================================
|
||||
|
||||
export const buttonStyles: StyleRecord = {
|
||||
/** Primary action button with gradient */
|
||||
primaryButton: {
|
||||
fontFamily: tokens.fontSans,
|
||||
padding: "1rem",
|
||||
fontSize: "1rem",
|
||||
fontWeight: 600,
|
||||
background: tokens.primaryGradient,
|
||||
color: tokens.white,
|
||||
border: "none",
|
||||
borderRadius: tokens.radiusLg,
|
||||
cursor: "pointer",
|
||||
transition: "transform 0.2s, box-shadow 0.2s",
|
||||
boxShadow: tokens.buttonShadow,
|
||||
},
|
||||
/** Secondary/cancel button */
|
||||
secondaryButton: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.85rem",
|
||||
padding: "0.6rem 1rem",
|
||||
background: tokens.surfaceHover,
|
||||
color: tokens.textSecondary,
|
||||
border: `1px solid ${tokens.inputBorder}`,
|
||||
borderRadius: tokens.radiusMd,
|
||||
cursor: "pointer",
|
||||
transition: "all 0.2s",
|
||||
},
|
||||
/** Accent button (indigo tinted) */
|
||||
accentButton: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.9rem",
|
||||
fontWeight: 500,
|
||||
padding: "0.75rem 1.5rem",
|
||||
background: "rgba(99, 102, 241, 0.3)",
|
||||
color: tokens.white,
|
||||
border: "1px solid rgba(99, 102, 241, 0.5)",
|
||||
borderRadius: tokens.radiusMd,
|
||||
cursor: "pointer",
|
||||
},
|
||||
/** Danger/destructive button */
|
||||
dangerButton: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.75rem",
|
||||
padding: "0.4rem 0.75rem",
|
||||
background: tokens.errorBg,
|
||||
color: "rgba(239, 68, 68, 0.9)",
|
||||
border: `1px solid ${tokens.errorBorder}`,
|
||||
borderRadius: tokens.radiusSm,
|
||||
cursor: "pointer",
|
||||
},
|
||||
/** Disabled button modifier */
|
||||
buttonDisabled: {
|
||||
opacity: 0.5,
|
||||
cursor: "not-allowed",
|
||||
boxShadow: "none",
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Badge/Status Styles
|
||||
// =============================================================================
|
||||
|
||||
export const badgeStyles: StyleRecord = {
|
||||
/** Base badge style */
|
||||
badge: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.7rem",
|
||||
fontWeight: 500,
|
||||
padding: "0.25rem 0.5rem",
|
||||
borderRadius: "4px",
|
||||
textTransform: "uppercase",
|
||||
display: "inline-block",
|
||||
},
|
||||
/** Ready/primary status */
|
||||
badgeReady: {
|
||||
background: "rgba(99, 102, 241, 0.2)",
|
||||
color: tokens.accentIndigoMuted,
|
||||
},
|
||||
/** Success/spent status */
|
||||
badgeSuccess: {
|
||||
background: tokens.successBg,
|
||||
color: tokens.success,
|
||||
},
|
||||
/** Error/revoked status */
|
||||
badgeError: {
|
||||
background: "rgba(239, 68, 68, 0.2)",
|
||||
color: "rgba(239, 68, 68, 0.9)",
|
||||
},
|
||||
/** Booked/active status */
|
||||
badgeBooked: {
|
||||
background: "rgba(99, 102, 241, 0.15)",
|
||||
color: tokens.accentIndigoMuted,
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Banner/Alert Styles
|
||||
// =============================================================================
|
||||
|
||||
export const bannerStyles: StyleRecord = {
|
||||
errorBanner: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.875rem",
|
||||
padding: "1rem",
|
||||
background: tokens.errorBg,
|
||||
border: `1px solid ${tokens.errorBorder}`,
|
||||
borderRadius: tokens.radiusMd,
|
||||
color: tokens.error,
|
||||
marginBottom: "1rem",
|
||||
},
|
||||
successBanner: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.875rem",
|
||||
padding: "1rem",
|
||||
background: "rgba(34, 197, 94, 0.15)",
|
||||
border: `1px solid ${tokens.successBorder}`,
|
||||
borderRadius: tokens.radiusMd,
|
||||
color: "#4ade80",
|
||||
marginBottom: "1rem",
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Modal Styles
|
||||
// =============================================================================
|
||||
|
||||
export const modalStyles: StyleRecord = {
|
||||
modalOverlay: {
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: "rgba(0, 0, 0, 0.7)",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "2rem",
|
||||
zIndex: 1000,
|
||||
},
|
||||
// Common UI component styles
|
||||
errorBanner: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
fontSize: "0.875rem",
|
||||
padding: "1rem",
|
||||
background: "rgba(239, 68, 68, 0.15)",
|
||||
border: "1px solid rgba(239, 68, 68, 0.3)",
|
||||
borderRadius: "8px",
|
||||
color: "#f87171",
|
||||
modal: {
|
||||
background: "#1a1a3e",
|
||||
border: `1px solid ${tokens.inputBorder}`,
|
||||
borderRadius: tokens.radiusXl,
|
||||
padding: "2rem",
|
||||
width: "90%",
|
||||
maxWidth: "400px",
|
||||
boxShadow: tokens.cardShadow,
|
||||
},
|
||||
modalTitle: {
|
||||
fontFamily: tokens.fontSerif,
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: 400,
|
||||
color: tokens.white,
|
||||
margin: "0 0 1.5rem 0",
|
||||
},
|
||||
modalError: {
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.85rem",
|
||||
padding: "0.75rem",
|
||||
background: tokens.errorBg,
|
||||
border: `1px solid ${tokens.errorBorder}`,
|
||||
borderRadius: tokens.radiusMd,
|
||||
color: tokens.error,
|
||||
marginBottom: "1rem",
|
||||
},
|
||||
cancelButton: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
fontSize: "0.85rem",
|
||||
padding: "0.6rem 1rem",
|
||||
background: "rgba(255, 255, 255, 0.05)",
|
||||
color: "rgba(255, 255, 255, 0.7)",
|
||||
border: "1px solid rgba(255, 255, 255, 0.1)",
|
||||
borderRadius: "8px",
|
||||
cursor: "pointer",
|
||||
transition: "all 0.2s",
|
||||
modalActions: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
gap: "1rem",
|
||||
},
|
||||
modalActionsRight: {
|
||||
display: "flex",
|
||||
gap: "0.75rem",
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Toast Styles
|
||||
// =============================================================================
|
||||
|
||||
export const toastStyles: StyleRecord = {
|
||||
toast: {
|
||||
position: "fixed",
|
||||
top: "1.5rem",
|
||||
right: "1.5rem",
|
||||
padding: "1rem 1.5rem",
|
||||
borderRadius: tokens.radiusLg,
|
||||
fontFamily: tokens.fontSans,
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 500,
|
||||
zIndex: 1000,
|
||||
boxShadow: "0 10px 25px rgba(0, 0, 0, 0.3)",
|
||||
},
|
||||
toastSuccess: {
|
||||
background: "rgba(34, 197, 94, 0.9)",
|
||||
color: tokens.white,
|
||||
},
|
||||
toastError: {
|
||||
background: "rgba(239, 68, 68, 0.9)",
|
||||
color: tokens.white,
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Misc Utility Styles
|
||||
// =============================================================================
|
||||
|
||||
export const utilityStyles: StyleRecord = {
|
||||
/** Horizontal divider */
|
||||
divider: {
|
||||
height: "1px",
|
||||
background: tokens.surfaceBorder,
|
||||
margin: "0.75rem 0",
|
||||
},
|
||||
/** Empty state container */
|
||||
emptyState: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
color: "rgba(255, 255, 255, 0.4)",
|
||||
fontFamily: tokens.fontSans,
|
||||
color: tokens.textDim,
|
||||
textAlign: "center" as const,
|
||||
padding: "1rem 0",
|
||||
},
|
||||
/** Read-only badge for form labels */
|
||||
readOnlyBadge: {
|
||||
fontSize: "0.7rem",
|
||||
fontWeight: 500,
|
||||
color: tokens.textDim,
|
||||
background: tokens.surfaceBorder,
|
||||
padding: "0.15rem 0.5rem",
|
||||
borderRadius: "4px",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.05em",
|
||||
},
|
||||
/** Flex row with gap */
|
||||
buttonRow: {
|
||||
display: "flex",
|
||||
gap: "0.75rem",
|
||||
},
|
||||
/** Filter group container */
|
||||
filterGroup: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "1rem",
|
||||
},
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Combined sharedStyles (backwards compatible export)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @deprecated Use individual style exports (layoutStyles, cardStyles, etc.) for better tree-shaking.
|
||||
* This combined export is maintained for backwards compatibility during migration.
|
||||
*/
|
||||
export const sharedStyles: StyleRecord = {
|
||||
// Layout
|
||||
main: layoutStyles.main,
|
||||
loader: layoutStyles.loader,
|
||||
content: layoutStyles.contentCentered,
|
||||
|
||||
// Header
|
||||
header: headerStyles.header,
|
||||
nav: headerStyles.nav,
|
||||
navLink: headerStyles.navLink,
|
||||
navDivider: headerStyles.navDivider,
|
||||
navCurrent: headerStyles.navCurrent,
|
||||
userInfo: headerStyles.userInfo,
|
||||
userEmail: headerStyles.userEmail,
|
||||
logoutBtn: headerStyles.logoutBtn,
|
||||
|
||||
// Common
|
||||
errorBanner: bannerStyles.errorBanner,
|
||||
cancelButton: buttonStyles.secondaryButton,
|
||||
emptyState: utilityStyles.emptyState,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue