# SidebarAppLauncher


`src/lib/components/sidebar/SidebarAppLauncher.svelte`

## Purpose

A sidebar menu button that shows the current `{app} / {module}` context and
opens a `Popover` panel with three columns: **Applications** (root levels),
**Modules** of the previewed app, and **Pages** of the previewed module under
that app. It replaces the old root/module switchers with a single
Finder-style cascade.

Column data comes straight from `shellNav` (the module discovery payload):
applications from `shellNav.roots`, modules from `shellNav.modulesForRoot(app)`,
pages from `ModuleInfo.nav` filtered to the previewed app root — already
access-filtered server-side, no second fetch. Selecting a module lazily loads
its translation dictionary via `loadModuleTranslations`.

## Select vs activate semantics

Selection and navigation are deliberately separate (touch + keyboard parity):

- **Selecting a row** (tap / click / arrow focus) only *previews* the next
  column — it never navigates.
- **Activating** lives on the trailing icon-only CTA (`ArrowUpRight`), or on
  Enter/Space for keyboard users. A page row is a leaf — its whole row IS the
  goto.

The activation chain follows the defaults declared in metadata:

| Row | Activation target |
|-----|-------------------|
| App CTA | the app's `is_default` module → its first page under that app |
| Module CTA | the module's first page under the previewed app |
| Page row | direct navigation to `item.href` |

## Behavior details

- The panel is always visible (even with a single app level) and opens on the
  current route's context — preview state resets on every open.
- Panel height ratchets between 4 and 12 rows (44px touch targets); within an
  open session it only grows — no jarring shrink on preview changes — and
  height changes animate.
- Keyboard: roving tabindex per column, arrows move focus (focus previews),
  Left/Right traverse columns with wrap, Enter/Space activates, Esc closes.
- A keyboard-hints footer (`Kbd`) summarizes the bindings.
- Disabled modules (`enabled === false`) render dimmed and skip activation.
- When `collapsed` is true the trigger shows only the app icon tile; the
  `{app} / {module}` label and chevron hide.

## Origin

**Custom** — Primebrick-written. Uses shadcn-svelte™ `Popover` + `Sidebar`
primitives, `DynamicIcon`, `Kbd`, and `@lucide/svelte` icons.

## Usage

### Default (mounted in AppSidebar content)

```svelte
<SidebarAppLauncher {collapsed} />
```

### Module activation wiring

Activating a module calls `shellNav.selectModule`, then navigates to the
module's home inside the previewed app root (`home[root]` from the discovery
payload, else the module's first nav entry under that root).

```svelte
<button onclick={(e) => { e.stopPropagation(); void activateModule(m); }}>
  <ArrowUpRight />
</button>
```

## Props

Full prop table: see [API reference — sidebarapplauncher](/frontend/dev/api-reference#sidebarapplauncher).

Key props: `collapsed: boolean` (whether the sidebar is in icon-only mode).

## Next steps

- [Component catalog](/frontend/dev/components)
- [App shell & sidebar](/frontend/dev/app-shell)
- [API reference](/frontend/dev/api-reference#sidebarapplauncher)
