ultisuite-client/components/gmail/mobile-bottom-bar.tsx
R3D347HR4Y 9266aa34cd huhu
2026-05-19 22:20:43 +02:00

170 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useState, useRef, useEffect, useCallback } from "react"
import {
Menu,
Search,
X,
Pencil,
Archive,
FolderInput,
Reply,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { useComposeActions } from "@/lib/compose-context"
import { MoveToDropdownItems } from "@/components/gmail/move-to-menu-items"
import { MAIL_MENU_SURFACE_CLASS } from "@/lib/mail-chrome-classes"
import type { MailXsViewChrome } from "@/lib/mail-xs-view-chrome"
import { cn } from "@/lib/utils"
interface MobileBottomBarProps {
sidebarOpen: boolean
onToggleSidebar: () => void
/** Lecture message xs : barre dactions à la place du menu / recherche. */
xsViewChrome?: MailXsViewChrome | null
}
const ROUNDED_BAR_BTN =
"size-11 shrink-0 rounded-full border border-gray-200 bg-white/80 text-[#444746] shadow-md backdrop-blur hover:bg-white"
export function MobileBottomBar({
sidebarOpen,
onToggleSidebar,
xsViewChrome = null,
}: MobileBottomBarProps) {
const [searchValue, setSearchValue] = useState("")
const inputRef = useRef<HTMLInputElement>(null)
const { openCompose } = useComposeActions()
const inMailView = Boolean(xsViewChrome)
const hasSearch = searchValue.length > 0
const handleClear = useCallback(() => {
setSearchValue("")
inputRef.current?.focus()
}, [])
useEffect(() => {
if (sidebarOpen) {
inputRef.current?.blur()
}
}, [sidebarOpen])
return (
<div className="fixed inset-x-0 bottom-0 z-50 flex flex-col items-center pb-[env(safe-area-inset-bottom)] sm:hidden">
<div className={cn(
"pointer-events-none absolute inset-0 bg-gradient-to-t to-transparent",
inMailView
? "from-black/90 via-black/50"
: "from-mail-surface/95 via-mail-surface/70 dark:from-background/95 dark:via-background/70"
)} />
<div className="relative z-10 flex w-full items-center gap-2 px-3 pb-3 pt-2">
{inMailView && xsViewChrome ? (
<div className="flex shrink-0 overflow-hidden rounded-full border border-gray-200 bg-white/80 shadow-md backdrop-blur">
<Button
type="button"
variant="ghost"
size="icon"
className="size-11 rounded-none text-[#444746] hover:bg-[#f1f3f4]"
onClick={xsViewChrome.onArchive}
aria-label="Archiver"
>
<Archive className="size-5" strokeWidth={1.5} />
</Button>
<span className="w-px shrink-0 self-stretch bg-gray-200" aria-hidden />
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
type="button"
variant="ghost"
size="icon"
className="size-11 rounded-none text-[#444746] hover:bg-[#f1f3f4]"
aria-label="Déplacer dans un dossier"
>
<FolderInput className="size-5" strokeWidth={1.5} />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
side="top"
sideOffset={8}
className={cn(MAIL_MENU_SURFACE_CLASS, "max-h-80 overflow-y-auto")}
>
<MoveToDropdownItems
targets={xsViewChrome.moveTargets}
onMoveTo={xsViewChrome.onMoveTo}
/>
</DropdownMenuContent>
</DropdownMenu>
<span className="w-px shrink-0 self-stretch bg-gray-200" aria-hidden />
<Button
type="button"
variant="ghost"
size="icon"
className="size-11 rounded-none text-[#444746] hover:bg-[#f1f3f4]"
onClick={xsViewChrome.onReply}
aria-label="Répondre"
>
<Reply className="size-5" strokeWidth={1.5} />
</Button>
</div>
) : (
<>
<Button
variant="ghost"
size="icon"
className={ROUNDED_BAR_BTN}
onClick={onToggleSidebar}
aria-label={sidebarOpen ? "Fermer le menu" : "Ouvrir le menu"}
>
{sidebarOpen ? (
<X className="size-5" />
) : (
<Menu className="size-5" />
)}
</Button>
{!sidebarOpen && (
<div className="relative flex min-w-0 flex-1 items-center">
<div className="pointer-events-none absolute left-3 z-10 flex items-center text-gray-500">
<Search className="size-5" />
</div>
<input
ref={inputRef}
type="text"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
placeholder="Rechercher"
className="h-11 w-full rounded-full border border-gray-200 bg-white/80 pl-10 pr-4 text-sm shadow-md backdrop-blur outline-none placeholder:text-gray-400 focus:ring-2 focus:ring-blue-500/40"
/>
</div>
)}
</>
)}
{!sidebarOpen && (
<Button
variant="ghost"
size="icon"
className={cn(ROUNDED_BAR_BTN, inMailView && "ml-auto")}
onClick={inMailView || !hasSearch ? openCompose : handleClear}
aria-label={!inMailView && hasSearch ? "Effacer la recherche" : "Nouveau message"}
>
{!inMailView && hasSearch ? (
<X className="size-5" />
) : (
<Pencil className="size-5" />
)}
</Button>
)}
</div>
</div>
)
}