"use client" /** * UtilityBarProductSwitcher — product switcher trigger for the "utility-bar" * shell layout variant (`useShellLayout()`). Same product data + dropdown * rows as the sidebar's `ProductLogoButton`, but: * - plain `Button` trigger, not `SidebarMenuButton` (no icon-rail/collapsed * concept in a horizontal bar — always renders the full wordmark). * - Round mark matches utility-bar profile avatar — * **size-8 frame, size-7 mark**. `px-2` insets the pill on the sides; * height stays `h-9` so vertical air stays tight (mark fills most of it). * - `ExxatProductLogo variant="utility-bar" mark="external"` — suffix-only * wordmark at `text-sm` density beside the rail mark. * - tooltip + dropdown open downward (`side="bottom"`), matching every * other utility-bar trigger, instead of `side="right"`. * * See `apps/web/components/sidebar/app-sidebar.tsx` `ProductLogoButton` for * the sidebar-variant sibling — keep the two in sync if product-switching * behavior changes. */ import * as React from "react" import { ExxatProductLogo, ExxatProductMark } from "@/components/exxat-product-logo" import { PRODUCT_SWITCHER_MENU_SURFACE_CLASS, ProductSwitcherMenuItems, } from "@/components/product-switcher-menu-items" import { Button } from "@/components/ui/button" import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip" import { useProduct } from "@/contexts/product-context" import { utilityBarActionButtonClass } from "@/components/utility-bar-chrome" import { cn } from "@/lib/utils" import { expandSwitcherProducts, resolveActiveSwitcherEntry, type SwitcherProductEntry, } from "@/lib/product-switcher-catalog" export function UtilityBarProductSwitcher() { const { product, customProducts, activeCustomIndex, hiddenProducts } = useProduct() const products = React.useMemo( () => expandSwitcherProducts(customProducts, hiddenProducts), [customProducts, hiddenProducts], ) const isCurrentProduct = React.useCallback( (entry: SwitcherProductEntry) => entry.id === product && (entry.customIndex === undefined || entry.customIndex === activeCustomIndex), [activeCustomIndex, product], ) const current = resolveActiveSwitcherEntry( products, product, activeCustomIndex, customProducts, isCurrentProduct, ) const previewCustomBrand = current.customIndex !== undefined ? customProducts[current.customIndex] : undefined return (