Account Switcher
ilinxa/account-switcherFreeBlock
Popover account and context switcher — active label trigger, switchable context list, and a footer slot for create or request actions.
Install it
npx shadcn@latest add https://ui.ilinxa.com/r/account-switcher.jsonSource
1"use client";23import { useCallback, useId, useMemo } from "react";4import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";5import { Separator } from "@/components/ui/separator";6import { cn } from "@/lib/utils";7import { useControllableState } from "./hooks/use-controllable-state";8import { enforceUniqueKeys } from "./lib/enforce-unique-keys";9import { resolveActiveItem } from "./lib/resolve-active-item";10import { EmptyPlaceholder } from "./parts/empty-placeholder";11import { SwitcherItemRow } from "./parts/switcher-item-row";12import {13 SwitcherTriggerContent,14 composeSwitcherTriggerAriaLabel,15 switcherTriggerClassName,16} from "./parts/switcher-trigger";17import type { AccountSwitcherProps, SwitcherItem } from "./types";1819const DEFAULT_ARIA_LABEL = "Switch account context";2021/**22 * Account Switcher — popover-with-switchable-items primitive.23 *24 * See [`docs/procomps/account-switcher-procomp/`](../../../../../docs/procomps/account-switcher-procomp/)25 * for description + plan + guide. Locks L1–L14, all PQs at default per26 * 2026-05-23 GATE 2 close.27 */28export function AccountSwitcher(props: AccountSwitcherProps) {29 const {30 items,31 activeKey,32 onSelect,33 fallbackActiveItem,34 footerSlot,35 isCollapsed = false,36 collapsedPopoverSide = "right",37 "aria-label": ariaLabel = DEFAULT_ARIA_LABEL,38 ariaCurrent = "true",39 open: openProp,40 defaultOpen,41 onOpenChange,42 className,43 } = props;4445 const listboxId = useId();4647 const [open, setOpen] = useControllableState<boolean>({48 value: openProp,49 defaultValue: defaultOpen ?? false,50 onChange: onOpenChange,51 componentName: "account-switcher",52 valuePropName: "open",53 });5455 // L3 + Q2 — dev-warn + strip duplicates once per items reference change.56 const dedupedItems = useMemo(() => enforceUniqueKeys(items), [items]);5758 const activeResolution = useMemo(59 () => resolveActiveItem(dedupedItems, activeKey, fallbackActiveItem),60 [dedupedItems, activeKey, fallbackActiveItem],61 );6263 const activeItem = activeResolution.kind === "empty" ? null : activeResolution.item;6465 // F-cross-13 guard at the shadcn-primitive boundary. The consumer's66 // `onOpenChange` is shielded — `useControllableState` always calls it with67 // the validated `boolean`. Plan §10.68 const handlePrimitiveOpenChange = useCallback(69 (next: unknown) => {70 if (typeof next !== "boolean") return;71 setOpen(next);72 },73 [setOpen],74 );7576// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from ilinxa
All 184 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Account Switcher (deprecated alias)account-switcher-01 | ilinxa | Blocks | Free | no deps | |
| Account Switcher — fixturesaccount-switcher-fixtures | ilinxa | Blocks | Free | no deps | |
| App Sidebarapp-sidebar | ilinxa | Blocks | Free | 1 dep · 37 files | |
| App Sidebar — fixturesapp-sidebar-fixtures | ilinxa | Blocks | Free | no deps | |
| Rich Text Editor (deprecated alias)article-body-01 | ilinxa | Blocks | Free | no deps | |
| Article Metaarticle-meta | ilinxa | Blocks | Free | 1 dep · 4 files | |
| Article Meta (deprecated alias)article-meta-01 | ilinxa | Blocks | Free | no deps | |
| Article Meta — fixturesarticle-meta-fixtures | ilinxa | Blocks | Free | no deps |
