Skip to main content

Launcher

Overview

The io.Connect embedded launcher is an app which acts as a central hub for managing interop-enabled apps, Layouts, Workspaces, search, notifications and various io.Connect Desktop settings. io.Connect Desktop comes with an embedded launcher - the io.Connect Launchpad.

Launchpad

Available since io.Connect Desktop 9.9

The io.Connect Launchpad is the default io.Connect launcher. It's an easily customizable web app that acts as a central hub for all io.Connect features - apps, Workspaces, Global Layouts, notifications, platform preferences, and more.

The Launchpad starts in expanded mode and contains conveniently placed sections with easy access to all available Workspaces, apps, and Global Layouts. At the top, you can find a search bar that's not just a simple item filter, but a fully functional global search implemented using the search capabilities of the io.Connect framework.

The Launchpad provides quick access to the Notification Panel, the Download Manager, the Feedback Form, and contains a menu with various platform settings. It can be moved, minimized, and collapsed to a compact horizontal toolbar in order to save screen real estate. Users who prefer the Launchpad to be always available on the screen can pin the Launchpad to the left or the right side of their monitors.

Available since io.Connect Desktop 10.0

The Launchpad can be docked to the top of the screen for convenient access:

If you dock the Launchpad, you can utilize the extended area located between the search bar and the system icons. This area can show lists of favorite items, recent items, and you can also add custom categories in it. The extended area can be enabled and configured from the Platform Preferences panel in the Launchpad menu - it's possible to hide or show the "Favorites" and "Recent" section or to hide the item titles to save space:

Available since io.Connect Desktop 10.5

The Global Layouts are listed in a "Layouts" section similarly to apps and Workspaces. The "Layouts" section is always rendered after all default and custom sections and can't be hidden or repositioned. The currently active Global Layout is displayed in a footer at the bottom of the Launchpad.

Favorite items are added and removed via the context menu for each section item. Apps, Workspaces, and Global Layouts can be added to the favorite items.

The buttons for creating a new Workspace and a new Global Layout are located in the headers of the "Workspaces" and "Layouts" sections respectively.

Launchpad Sections & Menus

Layout Sharing

Available since io.Connect Desktop 10.5

When Layout sharing is enabled, the "Layouts" and "Workspaces" sections of the Launchpad are divided into "Public" and "Private" sections. The "Public" section contains the public Layouts and the shared Layouts that have been published by you or shared with you. Layouts with a specified folder are grouped in folders.

The context menu of the Layouts and Workspaces provides the following options for Layout sharing:

Option Description
"Details" Available for shared and public Layouts to their viewers. Shows the details for the Layout.
"Edit" Available for private Layouts to their owner. Allows changing the name, folder, icon, and description of the Layout.
"Hide from Launchpad" / "Show in Launchpad" Available for shared and public Layouts to their owner, editors, and viewers. Hides or shows the Layout in the Launchpad. To see the hidden Layouts, enable the "Show hidden Layouts and Workspaces" setting in the "Layouts" section of the Platform Preferences panel.
"Manage" Available for shared and public Layouts to their owner and editors. Allows changing the users and groups with access to the Layout, as well as its name, folder, icon, and description.
"Publish" Available for private Layouts to their owner. Allows sharing the Layout with the selected users and groups with view or edit permissions. Select the "Keep a private copy" option to keep your private Layout and publish a shared copy of it.
"Save a Private Copy" Available for shared and public Layouts to their owner, editors, and viewers. Saves a copy of the Layout as a private one.

The "Rename", "Save", and "Save As" options of the context menu are available only for private Layouts. To change the name of a shared or a public Layout you can edit, use the "Manage" option.

Owners and editors have the following options available in the Launchpad for working with shared and public Global and Workspace Layouts:

Owners & Editors Options Public Layouts

Viewers have the following options available in the Launchpad for working with shared and public Global and Workspace Layouts:

Viewers Options Public Layouts

Owners have the following options available in the Launchpad for working with private Global and Workspace Layouts:

Owners Options Private Layouts

