use rem styling, make navbar scrollable on overflow, extrapolate styling to be re-usable and remove redundant nav item colors, rely on tailwind theme instead

This commit is contained in:
EthanHealy01 2025-07-22 16:48:11 +01:00
parent 7d09bf9e45
commit 3a76d13097
6 changed files with 94 additions and 69 deletions

View File

@ -3,7 +3,6 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,700,0,0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta <meta

View File

@ -27,6 +27,7 @@
"i18next-browser-languagedetector": "^8.1.0", "i18next-browser-languagedetector": "^8.1.0",
"i18next-http-backend": "^3.0.2", "i18next-http-backend": "^3.0.2",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"material-symbols": "^0.33.0",
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",
"pdfjs-dist": "^3.11.174", "pdfjs-dist": "^3.11.174",
"react": "^19.1.0", "react": "^19.1.0",
@ -4175,6 +4176,12 @@
"semver": "bin/semver.js" "semver": "bin/semver.js"
} }
}, },
"node_modules/material-symbols": {
"version": "0.33.0",
"resolved": "https://registry.npmjs.org/material-symbols/-/material-symbols-0.33.0.tgz",
"integrity": "sha512-t9/Gz+14fClRgN7oVOt5CBuwsjFLxSNP9BRDyMrI5el3IZNvoD94IDGJha0YYivyAow24rCS0WOkAv4Dp+YjNg==",
"license": "Apache-2.0"
},
"node_modules/math-intrinsics": { "node_modules/math-intrinsics": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",

View File

@ -23,6 +23,7 @@
"i18next-browser-languagedetector": "^8.1.0", "i18next-browser-languagedetector": "^8.1.0",
"i18next-http-backend": "^3.0.2", "i18next-http-backend": "^3.0.2",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"material-symbols": "^0.33.0",
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",
"pdfjs-dist": "^3.11.174", "pdfjs-dist": "^3.11.174",
"react": "^19.1.0", "react": "^19.1.0",

View File

@ -12,16 +12,38 @@
height: 32px; height: 32px;
} }
.fallbackDivider { /* Scrollable navbar styling - scrollbars only show when scrolling */
width: 60px; .quick-access-bar {
height: 1px; overflow-x: auto;
background-color: var(--color-gray-300); overflow-y: hidden;
margin: 8px 0; scrollbar-gutter: stable both-edges;
border-radius: 1px; -webkit-overflow-scrolling: touch;
} }
.mantineDivider { /* Hide scrollbar by default, show on scroll (Webkit browsers - Chrome, Safari, Edge) */
width: 60px; .quick-access-bar::-webkit-scrollbar {
margin: 8px 0; width: 8px;
border-color: var(--color-gray-300); height: 8px;
background: transparent;
}
.quick-access-bar:hover::-webkit-scrollbar,
.quick-access-bar:active::-webkit-scrollbar,
.quick-access-bar:focus::-webkit-scrollbar {
background: rgba(0, 0, 0, 0.1);
}
.quick-access-bar::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
.quick-access-bar::-webkit-scrollbar-track {
background: transparent;
}
/* Firefox scrollbar styling */
.quick-access-bar {
scrollbar-width: auto;
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
} }

View File

