Skip to content

Commit

Permalink
Merge pull request #48 from chartdb/left-panel-mobile
Browse files Browse the repository at this point in the history
add drawer to side panel on mobile
  • Loading branch information
guyb1 authored Aug 26, 2024
2 parents 0a189cf + 009ff7f commit 66db34d
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 15 deletions.
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
"react-use": "^17.5.1",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
"timeago-react": "^3.0.6"
"timeago-react": "^3.0.6",
"vaul": "^0.9.1"
},
"devDependencies": {
"@types/node": "^22.1.0",
Expand Down
116 changes: 116 additions & 0 deletions src/components/drawer/drawer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React from 'react';
import { Drawer as DrawerPrimitive } from 'vaul';

import { cn } from '@/lib/utils';

const Drawer = ({
shouldScaleBackground = true,
...props
}: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
<DrawerPrimitive.Root
shouldScaleBackground={shouldScaleBackground}
{...props}
/>
);
Drawer.displayName = 'Drawer';

const DrawerTrigger = DrawerPrimitive.Trigger;

const DrawerPortal = DrawerPrimitive.Portal;

const DrawerClose = DrawerPrimitive.Close;

const DrawerOverlay = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Overlay
ref={ref}
className={cn('fixed inset-0 z-50 bg-black/80', className)}
{...props}
/>
));
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;

const DrawerContent = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DrawerPortal>
<DrawerOverlay />
<DrawerPrimitive.Content
ref={ref}
className={cn(
'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background',
className
)}
{...props}
>
<div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
{children}
</DrawerPrimitive.Content>
</DrawerPortal>
));
DrawerContent.displayName = 'DrawerContent';

const DrawerHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn('grid gap-1.5 p-4 text-center sm:text-left', className)}
{...props}
/>
);
DrawerHeader.displayName = 'DrawerHeader';

const DrawerFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn('mt-auto flex flex-col gap-2 p-4', className)}
{...props}
/>
);
DrawerFooter.displayName = 'DrawerFooter';

const DrawerTitle = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Title
ref={ref}
className={cn(
'text-lg font-semibold leading-none tracking-tight',
className
)}
{...props}
/>
));
DrawerTitle.displayName = DrawerPrimitive.Title.displayName;

const DrawerDescription = React.forwardRef<
React.ElementRef<typeof DrawerPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Description
ref={ref}
className={cn('text-sm text-muted-foreground', className)}
{...props}
/>
));
DrawerDescription.displayName = DrawerPrimitive.Description.displayName;

export {
Drawer,
DrawerPortal,
DrawerOverlay,
DrawerTrigger,
DrawerClose,
DrawerContent,
DrawerHeader,
DrawerFooter,
DrawerTitle,
DrawerDescription,
};
8 changes: 8 additions & 0 deletions src/context/layout-context/layout-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export interface LayoutContext {

selectedSidebarSection: SidebarSection;
selectSidebarSection: (section: SidebarSection) => void;

isSidePanelShowed: boolean;
hideSidePanel: () => void;
showSidePanel: () => void;
}

