feat: introduce admin design tokens and redesign AdminLayout/AdminLogin

Create AdminApp.module.css with admin-specific design tokens (--admin-bg, --admin-surface, --admin-border, --admin-text, --admin-text-muted, --admin-primary, --admin-primary-hover, --admin-danger, --admin-radius, --admin-shadow, --admin-font, --admin-space-xs/sm/md/lg/xl) scoped to .adminRoot wrapper class to avoid collisions with public site tokens.

Create adminShared.module.css with composable component classes (page, card, table, form, error, button, buttonSecondary, buttonDanger) that all later admin pages will build against.

Wrap AdminApp Routes in div with adminRoot class to establish token scope.

Redesign AdminLayout.module.css to use new admin tokens with improved sidebar styling (240px width, better spacing, hover states, active link highlighting).

Redesign AdminLogin.module.css to use new admin tokens with improved form styling (better card styling, focus states, proper typography).

No changes to AdminLayout.tsx or AdminLogin.tsx needed — existing JSX structure matches new CSS selectors.

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
This commit is contained in:
belviskhoremk
2026-08-13 08:58:00 +02:00
parent a5b210f309
commit 728fc31e83
5 changed files with 255 additions and 44 deletions

View File

@@ -0,0 +1,24 @@
/* src/pages/admin/AdminApp.module.css */
.adminRoot {
--admin-bg: #F4F5F7;
--admin-surface: #FFFFFF;
--admin-border: #E1E4E9;
--admin-text: #1F2430;
--admin-text-muted: #6B7280;
--admin-primary: #2A5C8A;
--admin-primary-hover: #1E4566;
--admin-danger: #B3261E;
--admin-radius: 8px;
--admin-shadow: 0 1px 2px rgba(16, 24, 40, 0.06);
--admin-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
--admin-space-xs: 0.25rem;
--admin-space-sm: 0.5rem;
--admin-space-md: 1rem;
--admin-space-lg: 1.5rem;
--admin-space-xl: 2.5rem;
min-height: 100vh;
background: var(--admin-bg);
color: var(--admin-text);
font-family: var(--admin-font);
}

View File

@@ -7,23 +7,26 @@ import AdminServices from './AdminServices'
import AdminSchedule from './AdminSchedule'
import AdminBookings from './AdminBookings'
import AdminInquiries from './AdminInquiries'
import styles from './AdminApp.module.css'
function AdminApp() {
return (
<Routes>
<Route path="login" element={<AdminLogin />} />
<Route element={<ProtectedRoute />}>
<Route element={<AdminLayout />}>
<Route index element={<Navigate to="/admin/products" replace />} />
<Route path="products" element={<AdminProducts />} />
<Route path="services" element={<AdminServices />} />
<Route path="schedule" element={<AdminSchedule />} />
<Route path="bookings" element={<AdminBookings />} />
<Route path="inquiries" element={<AdminInquiries />} />
<Route path="*" element={<Navigate to="/admin/products" replace />} />
<div className={styles.adminRoot}>
<Routes>
<Route path="login" element={<AdminLogin />} />
<Route element={<ProtectedRoute />}>
<Route element={<AdminLayout />}>
<Route index element={<Navigate to="/admin/products" replace />} />
<Route path="products" element={<AdminProducts />} />
<Route path="services" element={<AdminServices />} />
<Route path="schedule" element={<AdminSchedule />} />
<Route path="bookings" element={<AdminBookings />} />
<Route path="inquiries" element={<AdminInquiries />} />
<Route path="*" element={<Navigate to="/admin/products" replace />} />
</Route>
</Route>
</Route>
</Routes>
</Routes>
</div>
)
}

View File

@@ -4,50 +4,71 @@
}
.sidebar {
width: 220px;
width: 240px;
flex-shrink: 0;
background: var(--color-charcoal);
color: var(--color-cream);
padding: var(--space-lg) var(--space-md);
background: var(--admin-surface);
border-right: 1px solid var(--admin-border);
padding: var(--admin-space-lg) var(--admin-space-md);
display: flex;
flex-direction: column;
gap: var(--space-lg);
gap: var(--admin-space-xl);
}
.brand {
font-family: var(--font-script);
font-size: 1.5rem;
color: var(--color-gold);
font-weight: 700;
font-size: 1.125rem;
color: var(--admin-text);
padding: 0 var(--admin-space-sm);
}
.sidebar nav {
display: flex;
flex-direction: column;
gap: var(--space-sm);
gap: var(--admin-space-xs);
}
.navLink {
color: var(--color-cream);
color: var(--admin-text-muted);
text-decoration: none;
padding: var(--space-sm);
padding: var(--admin-space-sm);
border-radius: var(--admin-radius);
font-size: 0.9375rem;
font-weight: 500;
}
.navLink:hover {
background: var(--admin-bg);
color: var(--admin-text);
}
.navLinkActive {
color: var(--color-gold);
font-weight: bold;
background: var(--admin-primary);
color: white;
}
.navLinkActive:hover {
background: var(--admin-primary-hover);
color: white;
}
.signOut {
margin-top: auto;
background: none;
border: 1px solid var(--color-gold);
color: var(--color-cream);
padding: var(--space-sm);
border: 1px solid var(--admin-border);
border-radius: var(--admin-radius);
color: var(--admin-text-muted);
padding: var(--admin-space-sm);
cursor: pointer;
font: inherit;
}
.signOut:hover {
border-color: var(--admin-danger);
color: var(--admin-danger);
}
.content {
flex: 1;
padding: var(--space-xl) var(--space-lg);
background: var(--color-cream-alt);
padding: var(--admin-space-xl) var(--admin-space-lg);
max-width: 1100px;
}

