# Club Switcher

> The club you're in, with its kit flag, name, and your roles, that opens a menu of every club you belong to.

- Name: `club-switcher`
- Status: beta
- Categories: navigation
- File: the install writes `club-switcher.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `@base-ui/react`, `lucide-react`. The install adds them.
- Other registry items: `@arbokui/menu`, `@arbokui/team-flag`. The install adds them.
- Gallery: https://arbokui.com/components/club-switcher
- Registry item: https://arbokui.com/r/club-switcher.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/club-switcher
   ```

## Use it for

- The top of an app's rail, for people in more than one club: a coach in one, a parent in another.
- Give each club an id, its name, its kit colors for the TeamFlag, and your roles there, like "Coach · Admin".
- Pressing it opens every club under it, with a check on the current one. Pass onJoin to end the menu with Join another club.
- Pass value and onChange to control it, or defaultValue to start in a club. Without either it starts in the first.
- Use inline to draw the open menu in a card or a doc, with no button.

## Avoid it for

- Drawing a club's crest. Its kit colors stand in for it. Brand logos are never drawn.
- Someone in one club only. Show the club's name and flag as plain text.
- Switching teams inside one club. Use a select or tabs.

## Props

- `clubs`: `{ id: string; name: string; colors?: [string, string]; pattern?: "hoops" | "halves" | "thirds" | "split"; role?: string }[]`. Required. Every club you belong to. colors are CSS colors from your data, set only on the flag's own style.
- `value`: `string`. The club you're in. Controlled, with onChange.
- `defaultValue`: `string`. The club you start in. Default the first.
- `onChange`: `(id: string) => void`. Runs with the club's id when you switch.
- `onJoin`: `() => void`. Offers "Join another club" at the end of the menu.
- `inline`: `boolean`. Default `false`. Draws the open menu in the page's flow, with no button. Nothing closes it.
- `className`: `string`. Extra classes on the button, or on the menu with inline. Later classes win.

## Accessibility

- The button is named by the club and your roles, and says it opens a menu.
- The menu opens with focus on your club. The arrow keys move without wrapping, Home and End go to the ends, letters jump to a club, Enter switches, and Esc closes it and puts focus back.
- Each club is a menuitemradio, checked for the one you're in. The check is drawn, not only colored.
- Inline, the menu is one Tab stop that lands on your club, with the same keys. Nothing closes it.
- The kit flag is hidden from screen readers, since the name beside it says the club.

## Examples

### At the top of a rail

```tsx
<ClubSwitcher
  clubs={[
    { id: "rovers", name: "Rovers", colors: ["#1e3a8a", "#ffffff"], pattern: "hoops", role: "Coach · Admin" },
    { id: "saints", name: "Saints", colors: ["#b91c1c", "#111827"], role: "Parent of Ava" },
  ]}
  defaultValue="rovers"
  onChange={(id) => console.log("switch to", id)}
  onJoin={() => console.log("join")}
/>
```