⚠️ Note that custom Launchpad apps must use @interopio/components-react 5.0 or later in order to provide the Layout sharing options.

Custom Launcher

Available since io.Connect Desktop 10.5 & @interopio/components-react 4.6

The io.Connect Launchpad is available as a standalone React component that you can use to create a custom launcher for io.Connect Desktop. The <Launchpad /> component is provided by the IOLaunchpadDesktop object of the @interopio/components-react library. This is the same component used by the default Launchpad of io.Connect Desktop.

To create a custom launcher:

  1. Implement the launcher with the <Launchpad /> component.
  2. Configure the launcher as a shell app of io.Connect Desktop.
  3. Customize the launcher styles.

For a quick start, use the Launchpad template built with the <Launchpad /> component. The template is also available as the launchpad template app of the io.Connect seed project.

The <Launchpad /> component renders a fully functional Launchpad without the need for any additional configuration. Use its components prop to change the components in the Launchpad header and to choose the sections that the Launchpad shows. Use the hooks exported by IOLaunchpadDesktop to read and change the Launchpad state from your own components and to interact with the Launchpad panels and popups.

Setup

Render the Launchpad within the <IOConnectProvider /> component of the @interopio/react-hooks library. Initialize the @interopio/desktop library and add the required Workspaces, Search, and Modals APIs, as demonstrated in the Launchpad template.

The Launchpad depends on a set of React context providers from @interopio/components-react. They supply the theme, platform preferences, notifications, downloads data, Launchpad state, panels, and popups that the Launchpad requires to operate properly. If a provider is missing, the Launchpad functionality that depends on it won't work. You must render the <Launchpad /> component within all of them, in the order demonstrated in the template and the following example.

You must also import the CSS files for the Launchpad and for the features it uses.

The following example demonstrates how to render the default Launchpad:

import { IOConnectProvider } from "@interopio/react-hooks";
import IODesktop from "@interopio/desktop";
import IOWorkspaces from "@interopio/workspaces-api";
import IOSearch from "@interopio/search-api";
import IOModals from "@interopio/modals-api";
import {
    ThemeProvider,
    PlatformPrefsProvider,
    IOActivePanelRenderer,
    IODownloadManager,
    IOLaunchpadDesktop,
    IONotifications
} from "@interopio/components-react";
import "@interopio/workspaces-ui-react/dist/styles/workspaces.css";
import "@interopio/components-react/dist/styles/components/ui/dropdown-menu.css";
import "@interopio/components-react/dist/styles/components/ui/overlay-scrollbars-container.css";
import "@interopio/components-react/dist/styles/features/active-panel-renderer/styles.css";
import "@interopio/components-react/dist/styles/features/notifications/styles.css";
import "@interopio/components-react/dist/styles/features/preferences/styles.css";
import "@interopio/components-react/dist/styles/features/profile/styles.css";
import "@interopio/components-react/dist/styles/features/launchpad/styles.css";
import "@interopio/components-react/dist/styles/features/launchpad-desktop/styles.css";

const { PanelManagerProvider } = IOActivePanelRenderer;
const { DownloadManagerProvider } = IODownloadManager;
const { NotificationsProvider } = IONotifications;
const {
    LaunchpadProvider,
    LaunchpadBodyPopupProvider,
    PanelPopupProvider,
    Launchpad
} = IOLaunchpadDesktop;

const settings = {
    desktop: {
        factory: IODesktop,
        config: {
            libraries: [IOWorkspaces, IOSearch, IOModals],
            appManager: "full",
            apps: true,
            layouts: "full"
        }
    }
};

const App = () => {
    return (
        <IOConnectProvider settings={settings}>
            <ThemeProvider>
                <PlatformPrefsProvider>
                    <NotificationsProvider>
                        <DownloadManagerProvider>
                            <PanelManagerProvider>
                                <LaunchpadProvider>
                                    <LaunchpadBodyPopupProvider>
                                        <PanelPopupProvider>
                                            <Launchpad />
                                        </PanelPopupProvider>
                                    </LaunchpadBodyPopupProvider>
                                </LaunchpadProvider>
                            </PanelManagerProvider>
                        </DownloadManagerProvider>
                    </NotificationsProvider>
                </PlatformPrefsProvider>
            </ThemeProvider>
        </IOConnectProvider>
    );
};

