-
Notifications
You must be signed in to change notification settings - Fork 1
side navigation bar and responsive design #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,23 +8,25 @@ | |||||||
| */ | ||||||||
|
|
||||||||
| import { | ||||||||
| makeStyles, | ||||||||
| Subtitle1, | ||||||||
| Tab, | ||||||||
| TabList, | ||||||||
| Text, | ||||||||
| tokens, | ||||||||
| Button, | ||||||||
| makeStyles, | ||||||||
| Subtitle1, | ||||||||
| Subtitle2, | ||||||||
| Text, | ||||||||
| tokens, | ||||||||
| } from '@fluentui/react-components' | ||||||||
| import { | ||||||||
| Bot24Regular, | ||||||||
| DataHistogram24Regular, | ||||||||
| DocumentEdit24Regular, | ||||||||
| Flow24Regular, | ||||||||
| Info24Regular, | ||||||||
| Pulse24Regular, | ||||||||
| Settings24Regular, | ||||||||
| Table24Regular, | ||||||||
| Wrench24Regular, | ||||||||
| Bot24Regular, | ||||||||
| ChevronLeft24Regular, | ||||||||
| ChevronRight24Regular, | ||||||||
| DataHistogram24Regular, | ||||||||
| DocumentEdit24Regular, | ||||||||
| Flow24Regular, | ||||||||
| Info24Regular, | ||||||||
| Pulse24Regular, | ||||||||
| Settings24Regular, | ||||||||
| Table24Regular, | ||||||||
| Wrench24Regular, | ||||||||
| } from '@fluentui/react-icons' | ||||||||
| import { useEffect, useMemo, useState } from 'react' | ||||||||
| import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom' | ||||||||
|
|
@@ -43,31 +45,174 @@ import SettingsPage from './features/settings/SettingsPage' | |||||||
| import useTabPreferences from './features/settings/useTabPreferences' | ||||||||
| import { listWorkbenchAgents } from './services/api' | ||||||||
|
|
||||||||
| const NAV_COLLAPSED_STORAGE_KEY = 'app-nav-collapsed' | ||||||||
|
|
||||||||
| const useStyles = makeStyles({ | ||||||||
| app: { | ||||||||
| minHeight: '100vh', | ||||||||
| backgroundColor: tokens.colorNeutralBackground3, | ||||||||
| overflowX: 'hidden', | ||||||||
| display: 'flex', | ||||||||
| flexDirection: 'column', | ||||||||
| }, | ||||||||
| header: { | ||||||||
| backgroundColor: tokens.colorBrandBackground, | ||||||||
| color: tokens.colorNeutralForegroundOnBrand, | ||||||||
| padding: `${tokens.spacingVerticalL} ${tokens.spacingHorizontalXL}`, | ||||||||
| boxShadow: tokens.shadow4, | ||||||||
| '@media (max-width: 768px)': { | ||||||||
| padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalL}`, | ||||||||
| }, | ||||||||
| '@media (max-width: 480px)': { | ||||||||
| padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalM}`, | ||||||||
| }, | ||||||||
| }, | ||||||||
| headerInner: { | ||||||||
| maxWidth: '1400px', | ||||||||
| margin: '0 auto', | ||||||||
| }, | ||||||||
| title: { | ||||||||
| color: tokens.colorNeutralForegroundOnBrand, | ||||||||
| overflowWrap: 'anywhere', | ||||||||
| }, | ||||||||
| subtitle: { | ||||||||
| color: tokens.colorNeutralForegroundOnBrand, | ||||||||
| opacity: 0.9, | ||||||||
| marginTop: tokens.spacingVerticalXS, | ||||||||
| overflowWrap: 'anywhere', | ||||||||
| }, | ||||||||
| nav: { | ||||||||
| shell: { | ||||||||
| display: 'flex', | ||||||||
| flex: 1, | ||||||||
| minHeight: 0, | ||||||||
| }, | ||||||||
| sidebar: { | ||||||||
| width: '280px', | ||||||||
| flexShrink: 0, | ||||||||
| display: 'flex', | ||||||||
| flexDirection: 'column', | ||||||||
| backgroundColor: tokens.colorNeutralBackground1, | ||||||||
| borderRight: `1px solid ${tokens.colorNeutralStroke1}`, | ||||||||
| transitionDuration: tokens.durationNormal, | ||||||||
| transitionProperty: 'width', | ||||||||
| transitionTimingFunction: tokens.curveEasyEase, | ||||||||
| minHeight: 0, | ||||||||
| '@media (max-width: 768px)': { | ||||||||
| width: '232px', | ||||||||
| }, | ||||||||
| }, | ||||||||
| sidebarCollapsed: { | ||||||||
| width: '88px', | ||||||||
| '@media (max-width: 768px)': { | ||||||||
| width: '72px', | ||||||||
| }, | ||||||||
| }, | ||||||||
| sidebarHeader: { | ||||||||
| display: 'flex', | ||||||||
| alignItems: 'center', | ||||||||
| justifyContent: 'space-between', | ||||||||
| gap: tokens.spacingHorizontalS, | ||||||||
| padding: `${tokens.spacingVerticalL} ${tokens.spacingHorizontalM}`, | ||||||||
| borderBottom: `1px solid ${tokens.colorNeutralStroke1}`, | ||||||||
| padding: `0 ${tokens.spacingHorizontalXL}`, | ||||||||
| }, | ||||||||
| sidebarTitle: { | ||||||||
| minWidth: 0, | ||||||||
| overflow: 'hidden', | ||||||||
| }, | ||||||||
| collapseButton: { | ||||||||
| minWidth: '36px', | ||||||||
| width: '36px', | ||||||||
| height: '36px', | ||||||||
| padding: 0, | ||||||||
| flexShrink: 0, | ||||||||
| }, | ||||||||
| navList: { | ||||||||
| display: 'flex', | ||||||||
| flexDirection: 'column', | ||||||||
| gap: tokens.spacingVerticalXS, | ||||||||
| padding: tokens.spacingHorizontalS, | ||||||||
| overflowY: 'auto', | ||||||||
| flex: 1, | ||||||||
| minHeight: 0, | ||||||||
| }, | ||||||||
| navButton: { | ||||||||
| width: '100%', | ||||||||
| display: 'flex', | ||||||||
| alignItems: 'center', | ||||||||
| gap: tokens.spacingHorizontalM, | ||||||||
| border: 'none', | ||||||||
| borderRadius: tokens.borderRadiusLarge, | ||||||||
| backgroundColor: 'transparent', | ||||||||
| color: tokens.colorNeutralForeground2, | ||||||||
| cursor: 'pointer', | ||||||||
| padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalM}`, | ||||||||
| textAlign: 'left', | ||||||||
| transitionDuration: tokens.durationNormal, | ||||||||
| transitionProperty: 'background-color, color', | ||||||||
| transitionTimingFunction: tokens.curveEasyEase, | ||||||||
| ':hover': { | ||||||||
| backgroundColor: tokens.colorNeutralBackground1Hover, | ||||||||
| color: tokens.colorNeutralForeground1, | ||||||||
| }, | ||||||||
| }, | ||||||||
| navButtonCollapsed: { | ||||||||
| justifyContent: 'center', | ||||||||
| padding: `${tokens.spacingVerticalS} 0`, | ||||||||
| }, | ||||||||
| navButtonActive: { | ||||||||
| backgroundColor: tokens.colorBrandBackground2, | ||||||||
| color: tokens.colorBrandForeground1, | ||||||||
| boxShadow: `inset 3px 0 0 ${tokens.colorBrandStroke1}`, | ||||||||
| ':hover': { | ||||||||
| backgroundColor: tokens.colorBrandBackground2Hover, | ||||||||
| color: tokens.colorBrandForeground1, | ||||||||
| }, | ||||||||
| }, | ||||||||
| navIcon: { | ||||||||
| display: 'flex', | ||||||||
| alignItems: 'center', | ||||||||
| justifyContent: 'center', | ||||||||
| flexShrink: 0, | ||||||||
| }, | ||||||||
| navLabelWrap: { | ||||||||
| minWidth: 0, | ||||||||
| display: 'flex', | ||||||||
| flexDirection: 'column', | ||||||||
| gap: '2px', | ||||||||
| }, | ||||||||
| navLabel: { | ||||||||
| overflow: 'hidden', | ||||||||
| textOverflow: 'ellipsis', | ||||||||
| whiteSpace: 'nowrap', | ||||||||
| }, | ||||||||
| navPath: { | ||||||||
| color: tokens.colorNeutralForeground4, | ||||||||
| overflow: 'hidden', | ||||||||
| textOverflow: 'ellipsis', | ||||||||
| whiteSpace: 'nowrap', | ||||||||
| }, | ||||||||
| contentArea: { | ||||||||
| flex: 1, | ||||||||
| minWidth: 0, | ||||||||
| minHeight: 0, | ||||||||
| display: 'flex', | ||||||||
| flexDirection: 'column', | ||||||||
| }, | ||||||||
| content: { | ||||||||
| width: '100%', | ||||||||
| flex: 1, | ||||||||
| minWidth: 0, | ||||||||
| minHeight: 0, | ||||||||
| padding: `${tokens.spacingVerticalL} ${tokens.spacingHorizontalXL}`, | ||||||||
| '@media (max-width: 768px)': { | ||||||||
| padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalL}`, | ||||||||
| }, | ||||||||
| '@media (max-width: 480px)': { | ||||||||
| padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalM}`, | ||||||||
| }, | ||||||||
| }, | ||||||||
| contentInner: { | ||||||||
| width: '100%', | ||||||||
| maxWidth: '1400px', | ||||||||
| margin: '0 auto', | ||||||||
| }, | ||||||||
|
|
@@ -77,8 +222,24 @@ export default function App() { | |||||||
| const styles = useStyles() | ||||||||
| const location = useLocation() | ||||||||
| const navigate = useNavigate() | ||||||||
| const [isNavCollapsed, setIsNavCollapsed] = useState(false) | ||||||||
|
|
||||||||
| const [menuAgents, setMenuAgents] = useState([]) | ||||||||
| useEffect(() => { | ||||||||
| const storedValue = window.localStorage.getItem(NAV_COLLAPSED_STORAGE_KEY) | ||||||||
| if (storedValue !== null) { | ||||||||
| setIsNavCollapsed(storedValue === 'true') | ||||||||
| return | ||||||||
| } | ||||||||
| if (window.innerWidth <= 1024) { | ||||||||
| setIsNavCollapsed(true) | ||||||||
| } | ||||||||
| }, []) | ||||||||
|
|
||||||||
| useEffect(() => { | ||||||||
| window.localStorage.setItem(NAV_COLLAPSED_STORAGE_KEY, String(isNavCollapsed)) | ||||||||
| }, [isNavCollapsed]) | ||||||||
|
|
||||||||
| useEffect(() => { | ||||||||
| listWorkbenchAgents() | ||||||||
| .then((data) => { | ||||||||
|
|
@@ -136,63 +297,105 @@ export default function App() { | |||||||
| ?? allTabs.find((tab) => location.pathname.startsWith(tab.path))?.value | ||||||||
| ?? 'csvtickets' | ||||||||
|
|
||||||||
| const mainNavTabs = navTabs.filter((tab) => tab.value !== 'settings') | ||||||||
|
|
||||||||
| const renderNavButton = (tab) => { | ||||||||
| const isActive = activeTab === tab.value | ||||||||
| return ( | ||||||||
| <button | ||||||||
| key={tab.value} | ||||||||
| type="button" | ||||||||
| className={`${styles.navButton} ${isNavCollapsed ? styles.navButtonCollapsed : ''} ${isActive ? styles.navButtonActive : ''}`} | ||||||||
| onClick={() => navigate(tab.path)} | ||||||||
| data-testid={tab.testId} | ||||||||
| aria-label={tab.label} | ||||||||
|
||||||||
| aria-label={tab.label} | |
| aria-label={tab.label} | |
| aria-current={isActive ? 'page' : undefined} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import blocks have inconsistent indentation (mix of 2 and 4 spaces) which hurts readability and is likely accidental. Please run the repo formatter (or manually normalize indentation) so the import list is consistently aligned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot apply changes based on this feedback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in f72dd03 — normalized all import indentation in
App.jsxto consistent 2-space style (also alphabetically sortedSubtitle1/Subtitle2while at it).