Create Contextual Bar

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: