Files
rainblogweb/frontend/src/tools/workbench/components/SidebarPane.jsx
T

71 lines
2.7 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
/* ============================================================
* SidebarPaneVSCode 风格侧边栏容器(一侧一个)
*
* - 该侧全部 sidebar 模式视图**常驻挂载**display 显隐切换),
* 切换视图/切标签页不丢编辑状态(记事本草稿、密码箱解锁态)
* - 每个视图由 ToolWindow 提供标题栏;内容按 activeView 显示
* - 视图处于 tab 模式时该视图不在侧栏 → 显示占位 + 「移回侧边栏」
* - 无障碍:容器 id=wb-sidebar-{side} 供活动栏 aria-controls
* aria-live 播报当前视图,配合活动栏焦点提示
* ============================================================ */
export default function SidebarPane({ side, views, activeId, renderView, renderPlaceholder }) {
const right = side === 'right';
const activeView = views.find((v) => v.id === activeId);
return (
<Box
component="aside"
id={`wb-sidebar-${side}`}
aria-label={right ? '右侧侧边栏' : '左侧侧边栏'}
sx={{
height: '100%', minWidth: 0, overflow: 'hidden', position: 'relative',
display: 'flex', flexDirection: 'column',
bgcolor: 'background.paper',
}}
>
{/* 活动栏激活后的屏幕阅读器播报(视觉隐藏) */}
<Box
aria-live="polite"
sx={{
position: 'absolute', width: 1, height: 1, overflow: 'hidden',
clip: 'rect(0 0 0 0)', whiteSpace: 'nowrap', m: -1, p: 0, border: 0,
}}
>
{activeView ? `当前视图:${activeView.label}` : '侧边栏为空'}
</Box>
{views.map((v) => {
const active = activeId === v.id;
return (
<Box
key={v.id}
sx={{
flex: 1, minHeight: 0, display: active ? 'flex' : 'none',
flexDirection: 'column',
}}
>
{renderView(v.id)}
</Box>
);
})}
{views.length === 0 && (
<Box sx={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', px: 3, textAlign: 'center' }}>
<Typography variant="caption" sx={{ color: 'text.disabled' }}>
从另一侧活动栏拖一个功能标签到这里
</Typography>
</Box>
)}
{views.length > 0 && !views.some((v) => v.id === activeId) && renderPlaceholder && (
<Box sx={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 1, px: 3, textAlign: 'center' }}>
{renderPlaceholder()}
</Box>
)}
</Box>
);
}