View File

@@ -3,46 +3,76 @@
display: flex;
align-items: center;
justify-content: center;
background: var(--color-cream);
padding: var(--space-lg);
background: var(--admin-bg);
padding: var(--admin-space-lg);
}
.form {
display: flex;
flex-direction: column;
gap: var(--space-md);
gap: var(--admin-space-md);
width: 100%;
max-width: 320px;
max-width: 340px;
background: var(--admin-surface);
border: 1px solid var(--admin-border);
border-radius: var(--admin-radius);
box-shadow: var(--admin-shadow);
padding: var(--admin-space-xl) var(--admin-space-lg);
}
.form h1 {
font-size: 1.25rem;
font-weight: 700;
color: var(--admin-text);
margin: 0 0 var(--admin-space-sm);
}
.field {
display: flex;
flex-direction: column;
gap: var(--space-sm);
gap: var(--admin-space-xs);
}
.field label {
color: var(--color-charcoal);
font-size: 0.875rem;
font-weight: 500;
color: var(--admin-text);
}
.field input {
padding: var(--space-sm);
border: 1px solid var(--color-gold);
background: white;
padding: var(--admin-space-sm);
border: 1px solid var(--admin-border);
border-radius: calc(var(--admin-radius) / 2);
font: inherit;
background: var(--admin-surface);
color: var(--admin-text);
}
.field input:focus {
outline: 2px solid var(--admin-primary);
outline-offset: 1px;
}
.error {
color: #a33;
color: var(--admin-danger);
font-size: 0.875rem;
}
.form button {
background: var(--color-charcoal);
color: var(--color-cream);
background: var(--admin-primary);
color: white;
border: none;
padding: var(--space-sm) var(--space-md);
border-radius: calc(var(--admin-radius) / 2);
padding: var(--admin-space-sm) var(--admin-space-md);
font: inherit;
font-weight: 600;
cursor: pointer;
}
.form button:hover {
background: var(--admin-primary-hover);
}
.form button:disabled {
opacity: 0.6;
cursor: default;

View File

@@ -0,0 +1,133 @@
/* src/pages/admin/adminShared.module.css */
.page {
display: flex;
flex-direction: column;
gap: var(--admin-space-lg);
}
.card {
background: var(--admin-surface);
border: 1px solid var(--admin-border);
border-radius: var(--admin-radius);
box-shadow: var(--admin-shadow);
}
.table {
composes: card;
width: 100%;
border-collapse: collapse;
}
.table th {
text-align: left;
padding: var(--admin-space-sm) var(--admin-space-md);
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--admin-text-muted);
border-bottom: 1px solid var(--admin-border);
background: var(--admin-bg);
}
.table td {
padding: var(--admin-space-sm) var(--admin-space-md);
border-bottom: 1px solid var(--admin-border);
vertical-align: middle;
}
.table tbody tr:last-child td {
border-bottom: none;
}
.table tbody tr:hover {
background: var(--admin-bg);
}
.form {
composes: card;
display: flex;
flex-direction: column;
gap: var(--admin-space-md);
max-width: 480px;
padding: var(--admin-space-lg);
}
.form label {
display: flex;
flex-direction: column;
gap: var(--admin-space-xs);
font-size: 0.875rem;
font-weight: 500;
color: var(--admin-text);
}
.form input,
.form select,
.form textarea {
padding: var(--admin-space-sm);
border: 1px solid var(--admin-border);
border-radius: calc(var(--admin-radius) / 2);
font: inherit;
color: var(--admin-text);
background: var(--admin-surface);
}
.form input:focus,
.form select:focus,
.form textarea:focus {
outline: 2px solid var(--admin-primary);
outline-offset: 1px;
}
.form textarea {
min-height: 6rem;
resize: vertical;
}
.button {
font: inherit;
font-weight: 600;
padding: var(--admin-space-sm) var(--admin-space-md);
border-radius: calc(var(--admin-radius) / 2);
border: 1px solid transparent;
cursor: pointer;
background: var(--admin-primary);
color: white;
}
.button:hover {
background: var(--admin-primary-hover);
}
.button:disabled {
opacity: 0.6;
cursor: default;
}
.buttonSecondary {
composes: button;
font-weight: 500;
background: var(--admin-surface);
color: var(--admin-text);
border-color: var(--admin-border);
}
.buttonSecondary:hover {
background: var(--admin-bg);
}
.buttonDanger {
composes: buttonSecondary;
color: var(--admin-danger);
}
.buttonDanger:hover {
background: #FEF2F2;
border-color: var(--admin-danger);
}
.error {
color: var(--admin-danger);
font-size: 0.875rem;
}