refactor: improve mobile layout navbar display if have much features
This commit is contained in:
parent
eebf00f882
commit
fd9108e77f
@ -329,6 +329,9 @@ importers:
|
|||||||
uuid:
|
uuid:
|
||||||
specifier: ^9.0.1
|
specifier: ^9.0.1
|
||||||
version: 9.0.1
|
version: 9.0.1
|
||||||
|
vaul:
|
||||||
|
specifier: ^0.9.0
|
||||||
|
version: 0.9.0(@types/react-dom@18.2.7)(@types/react@18.2.78)(react-dom@18.2.0)(react@18.2.0)
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.22.2
|
specifier: ^3.22.2
|
||||||
version: 3.22.2
|
version: 3.22.2
|
||||||
@ -27255,6 +27258,20 @@ packages:
|
|||||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
/vaul@0.9.0(@types/react-dom@18.2.7)(@types/react@18.2.78)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-bZSySGbAHiTXmZychprnX/dE0EsSige88xtyyL3/MCRbrFotRPQZo7UdydGXZWw+CKbNOw5Ow8gwAo93/nB/Cg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.78)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
- '@types/react-dom'
|
||||||
|
dev: false
|
||||||
|
|
||||||
/vfile-location@3.2.0:
|
/vfile-location@3.2.0:
|
||||||
resolution: {integrity: sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==}
|
resolution: {integrity: sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
116
src/client/components/ui/drawer.tsx
Normal file
116
src/client/components/ui/drawer.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { Drawer as DrawerPrimitive } from "vaul"
|
||||||
|
|
||||||
|
import { cn } from "@/utils/style"
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
@ -93,6 +93,7 @@
|
|||||||
"str2int": "^1.1.0",
|
"str2int": "^1.1.0",
|
||||||
"tailwind-merge": "^2.2.1",
|
"tailwind-merge": "^2.2.1",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
|
"vaul": "^0.9.0",
|
||||||
"zod": "^3.22.2",
|
"zod": "^3.22.2",
|
||||||
"zustand": "^4.4.1"
|
"zustand": "^4.4.1"
|
||||||
},
|
},
|
||||||
|
@ -4,7 +4,9 @@ import {
|
|||||||
LuFilePieChart,
|
LuFilePieChart,
|
||||||
LuMenu,
|
LuMenu,
|
||||||
LuMonitorDot,
|
LuMonitorDot,
|
||||||
|
LuMoreVertical,
|
||||||
LuServer,
|
LuServer,
|
||||||
|
LuTableProperties,
|
||||||
LuWifi,
|
LuWifi,
|
||||||
} from 'react-icons/lu';
|
} from 'react-icons/lu';
|
||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
@ -17,6 +19,16 @@ import { UserConfig } from './UserConfig';
|
|||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
|
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
Drawer,
|
||||||
|
DrawerClose,
|
||||||
|
DrawerContent,
|
||||||
|
DrawerDescription,
|
||||||
|
DrawerFooter,
|
||||||
|
DrawerHeader,
|
||||||
|
DrawerTitle,
|
||||||
|
DrawerTrigger,
|
||||||
|
} from '@/components/ui/drawer';
|
||||||
|
|
||||||
export const MobileLayout: React.FC<LayoutProps> = React.memo((props) => {
|
export const MobileLayout: React.FC<LayoutProps> = React.memo((props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -69,8 +81,32 @@ export const MobileLayout: React.FC<LayoutProps> = React.memo((props) => {
|
|||||||
to="/monitor"
|
to="/monitor"
|
||||||
/>
|
/>
|
||||||
<MobileNavItem title={t('Servers')} icon={LuServer} to="/server" />
|
<MobileNavItem title={t('Servers')} icon={LuServer} to="/server" />
|
||||||
<MobileNavItem title={t('Telemetry')} icon={LuWifi} to="/telemetry" />
|
|
||||||
<MobileNavItem title={t('Pages')} icon={LuFilePieChart} to="/page" />
|
<MobileNavItem title={t('Pages')} icon={LuFilePieChart} to="/page" />
|
||||||
|
|
||||||
|
<Drawer>
|
||||||
|
<DrawerTrigger asChild>
|
||||||
|
<div className="text-muted-foreground flex-1 rounded-lg p-1 text-center">
|
||||||
|
<LuMoreVertical size={24} className="m-auto mb-1" />
|
||||||
|
<div className={cn('text-sm font-semibold')}>{t('More')}</div>
|
||||||
|
</div>
|
||||||
|
</DrawerTrigger>
|
||||||
|
<DrawerContent>
|
||||||
|
<div className="flex flex-row items-center justify-center gap-2 p-3">
|
||||||
|
<MobileNavItem
|
||||||
|
title={t('Telemetry')}
|
||||||
|
icon={LuWifi}
|
||||||
|
to="/telemetry"
|
||||||
|
extraModal={true}
|
||||||
|
/>
|
||||||
|
<MobileNavItem
|
||||||
|
title={t('Survey')}
|
||||||
|
icon={LuTableProperties}
|
||||||
|
to="/survey"
|
||||||
|
extraModal={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</DrawerContent>
|
||||||
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -82,6 +118,7 @@ const MobileNavItem: React.FC<{
|
|||||||
title: string;
|
title: string;
|
||||||
icon: IconType;
|
icon: IconType;
|
||||||
to: string;
|
to: string;
|
||||||
|
extraModal?: boolean;
|
||||||
}> = React.memo((props) => {
|
}> = React.memo((props) => {
|
||||||
const pathname = useRouterState({
|
const pathname = useRouterState({
|
||||||
select: (state) => state.location.pathname,
|
select: (state) => state.location.pathname,
|
||||||
@ -92,10 +129,11 @@ const MobileNavItem: React.FC<{
|
|||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex-1 rounded-lg p-1 text-center',
|
'flex-1 rounded-lg p-1 py-2 text-center',
|
||||||
isSelect
|
isSelect
|
||||||
? 'bg-muted text-black dark:text-white'
|
? 'bg-muted text-black dark:text-white'
|
||||||
: 'text-muted-foreground'
|
: 'text-muted-foreground',
|
||||||
|
props.extraModal && 'flex-none p-3'
|
||||||
)}
|
)}
|
||||||
to={props.to}
|
to={props.to}
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user