Header "apps" grid - a button opening a panel of tiles that link to other systems
Tags: component apps launcher grid header links
AppLauncher is the "apps" button in a header: a grid icon that opens a panel of tiles, one per system people jump to - the API, reports, docs, the ERP, a password vault. Put it in DashboardLayout's headerEnd, next to the account menu.
Tiles are real links, so Ctrl/middle-click open a new tab; external tiles open in a new tab anyway and say so to screen readers. Arrow keys move between tiles (Up/Down by row), Home/End jump to the first and last, Escape closes and returns focus to the button. Picking a tile closes the panel.
Svelte only for now.
Import
<script>
import { AppLauncher } from '@classic-homes/theme-svelte';
</script>Basic Usage
<script>
import { AppLauncher } from '@classic-homes/theme-svelte';
const apps = [
{ id: 'reports', label: 'Reports', href: '/reports', icon: 'bar-chart-2' },
{
id: 'docs',
label: 'Documentation',
href: 'https://docs.example.com',
icon: 'book-open',
external: true,
},
{
id: 'vault',
label: 'Passwords',
href: 'https://vault.example.com',
icon: 'key',
external: true,
},
];
</script>
<AppLauncher {apps} title="Classic Homes apps" />Custom icons
The icon snippet draws a tile's icon instead of item.icon - for an app with its own mark.
<AppLauncher {apps}>
{#snippet icon(app)}
{#if app.id === 'field-app'}
<FieldAppIcon size={22} />
{:else}
<Icon name={app.icon ?? 'external-link'} size={22} />
{/if}
{/snippet}
</AppLauncher>The grid on its own
AppLauncherGrid is the panel's tile grid without the button and popover - for showing the apps elsewhere, such as a bottom Sheet opened from a phone's overflow menu. Same tiles and arrow-key navigation; onSelect runs when a tile is picked.
<script>
import { AppLauncherGrid, Sheet } from '@classic-homes/theme-svelte';
let open = $state(false);
</script>
<Sheet bind:open side="bottom" title="Apps">
<AppLauncherGrid {apps} label="Apps" columns={4} onSelect={() => (open = false)} />
</Sheet>AppLauncherGrid props: apps, label (accessible name, required), title, columns (3), onSelect, icon snippet, class.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
apps |
AppLauncherItem[] |
required | Tiles: { id, label, href, icon?, external?, description? } |
title |
string |
- | Heading at the top of the panel |
triggerLabel |
string |
"Apps" |
Accessible name of the button and panel |
columns |
number |
3 |
Tiles per row |
align |
'start' | 'center' | 'end' |
'end' |
Panel alignment against the button |
open |
boolean |
false |
Panel open (bindable) |
onOpenChange |
(open: boolean) => void |
- | Called when the panel opens or closes |
icon |
Snippet<[AppLauncherItem]> |
- | Draws a tile's icon |
class |
string |
- | Classes for the panel |
triggerClass |
string |
- | Classes for the button |
description becomes the tile's tooltip.
Accessibility
- The button is named by
triggerLabel; the panel is anavnamed bytitle(elsetriggerLabel). - Tiles are links; external ones carry "(opens in a new tab)" for screen readers.
- Arrow keys, Home and End move focus between tiles; Escape closes and returns focus to the button.