App Switcher
The AppSwitcher component provides a Google-style application switcher. It renders a trigger button that opens a popover containing a grid of application shortcuts. Each tile intelligently resolves its visual representation using an icon, an image, or an initials fallback, and fully supports both internal SPA navigation and external absolute URLs.
Features
- Intelligent Tile Resolution: Supports vector
icon(Nuxt Icon), rasterimage(URL or public path), or an automatic initials fallback for each app. - Configurable Grid: Customize the number of columns in the popover via the
columnsprop. - SPA & External Navigation: Uses a standard
toproperty, allowing internal paths to trigger SPA navigation and absolute URLs to perform a full application switch. - Popover Footer: Optional footer link (similar to Google's "More from..." row).
- Seamless Navigation Bar Integration: Easily added to the
NavigationBarvia theotherAppsprop or therightPreItemsslot.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
apps | AppSwitcherApp[] | Yes | Array of application entries to display in the grid. | |
triggerIcon | string | No | "i-lucide-grip" | Nuxt Icon name for the trigger button. |
triggerLabel | string | No | "Apps" | Accessible label (aria-label) for the trigger button. |
columns | number | No | 3 | Number of columns in the app switcher grid. |
footerTo | string | No | Optional link URL shown in the popover footer. | |
footerLabel | string | No | "More" | Label for the optional popover footer link. |
AppSwitcherApp Interface
Each entry in the apps array conforms to the exported AppSwitcherApp interface:
export interface AppSwitcherApp {
/** Name of the application, displayed below the tile. */
name: string;
/** Router path (internal SPA nav) or absolute URL (full app switch). */
to: string;
/** Nuxt Icon name, e.g. "i-lucide-mail". Takes precedence over `image`. */
icon?: string;
/** URL or public/ path to a raster image. Used only when `icon` is unset. */
image?: string;
/** Optional alt text for the image; defaults to `name`. */
alt?: string;
}Slots
| Slot | Description |
|---|---|
top | Optional content rendered above the apps grid. |
bottom | Optional content rendered below the apps grid. Overrides the default footer link generated by the props. |
Usage
Basic Implementation
To use the AppSwitcher, define an array of AppSwitcherApp objects and pass it to the apps prop.
<script setup lang="ts">
import type { AppSwitcherApp } from "@dcc-bs/common-ui.bs.js/components";
const apps: AppSwitcherApp[] = [
{ name: "Mail", to: "https://mail.google.com", icon: "i-lucide-mail" },
{ name: "Calendar", to: "https://calendar.google.com", icon: "i-lucide-calendar" },
{
name: "Maps",
to: "https://maps.google.com",
image: "https://www.google.com/images/branding/product/1x/maps_64dp.png",
},
{ name: "Drive", to: "https://drive.google.com" } // Falls back to 'D' initial
];
</script>
<template>
<AppSwitcher :apps="apps" />
</template>Adding a Footer Link
You can add a link to the bottom of the popover using the footerTo and footerLabel props.
<template>
<AppSwitcher
:apps="apps"
footer-to="https://about.google/products/"
footer-label="More"
/>
</template>Customizing the Grid and Trigger
Adjust the grid layout by changing the number of columns, and swap out the trigger icon using triggerIcon.
<template>
<AppSwitcher
:apps="apps"
trigger-icon="i-lucide-layout-grid"
:columns="2"
/>
</template>Tile Resolution Logic
When rendering an application tile, the component determines its visual representation using the following priority (first match wins):
- Icon (
icon): If provided, renders a vector Nuxt Icon. This is SSR-safe and requires no external image assets, making it the preferred choice for logos. - Image (
image): Ificonis omitted butimageis provided, renders a standard<img>tag. This accepts external URLs or local paths from yourpublic/directory. - Initials Fallback: If neither
iconnorimageis provided, the component generates a tinted tile using the first letter of the application'sname.
Integration with NavigationBar
The AppSwitcher is commonly placed inside the NavigationBar. You can either insert it manually via the rightPreItems slot, or use the otherApps prop directly on the NavigationBar for seamless integration.
Using the otherApps prop
<script setup lang="ts">
import type { AppSwitcherApp } from "@dcc-bs/common-ui.bs.js/components";
const apps: AppSwitcherApp[] = [
{ name: "Mail", to: "https://mail.google.com", icon: "i-lucide-mail" },
{ name: "Docs", to: "https://docs.google.com", icon: "i-lucide-file-text" }
];
</script>
<template>
<NavigationBar :other-apps="apps" />
</template>Using the rightPreItems Slot
<template>
<NavigationBar>
<template #rightPreItems>
<AppSwitcher :apps="apps" />
</template>
</NavigationBar>
</template>