{"id":13821000,"url":"https://github.com/escamez/slackviews","last_synced_at":"2025-05-16T11:30:58.759Z","repository":{"id":57468276,"uuid":"295498502","full_name":"escamez/slackviews","owner":"escamez","description":"Python 3 library to build Slack views using builder pattern","archived":false,"fork":false,"pushed_at":"2020-10-09T22:48:15.000Z","size":319,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-20T16:50:33.492Z","etag":null,"topics":["builder","python3","slack","views"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/escamez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-14T18:06:19.000Z","updated_at":"2021-08-23T17:57:34.000Z","dependencies_parsed_at":"2022-09-19T09:01:38.791Z","dependency_job_id":null,"html_url":"https://github.com/escamez/slackviews","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escamez%2Fslackviews","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escamez%2Fslackviews/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escamez%2Fslackviews/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/escamez%2Fslackviews/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/escamez","download_url":"https://codeload.github.com/escamez/slackviews/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254521745,"owners_count":22084977,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["builder","python3","slack","views"],"created_at":"2024-08-04T08:01:13.411Z","updated_at":"2025-05-16T11:30:54.028Z","avatar_url":"https://github.com/escamez.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# Slack View Library\n\n[Examples section](#examples)\n\nObjects:\n\n[AbstractBlock](#abstractblock), [AbstractBuilder](#abstractbuilder), [AbstractText](#abstracttext), [PlainText](#plaintext), [MarkDown](#markdown), [Divider](#divider), [Header](#header), [Image](#image), [Confirmation](#confirmation), [Button](#button), [Option](#option), [OptionGroup](#optiongroup), [SelectMenu](#selectmenu), [MultiSelectMenu](#multiselectmenu), [Overflow](#overflow), [PlainTextInput](#plaintextinput), [Section](#section)\n[PlainTextInput](#plaintextinput), [Actions](#actions), [Context](#context), [Input](#input), [View](#view), [Modal](#modal), [Home](#home), [BlocksArray](#blocksarray), [BlocksFactory](#blocksfactory)\n\n[Pydoc](docs/slack_view.html)\n\n## Introduction\n\nIf you're reading this, is because either you love Slack, or just need to work with its API somehow. Recently I had to \nstart implementing a bot in Slack which content was more complex than usual. Then, I found that Slack API was quite \neasy to use but.... its views, those contents in json can be soooo huge and complex, that I realized I spent most of my \ntime designing templates instead of coding the logic of the bot.\nThis is when I started to look around searching for some library that would allow me to code my views in Python easily, \nunfortunately, I didn't found any (hey, if it does exist, please let me know, I had no idea about it) so I decided to\nwrite this one.\nThe lib, includes \"almost\" all Block types, I just left out those that I was not gonna use for sure, but once you see \nthe source code you'll realize it can be extended to include those pretty easily.\n\nThere is another module with a basic model to handle  Slack commands and interactions, named *payloads*\n \n## Syntaxis\n\nThere is a convention to distinguish between *required*, *optional* and *mutually exclusive* attributes:\n\n - *required attributes*: Required attributes are represented for those builder's methods that **do not** have underscores at all.\n \n - *optional attributes*: Optional attributes are represented for those builder's methods that **do** have **one** underscore at the end, for example: `text()`, `element()`, ...\n \n - *mutually exclusive attributes*: In those cases where only one out of two attributes can be set, are represented for those builder's methods that **do** have a **double underscored** at the end, for example: `field__()`, `text__()`, ...\n \n \n## Library's elements\n\nMost of descriptions in next elements, has been extracted from current Slack's documentation.\n\n### **AbstractBlock**\n\nMain class that represents an instance of a Block element in Slack. Any instance that represents a block will inherit from it.\n\nBuilder's methods:\n\n  - `__eq__(self, other)`: Implementation to compare AbstractBlock instances\n  \n  - `serialize(self, as_json=False)`: Serialized current instance as a dictionary. If as_json is True, then a json dumps is done with serialized dictionary\n  \n  - `deserialize(cls, _dict, from_json=False)`: Creates an AbstractBlock instance from supplied dictionary. If from_json is True, then the dictionary is built first from json loads.\n\n### **AbstractBuilder**\n\nAbstract class that represents a builder of an AbstractBlock. Any builder in an AbstractBlock must inherit from it. It allows a \"method-chain-navigation\" of the Block using the Builder pattern, allowing to step back to uppper builder when all settings in current builder are done.\n\nBuilder's methods:\n\n  - `build()`: Provides the instance managed by current builder\n  \n  - `up()`: Returns previous builder\n  \n### **AbstractText**\n\nRepresents any Text block in Slack, and contains common functionality to both implementations, PlainText and MarkDown. \n\nBuilder's methods:\n\n  - `text()`: method to set current content.\n\n### **PlainText** \n\nText without any formatting.\n\nBuilder's methods:\n\n  - `emoji_(self, boolean)`: Indicates whether emojis in a text field should be escaped into the colon emoji format\n\n### **MarkDown**\n\nText with special slack formatting\n\nBuilder's methods:\n\n  - `verbatim_(self, boolean)`: When set to false (as is default) URLs will be auto-converted into links, conversation names will be link-ified, and certain mentions will be automatically parsed. Using a value of true will skip any preprocessing of this nature, although you can still include manual parsing strings.\n\n### **Divider**\n\nA block's divider. Adds a horizontal line that can be use to separate block's\n\n### **Header**\n\nIt's a block with the largest font text, and can be used for example as title at the begging of messages\n\nBuilder's methods:\n\n - `text(self, txt)`: Header content\n - `block_id_(self, block_id)`: Block id as a string\n        \n### **Image**\n\nIt's used to add any remote image to a message.        \n\nBuilder's methods:\n\n - `image_url(self, image_url)`: The URL of the image to be displayed.\n - `alt_text(self, alt_text)`: The text to be used as a a plain-text summary of the image. This should not contain any markup.\n        \n### **Confirmation**\n\nIt defines a dialog that provides a confirmation step to any interactive element.\n\nBuilder's methods:\n\n - `title(self, title)`: Confirmation dialog title\n - `confirm(self, confirm)`: The content of the plain_text-only text object that defines the text of the button\n    that confirms the action\n - `deny(self, deny)`: The text for the plain_text-only text object that defines the text of the button that cancels the  action.\n - `text(self, text, verbatim=False)`: A text object that defines the explanatory text that appears in the confirm dialog.    \n - `style_(self, style)`: Defines the color scheme applied to the confirm button. A value of \"danger\" will display the button with a red background on desktop, or red text on mobile. A value of \"primary\" will display the button with a green background on desktop, or blue text on mobile.\n            \n### **Button**\n\nCreates an interative component, a button. It can be clicked to set a value, perform an action, or open an url.\n\nBuilder's methods:\n\n - `action_id(self, action_id)`: An identifier for this action. You can use this when you receive an interaction payload to identify the source of the action. It MUST BE unique among all other action_ids used elsewhere in the app.\n        \n - `text(self, text)`: A string for the plain_text object that defines the button's text.\n\n - `url_(self, url)`: A URL to load in the user's browser when the button is clicked.\n\n - `value_(self, value)`: The value to send along with the interaction payload.\n\n - `style_(self, style)`: Decorates buttons with alternative visual color schemes, \"primary\" gives buttons a green outline and text, primary should only be used for one button within a set, \"danger\" gives buttons a red outline and text, and should be used when the action is destructive.\n\n - `Confirm_(self)`: Provides a Confirmation builder object to help creating an optional confirmation dialog after\n            the button is clicked.\n            \n### **Option**\n\nAn object that represents a single selectable item in a select menu, multi-select menu, checkbox group,radio button group, or overflow menu.\n\nBuilder's methods:\n\n - `text(self, text)`: A text object that defines the text shown in the option on the menu. Overflow, select, and multi-select\n            menus can only use plain_text objects, while radio buttons and checkboxes can use mrkdwn text objects.\n\n - `value(self, value)`: The string value that will be passed to your app when this option is chosen.\n\n - `description_(self, description)`: The text for the plain_text only text object that defines a line of descriptive text shown below the text field beside the radio button.\n\n - `url_(self, url)`: An URL to load in the user's browser when the option is clicked. The url attribute is only available\n            in overflow menus.\n\n### **OptionGroup** \n\nIt's used to group options in a select menu or multi-select menu.\n\nBuilder's methods:\n\n - `label(self, label)`: The text for the plain_text only text object that defines the label shown above this group of options.\n        \n - `Option(self)`: Provides an instance of Option's builder\n\n### **SelectMenu**\n\nA select menu, just as with a standard HTML _select_ tag, creates a drop down menu with a list of options for \na user to choose. The select menu also includes type-ahead functionality, where a user can type a part or all of an option string to filter the list.\n    \nInstance's methods:\n\n  - `set_default(self, text_option)`: Sets default value in the menu. It's possible to supply, or the text that represents the underlying value in the menu, or the  value itself\n\n  - `get_default(self)`: Provides the default option, if any, as a tuple\n\n  - `has_option(self, text_option)`: Checks if the text supplied is already included in the array of options\n    \nBuilder's methods:\n\n  - `action_id(self, action_id)`: An identifier for the action triggered when a menu option is selected.\n\n  - `placeholder(self, placeholder)`: A text for the plain_text object that defines the placeholder text shown on the menu.\n \n  - `Option__(self)`: Provides an instance of Option's builder.\n  \n  - `OptionGroup__(self)`: Provides an instance of OptionGroup's builder.\n                            \n  - `initial_option_(self, text_option)`: A single option that exactly matches one of the options within options or option_groups.\n            \n  - `Confirm_(self)`: An instance of Confirmation's builder\n            \n### **MultiSelectMenu**\n\nA multi-select menu is just like a Selectmenu, but allows a user to select multiple items from it.\n\nBuilder's methods, (others than Selectmenu):\n\n  - `max_selected_items_(self, max_selected_items)`: Sets the maximum number of items that can be selected in the selectmenu.\n\n### **Overflow**\n\nThis is like a cross between a button and a select menu - when a user clicks on this overflow button, they will be presented with a list of options to choose from. Unlike the select menu, there is no typeahead field, and the button always appears with an ellipsis (\"...\") rather than customisable text.\n\nBuilder's methods:\n\n  - `action_id(self, action_id)`: An identifier for the action triggered when a menu option is selected.\n\n  - `Option(self)`: An instance of Option's builder\n\n  - `Confirm_(self)`: An instance of Confirm's builder           \n\n### **PlainTextInput**\n\nA plain-text input, it creates a field where a user can enter freeform data.\n\nBuilder's methods:\n\n  - `action_id(self, action_id)`: An identifier for the input value when the parent modal is submitted.\n\n  - `initial_value_(self, initial_value)`: The initial value in the plain-text input when it is loaded.\n\n  - `min_length_(self, min_length)`: The minimum length of input that the user must provide.\n\n  - `max_length_(self, max_length)`: The maximum length of input that the user can provide.\n\n  - `multiline_(self, boolean)`: Indicates whether the input will be a single line (false) or a larger textarea (true). Default is false\n\n  - `placeholder_(self, placeholder)`: A text to user in plain_text object that defines the placeholder text shown in the plain-text input.\n\n### **Section**\n\nA section can be used as a simple text block, in combination with text fields, or side-by-side with any of the available block elements.\n\nBuilder's methods:\n\n  - `text__(self, text, verbatim=False)`: The text for the block, in the form of a text object.\n\n  - `block_id_(self, block_id)`: A string acting as a unique identifier for a block.\n  \n  -  `field__(self, text, verbatim=False)`: Creates an a new MarkDown instance, and add it to the array of text objects.\n\n  - `accessory_(self)`: Provides an inner class instance with a builder instance of each one of the available element objects. Namely: \n      - Button\n      - Image\n      - MultiSelectMenu\n      - Overflow\n      - PlainTextInput\n      - SelectMenu\n\n### **Actions**\n\nThis block is used to hold interactive elements.\n\nBuilder's methods:\n\n  - `block_id_(self, block_id)`: A string acting as a unique identifier for this block.\n\n  - `element(self)`: If no \"elements\" array is found, a new one is created, and an instance of an internal class with all builders from allowed elements is shown. The attribute \"elements\" holds an array of interactive element objects, namely:\n  \n    - Button\n    - Overflow\n    - SelectMenu\n\n### **Context**\n\nDisplays message context, which can include both images and text. The size (images, fonts etc) of this block is smaller than other Blocks.\n\nBuilder's methods:\n\n  - `block_id_(self, block_id)`: A string acting as a unique identifier for this block.\n\n  - `element(self)`: If no \"elements\" array is found, a new one is created, and an instance of an internal class with all builders from allowed elements is shown. The attribute \"elements\" holds an array of interactive element objects, namely:\n\n    - Image\n    - Text\n    \n### **Input**\n\nA block that collects information from users.\n\nBuilder's methods:\n\n  - `label(self, label)`: A label that appears above an input element in the form of a text object as plain_text.\n\n  - `element(self)`: If no \"elements\" array is found, a new one is created, and an instance of an internal class with all builders from allowed elements is shown. The attribute \"elements\" holds an array of interactive element objects, namely:\n\n    - PlainTextInput\n    - SelectMenu\n    - MultiSelectMenu\n    \n### **View**\n\nAbstract class that represents a View. There're two types of  views, namely Modals and Hometabs.\n\nBuilder's methods:\n\n  - `title(self, txt)`: View title\n\n  - `Blocks(self)`: Use this to build the array of blocks of the view\n\n  - `close_(self, close_txt)`: An optional text to create a plain_text element that  defines the text displayed in the close button at the bottom-right of the view.\n                \n  - `submit_(self, submit_txt)`: Text to create an optional plain_text element that defines the text displayed in the submit button at the bottom-right of the view.\n        \n  - `private_metadata_(self, private_metadata)`: An optional string that will be sent to your app in view_submission and block_actions events.\n\n  - `callback_id_(self, callback_id)`: An identifier to recognize interactions and submissions of this particular view.\n  \n  - `clear_on_close_(self, clear_on_close)`: When set to true, clicking on the close button will clear all views in a modal and close it. Defaults to false.\n\n  - `notify_on_close_(self, notify_on_close)`: Indicates whether Slack will send your request URL a view_closed event when a user clicks the close button. Defaults to false.\n\n  - `external_id_(self, external_id)`: A custom identifier that must be unique for all views on a per-team basis.\n\n### **Modal**\n\nA view which __type__ is \"modal\"\n\n### **Home**\n\nA view which __type__ is \"home\"\n\n### **BlocksArray**\n\nThis object represents the array of blocks being sent in a Slack message. It doesn't extend AbstractBlocks because actually it's not a block, but a group of blocks in an array. So it just acts as a wrapper of an array with a dictionary of blocks\n\nInstance's methods:\n\n  - `serialize(self, as_json=False)`: Returns the array of blocks's dictionary. It's an array,  not a dictionary with key \"blocks\". The array is ready to be serialized in Slack, If as_json is True, then a jdon dumps is done with dictionary\n       \n  - `has_input_block(self)`: True if an Input exists in the array of blocks, False otherwise\n  \n  - `num_of_blocks(self)`: Provides the number of blocks in the array, it's length\n\n  - `of(_array_of_dicts, from_json=False)`: Provides an instance of BlocksArray initialized with supplied array of serialized blocks. Supplied argument must be an array of Block's dictionaries, or a json dumps of such array, in this case from_json must be True.\n  \n  \nBuilder's methods:\n\nProvide an instance of layou's builders previously seen. Namely:\n\n  - Actions\n  - Context\n  - Divider\n  - Header           \n  - Input\n  - Section\n\n### **BlocksFactory**\n\nFactory class to deserialize AbstractBlock back to objects. Source object can be a dictionary or a json dump of such dict.\n\nClass's methods:\n\n  - `get_block_class(cls, dictionary)`: Provides the class associated to supplied dictionary \n  \n  - `of(dictionary, from_json=False)`: Builds an instance of a class that inherits from AbstractBlock from supplied dictionary. If supplied dictionary is a json dump, then from_json must be True\n  \n## Examples\n\nMost of these examples can be tested in [Slack Block Kit Builder](https://app.slack.com/block-kit-builder).\nJust clear the supplied default blocks and make sure to serialize supplied examples as json, for example:\n\n`plaintext = PlainText.Builder().text('Simple text without formatting').build()`\n\n  _{'type': 'plain_text', 'text': 'Simple text without formatting', 'emoji': False}_\n\nthen \n\n`plaintext = PlainText.Builder().text('Simple text without formatting').build().serialize(as_json=True)`\n\n  _'{\"type\": \"plain_text\", \"text\": \"Simple text without formatting\", \"emoji\": false}'_\n  \nand copy the content between quotes (without the quotes) to *blocks* array. \nSometimes, not all combinations are available in SBKB, but can be tested sending a message to a known private channel.\n\n**Simple plaintext elements**\n\n```\nplaintext = PlainText.Builder().text('Simple text without formatting').build()\nplanintext_escaped = PlainText.Builder().text('Simple text with emojis escaped into colon emoji format :)') \\\n    .emoji_(True).build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'{\"type\": \"plain_text\", \"text\": \"Simple text without formatting\", \"emoji\": false}'_\n  \n  _'{\"type\": \"plain_text\", \"text\": \"Simple text with emojis escaped into colon emoji format :)\", \"emoji\": true}'_\n\n**Section with markdown**\n```\nsection = Section.Builder().text__('Text with *markdown* _formatting_ and url processing http://anyurl.com').build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"Text with *markdown* _formatting_ and url processing http://anyurl.com\", \"verbatim\": false}}'_\n\nBlock Kit Builder image:\n\n  ![Section with formatted Markdown](images/markdown.png)\n\n**Section with markdown and verbatim mode**\n\n```\nsection_verbatim = Section.Builder().text__('Text in verbatim mode. For example urls are not processed: http://anyurl.com', verbatim=True).build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"Text in verbatim mode. For example urls are not processed: http://anyurl.com\", \"verbatim\": true}}'_\n\nBlock Kit Builder image:\n\n  ![Section with verbatim Markdown](images/markdown_verbatim.png)\n  \n**Section with 4 fields an a Button with confirmation**\n\n```\nsection_with_fields = Section.Builder().block_id_('any block id')\nfor i in range(4):\n    section_with_fields.field__(f'*Field_{i}*: value {i}')\nsection_with_fields.accessory_().Button().text('Click').action_id('action_name').style_('danger') \\\n    .Confirm_().title('Confirmation').style_('danger').text('are you sure?').confirm('yes').deny('no').up().up() \\\n    .build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'{\"type\": \"section\", \"accessory\": {\"type\": \"button\", \"confirm\": {\"style\": \"danger\", \"deny\": {\"type\": \"plain_text\", \"text\": \"no\", \"emoji\": false}, \"confirm\": {\"type\": \"plain_text\", \"text\": \"yes\", \"emoji\": false}, \"text\": {\"type\": \"mrkdwn\", \"text\": \"are you sure?\", \"verbatim\": false}, \"title\": {\"type\": \"plain_text\", \"text\": \"Confirmation\", \"emoji\": false}}, \"style\": \"danger\", \"action_id\": \"action_name\", \"text\": {\"type\": \"plain_text\", \"text\": \"Click\", \"emoji\": false}}, \"fields\": [{\"type\": \"mrkdwn\", \"text\": \"*Field_0*: value 0\", \"verbatim\": false}, {\"type\": \"mrkdwn\", \"text\": \"*Field_1*: value 1\", \"verbatim\": false}, {\"type\": \"mrkdwn\", \"text\": \"*Field_2*: value 2\", \"verbatim\": false}, {\"type\": \"mrkdwn\", \"text\": \"*Field_3*: value 3\", \"verbatim\": false}], \"block_id\": \"any block id\"}'_\n\nBlock Kit Builder image:\n\n  ![Section with 4 fields an a Button with confirmation](images/section_with_4_fields_and_button.png)\n  \n**Section with text an a button that opens an url**\n\n```\nsection_with_button = Section.Builder().text__('Click button to open google').accessory_() \\\n    .Button().action_id('any_action_name').text('Google').url_('http://www.google.com').up() \\\n    .build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'{\"type\": \"section\", \"accessory\": {\"type\": \"button\", \"url\": \"http://www.google.com\", \"action_id\": \"any_action_name\", \"text\": {\"type\": \"plain_text\", \"text\": \"Google\", \"emoji\": false}}, \"text\": {\"type\": \"mrkdwn\", \"text\": \"Click button to open google\", \"verbatim\": false}}'_\n\nBlock Kit Builder image:\n\n  ![Section with text an a button that opens an url](images/section_with_button_and_url.png)\n  \n**Section with a multiline PlainInputText**\n\n``` \nSection.Builder().text__('Please, input necessary content').accessory_() \\\n    .PlainTextInput().action_id('any_action_id').multiline_(True).initial_value_('Initial content').up() \\\n    .build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'{\"type\": \"section\", \"accessory\": {\"type\": \"plain_text_input\", \"multiline\": true, \"initial_value\": \"Initial content\", \"action_id\": \"any_action_id\"}, \"text\": {\"type\": \"mrkdwn\", \"text\": \"Please, input necessary content\", \"verbatim\": false}}'_\n\nBlock Kit Builder image:\n\n[Blocks builder does not allow me to show this in Blocks Kit Bilder]\n\n**Context with mardown text**\n\n```\ncontext_with_text = Context.Builder().element().Text().text('Any *formatted* text with smaller font').up().build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'{\"type\": \"context\", \"elements\": [{\"type\": \"mrkdwn\", \"text\": \"Any *formatted* text with smaller font\", \"verbatim\": false}]}'_\n\nBlock Kit Builder image:\n\n  ![Simple Context element](images/simple_context.png)\n \n**Overflow with options. As can be seen, since the reference of the builder is returned it's much easier to build\nany content**\n\n```\n_builder_section = Section.Builder().text__('Section with overflow and options')\n_builder_overflow = _builder_section.accessory_().Overflow()\n_builder_overflow.action_id('any_action_id')\nfor i in range(4):\n    _builder_overflow.Option().text(f'option {i}').value(f'{i}')\n_builder_overflow.Confirm_().text('Confirmation option').title('are you sure?').confirm('yes').deny('no') \\\n    .style_('primary')\nsection_with_overflow = _builder_section.build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'{\"type\": \"section\", \"accessory\": {\"type\": \"overflow\", \"confirm\": {\"style\": \"primary\", \"deny\": {\"type\": \"plain_text\", \"text\": \"no\", \"emoji\": false}, \"confirm\": {\"type\": \"plain_text\", \"text\": \"yes\", \"emoji\": false}, \"text\": {\"type\": \"mrkdwn\", \"text\": \"Confirmation option\", \"verbatim\": false}, \"title\": {\"type\": \"plain_text\", \"text\": \"are you sure?\", \"emoji\": false}}, \"options\": [{\"value\": \"0\", \"text\": {\"type\": \"plain_text\", \"text\": \"option 0\", \"emoji\": false}}, {\"value\": \"1\", \"text\": {\"type\": \"plain_text\", \"text\": \"option 1\", \"emoji\": false}}, {\"value\": \"2\", \"text\": {\"type\": \"plain_text\", \"text\": \"option 2\", \"emoji\": false}}, {\"value\": \"3\", \"text\": {\"type\": \"plain_text\", \"text\": \"option 3\", \"emoji\": false}}], \"action_id\": \"any_action_id\"}, \"text\": {\"type\": \"mrkdwn\", \"text\": \"Section with overflow and options\", \"verbatim\": false}}'_\n\nBlock Kit Builder image:\n\n ![Overflow with options](images/overflow_with_options.png)\n\n**BlocksArray with a Header, divider, Section with fields, Input with plaintextinput multiline and actions \nwith a couple of buttons, one green (primary style) an another one red (danger style)**\n\n```\nblocks_array = BlocksArray.Builder() \\\n    .Header().text('Header title').up() \\\n    .Divider().up() \\\n    .Section().field__('field 1').field__('field 2').field__('field 3').field__('field 4').up() \\\n    .Input().label('Input text').element().PlainTextInput().multiline_(True).action_id('input_action_id').up().up() \\\n    .Divider().up() \\\n    .Actions().element().Button().action_id('action_1').text('action 1').style_('primary').up() \\\n              .element().Button().action_id('action_2').text('action 2').style_('danger').up() \\\n    .up().build().serialize(as_json=True)\n```\n\nJson Serialized:\n\n  _'[{\"type\": \"header\", \"text\": {\"type\": \"plain_text\", \"text\": \"Header title\", \"emoji\": false}}, {\"type\": \"divider\"}, {\"type\": \"section\", \"fields\": [{\"type\": \"mrkdwn\", \"text\": \"field 1\", \"verbatim\": false}, {\"type\": \"mrkdwn\", \"text\": \"field 2\", \"verbatim\": false}, {\"type\": \"mrkdwn\", \"text\": \"field 3\", \"verbatim\": false}, {\"type\": \"mrkdwn\", \"text\": \"field 4\", \"verbatim\": false}]}, {\"type\": \"input\", \"element\": {\"type\": \"plain_text_input\", \"multiline\": true, \"action_id\": \"input_action_id\"}, \"label\": {\"type\": \"plain_text\", \"text\": \"Input text\", \"emoji\": false}}, {\"type\": \"divider\"}, {\"type\": \"actions\", \"elements\": [{\"type\": \"button\", \"style\": \"primary\", \"action_id\": \"action_1\", \"text\": {\"type\": \"plain_text\", \"text\": \"action 1\", \"emoji\": false}}, {\"type\": \"button\", \"style\": \"danger\", \"action_id\": \"action_2\", \"text\": {\"type\": \"plain_text\", \"text\": \"action 2\", \"emoji\": false}}]}]'_\n\nBlock Kit Builder image:\n\n ![Complex BlocksArray](images/blocksarray.png)\n   \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fescamez%2Fslackviews","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fescamez%2Fslackviews","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fescamez%2Fslackviews/lists"}