feat: sidebar reorg, compact view preference, and UI polish

- Remove redundant Settings link from sidebar (accessible via user menu)
- Move Transactions section below Board Reference for better grouping
- Promote Investment Scenarios to its own top-level sidebar item
- Add Compact View preference with tighter spacing theme
- Wire compact theme into MantineProvider with dynamic switching
- Enable Compact View toggle in both Preferences and Settings pages
- Install missing @simplewebauthn/browser package (lock file update)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 06:39:41 -04:00
parent 20438b7ef5
commit af68304692
7 changed files with 86 additions and 32 deletions

View File

@@ -1,12 +1,12 @@
{
"name": "hoa-ledgeriq-frontend",
"version": "2026.3.11",
"version": "2026.3.17",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "hoa-ledgeriq-frontend",
"version": "2026.3.11",
"version": "2026.3.17",
"dependencies": {
"@mantine/core": "^7.15.3",
"@mantine/dates": "^7.15.3",

View File

@@ -17,11 +17,9 @@ import {
IconChartAreaLine,
IconClipboardCheck,
IconSparkles,
IconHeartRateMonitor,
IconCalculator,
IconGitCompare,
IconScale,
IconSettings,
} from '@tabler/icons-react';
import { useAuthStore } from '../../stores/authStore';
@@ -47,14 +45,6 @@ const navSections = [
{ label: 'Assessment Groups', icon: IconCategory, path: '/assessment-groups', tourId: 'nav-assessment-groups' },
],
},
{
label: 'Transactions',
items: [
{ label: 'Transactions', icon: IconReceipt, path: '/transactions', tourId: 'nav-transactions' },
{ label: 'Invoices', icon: IconFileInvoice, path: '/invoices' },
{ label: 'Payments', icon: IconCash, path: '/payments' },
],
},
{
label: 'Board Planning',
items: [
@@ -68,12 +58,8 @@ const navSections = [
{
label: 'Assessment Scenarios', icon: IconCalculator, path: '/board-planning/assessments',
},
{
label: 'Investment Planning', icon: IconSparkles, path: '/investment-planning', tourId: 'nav-investment-planning',
children: [
{ label: 'Investment Scenarios', path: '/board-planning/investments' },
],
},
{ label: 'Investment Planning', icon: IconSparkles, path: '/investment-planning', tourId: 'nav-investment-planning' },
{ label: 'Investment Scenarios', icon: IconScale, path: '/board-planning/investments' },
{ label: 'Compare Scenarios', icon: IconGitCompare, path: '/board-planning/compare' },
],
},
@@ -83,6 +69,14 @@ const navSections = [
{ label: 'Vendors', icon: IconUsers, path: '/vendors' },
],
},
{
label: 'Transactions',
items: [
{ label: 'Transactions', icon: IconReceipt, path: '/transactions', tourId: 'nav-transactions' },
{ label: 'Invoices', icon: IconFileInvoice, path: '/invoices' },
{ label: 'Payments', icon: IconCash, path: '/payments' },
],
},
{
label: 'Reports',
items: [
@@ -103,12 +97,6 @@ const navSections = [
},
],
},
{
label: 'Account',
items: [
{ label: 'Settings', icon: IconSettings, path: '/settings' },
],
},
];
interface SidebarProps {

View File

@@ -9,7 +9,7 @@ import '@mantine/core/styles.css';
import '@mantine/dates/styles.css';
import '@mantine/notifications/styles.css';
import { App } from './App';
import { theme } from './theme/theme';
import { defaultTheme, compactTheme } from './theme/theme';
import { usePreferencesStore } from './stores/preferencesStore';
const queryClient = new QueryClient({
@@ -24,9 +24,11 @@ const queryClient = new QueryClient({
function Root() {
const colorScheme = usePreferencesStore((s) => s.colorScheme);
const compactView = usePreferencesStore((s) => s.compactView);
const activeTheme = compactView ? compactTheme : defaultTheme;
return (
<MantineProvider theme={theme} forceColorScheme={colorScheme}>
<MantineProvider theme={activeTheme} forceColorScheme={colorScheme}>
<Notifications position="top-right" />
<ModalsProvider>
<QueryClientProvider client={queryClient}>

View File

@@ -10,7 +10,7 @@ import { usePreferencesStore } from '../../stores/preferencesStore';
export function UserPreferencesPage() {
const { user, currentOrg } = useAuthStore();
const { colorScheme, toggleColorScheme } = usePreferencesStore();
const { colorScheme, toggleColorScheme, compactView, toggleCompactView } = usePreferencesStore();
return (
<Stack>
@@ -78,7 +78,7 @@ export function UserPreferencesPage() {
<Text size="sm">Compact View</Text>
<Text size="xs" c="dimmed">Reduce spacing in tables and lists</Text>
</div>
<Switch disabled />
<Switch checked={compactView} onChange={toggleCompactView} />
</Group>
<Divider />
<Text size="xs" c="dimmed" ta="center">More display preferences coming in a future release</Text>

View File

@@ -1,7 +1,7 @@
import { useState } from 'react';
import {
Title, Text, Card, Stack, Group, SimpleGrid, Badge, ThemeIcon, Divider,
Tabs, Button,
Tabs, Button, Switch,
} from '@mantine/core';
import {
IconBuilding, IconUser, IconSettings, IconShieldLock,
@@ -9,6 +9,7 @@ import {
} from '@tabler/icons-react';
import { notifications } from '@mantine/notifications';
import { useAuthStore } from '../../stores/authStore';
import { usePreferencesStore } from '../../stores/preferencesStore';
import { MfaSettings } from './MfaSettings';
import { PasskeySettings } from './PasskeySettings';
import { LinkedAccounts } from './LinkedAccounts';
@@ -16,6 +17,7 @@ import api from '../../services/api';
export function SettingsPage() {
const { user, currentOrg } = useAuthStore();
const { compactView, toggleCompactView } = usePreferencesStore();
const [loggingOutAll, setLoggingOutAll] = useState(false);
const handleLogoutEverywhere = async () => {
@@ -112,6 +114,14 @@ export function SettingsPage() {
<Text size="sm" c="dimmed">API</Text>
<Text size="sm" ff="monospace" c="dimmed">/api/docs</Text>
</Group>
<Divider />
<Group justify="space-between">
<div>
<Text size="sm">Compact View</Text>
<Text size="xs" c="dimmed">Reduce spacing in tables and lists</Text>
</div>
<Switch checked={compactView} onChange={toggleCompactView} />
</Group>
</Stack>
</Card>

View File

@@ -5,19 +5,26 @@ type ColorScheme = 'light' | 'dark';
interface PreferencesState {
colorScheme: ColorScheme;
compactView: boolean;
toggleColorScheme: () => void;
setColorScheme: (scheme: ColorScheme) => void;
toggleCompactView: () => void;
setCompactView: (compact: boolean) => void;
}
export const usePreferencesStore = create<PreferencesState>()(
persist(
(set) => ({
colorScheme: 'light',
compactView: false,
toggleColorScheme: () =>
set((state) => ({
colorScheme: state.colorScheme === 'light' ? 'dark' : 'light',
})),
setColorScheme: (scheme) => set({ colorScheme: scheme }),
toggleCompactView: () =>
set((state) => ({ compactView: !state.compactView })),
setCompactView: (compact) => set({ compactView: compact }),
}),
{
name: 'ledgeriq-preferences',

View File

@@ -1,10 +1,57 @@
import { createTheme } from '@mantine/core';
export const theme = createTheme({
const baseFontFamily = '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif';
export const defaultTheme = createTheme({
primaryColor: 'blue',
fontFamily: '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif',
fontFamily: baseFontFamily,
headings: {
fontFamily: '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif',
fontFamily: baseFontFamily,
},
defaultRadius: 'md',
});
export const compactTheme = createTheme({
primaryColor: 'blue',
fontFamily: baseFontFamily,
headings: {
fontFamily: baseFontFamily,
},
defaultRadius: 'md',
spacing: {
xs: '4px',
sm: '6px',
md: '10px',
lg: '12px',
xl: '16px',
},
fontSizes: {
xs: '11px',
sm: '12px',
md: '13px',
lg: '15px',
xl: '18px',
},
components: {
Table: {
defaultProps: {
verticalSpacing: 'xs',
horizontalSpacing: 'xs',
fz: 'sm',
},
},
Card: {
defaultProps: {
padding: 'sm',
},
},
AppShell: {
defaultProps: {
padding: 'xs',
},
},
},
});
/** @deprecated Use `defaultTheme` or `compactTheme` instead */
export const theme = defaultTheme;