export default App;

The complete setup is available in the Launchpad template.

⚠️ Note that to provide the Layout sharing options in your custom Launchpad, you must use @interopio/components-react 5.0 or later and @interopio/desktop 6.23 or later.

⚠️ Note that if using Layout sharing, you must enable the Apps API by setting the apps property of the configuration object for initializing the @interopio/desktop library to true. Currently, the Launchpad also requires the legacy App Management API to be enabled, with the appManager property of the configuration object set to "full".

Header

The Launchpad header contains the search bar and an area on each side of it. To set the components in these areas, use the BeforeSearch and AfterSearch properties of the header object in the components prop.

If you don't set a property, the Launchpad will render the default components for that area. To leave an area empty, set its property to null. If you set a property to a React component, the Launchpad will render your component instead of all default components in that area.

By default, the area before the search bar contains the <DragHandle /> and <LogoButton /> components. The area after the search bar contains the <ExtendedArea />, <NotificationsButton />, and <MainContextMenu /> components. All default components are exported, so you can combine them with your own components. To remove a default component, compose the area without it.

The following example demonstrates creating a custom Launchpad with a custom logo and without the button for opening the Notification Panel:

import { IOLaunchpadDesktop } from "@interopio/components-react";

const {
    Launchpad,
    DragHandle,
    LogoButton,
    ExtendedArea,
    MainContextMenu
} = IOLaunchpadDesktop;

// Components before the search bar.
const BeforeSearch = () => (
    <>
        <DragHandle />
        <LogoButton iconSrc="./my-logo.png" />
    </>
);

// Components after the search bar.
const AfterSearch = () => (
    <>
        <ExtendedArea />
        <MainContextMenu />
    </>
);

// Define the components outside the render function to prevent unnecessary re-mounting.
const components = { header: { BeforeSearch, AfterSearch } };

const MyLaunchpad = () => <Launchpad components={components} />;

Default Components

The following default components are available for the Launchpad header:

Component Description
<DragHandle /> Grip icon that shows the user can move the Launchpad by dragging its header.
<LogoButton /> Logo button. Clicking it collapses or expands the Launchpad. If the Launchpad is docked, clicking it will open or close a popup with the Launchpad sections. If the Launchpad is pinned, clicking it won't do anything. Dragging the button moves the Launchpad window. Dragging it while the Launchpad is docked undocks the Launchpad.
<ExtendedArea /> The extended area with the "Favorites", "Recent", and any custom categories. It renders only when the Launchpad is docked and the extended area is enabled in the Platform Preferences panel. You can always include it in your header.
<NotificationsButton /> Button that shows or hides the Notification Panel. If the notification badge is enabled in the notification settings, the button will show the number of notifications, up to "99+".
<MainContextMenu /> Button that opens the Launchpad menu. The menu contains the "Platform Preferences", "Notification Settings", "Profile", "Downloads", "Feedback", "Keyboard Shortcuts", "Pin Launchpad", "Dock Launchpad", "Minimize", "Restart", and "Shut Down" items. You can't change the menu items. To provide a different menu, use your own component instead.

All default components accept the standard HTML attributes of a <div> element, such as className and style.

Logo Button

Use the props of the <LogoButton /> component to change the logo and the click behavior without replacing the component:

Prop Type Description
icon string Name of an icon from the io.Connect icon set. Ignored if iconSrc is set. Defaults to "logo".
iconSrc string URL of an image to use as a logo.
onClick function Callback that replaces the default click behavior. Dragging the button still moves the Launchpad window.

Sections

Use the sections property of the components prop to specify the sections of the Launchpad and their order. It accepts an array of objects with placementId and Component properties. The default "Favorites", "Workspaces", and "Apps" sections are available as the <FavoritesSection />, <WorkspacesSection />, and <ApplicationsSection /> components. To create a custom section, use the <Section /> component. The default sections that you don't include in the array won't be displayed. The "Layouts" section is always rendered after all other sections and can't be hidden or repositioned.

