Files
HellreigN/frontend/src/modules/ide/components/TabBar.tsx
T
nikita f71a3b1a03
ci-front / build (push) Successful in 2m15s
feat: save files
2026-04-05 01:37:10 +03:00

208 lines
5.9 KiB
TypeScript

import React, { useState } from "react";
import { GoFile } from "react-icons/go";
import { MdClose } from "react-icons/md";
import type { FileNode } from "../types";
interface TabBarProps {
openFiles: FileNode[];
activeFile: FileNode | null;
onSelectFile: (file: FileNode) => void;
onCloseFile: (file: FileNode) => void;
onCloseAll: () => void;
onCloseOthers: (file: FileNode) => void;
}
export const TabBar: React.FC<TabBarProps> = ({
openFiles,
activeFile,
onSelectFile,
onCloseFile,
onCloseAll,
onCloseOthers,
}) => {
const [showContextMenu, setShowContextMenu] = useState<{
x: number;
y: number;
file: FileNode;
} | null>(null);
const handleContextMenu = (e: React.MouseEvent, file: FileNode) => {
e.preventDefault();
setShowContextMenu({ x: e.clientX, y: e.clientY, file });
};
return (
<>
<div
style={{
display: "flex",
alignItems: "center",
backgroundColor: "#1e1e1e",
borderBottom: "1px solid #3e3e42",
overflowX: "auto",
minHeight: "40px",
}}
>
<div
style={{
display: "flex",
padding: "0 12px",
gap: "8px",
borderRight: "1px solid #3e3e42",
height: "100%",
alignItems: "center",
}}
>
<button
onClick={onCloseAll}
style={{
background: "transparent",
border: "none",
color: "#cccccc",
cursor: "pointer",
fontSize: "14px",
padding: "6px 8px",
borderRadius: "4px",
display: "flex",
alignItems: "center",
gap: "6px",
transition: "all 0.1s",
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = "#2a2d2e";
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = "transparent";
}}
title="Close All"
>
<MdClose size={14} />
<span style={{ fontSize: "11px" }}>Close All</span>
</button>
</div>
{openFiles.map((file) => (
<div
key={file.path}
onClick={() => onSelectFile(file)}
onContextMenu={(e) => handleContextMenu(e, file)}
style={{
display: "flex",
alignItems: "center",
padding: "8px 16px",
backgroundColor:
activeFile?.path === file.path ? "#1e1e1e" : "#2d2d30",
color: activeFile?.path === file.path ? "#fff" : "#cccccc",
borderRight: "1px solid #3e3e42",
cursor: "pointer",
fontSize: "13px",
gap: "10px",
whiteSpace: "nowrap",
transition: "all 0.1s",
borderTop:
activeFile?.path === file.path
? "2px solid #0e639c"
: "2px solid transparent",
}}
>
<GoFile />
<span>{file.name}</span>
{file.dirty && (
<span
style={{
width: "8px",
height: "8px",
borderRadius: "50%",
backgroundColor: "#fbbf24",
marginLeft: "-4px",
}}
/>
)}
<button
onClick={(e) => {
e.stopPropagation();
onCloseFile(file);
}}
style={{
background: "none",
border: "none",
color: "#858585",
cursor: "pointer",
fontSize: "16px",
padding: "0 4px",
borderRadius: "4px",
}}
onMouseEnter={(e) => {
e.currentTarget.style.color = "#fff";
e.currentTarget.style.backgroundColor = "#3e3e42";
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = "#858585";
e.currentTarget.style.backgroundColor = "transparent";
}}
>
<MdClose size={14} />
</button>
</div>
))}
</div>
{showContextMenu && (
<div
style={{
position: "fixed",
top: showContextMenu.y,
left: showContextMenu.x,
backgroundColor: "#252526",
border: "1px solid #3e3e42",
borderRadius: "6px",
boxShadow: "0 4px 12px rgba(0,0,0,0.4)",
zIndex: 1000,
minWidth: "160px",
overflow: "hidden",
}}
>
<div
onClick={() => {
onCloseOthers(showContextMenu.file);
setShowContextMenu(null);
}}
style={{
padding: "8px 16px",
cursor: "pointer",
color: "#cccccc",
fontSize: "13px",
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = "#2a2d2e";
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = "transparent";
}}
>
Close Others
</div>
<div
onClick={() => {
onCloseAll();
setShowContextMenu(null);
}}
style={{
padding: "8px 16px",
cursor: "pointer",
color: "#cccccc",
fontSize: "13px",
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = "#2a2d2e";
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = "transparent";
}}
>
Close All
</div>
</div>
)}
</>
);
};