Refine Dashboard Styles and Tab Functionality for Enhanced User Experience
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

- Adjusted CSS styles for dashboard elements, including margin and positioning tweaks for improved layout and visual consistency.
- Updated tab masking logic to enhance scrolling behavior and visual integration.
- Removed unnecessary divider components to streamline the dashboard navigation structure.
- Implemented new logic for handling tab scrolling, ensuring better responsiveness and user interaction.
This commit is contained in:
Tom Butcher 2026-09-18 15:34:56 +01:00
parent 0b4b8128de
commit 48d2b0d15a
3 changed files with 82 additions and 36 deletions

View File

@ -175,13 +175,14 @@
position: relative;
height: 42px;
padding-top: 2px;
margin-left: 8px;
}
.dashboard-menu-container:after {
border-bottom: 1px solid var(--color-header-border);
content: '';
position: absolute;
left: 0;
right: -2px;
left: -8px;
right: 0px;
bottom: 0;
}
@ -3483,6 +3484,10 @@ body.objectKanbanColumnResizing * {
min-width: 0;
height: 100%;
position: relative;
--tab-mask-left: 4px;
--tab-mask-right: 8px;
--tab-mask-fade-left: var(--tab-mask-fade);
--tab-mask-fade-right: var(--tab-mask-fade);
}
.dashboard-tabs-wrap .simplebar-content-wrapper {
@ -3490,10 +3495,6 @@ body.objectKanbanColumnResizing * {
}
.dashboard-tabs-wrap .simplebar-mask {
--tab-mask-left: 4px;
--tab-mask-right: 4px;
--tab-mask-fade-left: var(--tab-mask-fade);
--tab-mask-fade-right: var(--tab-mask-fade);
-webkit-clip-path: inset(0 var(--tab-mask-right) 0 var(--tab-mask-left));
clip-path: inset(0 var(--tab-mask-right) 0 var(--tab-mask-left));
-webkit-mask-image: linear-gradient(
@ -3512,12 +3513,12 @@ body.objectKanbanColumnResizing * {
);
}
.dashboard-tabs[data-at-start] .dashboard-tabs-wrap .simplebar-mask {
.dashboard-tabs[data-at-start] .dashboard-tabs-wrap {
--tab-mask-left: 0px;
--tab-mask-fade-left: 0px;
}
.dashboard-tabs[data-at-end] .dashboard-tabs-wrap .simplebar-mask {
.dashboard-tabs[data-at-end] .dashboard-tabs-wrap {
--tab-mask-right: 0px;
--tab-mask-fade-right: 0px;
}
@ -3527,7 +3528,6 @@ body.objectKanbanColumnResizing * {
content: '';
position: absolute;
bottom: 0;
width: var(--tab-mask-fade);
height: 1px;
pointer-events: none;
z-index: 2;
@ -3536,14 +3536,32 @@ body.objectKanbanColumnResizing * {
.dashboard-tabs-wrap::before {
left: 0;
-webkit-mask-image: linear-gradient(to right, #000, transparent);
mask-image: linear-gradient(to right, #000, transparent);
width: calc(var(--tab-mask-left) + var(--tab-mask-fade-left));
-webkit-mask-image: linear-gradient(
to right,
#000 var(--tab-mask-left),
transparent calc(var(--tab-mask-left) + var(--tab-mask-fade-left))
);
mask-image: linear-gradient(
to right,
#000 var(--tab-mask-left),
transparent calc(var(--tab-mask-left) + var(--tab-mask-fade-left))
);
}
.dashboard-tabs-wrap::after {
right: 0.2px;
-webkit-mask-image: linear-gradient(to left, #000, transparent);
mask-image: linear-gradient(to left, #000, transparent);
width: calc(var(--tab-mask-right) + var(--tab-mask-fade-right));
-webkit-mask-image: linear-gradient(
to left,
#000 var(--tab-mask-right),
transparent calc(var(--tab-mask-right) + var(--tab-mask-fade-right))
);
mask-image: linear-gradient(
to left,
#000 var(--tab-mask-right),
transparent calc(var(--tab-mask-right) + var(--tab-mask-fade-right))
);
}
.dashboard-tabs-wrap .simplebar-track.simplebar-vertical {

View File

@ -78,14 +78,6 @@ const NAV_ELECTRON_CENTER_FADE_STYLE = {
alignItems: 'center'
}
const NAV_ELECTRON_TABS_STYLE = { flex: 1, minWidth: 0, display: 'flex' }
const NAV_ELECTRON_DIVIDER_STYLE_WITH_LABELS = {
margin: '3px 1px 0 4px',
height: '14px'
}
const NAV_ELECTRON_DIVIDER_STYLE = {
margin: '3px 1px 0 0',
height: '14px'
}
const NAV_TRAILING_FLEX_STYLE = { marginTop: '-2px', marginRight: '6px' }
const NAV_TRAILING_SPACE_STYLE = { paddingTop: '2px', marginRight: '8px' }
const NAV_SEARCH_BUTTON_STYLE = { marginTop: '4px' }
@ -237,14 +229,7 @@ const DashboardElectronCenterItems = memo(
>
{menu}
</div>
<Divider
type='vertical'
style={
showNavigationLabels
? NAV_ELECTRON_DIVIDER_STYLE_WITH_LABELS
: NAV_ELECTRON_DIVIDER_STYLE
}
/>
<div style={NAV_ELECTRON_TABS_STYLE}>
<DashboardTabs />
</div>

View File

@ -1,5 +1,5 @@
import PropTypes from 'prop-types'
import { useCallback, useLayoutEffect, useRef, useState } from 'react'
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'
import { Button, Flex, Typography } from 'antd'
import classNames from 'classnames'
import ScrollBox from './ScrollBox'
@ -177,17 +177,18 @@ const hideStickyClone = (cloneEl) => {
const setSimplebarMaskInset = (maskEl, edge, inset) => {
if (!maskEl) return
const wrapEl = maskEl.closest('.dashboard-tabs-wrap') || maskEl
if (!edge) {
maskEl.style.removeProperty('--tab-mask-left')
maskEl.style.removeProperty('--tab-mask-right')
wrapEl.style.removeProperty('--tab-mask-left')
wrapEl.style.removeProperty('--tab-mask-right')
return
}
if (edge === 'left') {
maskEl.style.setProperty('--tab-mask-left', `${inset}px`)
maskEl.style.removeProperty('--tab-mask-right')
wrapEl.style.setProperty('--tab-mask-left', `${inset}px`)
wrapEl.style.removeProperty('--tab-mask-right')
} else {
maskEl.style.removeProperty('--tab-mask-left')
maskEl.style.setProperty('--tab-mask-right', `${inset}px`)
wrapEl.style.removeProperty('--tab-mask-left')
wrapEl.style.setProperty('--tab-mask-right', `${inset}px`)
}
}
@ -391,6 +392,8 @@ const useActiveTabStickyScroll = (activeTabId, tabs) => {
const listRef = useRef(null)
const cloneRef = useRef(null)
const lineRef = useRef(null)
const prevTabCountRef = useRef(tabs.length)
const pendingScrollTabIdRef = useRef(null)
const tabLayoutKey = `${activeTabId}:${tabs.map((tab) => `${tab.id}:${tab.title || ''}`).join('|')}`
useLayoutEffect(() => {
@ -429,6 +432,46 @@ const useActiveTabStickyScroll = (activeTabId, tabs) => {
}
}, [tabLayoutKey])
useEffect(() => {
const lastTab = tabs[tabs.length - 1]
if (
tabs.length === prevTabCountRef.current + 1 &&
lastTab?.id === activeTabId
) {
pendingScrollTabIdRef.current = lastTab.id
}
prevTabCountRef.current = tabs.length
if (!lastTab || pendingScrollTabIdRef.current !== lastTab.id) {
return undefined
}
const list = listRef.current
const scrollEl = rootRef.current?.querySelector(
'.simplebar-content-wrapper'
)
const outlineEl = list?.lastElementChild?.querySelector(
'.dashboard-tab-item-outline-container'
)
if (!scrollEl || !outlineEl) return undefined
const scrollToEndIfReady = () => {
if (outlineEl.getBoundingClientRect().width <= 36) return false
scrollEl.scrollLeft = scrollEl.scrollWidth
pendingScrollTabIdRef.current = null
return true
}
if (scrollToEndIfReady()) return undefined
const observer = new ResizeObserver(() => {
if (scrollToEndIfReady()) observer.disconnect()
})
observer.observe(outlineEl)
return () => observer.disconnect()
}, [activeTabId, tabs])
return { rootRef, listRef, cloneRef, lineRef }
}