mirror of
https://github.com/chartdb/chartdb.git
synced 2026-02-06 03:29:17 -06:00
fix(sidebar): turn sidebar to responsive for mobile (#658)
This commit is contained in:
@@ -11,6 +11,7 @@ import type { Diagram } from '@/lib/domain/diagram';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { SidebarProvider } from '@/components/sidebar/sidebar';
|
||||
import { EditorSidebar } from './editor-sidebar/editor-sidebar';
|
||||
import { TopNavbar } from './top-navbar/top-navbar';
|
||||
|
||||
export interface EditorDesktopLayoutProps {
|
||||
initialDiagram?: Diagram;
|
||||
@@ -21,32 +22,35 @@ export const EditorDesktopLayout: React.FC<EditorDesktopLayoutProps> = ({
|
||||
const { isSidePanelShowed } = useLayout();
|
||||
|
||||
return (
|
||||
<SidebarProvider
|
||||
defaultOpen={false}
|
||||
open={false}
|
||||
className="h-full min-h-0"
|
||||
>
|
||||
<EditorSidebar />
|
||||
<ResizablePanelGroup direction="horizontal">
|
||||
<ResizablePanel
|
||||
defaultSize={25}
|
||||
minSize={25}
|
||||
maxSize={isSidePanelShowed ? 99 : 0}
|
||||
className={cn('transition-[flex-grow] duration-200', {
|
||||
'min-w-[350px]': isSidePanelShowed,
|
||||
})}
|
||||
>
|
||||
<SidePanel />
|
||||
</ResizablePanel>
|
||||
<ResizableHandle
|
||||
disabled={!isSidePanelShowed}
|
||||
className={!isSidePanelShowed ? 'hidden' : ''}
|
||||
/>
|
||||
<ResizablePanel defaultSize={75}>
|
||||
<Canvas initialTables={initialDiagram?.tables ?? []} />
|
||||
</ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
</SidebarProvider>
|
||||
<>
|
||||
<TopNavbar />
|
||||
<SidebarProvider
|
||||
defaultOpen={false}
|
||||
open={false}
|
||||
className="h-full min-h-0"
|
||||
>
|
||||
<EditorSidebar />
|
||||
<ResizablePanelGroup direction="horizontal">
|
||||
<ResizablePanel
|
||||
defaultSize={25}
|
||||
minSize={25}
|
||||
maxSize={isSidePanelShowed ? 99 : 0}
|
||||
className={cn('transition-[flex-grow] duration-200', {
|
||||
'min-w-[350px]': isSidePanelShowed,
|
||||
})}
|
||||
>
|
||||
<SidePanel />
|
||||
</ResizablePanel>
|
||||
<ResizableHandle
|
||||
disabled={!isSidePanelShowed}
|
||||
className={!isSidePanelShowed ? 'hidden' : ''}
|
||||
/>
|
||||
<ResizablePanel defaultSize={75}>
|
||||
<Canvas initialTables={initialDiagram?.tables ?? []} />
|
||||
</ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
</SidebarProvider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ import {
|
||||
} from '@/components/drawer/drawer';
|
||||
import { Separator } from '@/components/separator/separator';
|
||||
import type { Diagram } from '@/lib/domain/diagram';
|
||||
import { TopNavbarMobile } from './top-navbar/top-navbar-mobile';
|
||||
import { SidebarProvider } from '@/components/sidebar/sidebar';
|
||||
import { EditorSidebar } from './editor-sidebar/editor-sidebar';
|
||||
|
||||
export interface EditorMobileLayoutProps {
|
||||
initialDiagram?: Diagram;
|
||||
@@ -21,19 +24,30 @@ export const EditorMobileLayout: React.FC<EditorMobileLayoutProps> = ({
|
||||
const { isSidePanelShowed, hideSidePanel } = useLayout();
|
||||
return (
|
||||
<>
|
||||
<Drawer open={isSidePanelShowed} onClose={() => hideSidePanel()}>
|
||||
<DrawerContent className="h-full" fullScreen>
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>Manage Diagram</DrawerTitle>
|
||||
<DrawerDescription>
|
||||
Manage your diagram objects
|
||||
</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
<Separator orientation="horizontal" />
|
||||
<SidePanel data-vaul-no-drag />
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
<Canvas initialTables={initialDiagram?.tables ?? []} />
|
||||
<SidebarProvider
|
||||
defaultOpen={false}
|
||||
open={false}
|
||||
className="flex-col"
|
||||
>
|
||||
<EditorSidebar />
|
||||
<TopNavbarMobile />
|
||||
<Drawer
|
||||
open={isSidePanelShowed}
|
||||
onClose={() => hideSidePanel()}
|
||||
>
|
||||
<DrawerContent className="h-full" fullScreen>
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>Manage Diagram</DrawerTitle>
|
||||
<DrawerDescription>
|
||||
Manage your diagram objects
|
||||
</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
<Separator orientation="horizontal" />
|
||||
<SidePanel data-vaul-no-drag />
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
<Canvas initialTables={initialDiagram?.tables ?? []} />
|
||||
</SidebarProvider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { Suspense, useCallback, useEffect, useRef } from 'react';
|
||||
import { TopNavbar } from './top-navbar/top-navbar';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useChartDB } from '@/hooks/use-chartdb';
|
||||
import { useDialog } from '@/hooks/use-dialog';
|
||||
@@ -30,6 +29,7 @@ import { CanvasProvider } from '@/context/canvas-context/canvas-provider';
|
||||
import { HIDE_BUCKLE_DOT_DEV } from '@/lib/env';
|
||||
import { useDiagramLoader } from './use-diagram-loader';
|
||||
import { DiffProvider } from '@/context/diff-context/diff-provider';
|
||||
import { TopNavbarMock } from './top-navbar/top-navbar-mock';
|
||||
|
||||
const OPEN_STAR_US_AFTER_SECONDS = 30;
|
||||
const SHOW_STAR_US_AGAIN_AFTER_DAYS = 1;
|
||||
@@ -166,12 +166,16 @@ const EditorPageComponent: React.FC = () => {
|
||||
<section
|
||||
className={`bg-background ${isDesktop ? 'h-screen w-screen' : 'h-dvh w-dvw'} flex select-none flex-col overflow-x-hidden`}
|
||||
>
|
||||
<TopNavbar />
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="flex flex-1 items-center justify-center">
|
||||
<Spinner size={isDesktop ? 'large' : 'medium'} />
|
||||
</div>
|
||||
<>
|
||||
<TopNavbarMock />
|
||||
<div className="flex flex-1 items-center justify-center">
|
||||
<Spinner
|
||||
size={isDesktop ? 'large' : 'medium'}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
>
|
||||
{isDesktop ? (
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
SidebarFooter,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarHeader,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
@@ -15,6 +15,10 @@ import { SquareStack, Table, Workflow } from 'lucide-react';
|
||||
import { useLayout } from '@/hooks/use-layout';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { DiscordLogoIcon } from '@radix-ui/react-icons';
|
||||
import { useBreakpoint } from '@/hooks/use-breakpoint';
|
||||
import ChartDBLogo from '@/assets/logo-light.png';
|
||||
import ChartDBDarkLogo from '@/assets/logo-dark.png';
|
||||
import { useTheme } from '@/hooks/use-theme';
|
||||
|
||||
export interface SidebarItem {
|
||||
title: string;
|
||||
@@ -30,6 +34,8 @@ export const EditorSidebar: React.FC<EditorSidebarProps> = () => {
|
||||
const { selectSidebarSection, selectedSidebarSection, showSidePanel } =
|
||||
useLayout();
|
||||
const { t } = useTranslation();
|
||||
const { isMd: isDesktop } = useBreakpoint('md');
|
||||
const { effectiveTheme } = useTheme();
|
||||
const items: SidebarItem[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
@@ -96,9 +102,28 @@ export const EditorSidebar: React.FC<EditorSidebarProps> = () => {
|
||||
variant="sidebar"
|
||||
className="relative h-full"
|
||||
>
|
||||
{!isDesktop ? (
|
||||
<SidebarHeader>
|
||||
<a
|
||||
href="https://chartdb.io"
|
||||
className="cursor-pointer"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<img
|
||||
src={
|
||||
effectiveTheme === 'light'
|
||||
? ChartDBLogo
|
||||
: ChartDBDarkLogo
|
||||
}
|
||||
alt="chartDB"
|
||||
className="h-4 max-w-fit"
|
||||
/>
|
||||
</a>
|
||||
</SidebarHeader>
|
||||
) : null}
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel />
|
||||
{/* <SidebarGroupLabel /> */}
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
|
||||
64
src/pages/editor-page/top-navbar/top-navbar-mobile.tsx
Normal file
64
src/pages/editor-page/top-navbar/top-navbar-mobile.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import ChartDBLogo from '@/assets/logo-2.png';
|
||||
import { DiagramName } from './diagram-name';
|
||||
import { LanguageNav } from './language-nav/language-nav';
|
||||
import { Menu } from './menu/menu';
|
||||
import { Button } from '@/components/button/button';
|
||||
import { useSidebar } from '@/components/sidebar/use-sidebar';
|
||||
import { MenuIcon } from 'lucide-react';
|
||||
|
||||
export interface TopNavbarMobileProps {}
|
||||
|
||||
export const TopNavbarMobile: React.FC<TopNavbarMobileProps> = () => {
|
||||
const renderStars = useCallback(() => {
|
||||
return (
|
||||
<iframe
|
||||
src="https://ghbtns.com/github-btn.html?user=chartdb&repo=chartdb&type=star&size=small&text=false"
|
||||
width="25"
|
||||
height="20"
|
||||
title="GitHub"
|
||||
></iframe>
|
||||
);
|
||||
}, []);
|
||||
|
||||
const { toggleSidebar } = useSidebar();
|
||||
|
||||
return (
|
||||
<nav className="flex flex-col justify-between border-b px-3 md:h-12 md:flex-row md:items-center md:px-4">
|
||||
<div className="flex flex-1 flex-col justify-between gap-x-1 md:flex-row md:justify-normal">
|
||||
<div className="flex items-center justify-between pt-[8px] font-primary md:py-[10px]">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
size={'icon'}
|
||||
variant="ghost"
|
||||
onClick={toggleSidebar}
|
||||
>
|
||||
<MenuIcon className="size-5" />
|
||||
</Button>
|
||||
<a
|
||||
href="https://chartdb.io"
|
||||
className="cursor-pointer"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<img
|
||||
src={ChartDBLogo}
|
||||
alt="chartDB"
|
||||
className="h-4 max-w-fit"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{renderStars()}
|
||||
<LanguageNav />
|
||||
</div>
|
||||
</div>
|
||||
<Menu />
|
||||
</div>
|
||||
|
||||
<div className="flex flex-1 justify-center pb-2 pt-1">
|
||||
<DiagramName />
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
32
src/pages/editor-page/top-navbar/top-navbar-mock.tsx
Normal file
32
src/pages/editor-page/top-navbar/top-navbar-mock.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
|
||||
import ChartDBLogo from '@/assets/logo-light.png';
|
||||
import ChartDBDarkLogo from '@/assets/logo-dark.png';
|
||||
import { useTheme } from '@/hooks/use-theme';
|
||||
|
||||
export const TopNavbarMock: React.FC = () => {
|
||||
const { effectiveTheme } = useTheme();
|
||||
return (
|
||||
<nav className="flex h-[105px] flex-col justify-between border-b px-3 md:h-12 md:flex-row md:items-center md:px-4">
|
||||
<div className="flex flex-1 flex-col justify-between gap-x-1 md:flex-row md:justify-normal">
|
||||
<div className="flex items-center justify-between pt-[8px] font-primary md:py-[10px]">
|
||||
<a
|
||||
href="https://chartdb.io"
|
||||
className="cursor-pointer"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<img
|
||||
src={
|
||||
effectiveTheme === 'light'
|
||||
? ChartDBLogo
|
||||
: ChartDBDarkLogo
|
||||
}
|
||||
alt="chartDB"
|
||||
className="h-4 max-w-fit"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import ChartDBLogo from '@/assets/logo-light.png';
|
||||
import ChartDBDarkLogo from '@/assets/logo-dark.png';
|
||||
import { useBreakpoint } from '@/hooks/use-breakpoint';
|
||||
import { useTheme } from '@/hooks/use-theme';
|
||||
import { DiagramName } from './diagram-name';
|
||||
import { LastSaved } from './last-saved';
|
||||
@@ -12,18 +11,17 @@ export interface TopNavbarProps {}
|
||||
|
||||
export const TopNavbar: React.FC<TopNavbarProps> = () => {
|
||||
const { effectiveTheme } = useTheme();
|
||||
const { isMd: isDesktop } = useBreakpoint('md');
|
||||
|
||||
const renderStars = useCallback(() => {
|
||||
return (
|
||||
<iframe
|
||||
src={`https://ghbtns.com/github-btn.html?user=chartdb&repo=chartdb&type=star&size=${isDesktop ? 'large' : 'small'}&text=false`}
|
||||
width={isDesktop ? '40' : '25'}
|
||||
height={isDesktop ? '30' : '20'}
|
||||
src={`https://ghbtns.com/github-btn.html?user=chartdb&repo=chartdb&type=star&size=large&text=false`}
|
||||
width="40"
|
||||
height="30"
|
||||
title="GitHub"
|
||||
></iframe>
|
||||
);
|
||||
}, [isDesktop]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<nav className="flex flex-col justify-between border-b px-3 md:h-12 md:flex-row md:items-center md:px-4">
|
||||
@@ -44,29 +42,15 @@ export const TopNavbar: React.FC<TopNavbarProps> = () => {
|
||||
className="h-4 max-w-fit"
|
||||
/>
|
||||
</a>
|
||||
{!isDesktop ? (
|
||||
<div className="flex items-center gap-2">
|
||||
{renderStars()}
|
||||
<LanguageNav />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<Menu />
|
||||
</div>
|
||||
{isDesktop ? (
|
||||
<>
|
||||
<DiagramName />
|
||||
<div className="hidden flex-1 items-center justify-end gap-2 sm:flex">
|
||||
<LastSaved />
|
||||
{renderStars()}
|
||||
<LanguageNav />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex flex-1 justify-center pb-2 pt-1">
|
||||
<DiagramName />
|
||||
</div>
|
||||
)}
|
||||
<DiagramName />
|
||||
<div className="hidden flex-1 items-center justify-end gap-2 sm:flex">
|
||||
<LastSaved />
|
||||
{renderStars()}
|
||||
<LanguageNav />
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user