mirror of
https://github.com/papra-hq/papra
synced 2026-04-21 13:37:23 +00:00
refactor(client): move sidenav in dedicated ui component
This commit is contained in:
parent
a748e5be75
commit
db930651d4
6 changed files with 72 additions and 60 deletions
|
|
@ -4,7 +4,7 @@ import { Show } from 'solid-js';
|
|||
import { useI18n } from '@/modules/i18n/i18n.provider';
|
||||
import { Button } from '@/modules/ui/components/button';
|
||||
import { Sheet, SheetContent, SheetTrigger } from '@/modules/ui/components/sheet';
|
||||
import { SideNav } from '@/modules/ui/layouts/sidenav.layout';
|
||||
import { SideNav } from '@/modules/ui/components/sidenav';
|
||||
import { useCurrentUser } from '@/modules/users/composables/useCurrentUser';
|
||||
|
||||
const AdminLayout: ParentComponent = (props) => {
|
||||
|
|
|
|||
66
apps/papra-client/src/modules/ui/components/sidenav.tsx
Normal file
66
apps/papra-client/src/modules/ui/components/sidenav.tsx
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import type { Component, ComponentProps, JSX } from 'solid-js';
|
||||
import { A } from '@solidjs/router';
|
||||
import { For } from 'solid-js';
|
||||
import { cn } from '@/modules/shared/style/cn';
|
||||
import { Button } from './button';
|
||||
|
||||
export type SideNavMenuItem = {
|
||||
label: string;
|
||||
icon: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
badge?: JSX.Element;
|
||||
};
|
||||
|
||||
const MenuItemButton: Component<SideNavMenuItem> = (props) => {
|
||||
return (
|
||||
<Button
|
||||
class="justify-start items-center gap-2 dark:text-muted-foreground truncate"
|
||||
variant="ghost"
|
||||
{...(props.onClick
|
||||
? { onClick: props.onClick }
|
||||
: { as: A, href: props.href, activeClass: 'bg-accent/50! text-accent-foreground! truncate', end: true } as ComponentProps<typeof Button>)
|
||||
}
|
||||
>
|
||||
<div class={cn(props.icon, 'size-5 text-muted-foreground opacity-50')} />
|
||||
<div>{props.label}</div>
|
||||
{props.badge && <div class="ml-auto">{props.badge}</div>}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export const SideNav: Component<{
|
||||
mainMenu?: SideNavMenuItem[];
|
||||
footerMenu?: SideNavMenuItem[];
|
||||
header?: Component;
|
||||
footer?: Component;
|
||||
preFooter?: Component;
|
||||
}> = (props) => {
|
||||
return (
|
||||
<div class="flex h-full">
|
||||
{(props.header || props.mainMenu || props.footerMenu || props.footer || props.preFooter) && (
|
||||
<div class="h-full flex flex-col pb-6 flex-1 min-w-0">
|
||||
{props.header && <props.header />}
|
||||
|
||||
{props.mainMenu && (
|
||||
<nav class="flex flex-col gap-0.5 mt-4 px-4">
|
||||
<For each={props.mainMenu}>{menuItem => <MenuItemButton {...menuItem} />}</For>
|
||||
</nav>
|
||||
)}
|
||||
|
||||
<div class="flex-1" />
|
||||
|
||||
{props.preFooter && <props.preFooter />}
|
||||
|
||||
{props.footerMenu && (
|
||||
<nav class="flex flex-col gap-0.5 px-4">
|
||||
<For each={props.footerMenu}>{menuItem => <MenuItemButton {...menuItem} />}</For>
|
||||
</nav>
|
||||
)}
|
||||
|
||||
{props.footer && <props.footer />}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import type { ParentComponent } from 'solid-js';
|
||||
import { A, useParams } from '@solidjs/router';
|
||||
import { useI18n } from '@/modules/i18n/i18n.provider';
|
||||
import { SideNav } from '@/modules/ui/components/sidenav';
|
||||
import { Button } from '../components/button';
|
||||
import { SideNav } from './sidenav.layout';
|
||||
|
||||
export const OrganizationSettingsLayout: ParentComponent = (props) => {
|
||||
const params = useParams();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { queryClient } from '@/modules/shared/query/query-client';
|
|||
import { getErrorStatus } from '@/modules/shared/utils/errors';
|
||||
import { UpgradeDialog } from '@/modules/subscriptions/components/upgrade-dialog.component';
|
||||
import { fetchOrganizationSubscription } from '@/modules/subscriptions/subscriptions.services';
|
||||
import { SideNav } from '@/modules/ui/components/sidenav';
|
||||
import { Button } from '../components/button';
|
||||
import {
|
||||
Select,
|
||||
|
|
@ -21,7 +22,7 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '../components/select';
|
||||
import { SideNav, SidenavLayout } from './sidenav.layout';
|
||||
import { SidenavLayout } from './sidenav.layout';
|
||||
|
||||
const UpgradeCTAFooter: Component<{ organizationId: string }> = (props) => {
|
||||
const { t } = useI18n();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type { ParentComponent } from 'solid-js';
|
||||
import { A } from '@solidjs/router';
|
||||
import { useI18n } from '@/modules/i18n/i18n.provider';
|
||||
import { SideNav } from '@/modules/ui/components/sidenav';
|
||||
import { Button } from '../components/button';
|
||||
import { SideNav } from './sidenav.layout';
|
||||
|
||||
export const SettingsLayout: ParentComponent = (props) => {
|
||||
const { t } = useI18n();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { Component, ComponentProps, JSX, ParentComponent } from 'solid-js';
|
||||
import type { Component, ParentComponent } from 'solid-js';
|
||||
import { A, useNavigate, useParams } from '@solidjs/router';
|
||||
import { For, Show, Suspense } from 'solid-js';
|
||||
|
||||
|
|
@ -10,7 +10,6 @@ import { GlobalDropArea } from '@/modules/documents/components/global-drop-area.
|
|||
import { useI18n } from '@/modules/i18n/i18n.provider';
|
||||
import { usePendingInvitationsCount } from '@/modules/invitations/composables/usePendingInvitationsCount';
|
||||
import { AboutDialog, useAboutDialog } from '@/modules/shared/components/about-dialog';
|
||||
import { cn } from '@/modules/shared/style/cn';
|
||||
import { UsageWarningCard } from '@/modules/subscriptions/components/usage-warning-card';
|
||||
import { useThemeStore } from '@/modules/theme/theme.store';
|
||||
import { Button } from '@/modules/ui/components/button';
|
||||
|
|
@ -18,60 +17,6 @@ import { useCurrentUser } from '@/modules/users/composables/useCurrentUser';
|
|||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from '../components/dropdown-menu';
|
||||
import { Sheet, SheetContent, SheetTrigger } from '../components/sheet';
|
||||
|
||||
type MenuItem = {
|
||||
label: string;
|
||||
icon: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
badge?: JSX.Element;
|
||||
};
|
||||
|
||||
const MenuItemButton: Component<MenuItem> = (props) => {
|
||||
return (
|
||||
<Button class="justify-start items-center gap-2 dark:text-muted-foreground truncate" variant="ghost" {...(props.onClick ? { onClick: props.onClick } : { as: A, href: props.href, activeClass: 'bg-accent/50! text-accent-foreground! truncate', end: true } as ComponentProps<typeof Button>)}>
|
||||
<div class={cn(props.icon, 'size-5 text-muted-foreground opacity-50')} />
|
||||
<div>{props.label}</div>
|
||||
{props.badge && <div class="ml-auto">{props.badge}</div>}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export const SideNav: Component<{
|
||||
mainMenu?: MenuItem[];
|
||||
footerMenu?: MenuItem[];
|
||||
header?: Component;
|
||||
footer?: Component;
|
||||
preFooter?: Component;
|
||||
}> = (props) => {
|
||||
return (
|
||||
<div class="flex h-full">
|
||||
{(props.header || props.mainMenu || props.footerMenu || props.footer || props.preFooter) && (
|
||||
<div class="h-full flex flex-col pb-6 flex-1 min-w-0">
|
||||
{props.header && <props.header />}
|
||||
|
||||
{props.mainMenu && (
|
||||
<nav class="flex flex-col gap-0.5 mt-4 px-4">
|
||||
<For each={props.mainMenu}>{menuItem => <MenuItemButton {...menuItem} />}</For>
|
||||
</nav>
|
||||
)}
|
||||
|
||||
<div class="flex-1" />
|
||||
|
||||
{props.preFooter && <props.preFooter />}
|
||||
|
||||
{props.footerMenu && (
|
||||
<nav class="flex flex-col gap-0.5 px-4">
|
||||
<For each={props.footerMenu}>{menuItem => <MenuItemButton {...menuItem} />}</For>
|
||||
</nav>
|
||||
)}
|
||||
|
||||
{props.footer && <props.footer />}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ThemeSwitcher: Component = () => {
|
||||
const themeStore = useThemeStore();
|
||||
const { t } = useI18n();
|
||||
|
|
|
|||
Loading…
Reference in a new issue