Block Kit library

You’ve found documentation about extending the Transposit Developer Platform, which is accessible on request. In most cases, you can now set up and use Transposit without needing to extend the Transposit Developer Platform. Go here for the related docs and support.

What is Block Kit library?

Transposit's Block Kit library is inspired by Slack's Block Kit, which is a UI framework for creating apps in Slack. Our Block Kit library allows you to customize the appearance of information and interactivity in Transposit runbooks. With the library, you can customize the UI in both Slack and Transposit's web UI at the same time. No duplicate code needed!

Types of blocks

Blocks are components that are used to build the UI. You can use multiple types of blocks. Think of it like stacking or appending blocks. Transposit supports the following block types:

  • Context
  • Divider
  • Image
  • Input
  • Section
  • Transposit files

Block elements

Blocks elements can be used inside of context and section blocks. Transposit supports the following block elements:

  • Link button
  • Checkboxes
  • Date picker
  • Image
  • Plain-text input
  • Radio button group
  • Select menus (single and multi-select)

Note: Some blocks and elements have limits. The Slack Block Kit reference documentation is the authoritative source for these limitations.

Adding Block Kit library to your application

You can add the Block Kit library to any Transposit Developer Platform application.Inside of the application, go to Code > Data Connectors and click on the + plus icon. Search for "Slack Block Kit" and select -- None -- for the Operation and Save. Now, you are ready to start using the library!

Block Kit examples

Examples of input prompt UI

plain_text_section with text_input

Example in the Slack UI:

Slack UI with a text box titled, Name

def input_prompt(_params):
    blocks = []
    
    blocks.append(
        api.run("block_kit_lib.plain_text_section", {
            "text": "Please enter your name below:"
        })[0])
        
    blocks.append(
        api.run("block_kit_lib.text_input", {
            "label": "Name",
            "field_name": "name"
        })[0])
    
    return blocks

To retrieve the input you use the retrieve_input operation:

    name = api.run("block_kit_lib.retrieve_input", {
        "field_name": "name",
        "context": params["context"],
        "default_value": ""
    })[0]

Note: The string value in field_name in the input prompt is also what you use to retrieve the input in your execute operation.

static_select_input

Select menus use a static list of options passed in when defining the input options. Options each have fields text, the text displayed in the menu, and value, the string value returned when selected. Maximum number of options is 100. Maximum length for the text and value fields is 75 characters.

Example UI in Slack:

Slack UI with a dropdown box titled, Select User

def input_prompt(_params):
    blocks = []
    items = [{'id':'user1', 'name':'User 1'}, {'id':'user2', 'name':'User 2'}]
    
    options = []
    for item in items:
        options.append({
            "value": item["id"], 
            "text" : item["name"] 
        })
    
    blocks.append(
        api.run("block_kit_lib.static_select_input", {
            "label" : "Select user", 
            "field_name" : "user",
            "options": options
    })[0])
    
    return blocks

You can also change the operation to work with multiple select menu (multi_static_select_input), checkboxes (checkboxes_input), or radio buttons (radio_button_input).

Note: If there is a value that you want to use in your application, make sure to store it in the id, not name. This is a Slack limitation that you can read more about here.

As usual, to retrieve the input you use the retrieve_input operation:

    user_id = api.run("block_kit_lib.retrieve_input", {
        "field_name": "user",
        "context": params["context"],
        "default_value": ""
})[0]

Note: If there are possibly more than 1 values being retrieved from input, make sure to not dereference [0] in api.run().

Populating a static_select_input with external data

Sometimes you might want to populate a select menu with data from an API using a data connector. Here's a real example of getting a list of instances from a data source and including it as options in a select menu:

    # Get list of instances in zone/project
    try:
        instances = api.run("this.list_instances", {
            "zone": zone,
            "project": project
        })
        if not instances:
            raise ValueError("No instances found")
    except ValueError as ex:
        error_message = f"Could not get list of instances for project *{project}* and zone *{zone}*:\n{str(ex)}"
        return api.run("block_kit_lib.markdown_text_section",
                        {"text": error_message})
    
    blocks = []
    options = []
    
    for instance in instances:
        display_text = f'{instance["name"]} ({instance["status"]})'
        options.append({"value": instance["id"], "text": display_text})
    
    blocks.append(
        api.run(
            "block_kit_lib.static_select_input", {
                "label": "Choose instance to restart",
                "field_name": "instance_select",
                "options": options,
                "placeholder": "Select an instance"
            })[0])