The following example demonstrates adding a custom section between the "Favorites" and "Apps" sections and removing the "Workspaces" section:

import { IOLaunchpadDesktop } from "@interopio/components-react";

const {
    Launchpad,
    FavoritesSection,
    ApplicationsSection,
    Section
} = IOLaunchpadDesktop;

const ResearchSection = () => {
    const config = {
        id: "research-section",
        title: "Research",
        items: [
            { id: "market-news", title: "Market News", type: "application" }
        ]
    };

    const onItemClick = ({ item }) => console.log(`Clicked "${item.title}".`);

    return <Section config={config} onItemClick={onItemClick} />;
};

// Define the components outside the render function to prevent unnecessary re-mounting.
const components = {
    sections: [
        { placementId: "favorites-section", Component: FavoritesSection },
        { placementId: "research-section", Component: ResearchSection },
        { placementId: "applications-section", Component: ApplicationsSection }
    ]
};

const MyLaunchpad = () => <Launchpad components={components} />;

Custom Sections

The <Section /> component has the following props:

Prop Type Description
config object Required. Configuration for the section.
onItemClick function Callback invoked when the user clicks an item or selects an action from the item context menu.

The config object has the following properties:

Property Type Description
id string Required. ID for the section.
title string Required. Title for the section.
items object[] Required. Items and folders in the section.
isCollapsible boolean If true (default), the user will be able to collapse and expand the section.
getIcon function Receives a Boolean argument that is true if the section is expanded, and returns the icon for the section header. Return { variant: "<icon-name>" } to use an icon from the io.Connect icon set, or { src: "<image-url>" } to use an image.
HeaderButton React.ComponentType Component to render at the end of the section header. The "Workspaces" section uses it for its button for creating a new Workspace. Available since @interopio/components-react 5.0.

A section can contain individual items, as well as folders with items. You can group items in folders within a section by using nested objects in the items array. Each folder can contain items and other folders.

An object describing a folder has the same properties as the config object of the section.

An object describing an individual item has the following properties:

Property Type Description
id string Required. ID for the item, such as the name of an app or a Workspace. The combination of id and type must be unique within the section.
title string Required. Title for the item.
type string Required. Type of the item. Can be any string, such as "application" or "workspace". Together with id, identifies the item within the section.
description string Description for the item.
icon string Name of an icon from the io.Connect icon set. Defaults to "application".
iconSrc string URL of an image to use as an item icon. If set, icon will be ignored.
tooltip string Tooltip for the item. Defaults to the item title.
openInstances number Number of open instances of the item. If larger than 0, the item will show "Opened" or " opened".
className string CSS class for the item element.
contextMenuActions object[] Actions in the context menu of the item. The context menu button will appear only if you specify at least one action.
contextMenuSubtitle string Subtitle for the context menu of the item. Available since @interopio/components-react 5.0.
isContextMenuButtonHidden boolean If true, will hide the context menu button of the item. Available since @interopio/components-react 5.0.
isSelected boolean If true, the item will show a check mark. Available since @interopio/components-react 5.0.
statusPill object Status label for the item. Available since @interopio/components-react 5.0.

Each object in the contextMenuActions array has the following properties:

Property Type Description
name string Required. Name for the action passed to the onItemClick callback.
displayName string Text for the menu item. Defaults to the value of name.
icon string Name of an icon from the io.Connect icon set.
iconSrc string URL of an image to use as a menu item icon.
disabled boolean If true, the menu item will be disabled.
separatorAfter boolean If true, the menu will show a separator after the item.

The statusPill object has the following properties:

Property Type Description
text string Required. Text for the status label.
variant "default" | "primary" | "secondary" | "success" | "warning" | "critical" | "outline" | "flat" Required. Visual style of the status label.

Handling Item Clicks

To define what happens when the user clicks on a section item or selects an action from its context menu, use the onItemClick callback of the <Section /> component.

The callback receives as an argument an object with the following properties:

