Skip to main content

AppLauncher

AppLauncher

Header "apps" grid - a button opening a panel of tiles that link to other systems

Tags: component apps launcher grid header links

View Demo

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 a nav named by title (else triggerLabel).
  • 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.
On this page