Nav based file select

This commit is contained in:
Reece
2025-10-10 15:57:41 +01:00
parent 5d3710260f
commit 8e8e06628e
7 changed files with 146 additions and 118 deletions
@@ -0,0 +1,78 @@
import React from 'react';
import { Menu, Loader, Group, Text } from '@mantine/core';
import VisibilityIcon from '@mui/icons-material/Visibility';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
interface FileDropdownMenuProps {
displayName: string;
activeFiles: Array<{ fileId: string; name: string; versionNumber?: number }>;
currentFileIndex: number;
onFileSelect?: (index: number) => void;
switchingTo?: string | null;
viewOptionStyle: React.CSSProperties;
pillRef?: React.RefObject<HTMLDivElement>;
}
export const FileDropdownMenu: React.FC<FileDropdownMenuProps> = ({
displayName,
activeFiles,
currentFileIndex,
onFileSelect,
switchingTo,
viewOptionStyle,
}) => {
return (
<Menu trigger="click" position="bottom" width="30rem">
<Menu.Target>
<div style={{...viewOptionStyle, cursor: 'pointer'} as React.CSSProperties}>
{switchingTo === "viewer" ? (
<Loader size="xs" />
) : (
<VisibilityIcon fontSize="small" />
)}
<span>{displayName}</span>
<KeyboardArrowDownIcon fontSize="small" />
</div>
</Menu.Target>
<Menu.Dropdown style={{
backgroundColor: 'var(--right-rail-bg)',
border: '1px solid var(--border-subtle)',
borderRadius: '8px',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
maxHeight: '50vh',
overflowY: 'auto'
}}>
{activeFiles.map((file, index) => {
const itemName = file?.name || 'Untitled';
const itemDisplayName = itemName.length > 50 ? `${itemName.substring(0, 50)}...` : itemName;
const isActive = index === currentFileIndex;
return (
<Menu.Item
key={file.fileId}
onClick={(e) => {
e.stopPropagation();
onFileSelect?.(index);
}}
className="viewer-file-tab"
{...(isActive && { 'data-active': true })}
style={{
justifyContent: 'flex-start',
}}
>
<Group gap="xs" style={{ width: '100%', justifyContent: 'space-between' }}>
<Text size="sm" style={{ flex: 1, textAlign: 'left' }}>
{itemDisplayName}
</Text>
{file.versionNumber && file.versionNumber > 1 && (
<Text size="xs" c="dimmed">
v{file.versionNumber}
</Text>
)}
</Group>
</Menu.Item>
);
})}
</Menu.Dropdown>
</Menu>
);
};
+36 -5
View File
@@ -6,6 +6,7 @@ import VisibilityIcon from "@mui/icons-material/Visibility";
import EditNoteIcon from "@mui/icons-material/EditNote";
import FolderIcon from "@mui/icons-material/Folder";
import { WorkbenchType, isValidWorkbench } from '../../types/workbench';
import { FileDropdownMenu } from './FileDropdownMenu';
const viewOptionStyle = {
@@ -19,16 +20,40 @@ const viewOptionStyle = {
// Build view options showing text always
const createViewOptions = (currentView: WorkbenchType, switchingTo: WorkbenchType | null) => {
const createViewOptions = (
currentView: WorkbenchType,
switchingTo: WorkbenchType | null,
activeFiles: Array<{ fileId: string; name: string; versionNumber?: number }>,
currentFileIndex: number,
onFileSelect?: (index: number) => void
) => {
const currentFile = activeFiles[currentFileIndex];
const isInViewer = currentView === 'viewer';
const fileName = currentFile?.name || '';
const displayName = isInViewer && fileName
? (fileName.length > 30 ? `${fileName.substring(0, 30)}...` : fileName)
: 'Viewer';
const hasMultipleFiles = activeFiles.length > 1;
const showDropdown = isInViewer && hasMultipleFiles;
const viewerOption = {
label: (
label: showDropdown ? (
<FileDropdownMenu
displayName={displayName}
activeFiles={activeFiles}
currentFileIndex={currentFileIndex}
onFileSelect={onFileSelect}
switchingTo={switchingTo}
viewOptionStyle={viewOptionStyle}
/>
) : (
<div style={viewOptionStyle as React.CSSProperties}>
{switchingTo === "viewer" ? (
<Loader size="xs" />
) : (
<VisibilityIcon fontSize="small" />
)}
<span>Viewer</span>
<span>{displayName}</span>
</div>
),
value: "viewer",
@@ -83,12 +108,18 @@ const createViewOptions = (currentView: WorkbenchType, switchingTo: WorkbenchTyp
interface TopControlsProps {
currentView: WorkbenchType;
setCurrentView: (view: WorkbenchType) => void;
activeFiles?: Array<{ fileId: string; name: string; versionNumber?: number }>;
currentFileIndex?: number;
onFileSelect?: (index: number) => void;
}
const TopControls = ({
currentView,
setCurrentView,
}: TopControlsProps) => {
activeFiles = [],
currentFileIndex = 0,
onFileSelect,
}: TopControlsProps) => {
const { isRainbowMode } = useRainbowThemeContext();
const [switchingTo, setSwitchingTo] = useState<WorkbenchType | null>(null);
@@ -118,7 +149,7 @@ const TopControls = ({
<div className="absolute left-0 w-full top-0 z-[100] pointer-events-none">
<div className="flex justify-center mt-[0.5rem]">
<SegmentedControl
data={createViewOptions(currentView, switchingTo)}
data={createViewOptions(currentView, switchingTo, activeFiles, currentFileIndex, onFileSelect)}
value={currentView}
onChange={handleViewChange}
color="blue"