feat: workspace tabs as side-by-side segmented control in sidebar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -147,7 +147,6 @@ const SIDEBAR_BG = '#0f1923'
|
|||||||
const DIVIDER_COLOR = 'rgba(255,255,255,0.08)'
|
const DIVIDER_COLOR = 'rgba(255,255,255,0.08)'
|
||||||
const TEXT_MUTED = '#94a3b8'
|
const TEXT_MUTED = '#94a3b8'
|
||||||
const TEXT_WHITE = '#ffffff'
|
const TEXT_WHITE = '#ffffff'
|
||||||
const ACTIVE_BG = 'rgba(255,255,255,0.1)'
|
|
||||||
const NAV_ACTIVE_BG = 'rgba(255,255,255,0.12)'
|
const NAV_ACTIVE_BG = 'rgba(255,255,255,0.12)'
|
||||||
const NAV_HOVER_BG = 'rgba(255,255,255,0.06)'
|
const NAV_HOVER_BG = 'rgba(255,255,255,0.06)'
|
||||||
|
|
||||||
@@ -173,7 +172,7 @@ function Sidebar({
|
|||||||
orgName,
|
orgName,
|
||||||
}: SidebarProps) {
|
}: SidebarProps) {
|
||||||
const config = WORKSPACE_CONFIG[activeWorkspace]
|
const config = WORKSPACE_CONFIG[activeWorkspace]
|
||||||
const width = collapsed ? 60 : 240
|
const width = collapsed ? 60 : 264
|
||||||
const visibleWorkspaces = WORKSPACE_ORDER.filter((ws) => allowedWorkspaces.includes(ws))
|
const visibleWorkspaces = WORKSPACE_ORDER.filter((ws) => allowedWorkspaces.includes(ws))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -234,16 +233,16 @@ function Sidebar({
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Workspace tabs */}
|
{/* Workspace tabs — side-by-side segmented control */}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
borderBottom: `1px solid ${DIVIDER_COLOR}`,
|
borderBottom: `1px solid ${DIVIDER_COLOR}`,
|
||||||
py: 0.5,
|
display: 'grid',
|
||||||
px: 0.5,
|
gridTemplateColumns: collapsed ? '1fr' : `repeat(${visibleWorkspaces.length}, 1fr)`,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{visibleWorkspaces.map((ws) => {
|
{visibleWorkspaces.map((ws, idx) => {
|
||||||
const wsConfig = WORKSPACE_CONFIG[ws]
|
const wsConfig = WORKSPACE_CONFIG[ws]
|
||||||
const Icon = wsConfig.icon
|
const Icon = wsConfig.icon
|
||||||
const isActive = ws === activeWorkspace
|
const isActive = ws === activeWorkspace
|
||||||
@@ -253,29 +252,32 @@ function Sidebar({
|
|||||||
onClick={() => { onWorkspaceClick(ws); onClose?.() }}
|
onClick={() => { onWorkspaceClick(ws); onClose?.() }}
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
flexDirection: collapsed ? 'row' : 'column',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 1.25,
|
justifyContent: 'center',
|
||||||
px: collapsed ? 0 : 1.5,
|
gap: collapsed ? 0 : 0.5,
|
||||||
py: 0.75,
|
py: collapsed ? 1 : 1.25,
|
||||||
borderRadius: 1,
|
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
justifyContent: collapsed ? 'center' : 'flex-start',
|
backgroundColor: isActive ? wsConfig.chipColor : 'transparent',
|
||||||
backgroundColor: isActive ? ACTIVE_BG : 'transparent',
|
borderRight: !collapsed && idx < visibleWorkspaces.length - 1
|
||||||
'&:hover': {
|
? `1px solid ${DIVIDER_COLOR}`
|
||||||
backgroundColor: isActive ? ACTIVE_BG : NAV_HOVER_BG,
|
: 'none',
|
||||||
},
|
|
||||||
transition: 'background-color 0.15s ease',
|
transition: 'background-color 0.15s ease',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: isActive ? wsConfig.chipColor : NAV_HOVER_BG,
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon size={16} color={isActive ? TEXT_WHITE : TEXT_MUTED} />
|
<Icon size={15} color={isActive ? TEXT_WHITE : TEXT_MUTED} />
|
||||||
{!collapsed && (
|
{!collapsed && (
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="caption"
|
||||||
sx={{
|
sx={{
|
||||||
color: isActive ? TEXT_WHITE : TEXT_MUTED,
|
color: isActive ? TEXT_WHITE : TEXT_MUTED,
|
||||||
fontWeight: isActive ? 600 : 400,
|
fontWeight: isActive ? 700 : 400,
|
||||||
fontSize: '0.8125rem',
|
fontSize: '0.6875rem',
|
||||||
whiteSpace: 'nowrap',
|
lineHeight: 1,
|
||||||
|
letterSpacing: 0.2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{wsConfig.label}
|
{wsConfig.label}
|
||||||
@@ -557,7 +559,7 @@ export function AppShell() {
|
|||||||
onClose={() => setMobileOpen(false)}
|
onClose={() => setMobileOpen(false)}
|
||||||
variant="temporary"
|
variant="temporary"
|
||||||
ModalProps={{ keepMounted: true }}
|
ModalProps={{ keepMounted: true }}
|
||||||
slotProps={{ paper: { sx: { width: 240, bgcolor: 'transparent', boxShadow: 'none' } } }}
|
slotProps={{ paper: { sx: { width: 264, bgcolor: 'transparent', boxShadow: 'none' } } }}
|
||||||
>
|
>
|
||||||
{sidebarContent}
|
{sidebarContent}
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|||||||
Reference in New Issue
Block a user