Examples of messages (output) UI

Your action's messages or output will appear in your activity's timeline and in Slack. You can keep them simple or include elements like link buttons, images, multiple columns, or Markdown formatted text.

markdown_text_section

You can output simple messages like this:

    # Located in your execute operation  

    blocks = []
    blocks.append(api.run("block_kit_lib.markdown_text_section", {
        "text": "Hello world!"
    })[0])
    
    # You can pass block kit via the `blockKitOverride` parameter in your `workflow.log` or `dataParser.response()` call.

There is a 3,000 character limit on Slack messages. Transposit will truncate longer messages and store them as text files for you automatically.

If you want to include an image or link button, like this: Example text next to a picture of a dog, then example text next to a link

    # Located in your execute operation
  
    blocks = []
    image = api.run("block_kit_lib.image_element", {
        "image_url": "https://images.dog.ceo/breeds/corgi-cardigan/n02113186_694.jpg",
        "alt_text": "A corgi with blue eyes"
    })[0]

    button = api.run("block_kit_lib.link_button_element", {
        "text" : "Launch",
        "url" : "http://www.nasa.gov"
    })[0]
    
    blocks.append(api.run("block_kit_lib.markdown_text_section", {
        "text" : "Massa corgus massa in adipiscing set Quisque. Elementum massa in sed, enim tempor mattis sploot fritos massa in.",
        "accessory" : image
    })[0])    
    
    blocks.append(api.run("block_kit_lib.markdown_text_section", {
        "text" : "Click this to go to the *moon*",
        "accessory" : button
    })[0])  

    # You can pass block kit via the `blockKitOverride` parameter in your `workflow.log` or `dataParser.response()` call.

markdown_text_object

Sometimes you might want to format your message output with columns. You can use markdown_text_object inside of a fields array to do this.

Example UI in Slack:

Slack UI message that says: **Single line of text:** More info here, followed by two columns: Urgency level: P1 and Service: service_name

    # Located in your execute operation  

    blocks = []
    blocks.append(api.run("block_kit_lib.markdown_text_section", {
        "text": "*Single line of text:* More info here",
        "fields": [
            api.run("block_kit_lib.markdown_text_object",{"text": "*Urgency level:*"})[0],
            api.run("block_kit_lib.markdown_text_object",{"text": "*Service:*"})[0],
            api.run("block_kit_lib.markdown_text_object",{"text": "P1"})[0],
            api.run("block_kit_lib.markdown_text_object",{"text": "service_name"})[0]
        ]
    })[0])

    # You can pass block kit via the `blockKitOverride` parameter in your `workflow.log` or `dataParser.response()` call.

Transposit files

There are two block types that deserve a special mention, transposit_file_block and transposit_text_file_block. Transposit file blocks are a type of block that we have created custom to make uploading base64 or text files easier to Transposit. Transposit file blocks take base64 encoded data, create a file with it on Transposit servers, and share that file in your activity's timeline and Slack. The block must specify a content type (MIME type) for the data.

For an image:

    # Located in your execute operation  

    blocks = []    
    blocks.append(api.run("block_kit_lib.transposit_file_block", {
        "content" : image_blob,
        "content_type" : "image/png"
    })[0])

    # You can pass block kit via the `blockKitOverride` parameter in your `workflow.log` or `dataParser.response()` call.

Note: Plain-text content should be encoded in and specify utf-8 charset. e.g. "content_type": "text/plain; charset=utf-8"

For plain text:

This operation will create a Transposit file block, base64 encoding plain-text with the utf-8 charset.

    # Located in your execute operation  

    blocks = []
    blocks.append(api.run("block_kit_lib.transposit_text_file_block", {
        "text" : "Text to be encoded"
    })[0])

    # You can pass block kit via the `blockKitOverride` parameter in your `workflow.log` or `dataParser.response()` call.