117 lines
2.9 KiB
TypeScript
117 lines
2.9 KiB
TypeScript
"use client"
|
|
|
|
import { Fragment, useMemo } from "react"
|
|
import { Icon } from "@iconify/react"
|
|
import type { FolderTreeNode } from "@/lib/sidebar-nav-maps"
|
|
import type { LabelRowItem } from "@/lib/sidebar-nav-data"
|
|
import { breadcrumbItemsForVisitKey } from "@/lib/mail-folder-display"
|
|
import { resolveMailNavIcon } from "@/lib/mail-nav-icons"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
type MailFolderStackIndicatorProps = {
|
|
currentKey: string
|
|
folderTree: FolderTreeNode[]
|
|
folderIdToLabel: Record<string, string>
|
|
labelRows?: readonly LabelRowItem[]
|
|
className?: string
|
|
}
|
|
|
|
function MailNavIconGlyph({
|
|
visitKey,
|
|
folderTree,
|
|
labelRows,
|
|
}: {
|
|
visitKey: string
|
|
folderTree: FolderTreeNode[]
|
|
labelRows?: readonly LabelRowItem[]
|
|
}) {
|
|
const resolved = useMemo(
|
|
() => resolveMailNavIcon(visitKey, folderTree, labelRows),
|
|
[visitKey, folderTree, labelRows]
|
|
)
|
|
|
|
if (resolved.kind === "folder-dot") {
|
|
return (
|
|
<span
|
|
className={cn(
|
|
"inline-block size-4 shrink-0 rounded-full",
|
|
resolved.colorClass
|
|
)}
|
|
aria-hidden
|
|
/>
|
|
)
|
|
}
|
|
|
|
if (resolved.kind === "iconify") {
|
|
return (
|
|
<Icon
|
|
icon={resolved.icon}
|
|
className="size-4 shrink-0 text-[#5f6368]"
|
|
aria-hidden
|
|
/>
|
|
)
|
|
}
|
|
|
|
const { Icon: LucideIcon } = resolved
|
|
return (
|
|
<LucideIcon
|
|
className="size-4 shrink-0 text-[#5f6368]"
|
|
strokeWidth={1.5}
|
|
aria-hidden
|
|
/>
|
|
)
|
|
}
|
|
|
|
export function MailFolderStackIndicator({
|
|
currentKey,
|
|
folderTree,
|
|
folderIdToLabel,
|
|
labelRows,
|
|
className,
|
|
}: MailFolderStackIndicatorProps) {
|
|
const items = useMemo(
|
|
() => breadcrumbItemsForVisitKey(currentKey, folderTree, folderIdToLabel),
|
|
[currentKey, folderTree, folderIdToLabel]
|
|
)
|
|
|
|
const ariaLabel = items.map((i) => i.label).join(" · ")
|
|
|
|
return (
|
|
<div
|
|
role="status"
|
|
aria-live="polite"
|
|
aria-label={`Boîte actuelle : ${ariaLabel}`}
|
|
className={cn(
|
|
"flex max-w-[min(360px,calc(100vw-1rem))] items-center",
|
|
"border-t border-r border-[#dadce0]/90",
|
|
"bg-white/78 px-3.5 py-2.5 text-sm font-medium leading-snug text-[#3c4043]",
|
|
"rounded-tr-2xl shadow-sm backdrop-blur-md",
|
|
className
|
|
)}
|
|
>
|
|
<span className="flex min-w-0 items-center gap-1.5">
|
|
{items.map((item, i) => (
|
|
<Fragment key={`${item.visitKey}-${i}`}>
|
|
{i > 0 ? (
|
|
<span
|
|
className="shrink-0 text-xs leading-none text-[#9aa0a6]"
|
|
aria-hidden
|
|
>
|
|
·
|
|
</span>
|
|
) : null}
|
|
<span className="flex min-w-0 items-center gap-1.5">
|
|
<MailNavIconGlyph
|
|
visitKey={item.visitKey}
|
|
folderTree={folderTree}
|
|
labelRows={labelRows}
|
|
/>
|
|
<span className="truncate">{item.label}</span>
|
|
</span>
|
|
</Fragment>
|
|
))}
|
|
</span>
|
|
</div>
|
|
)
|
|
}
|