Workspace Switcher

Segmented workspace picker for switching between canvas views and operational contexts. Install Workspace Switcher from the VLLNT UI registry with the shadcn CLI.

Report a bug

What it is and when to use

Workspace Switcher is a compact, segmented control for moving between workspaces, canvas views, or operational contexts. It renders each option as a pill inside a radio group, highlighting the active one, and works either controlled or uncontrolled through value and defaultValue props. An onValueChange callback reports selection, and each option can carry a description shown as a tooltip and, on wider screens, inline. Reach for it when users toggle between a handful of top-level contexts rather than navigating a deep menu.

Navigation

Segmented workspace picker for switching between canvas views and operational contexts. Part of the navigation family in VLLNT UI, it ships as a machine-readable registry entry — copy the source directly into your app with the shadcn CLI and own it, no runtime dependency on a component library.

Preview

Switch between light and dark to inspect the embedded Storybook preview.

Installation

Add Workspace Switcher to your project with the shadcn CLI. The source lands in your codebase, ready to adapt:

pnpm dlx shadcn@latest add https://ui.vllnt.com/r/workspace-switcher.json

Source

"use client"; import { useMemo, useState } from "react"; import { cn } from "../../lib/utils"; export type WorkspaceOption = { description?: string; id: string; label: string; }; export type WorkspaceSwitcherProps = Omit< React.ComponentPropsWithoutRef<"div">, "defaultValue" | "onChange" > & { defaultValue?: string; onValueChange?: (value: string) => void; value?: string; workspaces: WorkspaceOption[]; }; const WorkspaceSwitcher = ({ className, defaultValue, onValueChange, ref, value, workspaces, ...props }: WorkspaceSwitcherProps & { ref?: React.Ref<HTMLDivElement> }) => { const fallbackValue = defaultValue ?? workspaces[0]?.id ?? ""; const [internalValue, setInternalValue] = useState(fallbackValue); const currentValue = value ?? internalValue; const currentWorkspace = useMemo( () => workspaces.find((workspace) => workspace.id === currentValue), [currentValue, workspaces], ); function handleSelect(nextValue: string) { if (value === undefined) { setInternalValue(nextValue); } onValueChange?.(nextValue); } return ( <div className={cn( "inline-flex min-w-0 items-center gap-1 rounded-full border border-border/70 bg-muted/50 p-1", className, )} ref={ref} role="radiogroup" {...props} > {workspaces.map((workspace) => { const isActive = workspace.id === currentValue; return ( <button aria-checked={isActive} className={cn( "rounded-full px-3 py-1.5 text-sm font-medium transition-colors", isActive ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground", )} key={workspace.id} onClick={() => { handleSelect(workspace.id); }} role="radio" title={workspace.description} type="button" > {workspace.label} </button> ); })} {currentWorkspace?.description ? ( <span className="hidden pl-2 pr-1 text-xs text-muted-foreground md:inline"> {currentWorkspace.description} </span> ) : null} </div> ); }; WorkspaceSwitcher.displayName = "WorkspaceSwitcher"; export { WorkspaceSwitcher };

Stories

Explore every variant and state in the interactive Storybook:

Preview

Switch between light and dark to inspect the embedded Storybook preview.

Dependencies

  • @vllnt/ui@^0.3.0

FAQ

What is Workspace Switcher?
Workspace Switcher is a React component that renders a segmented pill control for switching between workspaces, canvas views, or operational contexts. Options are supplied as an array of id and label pairs, and the active one is visually highlighted.
How do I add Workspace Switcher?
Run `pnpm dlx shadcn@latest add https://ui.vllnt.com/r/workspace-switcher.json` to install it into your React project via the shadcn CLI, then pass your workspaces array to the WorkspaceSwitcher component.
Is Workspace Switcher controlled or uncontrolled?
It works both ways. Pass value with onValueChange for a controlled component, or defaultValue to let it manage its own selection. It renders as an accessible radio group, marking the selected workspace with aria-checked.