diff --git a/apps/web/client/src/app/project/[id]/_components/left-panel/design-panel/index.tsx b/apps/web/client/src/app/project/[id]/_components/left-panel/design-panel/index.tsx index 2ca8c8973c..f70ff96b0f 100644 --- a/apps/web/client/src/app/project/[id]/_components/left-panel/design-panel/index.tsx +++ b/apps/web/client/src/app/project/[id]/_components/left-panel/design-panel/index.tsx @@ -1,10 +1,13 @@ -import { useEditorEngine } from '@/components/store/editor'; -import { transKeys } from '@/i18n/keys'; +import { observer } from 'mobx-react-lite'; +import { useTranslations } from 'next-intl'; + import { LeftPanelTabValue } from '@onlook/models'; +import { Button } from '@onlook/ui/button'; import { Icons } from '@onlook/ui/icons'; import { cn } from '@onlook/ui/utils'; -import { observer } from 'mobx-react-lite'; -import { useTranslations } from 'next-intl'; + +import { useEditorEngine } from '@/components/store/editor'; +import { transKeys } from '@/i18n/keys'; import { BranchesTab } from './branches-tab'; import { BrandTab } from './brand-tab'; import { HelpButton } from './help-button'; @@ -16,38 +19,41 @@ import { ZoomControls } from './zoom-controls'; const tabs: { value: LeftPanelTabValue; icon: React.ReactNode; - label: any, - disabled?: boolean -}[] = - [ - { - value: LeftPanelTabValue.LAYERS, - icon: , - label: transKeys.editor.panels.layers.tabs.layers, - }, - { - value: LeftPanelTabValue.BRAND, - icon: , - label: transKeys.editor.panels.layers.tabs.brand, - }, - { - value: LeftPanelTabValue.PAGES, - icon: , - label: transKeys.editor.panels.layers.tabs.pages, - }, - { - value: LeftPanelTabValue.IMAGES, - icon: , - label: transKeys.editor.panels.layers.tabs.images, - }, - { - value: LeftPanelTabValue.BRANCHES, - icon: , - label: transKeys.editor.panels.layers.tabs.branches, - }, - ]; + label: any; + disabled?: boolean; +}[] = [ + { + value: LeftPanelTabValue.LAYERS, + icon: , + label: transKeys.editor.panels.layers.tabs.layers, + }, + { + value: LeftPanelTabValue.BRAND, + icon: , + label: transKeys.editor.panels.layers.tabs.brand, + }, + { + value: LeftPanelTabValue.PAGES, + icon: , + label: transKeys.editor.panels.layers.tabs.pages, + }, + { + value: LeftPanelTabValue.IMAGES, + icon: , + label: transKeys.editor.panels.layers.tabs.images, + }, + { + value: LeftPanelTabValue.BRANCHES, + icon: , + label: transKeys.editor.panels.layers.tabs.branches, + }, +]; + +interface DesignPanelProps { + onClose?: () => void; +} -export const DesignPanel = observer(() => { +export const DesignPanel = observer(({ onClose }: DesignPanelProps) => { const editorEngine = useEditorEngine(); const t = useTranslations(); const isLocked = editorEngine.state.leftPanelLocked; @@ -98,21 +104,19 @@ export const DesignPanel = observer(() => { }; return ( -
+
{/* Left sidebar with tabs */} -
+
{tabs.map((tab) => ( ))} -
+
@@ -132,8 +136,18 @@ export const DesignPanel = observer(() => { {/* Content panel */} {editorEngine.state.leftPanelTab && ( <> -
-
+
+
+ {onClose && ( + + )} {selectedTab === LeftPanelTabValue.LAYERS && } {selectedTab === LeftPanelTabValue.BRAND && } {selectedTab === LeftPanelTabValue.PAGES && } @@ -143,7 +157,7 @@ export const DesignPanel = observer(() => {
{/* Invisible padding area that maintains hover state */} - {!isLocked &&
} + {!isLocked &&
} )}
diff --git a/apps/web/client/src/app/project/[id]/_components/left-panel/index.tsx b/apps/web/client/src/app/project/[id]/_components/left-panel/index.tsx index dc8fc0e5b6..3390764c0c 100644 --- a/apps/web/client/src/app/project/[id]/_components/left-panel/index.tsx +++ b/apps/web/client/src/app/project/[id]/_components/left-panel/index.tsx @@ -1,18 +1,38 @@ -import { useEditorEngine } from "@/components/store/editor"; -import { EditorMode } from "@onlook/models"; -import { cn } from "@onlook/ui/utils"; -import { observer } from "mobx-react-lite"; -import { CodePanel } from "./code-panel"; -import { DesignPanel } from "./design-panel"; +import { observer } from 'mobx-react-lite'; -export const LeftPanel = observer(() => { +import { EditorMode } from '@onlook/models'; +import { cn } from '@onlook/ui/utils'; + +import { useEditorEngine } from '@/components/store/editor'; +import { CodePanel } from './code-panel'; +import { DesignPanel } from './design-panel'; + +interface LeftPanelProps { + onClose?: () => void; +} + +export const LeftPanel = observer(({ onClose }: LeftPanelProps) => { const editorEngine = useEditorEngine(); - return <> -
- -
-
- -
- ; -}); \ No newline at end of file + return ( + <> +
+ +
+
+ +
+ + ); +}); diff --git a/apps/web/client/src/app/project/[id]/_components/main.tsx b/apps/web/client/src/app/project/[id]/_components/main.tsx index 4109496d6f..ff0547682f 100644 --- a/apps/web/client/src/app/project/[id]/_components/main.tsx +++ b/apps/web/client/src/app/project/[id]/_components/main.tsx @@ -1,17 +1,29 @@ 'use client'; -import { useEditorEngine } from '@/components/store/editor'; -import { SubscriptionModal } from '@/components/ui/pricing-modal'; -import { SettingsModalWithProjects } from '@/components/ui/settings-modal/with-project'; +import { useEffect, useRef } from 'react'; +import { useRouter } from 'next/navigation'; +import { observer } from 'mobx-react-lite'; + import { EditorAttributes } from '@onlook/constants'; -import { EditorMode } from '@onlook/models'; +import { EditorMode, LeftPanelTabValue } from '@onlook/models'; import { Button } from '@onlook/ui/button'; +import { + ContextMenu, + ContextMenuContent, + ContextMenuItem, + ContextMenuSeparator, + ContextMenuSub, + ContextMenuSubContent, + ContextMenuSubTrigger, + ContextMenuTrigger, +} from '@onlook/ui/context-menu'; import { Icons } from '@onlook/ui/icons'; import { TooltipProvider } from '@onlook/ui/tooltip'; import { cn } from '@onlook/ui/utils'; -import { observer } from 'mobx-react-lite'; -import { useRouter } from 'next/navigation'; -import { useEffect, useRef } from 'react'; + +import { useEditorEngine } from '@/components/store/editor'; +import { SubscriptionModal } from '@/components/ui/pricing-modal'; +import { SettingsModalWithProjects } from '@/components/ui/settings-modal/with-project'; import { usePanelMeasurements } from '../_hooks/use-panel-measure'; import { useStartProject } from '../_hooks/use-start-project'; import { BottomBar } from './bottom-bar'; @@ -32,15 +44,23 @@ export const Main = observer(() => { rightPanelRef, ); + const handleSidebarClick = (tab: LeftPanelTabValue) => { + editorEngine.state.leftPanelTab = tab; + editorEngine.state.leftPanelLocked = true; + }; + + const handleClosePanel = () => { + editorEngine.state.leftPanelTab = null; + editorEngine.state.leftPanelLocked = false; + }; + useEffect(() => { function handleGlobalWheel(event: WheelEvent) { if (!(event.ctrlKey || event.metaKey)) { return; } - const canvasContainer = document.getElementById( - EditorAttributes.CANVAS_CONTAINER_ID, - ); + const canvasContainer = document.getElementById(EditorAttributes.CANVAS_CONTAINER_ID); if (canvasContainer?.contains(event.target as Node | null)) { return; } @@ -56,14 +76,16 @@ export const Main = observer(() => { if (error) { return ( -
+
- +
Error starting project: {error}
-
@@ -72,8 +94,8 @@ export const Main = observer(() => { if (!isProjectReady) { return ( -
- +
+
Loading project...
); @@ -81,19 +103,78 @@ export const Main = observer(() => { return ( -
- +
+ + +
+ +
+
+ + + + Add Element + + + + Add Component + + + + + + Panels + + + handleSidebarClick(LeftPanelTabValue.LAYERS)} + > + Layers + + handleSidebarClick(LeftPanelTabValue.BRAND)} + > + Brand + + handleSidebarClick(LeftPanelTabValue.PAGES)} + > + Pages + + handleSidebarClick(LeftPanelTabValue.IMAGES)} + > + Images + + + handleSidebarClick(LeftPanelTabValue.BRANCHES)} + > + Branches + + + + + void editorEngine.copy.copy()}> + + Copy + ⌘ C + + void editorEngine.copy.paste()}> + + Paste + ⌘ V + + +
{/* Left Panel */} -
- +
+
{/* EditorBar anchored between panels */}
{
@@ -129,6 +210,6 @@ export const Main = observer(() => {
- + ); });