Implement comprehensive dark/light mode overhaul for admin panel

- Refactor color palette in `ui-design-spec.md` to utilize CSS variables exclusively, eliminating fixed hex values and Tailwind utility classes.
- Complete dark mode implementation in `uiStore.ts`, ensuring proper theme application via `applyTheme()` and `applyBrand()`.
- Create `admin-theme-dark-light-audit.md` to document the transition process, outlining issues with inline styles and fixed colors.
- Introduce `theme-tokens.test.ts` to enforce rules against fixed hex colors and ensure compliance with the design system.
- Update various components and styles to replace inline styles and fixed colors with CSS variables, ensuring consistent theming across light and dark modes.
- Ensure all changes maintain visual integrity in both light and dark modes, with a focus on accessibility and contrast standards.
This commit is contained in:
hamed
2026-07-27 16:41:52 +03:30
parent c29035c21e
commit 55ab2f5dfc
73 changed files with 1485 additions and 1110 deletions
+15 -23
View File
@@ -260,7 +260,7 @@ body {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
height: 40px; padding: 0 18px; border-radius: var(--r-sm);
font-size: 14px; font-weight: 700; white-space: nowrap; border: none; cursor: pointer;
background: var(--danger); color: #fff; transition: .16s;
background: var(--danger); color: var(--on-primary); transition: .16s;
}
.cp-btn-danger:hover { filter: brightness(.92); }
.cp-btn-danger:disabled { opacity: .5; cursor: not-allowed; }
@@ -408,7 +408,7 @@ body {
.user-meta span { font-size: 11.5px; color: var(--text-3); }
.cp-avatar {
width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
display: grid; place-items: center; font-weight: 700; color: #fff; font-size: 13px;
display: grid; place-items: center; font-weight: 700; color: var(--on-primary); font-size: 13px;
background: linear-gradient(145deg, var(--primary), var(--primary-700));
overflow: hidden;
}
@@ -595,7 +595,7 @@ body {
.btn.soft:hover { background: var(--primary-soft2); }
.btn.danger { background: var(--danger-bg); color: var(--danger); border-color: transparent; }
.btn.danger:hover { filter: brightness(.97); }
.btn.accent { background: var(--accent); color: #fff; box-shadow: 0 4px 14px rgba(240,104,42,.35); box-shadow: 0 4px 14px color-mix(in oklch, var(--accent) 35%, transparent); }
.btn.accent { background: var(--accent); color: var(--on-primary); box-shadow: 0 4px 14px rgba(240,104,42,.35); box-shadow: 0 4px 14px color-mix(in oklch, var(--accent) 35%, transparent); }
.btn.accent:hover { background: var(--accent-600); }
.btn.outline { background: transparent; border-color: var(--primary); color: var(--primary); }
.btn.outline:hover { background: var(--primary-soft); }
@@ -668,7 +668,7 @@ table.t tbody tr:last-child td { border-bottom: none; }
transition: transform .18s, background .18s;
}
.switch input:checked ~ .switch-track { background: var(--primary); border-color: var(--primary); }
.switch input:checked ~ .switch-track .switch-thumb { background: #fff; transform: translateX(-20px); }
.switch input:checked ~ .switch-track .switch-thumb { background: var(--on-primary); transform: translateX(-20px); }
.switch input:focus-visible ~ .switch-track { box-shadow: 0 0 0 4px var(--ring); }
/* ── Pagination ──────────────────────────────────────────────── */
@@ -772,7 +772,7 @@ table.t tbody tr:last-child td { border-bottom: none; }
/* ── Colored avatar (hue-based gradient) ─────────────────────── */
.avatar {
width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
display: grid; place-items: center; font-weight: 700; color: #fff; font-size: 14px;
display: grid; place-items: center; font-weight: 700; color: var(--on-primary); font-size: 14px;
overflow: hidden;
}
.avatar.sm { width: 32px; height: 32px; font-size: 12px; }
@@ -924,29 +924,23 @@ html, body { max-width: 100%; overflow-x: hidden; }
display: inline-block; width: 100px; text-align: center;
padding: 4px 8px; border-radius: 4px; font-size: 14px; font-weight: 500;
}
.inv-badge.in-stock { background: #E8FADD; color: #3c9a4f; }
.inv-badge.low-stock { background: #FFF3DD; color: #FDBA35; }
.inv-badge.out-of-stock { background: #FFE3E2; color: #FF5450; }
.dark .inv-badge.in-stock { background: #324A32; color: #75E22E; }
.dark .inv-badge.low-stock { background: #4E4234; color: #FDBA35; }
.dark .inv-badge.out-of-stock { background: rgba(255,84,80,0.20); color: #FF5450; }
.inv-badge.in-stock { background: var(--success-bg); color: var(--success); }
.inv-badge.low-stock { background: var(--warning-bg); color: var(--warning); }
.inv-badge.out-of-stock { background: var(--danger-bg); color: var(--danger); }
/* Tab row — mirrors inventory/TabsRow + TabItem. */
.inv-tabs {
display: flex; align-items: flex-end; gap: 24px;
border-bottom: 1px solid #EDEDED; margin: 4px 0 18px; width: 100%;
border-bottom: 1px solid var(--border); margin: 4px 0 18px; width: 100%;
overflow-x: auto; scrollbar-width: none;
}
.inv-tabs::-webkit-scrollbar { display: none; }
.dark .inv-tabs { border-color: #35343D; }
.inv-tab {
display: flex; align-items: center; gap: 6px; padding: 0 8px 6px;
font-size: 16px; cursor: pointer; white-space: nowrap;
border-bottom: 2px solid transparent; color: #6B7280; background: none;
border-bottom: 2px solid transparent; color: var(--text-2); background: none;
}
.dark .inv-tab { color: #A1A1A1; }
.inv-tab.active { border-bottom: 3px solid #5559ce; color: #5559ce; }
.dark .inv-tab.active { color: #5559ce; }
.inv-tab.active { border-bottom: 3px solid var(--primary); color: var(--primary); }
/* Inventory responsive table/card switch (md breakpoint = 768px, like tauri). */
.inv-desktop { display: block; }
@@ -956,19 +950,17 @@ html, body { max-width: 100%; overflow-x: hidden; }
.inv-mobile { display: grid; }
}
.inv-table { width: 100%; border-collapse: collapse; }
.inv-table thead tr { background: #e1e1e1; }
.inv-table thead tr { background: var(--surface-2); }
.inv-table th {
color: #616161; font-size: 14px; font-weight: 400;
color: var(--text-2); font-size: 14px; font-weight: 400;
padding: 10px 18px; text-align: start; white-space: nowrap;
}
.inv-table td {
padding: 12px 18px; text-align: start; white-space: nowrap;
font-size: 16px; font-weight: 500; color: var(--text-2);
border-bottom: 1px solid #DBDBDB;
border-bottom: 1px solid var(--border);
}
.dark .inv-table td { border-color: var(--border); }
.inv-table tbody tr:hover { background: #f4f5fd; }
.dark .inv-table tbody tr:hover { background: var(--surface-2); }
.inv-table tbody tr:hover { background: var(--surface-2); }
/* input[type=time] با آیکون سفارشی (گام «ایجاد سرویس»): آیکون native مرورگر حذف
می‌شود تا ساعت دوتایی نشود — مثل مبدأ tauri که فقط یک ClockField دارد. */