Create Contextual Bar

Prev Next

A contextual bar is a sidebar displayed on the screen after the user triggers it. In this document, we will see how to use the UIKit components to create a contextual bar containing blocks and elements. Defining contextual bars and modals is a little different from the UI blocks we saw in the previous document.

To create and update contextual bars and modals, use the following methods:

modify.getUiController().openSurfaceView({type, title, blocks}, triggerId, user)
modify.getUiController().updateSurfaceView({type, title, blocks}, context, user)

For details on these methods, see the IUIController interface TypeScript definition.

Letโ€™s look at a basic app to open a contextual bar that is triggered with a slash command using the openSurfaceView method.

  1. In your app folder, create a file to define the slash command and the context bar. For example, OpenCtxBarCommand.ts.

  2. Import the following:

import { IModify, IRead } from "@rocket.chat/apps-engine/definition/accessors";
import { App } from "@rocket.chat/apps-engine/definition/App";
import { ISlashCommand, SlashCommandContext } from "@rocket.chat/apps-engine/definition/slashcommands";
import { UIKitSurfaceType } from "@rocket.chat/apps-engine/definition/uikit";
  1. Now, in the class OpenCtxBarCommand, define the slash command as follows:

export class OpenCtxBarCommand implements ISlashCommand {
  public command = 'contextualbar'; // this is what we will type when calling the slashcommand: /contextualbar
  public i18nParamsExample = 'slashcommand_params';
  public i18nDescription = 'slashcommand_description';
  public providesPreview = false;
}
  1. Next, in the same class, define the context bar in the async executor method as follows:

constructor(private readonly app: App) { }

public async executor(context: SlashCommandContext, _read: IRead, modify: IModify): Promise<void> {
  modify.getUiController().openSurfaceView({
    type: UIKitSurfaceType.CONTEXTUAL_BAR, // The type of the UI, CONTEXTUAL_BAR or MODAL.
    title: { text: 'test', type: 'plain_text' }, // The title of the UI type that is displayed in the workspace.
    blocks: [{ // The content of the UI type. It can contain many elements (inputs, actions, etc.)
      type: 'section', // The type of the block.
      blockId: 'section_1', // The name of the block.
      text: { // The object contains the content that will be displayed in the contextual bar.
        type: 'plain_text',
        text: 'lorem ipsum ๐Ÿš€',
        emoji: true,
      } // Additionally, the `accessory` field can contain the block elements.
    }]
  },
    { triggerId: context.getTriggerId()! }, // The trigger ID is like a security measure - to show users the contextual bar or modal only if users interacted with Rocket.Chat.
      context.getSender() // The user that types the slash command.
  )
}
}

See Building blocks for details on how to use the blocks.

  1. Update the main app class to call the OpenCtxBarCommand.ts file.

import {
    IAppAccessors,
    IConfigurationExtend,
    ILogger,
} from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { OpenCtxBarCommand } from './contextbar'; // import the `OpenCtxBarCommand` class

export class HelloWorldApp extends App {
    
    protected async extendConfiguration(configuration: IConfigurationExtend): Promise<void> {
        await configuration.slashCommands.provideSlashCommand(
            new OpenCtxBarCommand(this)
        )
    }
}
  1. Deploy and test the app. In any channel, send the slash command /contextualbar.

The following screenshot shows the contextual bar called test with the content that we defined in the blocks.

Great! We have created a contextual bar for our app. You can now define additional UI elements for the contextual bar. For example, letโ€™s add an image to this.

To add an image block, we can modify the OpenCtxBarCommand.ts as follows:

public async executor(context: SlashCommandContext, _read: IRead, modify: IModify): Promise<void> {
  modify.getUiController().openSurfaceView
  ({
    type: UIKitSurfaceType.CONTEXTUAL_BAR, // The type of the UI, CONTEXTUAL_BAR or MODAL.
    title: { 
             text: 'Contextual bar', 
             type: 'plain_text' }, // The title of the UI type that is displayed in the workspace.
    blocks: [{ // The content of the UI type. It can contain many elements (inputs, actions, etc.)
      type: 'section', // The type of the block.
      blockId: 'section_1', // The name of the block.
      text: { // The object contains the content that will be displayed in the contextual bar.
        type: 'plain_text',
        text: 'lorem ipsum ๐Ÿš€',
        emoji: true,
      } // Additionally, the `accessory` field can contain the block elements.
    },
    {
        type: 'image', // the image block
        blockId: 'image_1',
        imageUrl: 'https://img.freepik.com/free-vector/rocket-background-flat-style_23-2147904992.jpg?size=338&ext=jpg&ga=GA1.1.2008272138.1726444800&semt=ais_hybrid',
        altText: 'An icon of a rocket',
    },
]
  },
    { triggerId: context.getTriggerId()! }, // The trigger ID is like a security measure - to show users the contextual bar or modal only if users interacted with Rocket.Chat.
      context.getSender() // The user that types the slash command.
  )
}
}

The contextual bar looks like this: