Enhance Dashboard Navigation and Settings with Show Navigation Labels Feature
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

- Introduced a new setting for showNavigationLabels in the ThemeContext to manage the visibility of navigation labels.
- Updated the Settings component to allow users to toggle navigation labels and persist this setting.
- Modified the DashboardNavigation component to conditionally render navigation labels based on user preference.
- Adjusted App.css to improve styling for navigation items when labels are hidden.
This commit is contained in:
Tom Butcher 2026-08-22 20:32:20 +01:00
parent 3e86170e5c
commit 978f444538
4 changed files with 143 additions and 44 deletions

View File

@ -1734,3 +1734,7 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
border: 1px solid #000;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}
.no-navigation-labels.ant-menu-horizontal .ant-menu-item {
padding: 0 5px;
}

View File

@ -28,8 +28,15 @@ const engineLabel = (engine) => {
}
const Settings = () => {
const { isDarkMode, isCompact, isSystem, setThemeMode, setDensityMode } =
useThemeContext()
const {
isDarkMode,
isCompact,
isSystem,
setThemeMode,
setDensityMode,
showNavigationLabels,
setShowNavigationLabels
} = useThemeContext()
const { fetchAppUpdateBranches } = useContext(ApiServerContext)
const { isElectron, getAppSettings, setAppSettings, getAppEngine } =
useContext(ElectronContext)
@ -77,11 +84,16 @@ const Settings = () => {
if (settingsLoading || isEditing) return
if (appSettings.theme) setThemeMode(appSettings.theme)
if (appSettings.density) setDensityMode(appSettings.density)
if (appSettings.showNavigationLabels !== undefined) {
setShowNavigationLabels(appSettings.showNavigationLabels)
}
}, [
appSettings.density,
appSettings.showNavigationLabels,
appSettings.theme,
isEditing,
setDensityMode,
setShowNavigationLabels,
setThemeMode,
settingsLoading
])
@ -137,6 +149,8 @@ const Settings = () => {
const currentThemeValue = getCurrentThemeValue()
const currentDensityValue = isCompact ? 'compact' : 'comfortable'
const currentShowNavigationLabels =
appSettings.showNavigationLabels ?? showNavigationLabels ?? false
const currentBranch =
appSettings.appUpdateBranch ||
(branches.includes(DEFAULT_UPDATE_BRANCH) ? DEFAULT_UPDATE_BRANCH : null) ||
@ -154,7 +168,8 @@ const Settings = () => {
currentBranch === 'Not configured' ? undefined : currentBranch,
appUpdateEngine: currentEngine,
theme: currentThemeValue,
density: currentDensityValue
density: currentDensityValue,
showNavigationLabels: currentShowNavigationLabels
})
setIsEditing(true)
}
@ -175,6 +190,7 @@ const Settings = () => {
...appSettings,
theme: draftSettings.theme,
density: draftSettings.density,
showNavigationLabels: Boolean(draftSettings.showNavigationLabels),
...(isElectron
? {
appUpdateBranch: draftSettings.appUpdateBranch,
@ -197,13 +213,15 @@ const Settings = () => {
settings: {
...(previous?.settings || {}),
theme: draftSettings.theme,
density: draftSettings.density
density: draftSettings.density,
showNavigationLabels: Boolean(draftSettings.showNavigationLabels)
}
}))
}
setThemeMode(draftSettings.theme)
setDensityMode(draftSettings.density)
setShowNavigationLabels(draftSettings.showNavigationLabels)
setAppSettingsState(nextSettings)
setDraftSettings(nextSettings)
setIsEditing(false)
@ -311,6 +329,29 @@ const Settings = () => {
<Text>{isCompact ? 'Compact' : 'Comfortable'}</Text>
)}
</Descriptions.Item>
<Descriptions.Item label='Navigation Labels'>
{isEditing ? (
<Select
value={
draftSettings.showNavigationLabels ? 'show' : 'hide'
}
onChange={(value) =>
setDraftSettings((previous) => ({
...previous,
showNavigationLabels: value === 'show'
}))
}
style={{ width: '100%' }}
>
<Option value='show'>Show</Option>
<Option value='hide'>Hide</Option>
</Select>
) : (
<Text>
{currentShowNavigationLabels ? 'Show' : 'Hide'}
</Text>
)}
</Descriptions.Item>
</Descriptions>
</InfoCollapse>
{isElectron && (

View File

@ -48,6 +48,7 @@ import {
} from '../../../database/Sidebars'
import { useAppUpdateContext } from '../context/AppUpdateContext'
import { useThemeContext } from '../context/ThemeContext'
const { Text } = Typography
@ -56,6 +57,7 @@ const DashboardNavigation = () => {
const { showSpotlight } = useContext(SpotlightContext)
const { connecting, connected } = useContext(ApiServerContext)
const { authenticated } = useContext(AuthContext)
const { showNavigationLabels, setShowNavigationLabels } = useThemeContext()
const { toggleNotificationCenter, unreadCount } =
useContext(NotificationContext)
const [apiServerState, setApiServerState] = useState('disconnected')
@ -71,50 +73,81 @@ const DashboardNavigation = () => {
const {
platform,
isElectron,
getAppSettings,
setSidebarViewMenu,
isFullScreen,
isMaximized
} = useContext(ElectronContext)
const { availableUpdate, checkForUpdates } = useAppUpdateContext()
useEffect(() => {
const hydrateNavigationLabels = async () => {
const settings = isElectron
? await getAppSettings()
: userProfile?.settings || {}
if (settings?.showNavigationLabels !== undefined) {
setShowNavigationLabels(settings.showNavigationLabels)
}
}
void hydrateNavigationLabels()
}, [
getAppSettings,
isElectron,
setShowNavigationLabels,
userProfile?.settings
])
const includeDev = import.meta.env.DEV
const mainMenuItems = useMemo(
() =>
[
{
key: 'production',
label: 'Production',
className: 'electrobun-webkit-app-region-no-drag',
icon: <ProductionIcon />
},
{
key: 'inventory',
label: 'Inventory',
className: 'electrobun-webkit-app-region-no-drag',
icon: <InventoryIcon />
},
{
key: 'sales',
label: 'Sales',
className: 'electrobun-webkit-app-region-no-drag',
icon: <SalesIcon />
},
{
key: 'finance',
label: 'Finance',
className: 'electrobun-webkit-app-region-no-drag',
icon: <FinanceIcon />
},
{
key: 'management',
label: 'Management',
className: 'electrobun-webkit-app-region-no-drag',
icon: <SettingsIcon />
}
].filter((item) =>
isSidebarSectionVisible(item.key, { includeDev, userProfile })
),
[includeDev, userProfile]
)
const mainMenuItems = useMemo(() => {
const iconStyles = {
fontSize: !showNavigationLabels ? '16px' : undefined,
marginLeft: !showNavigationLabels ? '10px' : undefined
}
const navigationIcon = (icon, label) =>
showNavigationLabels ? (
icon
) : (
<Tooltip title={label} listenParents={1}>
{icon}
</Tooltip>
)
return [
{
key: 'production',
label: 'Production',
className: 'electrobun-webkit-app-region-no-drag',
icon: navigationIcon(<ProductionIcon style={iconStyles} />, 'Production')
},
{
key: 'inventory',
label: 'Inventory',
className: 'electrobun-webkit-app-region-no-drag',
icon: navigationIcon(<InventoryIcon style={iconStyles} />, 'Inventory')
},
{
key: 'sales',
label: 'Sales',
className: 'electrobun-webkit-app-region-no-drag',
icon: navigationIcon(<SalesIcon style={iconStyles} />, 'Sales')
},
{
key: 'finance',
label: 'Finance',
className: 'electrobun-webkit-app-region-no-drag',
icon: navigationIcon(<FinanceIcon style={iconStyles} />, 'Finance')
},
{
key: 'management',
label: 'Management',
className: 'electrobun-webkit-app-region-no-drag',
icon: navigationIcon(<SettingsIcon style={iconStyles} />, 'Management')
}
].filter((item) =>
isSidebarSectionVisible(item.key, { includeDev, userProfile })
)
}, [includeDev, showNavigationLabels, userProfile])
const [userPopoverOpen, setUserPopoverOpen] = useState(false)
@ -219,8 +252,12 @@ const DashboardNavigation = () => {
{showControls && (
<Menu
mode='horizontal'
className={isElectron ? 'electron-navigation' : null}
items={mainMenuItems}
className={`${isElectron ? 'electron-navigation' : null} ${!showNavigationLabels ? 'no-navigation-labels' : ''}`}
items={
showNavigationLabels
? mainMenuItems
: mainMenuItems.map((item) => ({ ...item, label: undefined }))
}
style={{
flexWrap: 'wrap',
flexGrow: isMobile ? 0 : 1,

View File

@ -39,6 +39,10 @@ export const ThemeProvider = ({ children }) => {
const savedCompact = sessionStorage.getItem('isCompact')
return savedCompact ? JSON.parse(savedCompact) : false
})
const [showNavigationLabels, setShowNavigationLabelsState] = useState(() => {
const savedLabels = sessionStorage.getItem('showNavigationLabels')
return savedLabels ? JSON.parse(savedLabels) : false
})
const [primaryColorOverride, setPrimaryColorOverride] = useState(null)
@ -77,6 +81,13 @@ export const ThemeProvider = ({ children }) => {
sessionStorage.setItem('isCompact', JSON.stringify(isCompact))
}, [isCompact])
useEffect(() => {
sessionStorage.setItem(
'showNavigationLabels',
JSON.stringify(showNavigationLabels)
)
}, [showNavigationLabels])
const toggleTheme = () => {
if (isSystem) {
setIsSystem(false)
@ -111,6 +122,10 @@ export const ThemeProvider = ({ children }) => {
setIsCompact(value === 'compact')
}, [])
const setShowNavigationLabels = useCallback((value) => {
setShowNavigationLabelsState(Boolean(value))
}, [])
const getThemeAlgorithm = () => {
var baseAlgorithm
if (isDarkMode == true) {
@ -191,6 +206,8 @@ export const ThemeProvider = ({ children }) => {
toggleSystem,
setThemeMode,
setDensityMode,
showNavigationLabels,
setShowNavigationLabels,
getColors,
setPrimaryColorOverride,
themeConfig