diff --git a/web/components/nav-main.test.mjs b/web/components/nav-main.test.mjs new file mode 100644 index 0000000..e8525d4 --- /dev/null +++ b/web/components/nav-main.test.mjs @@ -0,0 +1,11 @@ +import assert from "node:assert/strict" +import { readFile } from "node:fs/promises" +import test from "node:test" + +const source = await readFile(new URL("./nav-main.tsx", import.meta.url), "utf8") + +test("dashboard nav items expose full labels when visual text is truncated", () => { + assert.match(source, /\{title\}<\/span>/) + assert.match(source, /tooltip=\{item\.title\}/) + assert.match(source, /\{item\.title\}<\/span>/) +}) diff --git a/web/components/nav-main.tsx b/web/components/nav-main.tsx index 1aaf661..fc970e1 100644 --- a/web/components/nav-main.tsx +++ b/web/components/nav-main.tsx @@ -3,10 +3,9 @@ import { ChevronRightIcon } from "lucide-react" import Link from "next/link" import { usePathname } from "next/navigation" -import { useEffect, useState } from "react" +import { useState } from "react" import { - dashboardNavSectionHasActiveItem, getDashboardNavSectionStorageKey, isDashboardNavItemActive, parseDashboardNavSectionOpenState, @@ -42,7 +41,6 @@ export function NavMain({ }> }) { const pathname = usePathname() - const hasActiveItem = dashboardNavSectionHasActiveItem(items, pathname) const storageKey = getDashboardNavSectionStorageKey(sectionKey) const [open, setOpen] = useState(() => { if (typeof window === "undefined") { @@ -51,19 +49,6 @@ export function NavMain({ return parseDashboardNavSectionOpenState(window.localStorage.getItem(storageKey)) ?? true }) - useEffect(() => { - const storedOpen = parseDashboardNavSectionOpenState( - window.localStorage.getItem(storageKey) - ) - if (storedOpen !== undefined) { - setOpen(storedOpen) - return - } - if (hasActiveItem) { - setOpen(true) - } - }, [hasActiveItem, storageKey]) - const handleOpenChange = (nextOpen: boolean) => { setOpen(nextOpen) window.localStorage.setItem(storageKey, String(nextOpen)) @@ -80,7 +65,7 @@ export function NavMain({ > }> {icon} - {title} + {title} @@ -90,8 +75,9 @@ export function NavMain({ } isActive={isDashboardNavItemActive(pathname, item.url)} + tooltip={item.title} > - {item.title} + {item.title} ))} diff --git a/web/components/nav-secondary.tsx b/web/components/nav-secondary.tsx index 285156c..d02905e 100644 --- a/web/components/nav-secondary.tsx +++ b/web/components/nav-secondary.tsx @@ -37,9 +37,10 @@ export function NavSecondary({ } isActive={isActive(item.url)} + tooltip={item.title} > {item.icon} - {item.title} + {item.title} ))} diff --git a/web/components/ui/sidebar.tsx b/web/components/ui/sidebar.tsx index 0c48440..475071d 100644 --- a/web/components/ui/sidebar.tsx +++ b/web/components/ui/sidebar.tsx @@ -668,14 +668,17 @@ function SidebarMenuSubButton({ render, size = "md", isActive = false, + tooltip, className, ...props }: useRender.ComponentProps<"a"> & React.ComponentProps<"a"> & { size?: "sm" | "md" isActive?: boolean + tooltip?: string | React.ComponentProps }) { - return useRender({ + const { isMobile } = useSidebar() + const comp = useRender({ defaultTagName: "a", props: mergeProps<"a">( { @@ -686,7 +689,7 @@ function SidebarMenuSubButton({ }, props ), - render, + render: !tooltip ? render : , state: { slot: "sidebar-menu-sub-button", sidebar: "menu-sub-button", @@ -694,6 +697,23 @@ function SidebarMenuSubButton({ active: isActive, }, }) + + if (!tooltip) { + return comp + } + + if (typeof tooltip === "string") { + tooltip = { + children: tooltip, + } + } + + return ( + + {comp} + + ) } export {