export const layoutContext = createContext<LayoutContext>({
Expand All @@ -27,4 +31,8 @@ export const layoutContext = createContext<LayoutContext>({
selectSidebarSection: emptyFn,
openTableFromSidebar: emptyFn,
closeAllTablesInSidebar: emptyFn,

isSidePanelShowed: false,
hideSidePanel: emptyFn,
showSidePanel: emptyFn,
});
11 changes: 11 additions & 0 deletions src/context/layout-context/layout-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,20 @@ export const LayoutProvider: React.FC<React.PropsWithChildren> = ({
React.useState<string | undefined>();
const [selectedSidebarSection, setSelectedSidebarSection] =
React.useState<SidebarSection>('tables');
const [isSidePanelShowed, setIsSidePanelShowed] =
React.useState<boolean>(false);

const closeAllTablesInSidebar: LayoutContext['closeAllTablesInSidebar'] =
() => setOpenedTableInSidebar('');

const closeAllRelationshipsInSidebar: LayoutContext['closeAllRelationshipsInSidebar'] =
() => setOpenedRelationshipInSidebar('');

const hideSidePanel: LayoutContext['hideSidePanel'] = () =>
setIsSidePanelShowed(false);

const showSidePanel: LayoutContext['showSidePanel'] = () =>
setIsSidePanelShowed(true);
return (
<layoutContext.Provider
value={{
Expand All @@ -28,6 +36,9 @@ export const LayoutProvider: React.FC<React.PropsWithChildren> = ({
openRelationshipFromSidebar: setOpenedRelationshipInSidebar,
closeAllTablesInSidebar,
closeAllRelationshipsInSidebar,
isSidePanelShowed,
hideSidePanel,
showSidePanel,
}}
>
{children}
Expand Down
23 changes: 23 additions & 0 deletions src/pages/editor-page/canvas/canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import { useChartDB } from '@/hooks/use-chartdb';
import { LEFT_HANDLE_ID_PREFIX, TARGET_ID_PREFIX } from './table-node-field';
import { Toolbar } from './toolbar/toolbar';
import { useToast } from '@/components/toast/use-toast';
import { Pencil } from 'lucide-react';
import { Button } from '@/components/button/button';
import { useLayout } from '@/hooks/use-layout';
import { useBreakpoint } from '@/hooks/use-breakpoint';

type AddEdgeParams = Parameters<typeof addEdge<TableEdgeType>>[0];

Expand All @@ -41,6 +45,8 @@ export const Canvas: React.FC<CanvasProps> = () => {
removeRelationships,
getField,
} = useChartDB();
const { showSidePanel } = useLayout();
const { isMd: isDesktop } = useBreakpoint('md');
const nodeTypes = useMemo(() => ({ table: TableNode }), []);
const edgeTypes = useMemo(() => ({ 'table-edge': TableEdge }), []);

Expand Down Expand Up @@ -250,6 +256,23 @@ export const Canvas: React.FC<CanvasProps> = () => {
}}
panOnScroll
>
{!isDesktop ? (
<Controls
position="bottom-left"
orientation="horizontal"
showZoom={false}
showFitView={false}
showInteractive={false}
className="!shadow-none"
>
<Button
className="bg-pink-600 hover:bg-pink-500 w-11 h-11 p-2"
onClick={showSidePanel}
>
<Pencil />
</Button>
</Controls>
) : null}
<Controls
position="bottom-center"
orientation="horizontal"
Expand Down
62 changes: 49 additions & 13 deletions src/pages/editor-page/editor-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,19 @@ import { useRedoUndoStack } from '@/hooks/use-redo-undo-stack';
import { Toaster } from '@/components/toast/toaster';
import { useFullScreenLoader } from '@/hooks/use-full-screen-spinner';
import { useBreakpoint } from '@/hooks/use-breakpoint';
import { useLayout } from '@/hooks/use-layout';
import {
Drawer,
DrawerContent,
DrawerDescription,
DrawerHeader,
DrawerTitle,
} from '@/components/drawer/drawer';
import { Separator } from '@/components/separator/separator';

export const EditorPage: React.FC = () => {
const { loadDiagram, currentDiagram } = useChartDB();
const { isSidePanelShowed, hideSidePanel } = useLayout();
const { resetRedoStack, resetUndoStack } = useRedoUndoStack();
const { showLoader, hideLoader } = useFullScreenLoader();
const { openCreateDiagramDialog } = useDialog();
Expand All @@ -26,6 +36,7 @@ export const EditorPage: React.FC = () => {
const navigate = useNavigate();
const { isLg } = useBreakpoint('lg');
const { isXl } = useBreakpoint('xl');
const { isMd: isDesktop } = useBreakpoint('md');

useEffect(() => {
if (!config) {
Expand Down Expand Up @@ -68,21 +79,46 @@ export const EditorPage: React.FC = () => {

return (
<>
<section className="bg-background h-screen w-screen flex flex-col">
<section
className={`bg-background ${isDesktop ? 'h-screen w-screen' : 'h-dvh w-dvw'} flex flex-col overflow-x-hidden`}
>
<TopNavbar />
<ResizablePanelGroup direction="horizontal">
<ResizablePanel
defaultSize={isXl ? 25 : isLg ? 35 : 50}
minSize={isXl ? 25 : isLg ? 35 : 50}
maxSize={99}
>
<SidePanel />
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={isXl ? 75 : isLg ? 65 : 50}>
{isDesktop ? (
<ResizablePanelGroup direction="horizontal">
<ResizablePanel
defaultSize={isXl ? 25 : isLg ? 35 : 50}
minSize={isXl ? 25 : isLg ? 35 : 50}
maxSize={!isSidePanelShowed ? 99 : 0}
>
<SidePanel />
</ResizablePanel>
<ResizableHandle />
<ResizablePanel
defaultSize={isXl ? 75 : isLg ? 65 : 50}
>
<Canvas />
</ResizablePanel>
</ResizablePanelGroup>
) : (
<>
<Drawer
open={isSidePanelShowed}
onClose={() => hideSidePanel()}
>
<DrawerContent className="h-full">
<DrawerHeader>
<DrawerTitle>Manage Diagram</DrawerTitle>
<DrawerDescription>
Manage your diagram objects
</DrawerDescription>
</DrawerHeader>
<Separator orientation="horizontal" />
<SidePanel />
</DrawerContent>
</Drawer>
<Canvas />
</ResizablePanel>
</ResizablePanelGroup>
</>
)}
</section>
<Toaster />
</>
Expand Down

0 comments on commit 66db34d

Please sign in to comment.