A warmer, friendlier admin: first pass

- The INBUXA palette on warm surfaces, softer cards, buttons and inputs, and
  self-hosted Inter and Space Grotesk.
- Each section's icon sits on a colored tile, colored by what the section is
  about.
- The sidebar gets a guide line for sub-pages and a labeled Management /
  Settings / Account switch, and folds to a rail of tiles (remembered).
- Every page has a header with its section's tile.
- Fields and pages with no label of their own are spelled out in words
  (defaultCertificateId becomes Default certificate ID).
- The dashboard greets you, and its stat cards wear colored tiles.
- Unavailable live numbers are a calm note, not an error.
- The cat appears in empty lists and while loading.
- Chart colors work again: they were hex values wrapped in hsl().
This commit is contained in:
2026-09-19 00:38:53 -07:00
parent 92bcb58f76
commit e4ad5e2c1e
26 changed files with 789 additions and 161 deletions
+9
View File
@@ -13,12 +13,15 @@ type Theme = 'light' | 'dark';
interface UIState {
theme: Theme;
sidebarOpen: boolean;
/** INBUXA: the sidebar folded to a rail of icon tiles, on wide screens. */
sidebarCollapsed: boolean;
activeSection: string;
toggleTheme: () => void;
setTheme: (theme: Theme) => void;
toggleSidebar: () => void;
setSidebarOpen: (open: boolean) => void;
toggleSidebarCollapsed: () => void;
setActiveSection: (section: string) => void;
}
@@ -36,6 +39,7 @@ export const useUIStore = create<UIState>()(
theme:
typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light',
sidebarOpen: typeof window !== 'undefined' ? (window.matchMedia?.('(min-width: 768px)').matches ?? true) : true,
sidebarCollapsed: false,
activeSection: '',
toggleTheme: () => {
@@ -57,6 +61,10 @@ export const useUIStore = create<UIState>()(
set({ sidebarOpen: open });
},
toggleSidebarCollapsed: () => {
set({ sidebarCollapsed: !get().sidebarCollapsed });
},
setActiveSection: (section) => {
set({ activeSection: section });
},
@@ -65,6 +73,7 @@ export const useUIStore = create<UIState>()(
name: 'inbuxa-ui',
partialize: (state) => ({
theme: state.theme,
sidebarCollapsed: state.sidebarCollapsed,
}),
onRehydrateStorage: () => {
return (state) => {