Property Type Description
item object The item that the user clicked.
modifier string | null Name of the key that the user held while clicking, such as "Control" or "Shift". If the user held no key or more than one key, the value will be null.
selectedContextMenuActionName string Name of the context menu action that the user selected. If the user clicked the item itself, the value will be undefined.

The following example demonstrates creating a section with an app and a folder with a Workspace. The app has a context menu action for opening a help page:

import { useContext } from "react";
import { IOConnectContext } from "@interopio/react-hooks";
import { IOLaunchpadDesktop } from "@interopio/components-react";

const { Section } = IOLaunchpadDesktop;

const config = {
    id: "research-section",
    title: "Research",
    items: [
        {
            id: "market-news",
            title: "Market News",
            type: "application",
            description: "Latest market headlines",
            contextMenuActions: [
                { name: "open-help", displayName: "Open Help" }
            ]
        },
        {
            id: "reports-folder",
            title: "Reports",
            items: [
                { id: "Client Reports", title: "Client Reports", type: "workspace" }
            ]
        }
    ]
};

const ResearchSection = () => {
    const io = useContext(IOConnectContext);

    const onItemClick = ({ item, selectedContextMenuActionName }) => {
        if (selectedContextMenuActionName === "open-help") {
            io.windows.open(`${item.id}-help`, `https://example.com/help/${item.id}`);
            return;
        }

        if (item.type === "application") {
            const options = { name: item.id };

            io.apps.instances.start(options);
        } else if (item.type === "workspace") {
            io.workspaces.restoreWorkspace(item.id);
        }
    };

    return <Section config={config} onItemClick={onItemClick} />;
};

Hooks

The IOLaunchpadDesktop object exports hooks for reading and changing the Launchpad state and manipulating the Launchpad panels and popups. Use them in components that you render within the Launchpad providers, such as your header components and custom sections.

The following sections describe the available hooks and the tools they provide for interacting with the Launchpad state, panels, and popups.

Pinned, Docked & Collapsed State

The useLaunchpadContext() hook returns an object with the following properties:

Property Type Description
isPinned boolean Flag indicating whether the Launchpad is pinned.
isDocked boolean Flag indicating whether the Launchpad is docked.
isCollapsed boolean | undefined Flag indicating whether the Launchpad is collapsed. The value will be undefined until the internal platform preferences have been loaded.
isExtendedAreaVisible boolean Flag indicating whether the extended area is enabled in the Platform Preferences panel.
setIsPinned function Accepts a Boolean argument. Pins or unpins the Launchpad. Returns a Promise<void>.
setIsCollapsed function Accepts a Boolean argument. Collapses or expands the Launchpad. The Launchpad window changes its size only when the Launchpad isn't pinned or docked. Returns a Promise<void>.
setIsDocked function Accepts a Boolean argument. Sets the docked state that the Launchpad uses to switch between its regular and docked layouts. It doesn't dock or undock the Launchpad window. Use it only to update the state immediately after you dock or undock the window yourself - otherwise, the state is updated automatically when the window is docked or undocked. The state isn't kept across restarts unless the window itself is docked. The Launchpad can be docked only to the top of the screen. To dock or undock the window, use the "Dock Launchpad" item in the Launchpad menu, drag the Launchpad window to the top of the screen, or dock the window programmatically. Returns a Promise<void>.

Panels

The usePanelPopupContext() hook returns an object with the following properties:

Property Type Description
openPanel function Accepts the ID of a panel and opens the panel. If the Launchpad is docked, the panel will open in a popup. Otherwise, the panel will open inside the Launchpad.
closePanel function Closes the open panel.
activePanel string | null ID of the panel that is open in a popup while the Launchpad is docked.

The following panel IDs are available:

Panel ID Panel
"preferences" Platform Preferences panel.
"notification-settings" Notification Settings panel.
"profile" Profile panel.

If the Launchpad is collapsed, expand it before opening a panel so that the panel is visible.

The following example demonstrates adding a button for opening the Platform Preferences panel before the Launchpad menu:

import { IOLaunchpadDesktop } from "@interopio/components-react";

