Configure Storefront App cards

By default, an App card in your Storefront includes a single default button with the text "Launch". If your users click anywhere else in the body of the card, an App Details page appears.

In Workspace v11 or later, you can provide custom text and actions for primary and secondary buttons on the card. In Workspace v16 or later, you can remove the buttons entirely, or skip the App Details page.

How it works

Individual App cards

The primaryButton property of the App interface specifies a StoreButtonConfig object. The secondaryButtons property specifies an array of StoreButtonConfig objects. The title and action properties of the StoreButtonConfig object specify button text and behavior. A StoreCustomButtonActionPayload object adds any data that's required to complete the button action.

To dynamically update buttons, an updateAppCardButtons method is included in the StoreRegistration object that's returned by the register method of the Storefront API.

Interactions for all cards

Unlike button customization of the App object, whether buttons appear at all, or whether an App Details page appears for App cards, are properties of the StorefrontProvider object:

  • buttonVisibility determines whether a button appears on any App card. Default value "visible". Set to "hidden" to disable buttons on App cards.

  • cardClickBehavior determines whether an App Details page appears when the user clicks an App card. Default value "show-app-details".

    • If you choose "perform-primary-button-action" instead, the App Details page does not appear, and the app launches directly. If you explicitly define a custom action for the primaryButton property, that action is performed instead of launching the app.

How to do it

Individual cards

  1. Define the custom actions your platform wants to invoke from a Store button. This example defines three custom actions we'll then invoke from an App definition:

    import { init } from "@openfin/workspace-platform";
    await init(
      {
        customActions:
          {
            "requestAccess": async (payload: StoreCustomButtonActionPayload) => {
              const { appId } = payload;
              // requestAccess is a hypothetical long running function.
              await requestAccess(payload.appId);
            },
            "launchMoreInfo": async (payload: StoreCustomButtonActionPayload) => {
              // launchMoreInfo is a hypothetical function that does something with appid and a payload. 
              await launchMoreInfo(payload.appId, payload.data);
            },
            "launchApp": async (payload: StoreCustomButtonActionPayload) => {
              // launchApp is another hypothetical function that does something with appid and a payload. 
              await launchApp(payload.appId, payload.data);
            }
          }
      }
    );
    

    or, for buttons that are updated dynamically, something like the following:

    import { init } from "@openfin/workspace-platform";
    import { Storefront, StorefrontProvider} from "@openfin/workspace";
    
    const storeRegistration = await Storefront.register(...);
    
    await init(
      {
        customActions: {
            "requestAccess": async (payload: StoreCustomButtonActionPayload) => {
              registration.updateAppCardButtons({
                 appId: payload.appId,
                 primaryButton: {
                    ...payload.PrimaryButton,
                    title: "Requesting access...",
                    disabled: true
                },
                secondaryButtons: payload.SecondaryButtons
              });
            }
          }
      }
    );
    
  2. Include the primaryButton or secondaryButtons properties in your App definition. The following example omits other optional properties.

    Note that manifest and manifestType are no longer required properties. They are still supported, but depending on your App definition you can work with the action property of the StoreButtonConfig object instead.

    const sampleApp: App = {
      appId: 1,
      title: 'Sample app',
      icons: [
        {
          src: "FAVICON.ico"
        }
        ],
      publisher: WHO_OWNS_IT,
      primaryButton: {
        title: 'Request Access',
        action: {
          id: 'requestAccess'
        }
      },
      secondaryButtons: [
        {
          title: 'More Info',
          action: {
            id: 'launchMoreInfo',
            data: {
              additionalData: 'some data...'
            }
          }
        },
        {
          title: 'Launch App',
          action: {
            id: 'launchApp',
            data: {
              additionalData: 'start sample app ...'
            }
          }
        }
      ]
    };
    

All card interactions

Add buttonVisibility or cardClickBehavior to your call to register your StorefrontProvider. For more information about the register() function, see Store overview.

import { Storefront, StorefrontProvider } from "@openfin/workspace";

// Declare the provider
const myStorefrontProvider: StorefrontProvider = 
{
  id: "my-storefront-id"
  title: "My StorefrontProvider"
  icon: "https://cdn.openfin.co/demos/notifications/generator/images/icon-blue.png",

  // hide all buttons on the App card
  buttonVisibility: "hidden",

  // omit the App Details page and launch the app when the card is clicked
  // in the case of the sampleApp defined in the previous example, Request Access launches instead
  // if no primaryButton is defined, or if this property is not specified, the App Details page is launched
  cardClickBehavior: "perform-primary-button-action",

  getApps: () => {...},
  getNavigation: () => {...},
  getLandingPage: () => {...},
  getFooter: () => {...},
  launchApp: () => {...}
};

await Storefront.register(myStorefrontProvider);
// show the Storefront. Hidden by default.
await Storefront.show();