summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/panels/panel-base-view.tsx
diff options
context:
space:
mode:
authorMaze <167211895+mazeincoding@users.noreply.github.com>2026-01-31 00:20:04 +0100
committerGitHub <noreply@github.com>2026-01-31 00:20:04 +0100
commit7bf0984698e43b9aa2dd879f65951318ed410390 (patch)
treeccf2cd590a47d550152afc07129cb55c71a9ec35 /apps/web/src/components/editor/panels/panel-base-view.tsx
parent0173db99448d1c4c6415dcf15272e17551b48b04 (diff)
downloadopencut-7bf0984698e43b9aa2dd879f65951318ed410390.tar.gz
codebase overhaul (#697)
Diffstat (limited to 'apps/web/src/components/editor/panels/panel-base-view.tsx')
-rw-r--r--apps/web/src/components/editor/panels/panel-base-view.tsx85
1 files changed, 85 insertions, 0 deletions
diff --git a/apps/web/src/components/editor/panels/panel-base-view.tsx b/apps/web/src/components/editor/panels/panel-base-view.tsx
new file mode 100644
index 00000000..b16d1db6
--- /dev/null
+++ b/apps/web/src/components/editor/panels/panel-base-view.tsx
@@ -0,0 +1,85 @@
+import { ScrollArea } from "@/components/ui/scroll-area";
+import { Separator } from "@/components/ui/separator";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+import { cn } from "@/utils/ui";
+
+interface PanelBaseViewProps {
+ children?: React.ReactNode;
+ defaultTab?: string;
+ value?: string;
+ onValueChange?: (value: string) => void;
+ tabs?: {
+ value: string;
+ label: string;
+ icon?: React.ReactNode;
+ content: React.ReactNode;
+ }[];
+ className?: string;
+ ref?: React.RefObject<HTMLDivElement>;
+}
+
+function ViewContent({
+ children,
+ className,
+}: {
+ children: React.ReactNode;
+ className?: string;
+}) {
+ return (
+ <ScrollArea className="flex-1">
+ <div className={cn("p-5", className)}>{children}</div>
+ </ScrollArea>
+ );
+}
+
+export function PanelBaseView({
+ children,
+ defaultTab,
+ value,
+ onValueChange,
+ tabs,
+ className = "",
+ ref,
+}: PanelBaseViewProps) {
+ return (
+ <div className={cn("flex h-full flex-col", className)} ref={ref}>
+ {!tabs || tabs.length === 0 ? (
+ <ViewContent className={className}>{children}</ViewContent>
+ ) : (
+ <Tabs
+ defaultValue={defaultTab}
+ value={value}
+ onValueChange={onValueChange}
+ className="flex h-full flex-col"
+ >
+ <div className="bg-panel sticky top-0 z-10">
+ <div className="px-3 pt-3 pb-0">
+ <TabsList>
+ {tabs.map((tab) => (
+ <TabsTrigger key={tab.value} value={tab.value}>
+ {tab.icon ? (
+ <span className="mr-1 inline-flex items-center">
+ {tab.icon}
+ </span>
+ ) : null}
+ {tab.label}
+ </TabsTrigger>
+ ))}
+ </TabsList>
+ </div>
+ <Separator className="mt-3" />
+ </div>
+ {tabs.map((tab) => (
+ <TabsContent
+ key={tab.value}
+ value={tab.value}
+ className="mt-0 flex min-h-0 flex-1 flex-col"
+ >
+ <ViewContent className={className}>{tab.content}</ViewContent>
+ </TabsContent>
+ ))}
+ </Tabs>
+ )}
+ </div>
+ );
+}