App Switcher
<sl-app-switcher> | SlAppSwitcher
App switcher provides a trigger button in the application header that opens a panel of links. On desktop
the panel appears as a dropdown, while on tablet/mobile it slides in from the left inside an
<sl-drawer>.
sl-app-switcher renders a complete switchable-app panel that includes its own trigger
buttons. On desktop viewports (>989 px) it wraps the panel in an sl-dropdown; on
tablet and mobile it uses a slide-in sl-drawer. The component closes automatically when
the user resizes across the breakpoint.
Add entries by slotting sl-app-tile elements.
Tiles in the default slot form the primary section; tiles in the secondary slot form a
second section shown under the optional secondary-label heading. The divider appears only
when both sections have content. Preview tiles use href="#" placeholders; their default
navigation is prevented to avoid jumping to the top of the page.
<sl-app-switcher id="switcher-basic" secondary-label="Integrations" mobile-header-img-url="/assets/images/hub24.svg"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="myHUB" href="#" icon-src="/assets/images/logo-icon-myhub.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile label="NowInfinity" href="#" icon-src="/assets/images/logo-icon-ni.svg"></sl-app-tile> <sl-app-tile slot="secondary" label="Chrome" href="#" icon-src="/assets/images/chrome.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Firefox" href="#" icon-src="/assets/images/firefox.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Edge" href="#" icon-src="/assets/images/edge.png"></sl-app-tile> </sl-app-switcher> <script> document.addEventListener( 'click', event => { const tile = event.composedPath().find( element => element instanceof Element && element.matches('sl-app-tile[href="#"]') ); if (tile) event.preventDefault(); }, true ); </script>
Examples
Primary Only
Leave the secondary slot empty to show only the primary section without a heading or
divider.
<sl-app-switcher id="switcher-apps-only"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="myHUB" href="#" icon-src="/assets/images/logo-icon-myhub.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> </sl-app-switcher>
Few Tiles
The desktop panel keeps a two-column minimum, so one or two tiles don’t collapse it into a narrow
strip. With three or more tiles it expands to three columns. Adjust
--app-switcher-tile-size to scale the standard tile width the panel lays out against.
<sl-app-switcher id="switcher-two-tiles"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> </sl-app-switcher>
Tile Size Is Standardised
The switcher standardises slotted tiles to the medium presentation, so a tile’s own
size attribute is ignored inside the switcher. Here the second tile sets
size="large" but still matches the others.
<sl-app-switcher id="switcher-size-normalised"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile size="large" label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile label="myHUB" href="#" icon-src="/assets/images/logo-icon-myhub.svg"></sl-app-tile> </sl-app-switcher>
Tiles in a row share the same height, so the icons and primary labels stay aligned even when only some
tiles have a sub-label.
<sl-app-switcher id="switcher-sublabels-mixed"> <sl-app-tile label="HUB24" sub-label="Platform" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="Class" sub-label="SMSF" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> </sl-app-switcher>
Secondary Section
Put tiles in the secondary slot and set secondary-label to add a labelled
second section.
<sl-app-switcher id="switcher-ints-only" secondary-label="Integrations"> <sl-app-tile slot="secondary" label="Chrome" href="#" icon-src="/assets/images/chrome.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Firefox" href="#" icon-src="/assets/images/firefox.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Edge" href="#" icon-src="/assets/images/edge.png"></sl-app-tile> </sl-app-switcher>
Scrolling
The desktop panel caps its height at 800px. When the combined sections exceed that, the
panel scrolls internally instead of growing taller.
<sl-app-switcher id="switcher-scroll" secondary-label="Integrations"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="myHUB" href="#" icon-src="/assets/images/logo-icon-myhub.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile label="NowInfinity" href="#" icon-src="/assets/images/logo-icon-ni.svg"></sl-app-tile> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="myHUB" href="#" icon-src="/assets/images/logo-icon-myhub.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile label="NowInfinity" href="#" icon-src="/assets/images/logo-icon-ni.svg"></sl-app-tile> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="myHUB" href="#" icon-src="/assets/images/logo-icon-myhub.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile label="NowInfinity" href="#" icon-src="/assets/images/logo-icon-ni.svg"></sl-app-tile> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="myHUB" href="#" icon-src="/assets/images/logo-icon-myhub.svg"></sl-app-tile> <sl-app-tile slot="secondary" label="Chrome" href="#" icon-src="/assets/images/chrome.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Firefox" href="#" icon-src="/assets/images/firefox.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Edge" href="#" icon-src="/assets/images/edge.png"></sl-app-tile> </sl-app-switcher>
Footer Slot
Use the footer slot to pin content — such as a button — to the bottom-left of the desktop
panel.
<sl-app-switcher id="switcher-footer" secondary-label="Integrations"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="myHUB" href="#" icon-src="/assets/images/logo-icon-myhub.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile label="NowInfinity" href="#" icon-src="/assets/images/logo-icon-ni.svg"></sl-app-tile> <sl-app-tile slot="secondary" label="Chrome" href="#" icon-src="/assets/images/chrome.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Firefox" href="#" icon-src="/assets/images/firefox.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Edge" href="#" icon-src="/assets/images/edge.png"></sl-app-tile> <sl-button slot="footer" size="small" variant="secondary"> Manage integrations <sl-icon slot="suffix" name="arrow-right"></sl-icon> </sl-button> </sl-app-switcher>
Keep Open on Select
Selecting a primary or secondary tile closes the panel by default. Add
stay-open-on-select to keep the panel open after a tile is selected.
<sl-app-switcher id="switcher-stay-open" stay-open-on-select secondary-label="Integrations"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile slot="secondary" label="Chrome" href="#" icon-src="/assets/images/chrome.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Firefox" href="#" icon-src="/assets/images/firefox.png"></sl-app-tile> </sl-app-switcher>
Mobile Header Image
Use the mobile-header-img-url attribute to display a logo or branding image in the
top-left corner of the mobile drawer header.
<sl-app-switcher id="switcher-mobile-header" mobile-header-img-url="/assets/images/hub24.svg"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> </sl-app-switcher>
Dark Trigger
Add the dark attribute when the trigger sits on a dark surface (e.g. a dark app header) —
it makes the trigger icon light. The panel is a separate surface and stays light; control its
background independently with --app-switcher-panel-bg.
<sl-app-header-hds> <img slot="app-logo" src="/dist/images/hub24_logo_primary_reverse.svg" alt="app logo" /> <sl-app-switcher slot="app-switcher" dark id="switcher-header" secondary-label="Integrations" mobile-header-img-url="/assets/images/hub24.svg"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile slot="secondary" label="Chrome" href="#" icon-src="/assets/images/chrome.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Firefox" href="#" icon-src="/assets/images/firefox.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Edge" href="#" icon-src="/assets/images/edge.png"></sl-app-tile> </sl-app-switcher> </sl-app-header-hds>
Dark Panel
Add the panel-dark attribute to darken the panel. Slotted tiles are set to a dark scheme
automatically; a tile with an explicit mode keeps its own.
<sl-app-switcher panel-dark secondary-label="Integrations"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="Stays light" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile slot="secondary" label="Chrome" href="#" icon-src="/assets/images/chrome.png"></sl-app-tile> <sl-app-tile slot="secondary" label="Firefox" href="#" icon-src="/assets/images/firefox.png"></sl-app-tile> </sl-app-switcher>
Open by Default
Set the open attribute or property to open the panel on first render.
<sl-app-switcher id="switcher-open" open> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> </sl-app-switcher>
Controlling Programmatically
Use the show() and hide() methods to open and close the panel from
JavaScript. The example below binds Alt + A as a keyboard shortcut to toggle the
switcher.
Press Alt + A to toggle the app switcher.
<sl-app-switcher id="switcher-kbd"> <sl-app-tile label="HUB24" href="#" icon-src="/assets/images/logo-icon-hub.svg"></sl-app-tile> <sl-app-tile label="myprosperity" href="#" icon-src="/assets/images/logo-icon-myp.svg"></sl-app-tile> <sl-app-tile label="Class" href="#" icon-src="/assets/images/logo-icon-class.svg"></sl-app-tile> </sl-app-switcher> <p style="margin-top: 12px; font-size: 14px; color: var(--hds-color-fg-subtle);"> Press <kbd>Alt</kbd> + <kbd>A</kbd> to toggle the app switcher. </p> <script> const switcher = document.getElementById('switcher-kbd'); document.addEventListener('keydown', e => { if (e.altKey && e.key === 'a') { e.preventDefault(); switcher.open ? switcher.hide() : switcher.show(); } }); </script>
Animation
Hovering over an app tile applies a background color transition using
--sl-transition-fast. The same transition is applied to the trigger icon.
- Desktop dropdown: uses a
100msease animation. - Mobile drawer: slides in from the start edge using the drawer’s default open/close animation.
Slots
| Name | Description |
|---|---|
| (default) | sl-app-tile entries for the primary section. |
secondary
|
sl-app-tile entries for the secondary section, shown under an optional heading.
|
footer
|
Content pinned to the bottom-left of the panel (e.g. a button). |
Learn more about using slots.
Properties
| Name | Description | Reflects | Type | Default |
|---|---|---|---|---|
open
|
When true, the desktop dropdown or mobile drawer is open. |
|
boolean
|
false
|
dark
|
Styles the trigger for a dark surface (e.g. a dark app header). |
|
boolean
|
false
|
panelDark
panel-dark
|
Darkens the panel and sets slotted tiles to a dark scheme (tiles with an explicit
mode are left alone).
|
|
boolean
|
false
|
mobileHeaderImgUrl
mobile-header-img-url
|
Optional image URL rendered in the left side of the mobile/tablet drawer header. |
string | undefined
|
- | |
secondaryLabel
secondary-label
|
Optional heading for the secondary section. When empty, no heading is shown. |
string
|
''
|
|
emptyText
empty-text
|
Message shown when no app tiles are slotted. |
string
|
'Connect at least one application.'
|
|
stayOpenOnSelect
stay-open-on-select
|
Keeps the panel open after a tile is selected. |
|
boolean
|
false
|
updateComplete |
A read-only promise that resolves when the component has finished updating. |
Learn more about attributes and properties.
Events
| Name | React Event | Description | Event Detail |
|---|---|---|---|
sl-show |
|
Emitted when the panel opens (either the desktop dropdown or mobile drawer). | - |
sl-hide |
|
Emitted when the panel closes. | - |
Learn more about events.
Methods
| Name | Description | Arguments |
|---|---|---|
show() |
Opens the desktop dropdown or mobile drawer. | - |
hide() |
Closes the desktop dropdown or mobile drawer. | - |
Learn more about methods.
Custom Properties
| Name | Description | Default |
|---|---|---|
--app-switcher-trigger-color |
Colour of the trigger icon. | |
--app-switcher-trigger-bg-open |
Background of the trigger when open / hovered / focused. | |
--app-switcher-panel-bg |
Background of the dropdown / drawer panel. |
Learn more about customizing CSS custom properties.
Parts
| Name | Description |
|---|---|
base |
The component’s base wrapper. |
drawer |
The slide-in / full-screen drawer panel (tablet & mobile only). |
close-button |
The drawer close button (tablet & mobile only). |
dropdown |
The dropdown panel (desktop only). |
grid |
The wrapper for the grid of app/integration items. |
Learn more about customizing CSS parts.