@ -26,45 +26,39 @@ interface ButtonConfig {
name: string; name: string;
icon: React.ReactNode; icon: React.ReactNode;
tooltip: string; tooltip: string;
color: string;
isRound?: boolean; isRound?: boolean;
size?: 'sm' | 'md' | 'lg' | 'xl'; size?: 'sm' | 'md' | 'lg' | 'xl';
onClick: () => void; onClick: () => void;
} }
const actionIconStyle = {
backgroundColor: 'var(--icon-user-bg)',
color: 'var(--icon-user-color)',
borderRadius: '50%',
width: '1.5rem',
height: '1.5rem',
};
function NavHeader() { function NavHeader() {
return ( return (
<> <>
<div className="flex flex-row items-center justify-center mb-0"> <div className="flex flex-row items-center justify-center mb-0" style={{ gap: '0.5rem' }}>
<Tooltip label="User Profile" position="right"> <Tooltip label="User Profile" position="right">
<ActionIcon <ActionIcon
size="md" size="md"
variant="subtle" variant="subtle"
style={{ style={actionIconStyle}
backgroundColor: 'var(--icon-user-bg)',
color: 'var(--icon-user-color)',
borderRadius: '50%',
width: '24px',
height: '24px',
marginRight: '8px'
}}
> >
<PersonIcon sx={{ fontSize: 16 }} /> <PersonIcon sx={{ fontSize: "1rem" }} />
</ActionIcon> </ActionIcon>
</Tooltip> </Tooltip>
<Tooltip label="Notifications" position="right"> <Tooltip label="Notifications" position="right">
<ActionIcon <ActionIcon
size="md" size="md"
variant="subtle" variant="subtle"
style={{ style={actionIconStyle}
backgroundColor: 'var(--icon-notifications-bg)',
color: 'var(--icon-notifications-color)',
borderRadius: '50%',
width: '24px',
height: '24px'
}}
> >
<NotificationsIcon sx={{ fontSize: 16 }} /> <NotificationsIcon sx={{ fontSize: "1rem" }} />
</ActionIcon> </ActionIcon>
</Tooltip> </Tooltip>
</div> </div>
@ -72,7 +66,7 @@ function NavHeader() {
<Divider <Divider
size="xs" size="xs"
style={{ style={{
width: '60px', width: '3.75rem',
borderColor: 'var(--color-gray-300)' borderColor: 'var(--color-gray-300)'
}} }}
/> />
@ -98,8 +92,8 @@ const QuickAccessBar = ({
name: 'All Tools', name: 'All Tools',
icon: <AppsIcon sx={{ fontSize: 26 }} />, icon: <AppsIcon sx={{ fontSize: 26 }} />,
tooltip: 'View all available tools', tooltip: 'View all available tools',
color: '#1E88E5',
size: 'lg', size: 'lg',
isRound: false,
onClick: () => { onClick: () => {
setActiveButton('tools'); setActiveButton('tools');
onReaderToggle(); onReaderToggle();
@ -111,8 +105,8 @@ const QuickAccessBar = ({
name: 'Read', name: 'Read',
icon: <MenuBookIcon sx={{ fontSize: 20 }} />, icon: <MenuBookIcon sx={{ fontSize: 20 }} />,
tooltip: 'Read documents', tooltip: 'Read documents',
color: '#4CAF50',
size: 'lg', size: 'lg',
isRound: false,
onClick: () => { onClick: () => {
setActiveButton('read'); setActiveButton('read');
onReaderToggle(); onReaderToggle();
@ -122,12 +116,12 @@ const QuickAccessBar = ({
id: 'sign', id: 'sign',
name: 'Sign', name: 'Sign',
icon: icon:
<span className="material-symbols-outlined" style={{ fontSize: 20 }}> <span className="material-symbols-rounded" style={{ fontSize: 20 }}>
signature signature
</span>, </span>,
tooltip: 'Sign your document', tooltip: 'Sign your document',
color: '#3BA99C',
size: 'lg', size: 'lg',
isRound: false,
onClick: () => setActiveButton('sign') onClick: () => setActiveButton('sign')
}, },
{ {
@ -135,8 +129,8 @@ const QuickAccessBar = ({
name: 'Automate', name: 'Automate',
icon: <AutoAwesomeIcon sx={{ fontSize: 20 }} />, icon: <AutoAwesomeIcon sx={{ fontSize: 20 }} />,
tooltip: 'Automate workflows', tooltip: 'Automate workflows',
color: '#A576E3',
size: 'lg', size: 'lg',
isRound: false,
onClick: () => setActiveButton('automate') onClick: () => setActiveButton('automate')
}, },
{ {
@ -144,34 +138,18 @@ const QuickAccessBar = ({
name: 'Files', name: 'Files',
icon: <FolderIcon sx={{ fontSize: 20 }} />, icon: <FolderIcon sx={{ fontSize: 20 }} />,
tooltip: 'Manage files', tooltip: 'Manage files',
color: '', // the round icons are blue always, this logic lives in getButtonStyle
isRound: true, isRound: true,
size: 'lg', size: 'lg',
onClick: () => setActiveButton('files') onClick: () => setActiveButton('files')
}, },
/* Access isn't going to be available yet */
/*
{
id: 'access',
name: 'Access',
icon: <GroupIcon sx={{ fontSize: 20 }} />,
tooltip: 'Manage access and permissions',
color: '#00BCD4',
isRound: true,
size: 'lg',
onClick: () => setActiveButton('access')
},
*/
{ {
id: 'activity', id: 'activity',
name: 'Activity', name: 'Activity',
icon: icon:
<span className="material-symbols-outlined" style={{ fontSize: 20 }}> <span className="material-symbols-rounded" style={{ fontSize: 20 }}>
vital_signs vital_signs
</span>, </span>,
tooltip: 'View activity and analytics', tooltip: 'View activity and analytics',
color: '',
isRound: true, isRound: true,
size: 'lg', size: 'lg',
onClick: () => setActiveButton('activity') onClick: () => setActiveButton('activity')
@ -181,7 +159,6 @@ const QuickAccessBar = ({
name: 'Config', name: 'Config',
icon: <SettingsIcon sx={{ fontSize: 16 }} />, icon: <SettingsIcon sx={{ fontSize: 16 }} />,
tooltip: 'Configure settings', tooltip: 'Configure settings',
color: '#9CA3AF',
size: 'lg', size: 'lg',
onClick: () => { onClick: () => {
setConfigModalOpen(true); setConfigModalOpen(true);
@ -189,6 +166,13 @@ const QuickAccessBar = ({
} }
]; ];
const ROUND_BORDER_RADIUS = '50%';
const NOT_ROUND_BORDER_RADIUS = '8px';
const getBorderRadius = (config: ButtonConfig): string => {
return config.isRound ? ROUND_BORDER_RADIUS : NOT_ROUND_BORDER_RADIUS;
};
const getButtonStyle = (config: ButtonConfig) => { const getButtonStyle = (config: ButtonConfig) => {
const isActive = activeButton === config.id; const isActive = activeButton === config.id;
@ -199,7 +183,7 @@ const QuickAccessBar = ({
backgroundColor: 'var(--icon-tools-bg)', backgroundColor: 'var(--icon-tools-bg)',
color: 'var(--icon-tools-color)', color: 'var(--icon-tools-color)',
border: 'none', border: 'none',
borderRadius: config.isRound ? '50%' : '8px', borderRadius: getBorderRadius(config),
}; };
} }
if (config.id === 'read') { if (config.id === 'read') {
@ -207,7 +191,7 @@ const QuickAccessBar = ({
backgroundColor: 'var(--icon-read-bg)', backgroundColor: 'var(--icon-read-bg)',
color: 'var(--icon-read-color)', color: 'var(--icon-read-color)',
border: 'none', border: 'none',
borderRadius: config.isRound ? '50%' : '8px', borderRadius: getBorderRadius(config),
}; };
} }
if (config.id === 'sign') { if (config.id === 'sign') {
@ -215,7 +199,7 @@ const QuickAccessBar = ({
backgroundColor: 'var(--icon-sign-bg)', backgroundColor: 'var(--icon-sign-bg)',
color: 'var(--icon-sign-color)', color: 'var(--icon-sign-color)',
border: 'none', border: 'none',
borderRadius: config.isRound ? '50%' : '8px', borderRadius: getBorderRadius(config),
}; };
} }
if (config.id === 'automate') { if (config.id === 'automate') {
@ -223,21 +207,21 @@ const QuickAccessBar = ({
backgroundColor: 'var(--icon-automate-bg)', backgroundColor: 'var(--icon-automate-bg)',
color: 'var(--icon-automate-color)', color: 'var(--icon-automate-color)',
border: 'none', border: 'none',
borderRadius: config.isRound ? '50%' : '8px', borderRadius: getBorderRadius(config),
}; };
} }
if (config.id === 'files') { if (config.id === 'files') {
return { return {
backgroundColor: 'var(--icon-files-bg)', backgroundColor: 'var(--icon-files-bg)',
color: 'var(--icon-files-color)', color: 'var(--icon-files-color)',
borderRadius: '50%', borderRadius: ROUND_BORDER_RADIUS,
}; };
} }
if (config.id === 'activity') { if (config.id === 'activity') {
return { return {
backgroundColor: 'var(--icon-activity-bg)', backgroundColor: 'var(--icon-activity-bg)',
color: 'var(--icon-activity-color)', color: 'var(--icon-activity-color)',
borderRadius: '50%', borderRadius: ROUND_BORDER_RADIUS,
}; };
} }
if (config.id === 'config') { if (config.id === 'config') {
@ -245,7 +229,7 @@ const QuickAccessBar = ({
backgroundColor: 'var(--icon-config-bg)', backgroundColor: 'var(--icon-config-bg)',
color: 'var(--icon-config-color)', color: 'var(--icon-config-color)',
border: 'none', border: 'none',
borderRadius: config.isRound ? '50%' : '8px', borderRadius: getBorderRadius(config),
}; };
} }
} }
@ -255,15 +239,15 @@ const QuickAccessBar = ({
backgroundColor: 'var(--icon-inactive-bg)', backgroundColor: 'var(--icon-inactive-bg)',
color: 'var(--icon-inactive-color)', color: 'var(--icon-inactive-color)',
border: 'none', border: 'none',
borderRadius: config.isRound ? '50%' : '8px', borderRadius: getBorderRadius(config),
}; };
}; };
const getTextStyle = (config: ButtonConfig) => { const getTextStyle = (config: ButtonConfig) => {
const isActive = activeButton === config.id; const isActive = activeButton === config.id;
return { return {
marginTop: '12px', marginTop: '0.75rem',
fontSize: '12px', fontSize: '0.75rem',
color: isActive ? 'var(--text-primary)' : 'var(--color-gray-700)', color: isActive ? 'var(--text-primary)' : 'var(--color-gray-700)',
fontWeight: isActive ? 'bold' : 'normal', fontWeight: isActive ? 'bold' : 'normal',
textRendering: 'optimizeLegibility' as const, textRendering: 'optimizeLegibility' as const,
@ -273,13 +257,19 @@ const QuickAccessBar = ({
return ( return (
<div <div
className={`h-screen flex flex-col w-20 ${isRainbowMode ? rainbowStyles.rainbowPaper : ''}`} className={`h-screen flex flex-col w-20 quick-access-bar ${isRainbowMode ? rainbowStyles.rainbowPaper : ''}`}
style={{ style={{
padding: '1rem 0.5rem', padding: '1rem 0.5rem',
backgroundColor: 'var(--bg-muted)', backgroundColor: 'var(--bg-muted)',
width: '80px', width: '5rem',
minWidth: '80px', minWidth: '5rem',
maxWidth: '80px' maxWidth: '5rem',
position: 'relative',
zIndex: 10
}}
onWheel={(e) => {
// Prevent the wheel event from bubbling up to parent containers
e.stopPropagation();
}} }}
> >
<Stack gap="lg" align="center" className="flex-1"> <Stack gap="lg" align="center" className="flex-1">
@ -310,7 +300,7 @@ const QuickAccessBar = ({
<Divider <Divider
size="xs" size="xs"
style={{ style={{
width: '60px', width: '3.75rem',
borderColor: 'var(--color-gray-300)' borderColor: 'var(--color-gray-300)'
}} }}
/> />

View File

@ -1,3 +1,9 @@
@import 'material-symbols/rounded.css';
.material-symbols-rounded {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
body { body {
margin: 0; margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',