const {
    Launchpad,
    ExtendedArea,
    NotificationsButton,
    MainContextMenu,
    useLaunchpadContext,
    usePanelPopupContext
} = IOLaunchpadDesktop;

const PreferencesButton = () => {
    const { isDocked, isCollapsed, setIsCollapsed } = useLaunchpadContext();
    const { openPanel } = usePanelPopupContext();

    const onClick = async () => {
        // Expand the Launchpad so that the panel is visible.
        if (!isDocked && isCollapsed) {
            await setIsCollapsed(false);
        }

        openPanel("preferences");
    };

    // The `non-draggable` class allows the button to receive clicks in the header.
    return <button className="non-draggable" onClick={onClick}>Preferences</button>;
};

const AfterSearch = () => (
    <>
        <ExtendedArea />
        <NotificationsButton />
        <PreferencesButton />
        <MainContextMenu />
    </>
);

const components = { header: { AfterSearch } };

const MyLaunchpad = () => <Launchpad components={components} />;

Sections Popup

When the Launchpad is docked, its sections appear in a popup that the user opens by clicking the logo button. If you replace the <LogoButton /> component with your own component, use the useLaunchpadBodyPopupContext() hook to control this popup. The hook returns an object with the following properties:

Property Type Description
showPopup boolean Flag indicating whether the popup is open.
openPopup function Opens the popup.
closePopup function Closes the popup.
togglePopup function Opens the popup if it's closed, or closes it if it's open.

Configuration

Once you have implemented a launcher, you must host it, create an app definition file for it, and add it to your app store.

  1. To instruct the platform that this is your shell app, set the "shell" top-level key to true:
{
    "shell": true
}
  1. To make your launcher start automatically when the platform is initiated, also set the "autoStart" top-level key to true:
{
    "shell": true,
    "autoStart": true
}
  1. To prevent the launcher from displaying itself in the list of available apps, set the "hidden" top-level key to true:
{
    "shell": true,
    "autoStart": true,
    "hidden": true
}
  1. If you don't want the users to be able to start more than one instance of your launcher, set the "allowMultiple" top-level key to false:
{
    "shell": true,
    "autoStart": true,
    "hidden": true,
    "allowMultiple": false
}
  1. Use the "url" property of the "details" top-level key to provide the location of your custom launcher and also set the other required properties - "name" and "type":
{
    "name": "my-launcher",
    "type": "window",
    "shell": true,
    "autoStart": true,
    "hidden": true,
    "allowMultiple": false,
    "details": {
        "url": "./my-custom-launcher/index.html"
    }
}
  1. Finally, to disable the default io.Connect Desktop launcher, set the "useEmbeddedShell" top-level key in the system.json system configuration file of io.Connect Desktop to false:
{
    "useEmbeddedShell": false
}
  1. Restart io.Connect Desktop for the changes to take effect and start using your custom launcher.

Extended Area Custom Categories

Available since io.Connect Desktop 10.0

To add custom categories to the extended area of the Launchpad that is available when the Launchpad is docked, use the "extendedAreaCategories" property of the "customProperties" top-level key in the Launchpad app definition:

{
    "customProperties": {
        "extendedAreaCategories": [
            {
                "name": "Client Management",
                "items": [
                    {
                        "name": "channelsclientlist",
                        "type": "application"
                    },
                    {
                        "name": "Client Info",
                        "type": "workspace"
                    }
                ]
            }
        ]
    }
}

Each object in the "extendedAreaCategories" array has the following properties:

Property Type Description
"name" string Required. Name for the category to be displayed in the Launchpad extended area.
"items" object[] Required. Array of objects describing the items (apps and Workspaces) to be displayed in the specified category.

Each object in the "items" array has the following properties:

Property Type Description
"name" string Required. The name of an app as specified in its app definition, or the name of a Workspace to be displayed in the category list.
"type" "application" | "workspace" Required. The type of the item to be displayed in the category list - an app or a Workspace.

Styles

Available since io.Connect Desktop 9.9

To customize the io.Connect Launchpad styles, use the CSS variables provided by the io.Connect themes.