telega/menu_builder
Menu Builder Module
This module provides an advanced menu system for Telegram bots, extending beyond basic keyboards to create rich, interactive menu experiences with state management, navigation, and pagination.
Key Features
- Stateful Menus: Menus that maintain state across interactions
- Navigation System: Back/forward navigation with breadcrumbs
- Pagination: Built-in pagination for large datasets
- Dynamic Menus: Menus that update based on data changes
- Context Actions: Actions that can modify menu state
- Nested Menus: Support for hierarchical menu structures
Quick Start
Simple Menu
let menu = menu_builder.new("main_menu")
|> menu_builder.title("๐ Main Menu")
|> menu_builder.add_item("๐ View Items", "view_items")
|> menu_builder.add_item("โ Add Item", "add_item")
|> menu_builder.add_item("โ๏ธ Settings", "settings")
|> menu_builder.build()
Paginated Menu
let items = ["Item 1", "Item 2", "Item 3", ..., "Item 100"]
let menu = menu_builder.new("item_list")
|> menu_builder.title("๐ Items")
|> menu_builder.paginate(items, page: 1, items_per_page: 10)
|> menu_builder.with_back_button("main_menu")
|> menu_builder.build()
Stateful Menu with Actions
pub type MenuState {
MenuState(items: List(String), selected: Option(Int))
}
let menu = menu_builder.new_stateful("item_selector", initial_state)
|> menu_builder.title("Select an Item")
|> menu_builder.add_stateful_items(state.items, fn(item, index) {
let selected = case state.selected {
Some(i) if i == index -> "โ
"
_ -> ""
}
#(selected <> item, "select:" <> int.to_string(index))
})
|> menu_builder.on_action("select", fn(state, data) {
let index = int.parse(data) |> result.unwrap(0)
MenuState(..state, selected: Some(index))
})
|> menu_builder.build()
Types
Menu builder for constructing menus
pub opaque type MenuBuilder(state)
Represents a menu item with text and action data
pub type MenuItem {
MenuItem(text: String, action: String, enabled: Bool)
}
Constructors
-
MenuItem(text: String, action: String, enabled: Bool)
Menu layout configuration
pub type MenuLayout {
MenuLayout(
columns: Int,
max_rows_per_section: option.Option(Int),
section_separator: Bool,
)
}
Constructors
-
MenuLayout( columns: Int, max_rows_per_section: option.Option(Int), section_separator: Bool, )
Represents a menu section for grouping related items
pub type MenuSection {
MenuSection(
title: option.Option(String),
items: List(MenuItem),
)
}
Constructors
-
MenuSection(title: option.Option(String), items: List(MenuItem))
Menu state for stateful menus
pub type MenuState(state) {
MenuState(
id: String,
data: state,
current_page: Int,
navigation_stack: List(String),
context: dict.Dict(String, String),
)
}
Constructors
-
MenuState( id: String, data: state, current_page: Int, navigation_stack: List(String), context: dict.Dict(String, String), )
Navigation configuration
pub type NavigationConfig {
NavigationConfig(
back_button: option.Option(String),
back_text: String,
home_button: option.Option(String),
home_text: String,
show_breadcrumbs: Bool,
)
}
Constructors
-
NavigationConfig( back_button: option.Option(String), back_text: String, home_button: option.Option(String), home_text: String, show_breadcrumbs: Bool, )
Configuration for pagination
pub type PaginationConfig {
PaginationConfig(
items_per_page: Int,
show_page_info: Bool,
prev_text: String,
next_text: String,
page_info_template: String,
)
}
Constructors
-
PaginationConfig( items_per_page: Int, show_page_info: Bool, prev_text: String, next_text: String, page_info_template: String, )
Values
pub fn add_disabled_item(
builder: MenuBuilder(state),
text: String,
action: String,
) -> MenuBuilder(state)
Add a disabled menu item
pub fn add_item(
builder: MenuBuilder(state),
text: String,
action: String,
) -> MenuBuilder(state)
Add a simple menu item
pub fn add_items_from_list(
builder: MenuBuilder(state),
items: List(item),
formatter: fn(item, Int) -> #(String, String),
) -> MenuBuilder(state)
Add multiple items from a list with custom formatting
pub fn add_stateful_items(
builder: MenuBuilder(state),
items: List(item),
formatter: fn(item, Int, state) -> #(String, String, Bool),
) -> MenuBuilder(state)
Add items for stateful menus that can access state
pub fn add_submenu(
builder: MenuBuilder(state),
text: String,
submenu_id: String,
) -> MenuBuilder(state)
Create a submenu item that navigates to another menu
pub fn add_toggle(
builder: MenuBuilder(state),
text_template: String,
action: String,
current_value: Bool,
) -> MenuBuilder(state)
Create a toggle item for boolean settings
pub fn confirmation(
id: String,
message: String,
confirm_action: String,
cancel_action: String,
confirm_text: String,
cancel_text: String,
) -> Menu(Nil)
Create a confirmation menu
pub fn get_callback_data(
menu: Menu(state),
) -> keyboard.KeyboardCallbackData(String)
Get menu callback data for filtering
pub fn get_state(
menu: Menu(state),
) -> option.Option(MenuState(state))
Get menu state
pub fn get_title(menu: Menu(state)) -> String
Helper to get menu title with optional state formatting
pub fn handle_action(
menu: Menu(state),
action: String,
) -> Result(Menu(state), String)
Handle menu action and return updated menu
pub fn layout(
builder: MenuBuilder(state),
columns: Int,
max_rows_per_section: option.Option(Int),
section_separator: Bool,
) -> MenuBuilder(state)
Configure menu layout
pub fn new_stateful(
id: String,
initial_state: state,
) -> MenuBuilder(state)
Create a new stateful menu builder
pub fn on_action(
builder: MenuBuilder(state),
action_name: String,
handler: fn(MenuState(state), String) -> MenuState(state),
) -> MenuBuilder(state)
Register an action handler for stateful menus
pub fn paginate(
builder: MenuBuilder(state),
items_per_page: Int,
show_page_info: Bool,
) -> MenuBuilder(state)
Configure pagination
pub fn paginate_with_text(
builder: MenuBuilder(state),
items_per_page: Int,
show_page_info: Bool,
prev_text: String,
next_text: String,
page_info_template: String,
) -> MenuBuilder(state)
Configure pagination with custom texts
pub fn section(
builder: MenuBuilder(state),
title: option.Option(String),
) -> MenuBuilder(state)
Start a new section with optional title
pub fn settings_menu(
id: String,
menu_title: String,
settings: List(#(String, String, Bool)),
) -> Menu(Nil)
Create a settings menu with toggles
pub fn title(
builder: MenuBuilder(state),
title: String,
) -> MenuBuilder(state)
Set the menu title
pub fn to_keyboard(
menu: Menu(state),
) -> Result(keyboard.InlineKeyboard, String)
Convert menu to inline keyboard
pub fn update_state(
menu: Menu(state),
updater: fn(MenuState(state)) -> MenuState(state),
) -> Menu(state)
Update menu state
pub fn with_back_button(
builder: MenuBuilder(state),
back_action: String,
) -> MenuBuilder(state)
Add back button navigation
pub fn with_back_button_text(
builder: MenuBuilder(state),
back_action: String,
back_text: String,
) -> MenuBuilder(state)
Add back button navigation with custom text
pub fn with_home_button(
builder: MenuBuilder(state),
home_action: String,
) -> MenuBuilder(state)
Add home button navigation
pub fn with_home_button_text(
builder: MenuBuilder(state),
home_action: String,
home_text: String,
) -> MenuBuilder(state)
Add home button navigation with custom text