refactor(client): move sidenav in dedicated ui component

This commit is contained in:
Corentin Thomasset 2026-01-17 22:51:24 +01:00
parent a748e5be75
commit db930651d4
No known key found for this signature in database
GPG key ID: 3A871907120CFC5F
6 changed files with 72 additions and 60 deletions

View file

@ -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) => {

View 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>
);
};

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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();