feat: add resizable inner sidebar (#21548)

* init

* update import names

* Update resizable.tsx

* resizable bg now goes lighter on drag

* only resizable for table editor and sql editor

* Update ProjectLayout.tsx

* Update index.tsx

* Remove unneeded console.log.

---------

Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
This commit is contained in:
Jonathan Summers-MuirandIvan Vasilov authored and GitHub committed 2024-02-26 18:50:44 +08:00
1 parent 7c7b10d83d
commit e1bbdd0ca7
7 files changed
+72 -44

No files matched your search

@@ -8,7 +8,7 @@ const ProductMenuBar = ({ title, children }: PropsWithChildren<ProductMenuBarPro
return (
<div
className={[
'hide-scrollbar flex w-64 flex-col border-r', // Layout
'hide-scrollbar flex flex-col w-full h-full', // Layout
'bg-studio',
'border-default ',
].join(' ')}
@@ -23,6 +23,7 @@ import { ProjectContextProvider } from './ProjectContext'
import ProjectPausedState from './ProjectPausedState'
import RestoringState from './RestoringState'
import UpgradingState from './UpgradingState'
import { ResizableHandle, ResizablePanelGroup, ResizablePanel, cn } from 'ui'
// [Joshen] This is temporary while we unblock users from managing their project
// if their project is not responding well for any reason. Eventually needs a bit of an overhaul
@@ -57,6 +58,7 @@ export interface ProjectLayoutProps {
hideHeader?: boolean
hideIconBar?: boolean
selectedTable?: string
resizableSidebar?: boolean
}
const ProjectLayout = ({
@@ -69,6 +71,7 @@ const ProjectLayout = ({
hideHeader = false,
hideIconBar = false,
selectedTable,
resizableSidebar = false,
}: PropsWithChildren<ProjectLayoutProps>) => {
const router = useRouter()
const { ref: projectRef } = useParams()
@@ -105,26 +108,46 @@ const ProjectLayout = ({
{/* Left-most navigation side bar to access products */}
{!hideIconBar && <NavigationBar />}
{/* Product menu bar */}
{!showPausedState && (
<MenuBarWrapper isLoading={isLoading} isBlocking={isBlocking} productMenu={productMenu}>
<ProductMenuBar title={product}>{productMenu}</ProductMenuBar>
</MenuBarWrapper>
)}
<main className="flex flex-col flex-1 w-full overflow-x-hidden">
{!navLayoutV2 && !hideHeader && IS_PLATFORM && <LayoutHeader />}
{showPausedState ? (
<div className="mx-auto my-16 w-full h-full max-w-7xl flex items-center">
<div className="w-full">
<ProjectPausedState product={product} />
</div>
</div>
) : (
<ContentWrapper isLoading={isLoading} isBlocking={isBlocking}>
<ResourceExhaustionWarningBanner />
{children}
</ContentWrapper>
<ResizablePanelGroup
className="flex h-full"
direction="horizontal"
autoSaveId="project-layout"
>
{!showPausedState && productMenu && (
<>
<ResizablePanel
className={cn(resizableSidebar ? 'min-w-64 max-w-[32rem]' : 'min-w-64 max-w-64')}
defaultSize={1} // forces panel to smallest width possible, at w-64
>
<MenuBarWrapper
isLoading={isLoading}
isBlocking={isBlocking}
productMenu={productMenu}
>
<ProductMenuBar title={product}>{productMenu}</ProductMenuBar>
</MenuBarWrapper>
</ResizablePanel>
<ResizableHandle withHandle disabled={resizableSidebar ? false : true} />
</>
)}
</main>
<ResizablePanel className="h-full">
<main className="h-full flex flex-col flex-1 w-full overflow-x-hidden">
{!navLayoutV2 && !hideHeader && IS_PLATFORM && <LayoutHeader />}
{showPausedState ? (
<div className="mx-auto my-16 w-full h-full max-w-7xl flex items-center">
<div className="w-full">
<ProjectPausedState product={product} />
</div>
</div>
) : (
<ContentWrapper isLoading={isLoading} isBlocking={isBlocking}>
<ResourceExhaustionWarningBanner />
{children}
</ContentWrapper>
)}
</main>
</ResizablePanel>
</ResizablePanelGroup>
</div>
<EnableBranchingModal />
@@ -17,6 +17,7 @@ const SQLEditorLayout = ({ title, children }: SQLEditorLayoutProps) => {
product="SQL Editor"
productMenu={productMenu}
isBlocking={false}
resizableSidebar
>
{children}
</ProjectLayout>
@@ -23,7 +23,12 @@ const TableEditorLayout = ({ children }: PropsWithChildren<{}>) => {
}
return (
<ProjectLayoutWithAuth product="Table Editor" productMenu={tableEditorMenu} isBlocking={false}>
<ProjectLayoutWithAuth
product="Table Editor"
productMenu={tableEditorMenu}
isBlocking={false}
resizableSidebar
>
{children}
</ProjectLayoutWithAuth>
)
+4 -20
View File
@@ -838,7 +838,6 @@
"react-intersection-observer": "^9.5.3",
"react-markdown": "^8.0.3",
"react-simple-maps": "4.0.0-beta.6",
"react-split": "^2.0.13",
"react-tracked": "^1.7.11",
"react-virtualized-auto-sizer": "^1.0.20",
"react-window": "^1.8.6",
@@ -30237,9 +30236,9 @@
}
},
"node_modules/react-resizable-panels": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.0.9.tgz",
"integrity": "sha512-ZylBvs7oG7Y/INWw3oYGolqgpFvoPW8MPeg9l1fURDeKpxrmUuCHBUmPj47BdZ11MODImu3kZYXG85rbySab7w==",
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.0.11.tgz",
"integrity": "sha512-tA3OvGFEK/U9rKuEg6TpXcr+i+cN5X8B4UIvs7jqr5lby629pDTGvqRjo1EJLhBpRZfkg0Zz1INJlSYigaS99g==",
"peerDependencies": {
"react": "^16.14.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0"
@@ -30306,17 +30305,6 @@
"react-dom": ">=15.0.0"
}
},
"node_modules/react-split": {
"version": "2.0.14",
"license": "MIT",
"dependencies": {
"prop-types": "^15.5.7",
"split.js": "^1.6.0"
},
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-style-singleton": {
"version": "2.2.1",
"license": "MIT",
@@ -32990,10 +32978,6 @@
"tiny-updater": "^3.5.1"
}
},
"node_modules/split.js": {
"version": "1.6.5",
"license": "MIT"
},
"node_modules/split2": {
"version": "4.2.0",
"dev": true,
@@ -37662,7 +37646,7 @@
"react-hook-form": "^7.45.0",
"react-hot-toast": "^2.4.1",
"react-markdown": "^8.0.3",
"react-resizable-panels": "^2.0.9",
"react-resizable-panels": "^2.0.11",
"react-syntax-highlighter": "^15.5.0",
"react-tooltip": "^4.2.17",
"reactflow": "^11.10.1",
+1 -1
View File
@@ -74,7 +74,7 @@
"react-hook-form": "^7.45.0",
"react-hot-toast": "^2.4.1",
"react-markdown": "^8.0.3",
"react-resizable-panels": "^2.0.9",
"react-resizable-panels": "^2.0.11",
"react-syntax-highlighter": "^15.5.0",
"react-tooltip": "^4.2.17",
"reactflow": "^11.10.1",
@@ -1,5 +1,8 @@
'use client'
import { GripVertical } from 'lucide-react'
import * as ResizablePrimitive from 'react-resizable-panels'
import { cn } from '../../../lib/utils/cn'
const ResizablePanelGroup = ({
@@ -24,16 +27,28 @@ const ResizableHandle = ({
<ResizablePrimitive.PanelResizeHandle
className={cn(
'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
'data-[resize-handle-state=drag]:bg-border-strong',
'group',
'transition-colors',
className
)}
{...props}
>
{withHandle && (
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
<div
className={cn(
'z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border focus:bg-surface-400',
'opacity-0 transition-opacity duration-200',
'group-data-[resize-handle-state=hover]:opacity-100',
'hover:bg-surface-400',
'group-data-[resize-handle-state=drag]:opacity-100',
'group-data-[resize-handle-state=drag]:bg-foreground-muted'
)}
>
<GripVertical className="h-2.5 w-2.5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>
)
export { ResizableHandle, ResizablePanel, ResizablePanelGroup }
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }