feat(fixing forms tunnel & wip dashboard)

This commit is contained in:
2026-04-08 14:02:36 +02:00
parent c848a8b47f
commit 341032162a
20 changed files with 330 additions and 275 deletions

View File

@@ -13,54 +13,27 @@ import {
NavigationMenuList,
navigationMenuTriggerStyle,
} from '@/components/ui/navigation-menu';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@/components/ui/sheet';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { UserMenuContent } from '@/components/user-menu-content';
import { useAppearance } from '@/hooks/use-appearance';
import { useInitials } from '@/hooks/use-initials';
import { useMobileNavigation } from '@/hooks/use-mobile-navigation';
import { cn } from '@/lib/utils';
import { dashboard } from '@/routes';
import { dashboard, logout } from '@/routes';
import { type BreadcrumbItem, type NavItem, type SharedData } from '@/types';
import { Link, usePage } from '@inertiajs/react';
import { BookOpen, Folder, LayoutGrid, Menu, Search } from 'lucide-react';
import AppearanceToggleDropdown from './appearance-dropdown';
import { Link, router, usePage } from '@inertiajs/react';
import { LayoutGrid, LogOut, Menu, Moon, Settings, Sun, X } from 'lucide-react';
import { useEffect, useState } from 'react';
import AppLogo from './app-logo';
import AppLogoIcon from './app-logo-icon';
const mainNavItems: NavItem[] = [
{
title: 'Dashboard',
title: 'Tableau de Bord',
href: dashboard(),
icon: LayoutGrid,
},
];
const rightNavItems: NavItem[] = [
{
title: 'Repository',
href: 'https://github.com/laravel/react-starter-kit',
icon: Folder,
},
{
title: 'Documentation',
href: 'https://laravel.com/docs/starter-kits#react',
icon: BookOpen,
},
];
const activeItemStyles =
'text-neutral-900 dark:bg-neutral-800 dark:text-neutral-100';
interface AppHeaderProps {
breadcrumbs?: BreadcrumbItem[];
}
@@ -69,122 +42,68 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {
const page = usePage<SharedData>();
const { auth } = page.props;
const getInitials = useInitials();
const cleanup = useMobileNavigation();
const { appearance, updateAppearance } = useAppearance();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const toggleAppearance = () => {
updateAppearance(appearance === 'dark' ? 'light' : 'dark');
};
const closeMenu = () => setIsMenuOpen(false);
const handleLogout = () => {
cleanup();
router.flushAll();
};
useEffect(() => {
return router.on('navigate', closeMenu);
}, []);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') closeMenu();
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, []);
useEffect(() => {
document.body.style.overflow = isMenuOpen ? 'hidden' : '';
return () => { document.body.style.overflow = ''; };
}, [isMenuOpen]);
return (
<>
<div className="border-b border-sidebar-border/80">
<div className="border-b border-border bg-background">
<div className="mx-auto flex h-16 items-center px-4 md:max-w-7xl">
{/* Mobile Menu */}
<div className="lg:hidden">
<Sheet>
<SheetTrigger asChild>
<Button
variant="ghost"
size="icon"
className="mr-2 h-[34px] w-[34px]"
>
<Menu className="h-5 w-5" />
</Button>
</SheetTrigger>
<SheetContent
side="left"
className="flex h-full w-64 flex-col items-stretch justify-between bg-sidebar"
>
<SheetTitle className="sr-only">
Navigation Menu
</SheetTitle>
<SheetHeader className="flex justify-start text-left">
<AppLogoIcon className="h-6 w-6 fill-current text-black dark:text-white" />
</SheetHeader>
<div className="flex h-full flex-1 flex-col space-y-4 p-4">
<div className="flex h-full flex-col justify-between text-sm">
<div className="flex flex-col space-y-4">
{mainNavItems.map((item) => (
<Link
key={item.title}
href={item.href}
className="flex items-center space-x-2 font-medium"
>
{item.icon && (
<Icon
iconNode={item.icon}
className="h-5 w-5"
/>
)}
<span>{item.title}</span>
</Link>
))}
</div>
<div className="flex flex-col space-y-4">
{rightNavItems.map((item) => (
<a
key={item.title}
href={
typeof item.href ===
'string'
? item.href
: item.href.url
}
target="_blank"
rel="noopener noreferrer"
className="flex items-center space-x-2 font-medium"
>
{item.icon && (
<Icon
iconNode={item.icon}
className="h-5 w-5"
/>
)}
<span>{item.title}</span>
</a>
))}
</div>
</div>
</div>
</SheetContent>
</Sheet>
</div>
<Link
href={dashboard()}
prefetch
className="flex items-center space-x-2 no-underline"
>
<AppLogo />
{/* Logo */}
<Link href={dashboard()} prefetch className="flex items-center no-underline text-foreground">
<AppLogo className="h-8 w-auto max-w-[180px]" />
</Link>
{/* Desktop Navigation */}
<div className="ml-6 hidden h-full items-center space-x-6 lg:flex">
{/* Desktop nav */}
<div className="ml-6 hidden h-full items-center lg:flex">
<NavigationMenu className="flex h-full items-stretch">
<NavigationMenuList className="flex h-full items-stretch space-x-2">
<NavigationMenuList className="flex h-full items-stretch gap-1">
{mainNavItems.map((item, index) => (
<NavigationMenuItem
key={index}
className="relative flex h-full items-center"
>
<NavigationMenuItem key={index} className="relative flex h-full items-center">
<Link
href={item.href}
className={cn(
navigationMenuTriggerStyle(),
page.url ===
(typeof item.href ===
'string'
? item.href
: item.href.url) &&
activeItemStyles,
'h-9 cursor-pointer px-3',
'h-9 cursor-pointer px-3 text-foreground no-underline',
page.url === (typeof item.href === 'string' ? item.href : item.href.url) &&
'font-semibold',
)}
>
{item.icon && (
<Icon
iconNode={item.icon}
className="mr-2 h-4 w-4"
/>
)}
{item.icon && <Icon iconNode={item.icon} className="mr-2 h-4 w-4" />}
{item.title}
</Link>
{page.url === item.href && (
<div className="absolute bottom-0 left-0 h-0.5 w-full translate-y-px bg-black dark:bg-white"></div>
{page.url === (typeof item.href === 'string' ? item.href : item.href.url) && (
<div className="absolute bottom-0 left-0 h-0.5 w-full translate-y-px bg-primary" />
)}
</NavigationMenuItem>
))}
@@ -192,66 +111,23 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {
</NavigationMenu>
</div>
<div className="ml-auto flex items-center space-x-2">
<div className="relative flex items-center space-x-1">
<Button
variant="ghost"
size="icon"
className="group h-9 w-9 cursor-pointer"
>
<Search className="!size-5 opacity-80 group-hover:opacity-100" />
</Button>
<div className="hidden lg:flex">
{rightNavItems.map((item) => (
<TooltipProvider
key={item.title}
delayDuration={0}
>
<Tooltip>
<TooltipTrigger>
<a
href={
typeof item.href ===
'string'
? item.href
: item.href.url
}
target="_blank"
rel="noopener noreferrer"
className="group ml-1 inline-flex h-9 w-9 items-center justify-center rounded-md bg-transparent p-0 text-sm font-medium text-accent-foreground ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50"
>
<span className="sr-only">
{item.title}
</span>
{item.icon && (
<Icon
iconNode={item.icon}
className="size-5 opacity-80 group-hover:opacity-100"
/>
)}
</a>
</TooltipTrigger>
<TooltipContent>
<p>{item.title}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
))}
</div>
</div>
<AppearanceToggleDropdown />
{/* Right actions */}
<div className="ml-auto flex items-center gap-2">
{/* Theme toggle — desktop only */}
<button
onClick={toggleAppearance}
className="hidden lg:flex nb-shadow bg-primary text-secondary-foreground hover:bg-primary/80 h-10 px-4 py-2 font-bold"
aria-label="Changer le thème"
>
{appearance === 'dark' ? <Sun className="size-4" /> : <Moon className="size-4" />}
</button>
{/* Avatar dropdown — always visible */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="size-10 rounded-full p-1"
>
<Button variant="secondary" className="size-10 rounded-full mr-2">
<Avatar className="size-8 overflow-hidden rounded-full">
<AvatarImage
src={auth.user.avatar}
alt={auth.user.name}
/>
<AvatarFallback className="rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white">
<AvatarFallback className="rounded-full bg-secondary text-secondary-foreground font-semibold text-sm">
{getInitials(auth.user.name)}
</AvatarFallback>
</Avatar>
@@ -261,12 +137,109 @@ export function AppHeader({ breadcrumbs = [] }: AppHeaderProps) {
<UserMenuContent user={auth.user} />
</DropdownMenuContent>
</DropdownMenu>
{/* Hamburger — mobile only */}
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="flex lg:hidden nb-shadow bg-primary text-secondary-foreground hover:bg-primary/80 h-10 px-4 py-2 font-bold"
aria-label={isMenuOpen ? 'Fermer le menu' : 'Ouvrir le menu'}
aria-expanded={isMenuOpen}
>
{isMenuOpen ? <X className="size-5" /> : <Menu className="size-5" />}
</button>
</div>
</div>
</div>
{/* Mobile menu */}
{isMenuOpen && (
<>
<div
className="fixed inset-0 z-40 bg-black/30 lg:hidden"
onClick={closeMenu}
aria-hidden="true"
/>
<div className="fixed inset-x-0 top-0 z-50 lg:hidden bg-[#F5F5F5] dark:bg-[#0a0a0a] border-b-4 border-black flex flex-col gap-6 p-6">
{/* Header du panel */}
<div className="flex justify-between items-center">
<Link href={dashboard()} onClick={closeMenu} className="flex items-center gap-2 no-underline text-foreground">
<AppLogoIcon className="size-8" />
<span className="font-bold text-foreground">Le Retzien Libre</span>
</Link>
<button
onClick={closeMenu}
className="p-2 rounded-md border border-black/20 dark:border-white/20 hover:bg-black/5 dark:hover:bg-white/5 transition"
aria-label="Fermer le menu"
>
<X className="size-5" />
</button>
</div>
{/* Nav links */}
<nav className="flex flex-col">
{mainNavItems.map((item) => (
<Link
key={item.title}
href={item.href}
onClick={closeMenu}
className="flex items-center gap-2 text-lg py-3 border-b border-black/10 dark:border-white/10 no-underline text-foreground hover:underline"
>
{item.icon && <Icon iconNode={item.icon} className="size-5" />}
<span>{item.title}</span>
</Link>
))}
</nav>
{/* Theme toggle */}
<button
onClick={toggleAppearance}
className="flex items-center gap-2 text-lg py-3 border-b border-black/10 dark:border-white/10 text-foreground hover:underline w-full"
aria-label="Changer le thème"
>
{appearance === 'dark' ? <Sun className="size-5" /> : <Moon className="size-5" />}
<span>{appearance === 'dark' ? 'Mode clair' : 'Mode sombre'}</span>
</button>
{/* User actions */}
<div className="flex flex-col gap-3">
<div className="flex items-center gap-3 py-2 border-b border-black/10 dark:border-white/10">
<Avatar className="size-8 rounded-full">
<AvatarFallback className="rounded-full bg-secondary text-secondary-foreground font-semibold text-sm">
{getInitials(auth.user.name)}
</AvatarFallback>
</Avatar>
<div className="flex flex-col">
<span className="text-sm font-semibold text-foreground">{auth.user.name}</span>
<span className="text-xs text-muted-foreground">{auth.user.email}</span>
</div>
</div>
<Link
href="/profile/edit"
onClick={closeMenu}
className="flex items-center gap-2 text-lg py-3 border-b border-black/10 dark:border-white/10 no-underline text-foreground hover:underline"
>
<Settings className="size-5" />
<span>Paramètres</span>
</Link>
<Link
href={logout()}
method="post"
as="button"
onClick={() => { closeMenu(); handleLogout(); }}
className="flex bg-primary items-center gap-2 text-lg py-3 no-underline text-foreground hover:underline border-black border-3 shadow-[4px_4px_0px_rgba(0,0,0,1)]"
data-test="logout-button"
>
<LogOut className="size-5" />
<span>Se déconnecter</span>
</Link>
</div>
</div>
</>
)}
{breadcrumbs.length > 1 && (
<div className="flex w-full border-b border-sidebar-border/70">
<div className="mx-auto flex h-12 w-full items-center justify-start px-4 text-neutral-500 md:max-w-7xl">
<div className="flex w-full border-b border-border">
<div className="mx-auto flex h-12 w-full items-center justify-start px-4 text-muted-foreground md:max-w-7xl">
<Breadcrumbs breadcrumbs={breadcrumbs} />
</div>
</div>

View File

@@ -3,12 +3,12 @@ import { SVGAttributes } from 'react';
export default function AppLogoIcon(props: SVGAttributes<SVGElement>) {
return (
<svg {...props} viewBox="0 0 42 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="21.138" cy="16.5" r="15" stroke="#000" strokeWidth="3"/>
<path d="M21.138 15c-4.4-5.2-11-2.167-13.5 0 1.6-10.4 9.333-12 13-12 10.4.4 13.667 8.167 14 12-6.4-5.6-11.5-2.333-13.5 0Z" fill="#000" stroke="#000"/>
<circle cx="21.138" cy="16.5" r="15" stroke="currentColor" strokeWidth="3"/>
<path d="M21.138 15c-4.4-5.2-11-2.167-13.5 0 1.6-10.4 9.333-12 13-12 10.4.4 13.667 8.167 14 12-6.4-5.6-11.5-2.333-13.5 0Z" fill="currentColor" stroke="currentColor"/>
<circle cx="13" cy="17" r="2" fill="#FFA8BA"/>
<circle cx="29" cy="17" r="2" fill="#FFA8BA"/>
<path d="M5.638 11.5c-3.5 5.167-8.4 14.2 0 9v-9ZM36.638 11.5c3.5 5.167 8.4 14.2 0 9v-9Z" fill="#000" stroke="#000"/>
<path d="M5.638 11.5c-3.5 5.167-8.4 14.2 0 9v-9ZM36.638 11.5c3.5 5.167 8.4 14.2 0 9v-9Z" fill="currentColor" stroke="currentColor"/>
<path d="M21.736 18.768a1.28 1.28 0 0 1-1.472 0l-2.879-2.117c-.778-.572-.298-1.651.736-1.651h5.758c1.034 0 1.514 1.079.736 1.651l-2.88 2.117Z" fill="#FAAE2B"/>
</svg>
);
);
}

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,3 @@
import { NavFooter } from '@/components/nav-footer';
import { NavMain } from '@/components/nav-main';
import { NavUser } from '@/components/nav-user';
import {
@@ -13,7 +12,7 @@ import {
import { dashboard } from '@/routes';
import { type NavItem } from '@/types';
import { Link } from '@inertiajs/react';
import { BookOpen, Folder, LayoutGrid } from 'lucide-react';
import { LayoutGrid } from 'lucide-react';
import AppLogo from './app-logo';
const mainNavItems: NavItem[] = [
@@ -24,19 +23,6 @@ const mainNavItems: NavItem[] = [
},
];
const footerNavItems: NavItem[] = [
{
title: 'Repository',
href: 'https://github.com/laravel/react-starter-kit',
icon: Folder,
},
{
title: 'Documentation',
href: 'https://laravel.com/docs/starter-kits#react',
icon: BookOpen,
},
];
export function AppSidebar() {
return (
<Sidebar collapsible="icon" variant="inset">
@@ -44,7 +30,7 @@ export function AppSidebar() {
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" asChild>
<Link href={dashboard()} prefetch>
<Link href={dashboard()} prefetch className="text-foreground">
<AppLogo />
</Link>
</SidebarMenuButton>
@@ -57,7 +43,6 @@ export function AppSidebar() {
</SidebarContent>
<SidebarFooter>
<NavFooter items={footerNavItems} className="mt-auto" />
<NavUser />
</SidebarFooter>
</Sidebar>

View File

@@ -25,7 +25,7 @@ export function ScrollToTop() {
<button
onClick={scrollToTop}
aria-label="Retour en haut"
className="fixed bottom-6 right-6 z-50 p-3 rounded-full border-3 border-black bg-primary shadow-[4px_4px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-x-1 hover:translate-y-1 transition duration-200"
className="nb-shadow fixed bottom-6 right-6 z-50 p-3 rounded-full bg-primary"
>
<ChevronUp className="size-5" />
</button>

View File

@@ -9,7 +9,7 @@ export function AboutSection() {
subtitle="Le Retzien Libre, cest une association qui promeut lauto-hébergement et la décentralisation des services en ligne depuis 2017."
align='left'/>
<div
className="bg-white rounded-4xl border-3 border-black mt-10 px-10 pt-20 pb-10 shadow-[4px_4px_0px_rgba(0,0,0,1)]">
className="nb-shadow-static bg-white rounded-4xl mt-10 px-10 pt-20 pb-10">
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
<div className="flex flex-col gap-3 lg:border-r-2 border-black lg:pr-10 border-0">
<h3 className="text-xl text-primary font-semibold">Une association locale</h3>

View File

@@ -3,7 +3,7 @@ import {Service} from "@/types";
export function ServiceCard({title, colorTitle, bgColor, bgTitle, description, link, illustration}: Service) {
return (
<div
className={`flex gap-1 items-center bg-${bgColor} justify-center gap-4 rounded-4xl p-10 border-3 border-black shadow-[4px_4px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-2 transition delay-50 duration-200 ease-in-out`}>
className={`nb-shadow flex gap-1 items-center bg-${bgColor} justify-center gap-4 rounded-4xl p-10`}>
<div>
<div className="max-w-[150px]">
<h3 className={`inline text-2xl font-semibold text-${colorTitle} font-medium bg-${bgTitle} rounded p-1 line-clamp-2`}>{title}</h3>

View File

@@ -6,7 +6,7 @@ export function Footer() {
const currentYear = new Date().getFullYear();
return (
<footer className="gap-10 bg-accent rounded-t-4xl text-white py-10 px-20 mt-auto mx-5">
<footer className="gap-10 bg-accent dark:bg-primary rounded-t-4xl text-white py-10 px-20 mt-auto mx-5">
<div className="max-w-7xl mx-auto px-4 flex flex-col gap-8">
<div className="flex flex-col lg:flex-row justify-between gap-8">
<div className="flex flex-col gap-3">

View File

@@ -14,13 +14,13 @@ const buttonVariants = cva(
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
outline:
"bg-white shadow-sm hover:bg-background",
"bg-background text-foreground shadow-sm hover:bg-muted",
secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "bg-accent hover:text-accent-foreground hover:text-accent-foreground",
ghost: "bg-transparent text-foreground border-transparent shadow-none hover:bg-primary/10",
},
size: {
default: "h-10 px-4 py-2 shadow-[4px_4px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-2 transition delay-50 duration-200 ease-in-out",
default: "h-10 px-4 py-2 nb-shadow",
sm: "h-8 rounded-md px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",

View File

@@ -12,7 +12,7 @@ function Checkbox({
<CheckboxPrimitive.Root
data-slot="checkbox"
className={cn(
"border-3 border-black bg-white peer pr-0 data-[state=checked]:bg-black data-[state=checked]:text-white data-[state=checked]:border-black focus-visible:shadow-[4px_4px_0px_rgba(0,0,0,1)] transition duration-100 ease-in-out aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] shadow-xs outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
"flex items-center justify-center border-3 border-black bg-white peer data-[state=checked]:bg-black data-[state=checked]:text-white data-[state=checked]:border-black focus-visible:shadow-[4px_4px_0px_rgba(0,0,0,1)] transition duration-100 ease-in-out aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive w-5 h-5 aspect-square shrink-0 rounded-[4px] shadow-xs outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}

View File

@@ -40,7 +40,7 @@ function DropdownMenuContent({
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md",
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-xl border-2 border-black dark:border-border p-1 shadow-[4px_4px_0px_rgba(0,0,0,1)] dark:shadow-[4px_4px_0px_rgba(255,255,255,0.1)]",
className
)}
{...props}
@@ -72,7 +72,7 @@ function DropdownMenuItem({
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive-foreground data-[variant=destructive]:*:[svg]:!text-destructive-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-primary/15 focus:text-foreground data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive-foreground data-[variant=destructive]:*:[svg]:!text-destructive-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
@@ -90,7 +90,7 @@ function DropdownMenuCheckboxItem({
<DropdownMenuPrimitive.CheckboxItem
data-slot="dropdown-menu-checkbox-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-primary/15 focus:text-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
checked={checked}
@@ -126,7 +126,7 @@ function DropdownMenuRadioItem({
<DropdownMenuPrimitive.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-primary/15 focus:text-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
@@ -209,7 +209,7 @@ function DropdownMenuSubTrigger({
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
"focus:bg-primary/15 focus:text-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
className
)}
{...props}

View File

@@ -42,7 +42,7 @@ export function UserMenuContent({ user }: UserMenuContentProps) {
onClick={cleanup}
>
<Settings className="mr-2" />
Settings
Paramètres
</Link>
</DropdownMenuItem>
</DropdownMenuGroup>
@@ -56,7 +56,7 @@ export function UserMenuContent({ user }: UserMenuContentProps) {
data-test="logout-button"
>
<LogOut className="mr-2" />
Log out
Se déconnecter
</Link>
</DropdownMenuItem>
</>