refactor(frontend): conversation tab content component (#10956)

This commit is contained in:
Hiep Le 2025-09-15 20:56:38 +07:00 committed by GitHub
parent e74bbd81d1
commit d664f516db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 79 additions and 68 deletions

View File

@ -2,7 +2,7 @@ import { useSelector } from "react-redux";
import { useWindowSize } from "@uidotdev/usehooks";
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
import { ChatInterface } from "../chat/chat-interface";
import { ConversationTabContent } from "./conversation-tabs/conversation-tab-content";
import { ConversationTabContent } from "./conversation-tabs/conversation-tab-content/conversation-tab-content";
import { cn } from "#/utils/utils";
import { RootState } from "#/store";

View File

@ -1,12 +1,14 @@
import { lazy, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import { cn } from "#/utils/utils";
import { RootState } from "#/store";
import { ConversationLoading } from "../conversation-loading";
import Terminal from "../../terminal/terminal";
import { ConversationTabTitle } from "./conversation-tab-title";
import { ConversationLoading } from "../../conversation-loading";
import { I18nKey } from "#/i18n/declaration";
import { TabWrapper } from "./tab-wrapper";
import { TabContainer } from "./tab-container";
import { TabContentArea } from "./tab-content-area";
import { ConversationTabTitle } from "../conversation-tab-title";
import Terminal from "#/components/features/terminal/terminal";
// Lazy load all tab components
const EditorTab = lazy(() => import("#/routes/changes-tab"));
@ -33,6 +35,28 @@ export function ConversationTabContent() {
const isVSCodeActive = selectedTab === "vscode";
const isTerminalActive = selectedTab === "terminal";
// Define tab configurations
const tabs = [
{ key: "editor", component: EditorTab, isActive: isEditorActive },
{
key: "browser",
component: BrowserTab,
isActive: isBrowserActive,
},
{
key: "jupyter",
component: JupyterTab,
isActive: isJupyterActive,
},
{ key: "served", component: ServedTab, isActive: isServedActive },
{ key: "vscode", component: VSCodeTab, isActive: isVSCodeActive },
{
key: "terminal",
component: Terminal,
isActive: isTerminalActive,
},
];
const conversationTabTitle = useMemo(() => {
if (isEditorActive) {
return t(I18nKey.COMMON$CHANGES);
@ -67,69 +91,15 @@ export function ConversationTabContent() {
}
return (
<div
className={cn(
"bg-[#25272D] border border-[#525252] rounded-xl flex flex-col h-full w-full",
"h-full w-full",
)}
>
<TabContainer>
<ConversationTabTitle title={conversationTabTitle} />
<div className="overflow-hidden flex-grow rounded-b-xl">
<div className="h-full w-full">
<div className="h-full w-full relative">
{/* Each tab content is always loaded but only visible when active */}
<div
className={cn(
"absolute inset-0",
isEditorActive ? "block" : "hidden",
)}
>
<EditorTab />
</div>
<div
className={cn(
"absolute inset-0",
isBrowserActive ? "block" : "hidden",
)}
>
<BrowserTab />
</div>
<div
className={cn(
"absolute inset-0",
isJupyterActive ? "block" : "hidden",
)}
>
<JupyterTab />
</div>
<div
className={cn(
"absolute inset-0",
isServedActive ? "block" : "hidden",
)}
>
<ServedTab />
</div>
<div
className={cn(
"absolute inset-0",
isVSCodeActive ? "block" : "hidden",
)}
>
<VSCodeTab />
</div>
<div
className={cn(
"absolute inset-0",
isTerminalActive ? "block" : "hidden",
)}
>
<Terminal />
</div>
</div>
</div>
</div>
</div>
<TabContentArea>
{tabs.map(({ key, component: Component, isActive }) => (
<TabWrapper key={key} isActive={isActive}>
<Component />
</TabWrapper>
))}
</TabContentArea>
</TabContainer>
);
}

View File

@ -0,0 +1,13 @@
import { ReactNode } from "react";
interface TabContainerProps {
children: ReactNode;
}
export function TabContainer({ children }: TabContainerProps) {
return (
<div className="bg-[#25272D] border border-[#525252] rounded-xl flex flex-col h-full w-full">
{children}
</div>
);
}

View File

@ -0,0 +1,13 @@
import { ReactNode } from "react";
interface TabContentAreaProps {
children: ReactNode;
}
export function TabContentArea({ children }: TabContentAreaProps) {
return (
<div className="overflow-hidden flex-grow rounded-b-xl h-full w-full relative">
{children}
</div>
);
}

View File

@ -0,0 +1,15 @@
import { ReactNode } from "react";
import { cn } from "#/utils/utils";
interface TabWrapperProps {
isActive: boolean;
children: ReactNode;
}
export function TabWrapper({ isActive, children }: TabWrapperProps) {
return (
<div className={cn("absolute inset-0", isActive ? "block" : "hidden")}>
{children}
</div>
);
}