Skip to content

tux.ui.help_components

UI components for the help command system.

This module contains all the UI components used by the help command, including: - Base views and components - Select menus for categories, commands, and subcommands - Navigation buttons - Pagination components

Classes:

Name Description
HelpCommandProtocol

Protocol defining methods a help command must implement.

BaseHelpView

Base view for all help command navigation.

BaseSelectMenu

Base class for help selection menus.

BaseButton

Base class for help navigation buttons.

CategorySelectMenu

Select menu for choosing a command category.

CommandSelectMenu

Select menu for choosing a command within a category.

SubcommandSelectMenu

Select menu for choosing a subcommand within a command group.

BackButton

Button for navigating back to the previous page.

CloseButton

Button for closing the help menu.

PaginationButton

Base class for pagination buttons.

NextButton

Button for navigating to the next page of subcommands.

PrevButton

Button for navigating to the previous page of subcommands.

HelpView

Main view for the help command with standard navigation.

DirectHelpView

View for paginated direct help commands with previous/next buttons.

Classes

HelpCommandProtocol

Bases: Protocol

Protocol defining methods a help command must implement.

BaseHelpView(help_command: HelpCommandProtocol, timeout: int = 180)

Bases: View

Base view for all help command navigation.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol, timeout: int = 180):
    super().__init__(timeout=timeout)
    self.help_command = help_command

BaseSelectMenu(help_command: HelpCommandProtocol, options: list[discord.SelectOption], placeholder: str)

Bases: Select[BaseHelpView]

Base class for help selection menus.

Methods:

Name Description
handle_select

Handle a selection from this menu.

callback

Handle the callback when an option is selected.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol, options: list[discord.SelectOption], placeholder: str):
    super().__init__(
        placeholder=placeholder,
        min_values=1,
        max_values=1,
        options=options,
    )
    self.help_command = help_command

Functions

handle_select(interaction: discord.Interaction, selected_value: str) -> None abstractmethod async

Handle a selection from this menu.

Source code in tux/ui/help_components.py
Python
@abc.abstractmethod
async def handle_select(self, interaction: discord.Interaction, selected_value: str) -> None:
    """Handle a selection from this menu."""
callback(interaction: discord.Interaction) -> None async

Handle the callback when an option is selected.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when an option is selected."""
    await interaction.response.defer()
    value = self.values[0]
    await self.handle_select(interaction, value)

BaseButton(help_command: HelpCommandProtocol, style: discord.ButtonStyle, label: str, emoji: str, custom_id: str, disabled: bool = False)

Bases: Button[BaseHelpView]

Base class for help navigation buttons.

Methods:

Name Description
handle_click

Handle a click on this button.

callback

Handle the callback when the button is clicked.

Source code in tux/ui/help_components.py
Python
def __init__(
    self,
    help_command: HelpCommandProtocol,
    style: discord.ButtonStyle,
    label: str,
    emoji: str,
    custom_id: str,
    disabled: bool = False,
):
    super().__init__(
        style=style,
        label=label,
        emoji=emoji,
        custom_id=custom_id,
        disabled=disabled,
    )
    self.help_command = help_command

Functions

handle_click(interaction: discord.Interaction) -> None abstractmethod async

Handle a click on this button.

Source code in tux/ui/help_components.py
Python
@abc.abstractmethod
async def handle_click(self, interaction: discord.Interaction) -> None:
    """Handle a click on this button."""
callback(interaction: discord.Interaction) -> None async

Handle the callback when the button is clicked.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when the button is clicked."""
    await interaction.response.defer()
    await self.handle_click(interaction)

CategorySelectMenu(help_command: HelpCommandProtocol, options: list[discord.SelectOption], placeholder: str)

Bases: BaseSelectMenu

Select menu for choosing a command category.

Methods:

Name Description
callback

Handle the callback when an option is selected.

handle_select

Handle when a category is selected.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol, options: list[discord.SelectOption], placeholder: str):
    super().__init__(
        placeholder=placeholder,
        min_values=1,
        max_values=1,
        options=options,
    )
    self.help_command = help_command

Functions

callback(interaction: discord.Interaction) -> None async

Handle the callback when an option is selected.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when an option is selected."""
    await interaction.response.defer()
    value = self.values[0]
    await self.handle_select(interaction, value)
handle_select(interaction: discord.Interaction, selected_value: str) -> None async

Handle when a category is selected.

Source code in tux/ui/help_components.py
Python
async def handle_select(self, interaction: discord.Interaction, selected_value: str) -> None:
    """Handle when a category is selected."""
    await self.help_command.on_category_select(interaction, selected_value)

CommandSelectMenu(help_command: HelpCommandProtocol, options: list[discord.SelectOption], placeholder: str)

Bases: BaseSelectMenu

Select menu for choosing a command within a category.

Methods:

Name Description
callback

Handle the callback when an option is selected.

handle_select

Handle when a command is selected.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol, options: list[discord.SelectOption], placeholder: str):
    super().__init__(
        placeholder=placeholder,
        min_values=1,
        max_values=1,
        options=options,
    )
    self.help_command = help_command

Functions

callback(interaction: discord.Interaction) -> None async

Handle the callback when an option is selected.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when an option is selected."""
    await interaction.response.defer()
    value = self.values[0]
    await self.handle_select(interaction, value)
handle_select(interaction: discord.Interaction, selected_value: str) -> None async

Handle when a command is selected.

Source code in tux/ui/help_components.py
Python
async def handle_select(self, interaction: discord.Interaction, selected_value: str) -> None:
    """Handle when a command is selected."""
    await self.help_command.on_command_select(interaction, selected_value)

SubcommandSelectMenu(help_command: HelpCommandProtocol, options: list[discord.SelectOption], placeholder: str)

Bases: BaseSelectMenu

Select menu for choosing a subcommand within a command group.

Methods:

Name Description
callback

Handle the callback when an option is selected.

handle_select

Handle when a subcommand is selected.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol, options: list[discord.SelectOption], placeholder: str):
    super().__init__(
        placeholder=placeholder,
        min_values=1,
        max_values=1,
        options=options,
    )
    self.help_command = help_command

Functions

callback(interaction: discord.Interaction) -> None async

Handle the callback when an option is selected.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when an option is selected."""
    await interaction.response.defer()
    value = self.values[0]
    await self.handle_select(interaction, value)
handle_select(interaction: discord.Interaction, selected_value: str) -> None async

Handle when a subcommand is selected.

Source code in tux/ui/help_components.py
Python
async def handle_select(self, interaction: discord.Interaction, selected_value: str) -> None:
    """Handle when a subcommand is selected."""
    await self.help_command.on_subcommand_select(interaction, selected_value)

BackButton(help_command: HelpCommandProtocol)

Bases: BaseButton

Button for navigating back to the previous page.

Methods:

Name Description
callback

Handle the callback when the button is clicked.

handle_click

Handle when the back button is clicked.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol):
    super().__init__(
        help_command=help_command,
        style=discord.ButtonStyle.secondary,
        label="Back",
        emoji="↩️",
        custom_id="back_button",
    )

Functions

callback(interaction: discord.Interaction) -> None async

Handle the callback when the button is clicked.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when the button is clicked."""
    await interaction.response.defer()
    await self.handle_click(interaction)
handle_click(interaction: discord.Interaction) -> None async

Handle when the back button is clicked.

Source code in tux/ui/help_components.py
Python
async def handle_click(self, interaction: discord.Interaction) -> None:
    """Handle when the back button is clicked."""
    await self.help_command.on_back_button(interaction)

CloseButton()

Bases: Button[BaseHelpView]

Button for closing the help menu.

Methods:

Name Description
callback

Handle when the close button is clicked.

Source code in tux/ui/help_components.py
Python
def __init__(self):
    super().__init__(
        style=discord.ButtonStyle.danger,
        label="Close",
        emoji="✖️",
        custom_id="close_button",
    )

Functions

callback(interaction: discord.Interaction) -> None async

Handle when the close button is clicked.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle when the close button is clicked."""
    if interaction.message:
        await interaction.message.delete()

PaginationButton(help_command: HelpCommandProtocol, label: str, emoji: str, custom_id: str, is_next: bool)

Bases: BaseButton

Base class for pagination buttons.

Methods:

Name Description
handle_click

Handle a click on this button.

callback

Handle the callback when the button is clicked.

Source code in tux/ui/help_components.py
Python
def __init__(
    self,
    help_command: HelpCommandProtocol,
    label: str,
    emoji: str,
    custom_id: str,
    is_next: bool,
):
    # Determine if button should be disabled based on current page
    current_page = help_command.current_subcommand_page
    disabled = False
    if is_next:
        total_pages = len(help_command.subcommand_pages)

        disabled = current_page >= total_pages - 1
    else:  # Previous button
        disabled = current_page <= 0

    super().__init__(
        help_command=help_command,
        style=discord.ButtonStyle.primary,
        label=label,
        emoji=emoji,
        custom_id=f"{custom_id}_{current_page}",
        disabled=disabled,
    )
    self.is_next = is_next

Functions

handle_click(interaction: discord.Interaction) -> None abstractmethod async

Handle a click on this button.

Source code in tux/ui/help_components.py
Python
@abc.abstractmethod
async def handle_click(self, interaction: discord.Interaction) -> None:
    """Handle a click on this button."""
callback(interaction: discord.Interaction) -> None async

Handle the callback when the button is clicked.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when the button is clicked."""
    await interaction.response.defer()
    await self.handle_click(interaction)

NextButton(help_command: HelpCommandProtocol)

Bases: PaginationButton

Button for navigating to the next page of subcommands.

Methods:

Name Description
callback

Handle the callback when the button is clicked.

handle_click

Handle when the next button is clicked.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol):
    super().__init__(
        help_command=help_command,
        label="Next",
        emoji="▶️",
        custom_id="next_button",
        is_next=True,
    )

Functions

callback(interaction: discord.Interaction) -> None async

Handle the callback when the button is clicked.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when the button is clicked."""
    await interaction.response.defer()
    await self.handle_click(interaction)
handle_click(interaction: discord.Interaction) -> None async

Handle when the next button is clicked.

Source code in tux/ui/help_components.py
Python
async def handle_click(self, interaction: discord.Interaction) -> None:
    """Handle when the next button is clicked."""
    await self.help_command.on_next_button(interaction)

PrevButton(help_command: HelpCommandProtocol)

Bases: PaginationButton

Button for navigating to the previous page of subcommands.

Methods:

Name Description
callback

Handle the callback when the button is clicked.

handle_click

Handle when the previous button is clicked.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol):
    super().__init__(
        help_command=help_command,
        label="Previous",
        emoji="◀️",
        custom_id="prev_button",
        is_next=False,
    )

Functions

callback(interaction: discord.Interaction) -> None async

Handle the callback when the button is clicked.

Source code in tux/ui/help_components.py
Python
async def callback(self, interaction: discord.Interaction) -> None:
    """Handle the callback when the button is clicked."""
    await interaction.response.defer()
    await self.handle_click(interaction)
handle_click(interaction: discord.Interaction) -> None async

Handle when the previous button is clicked.

Source code in tux/ui/help_components.py
Python
async def handle_click(self, interaction: discord.Interaction) -> None:
    """Handle when the previous button is clicked."""
    await self.help_command.on_prev_button(interaction)

HelpView(help_command: HelpCommandProtocol, timeout: int = 180)

Bases: BaseHelpView

Main view for the help command with standard navigation.

Source code in tux/ui/help_components.py
Python
def __init__(self, help_command: HelpCommandProtocol, timeout: int = 180):
    super().__init__(timeout=timeout)
    self.help_command = help_command

DirectHelpView(help_command: HelpCommandProtocol, group: commands.Group[Any, Any, Any], pages: list[list[commands.Command[Any, Any, Any]]])

Bases: BaseHelpView

View for paginated direct help commands with previous/next buttons.

Methods:

Name Description
get_embed

Get the embed for the current page.

prev_button_callback

Handle previous page button press.

next_button_callback

Handle next page button press.

close_button_callback

Handle close button press.

Source code in tux/ui/help_components.py
Python
def __init__(
    self,
    help_command: HelpCommandProtocol,
    group: commands.Group[Any, Any, Any],
    pages: list[list[commands.Command[Any, Any, Any]]],
):
    super().__init__(help_command)
    self.group = group
    self.current_page = 0
    self.pages = pages

    # Add navigation buttons
    self.prev_button = discord.ui.Button[BaseHelpView](
        label="Previous",
        style=discord.ButtonStyle.primary,
        emoji="◀️",
        custom_id="prev_page",
        disabled=True,
    )
    self.prev_button.callback = self.prev_button_callback
    self.add_item(self.prev_button)

    self.next_button = discord.ui.Button[BaseHelpView](
        label="Next",
        style=discord.ButtonStyle.primary,
        emoji="▶️",
        custom_id="next_page",
        disabled=len(self.pages) <= 1,
    )
    self.next_button.callback = self.next_button_callback
    self.add_item(self.next_button)

    # Add close button
    close_button = discord.ui.Button[BaseHelpView](
        label="Close",
        style=discord.ButtonStyle.danger,
        emoji="✖️",
        custom_id="close_help",
    )
    close_button.callback = self.close_button_callback
    self.add_item(close_button)

Functions

get_embed() -> discord.Embed async

Get the embed for the current page.

Source code in tux/ui/help_components.py
Python
async def get_embed(self) -> discord.Embed:
    """Get the embed for the current page."""
    # Get prefix from the context
    prefix = self.help_command.context.clean_prefix

    # Format help text with proper quoting for all lines
    help_text = self.group.help or "No documentation available."
    formatted_help = "\n".join(f"> {line}" for line in help_text.split("\n"))

    embed = discord.Embed(
        title=f"{prefix}{self.group.qualified_name}",
        description=formatted_help,
        color=CONST.EMBED_COLORS["DEFAULT"],
    )

    # Add basic command info
    embed.add_field(
        name="Usage",
        value=f"`{prefix}{self.group.qualified_name} <subcommand>`",
        inline=False,
    )

    if self.group.aliases:
        embed.add_field(
            name="Aliases",
            value=f"`{', '.join(self.group.aliases)}`",
            inline=False,
        )

    # If we have pages
    if self.pages:
        current_page_cmds = self.pages[self.current_page]
        page_num = self.current_page + 1
        total_pages = len(self.pages)

        embed.add_field(
            name=f"Subcommands (Page {page_num}/{total_pages})",
            value=f"This command has {sum(len(page) for page in self.pages)} subcommands:",
            inline=False,
        )

        # Add each subcommand with a non-inline field
        for cmd in current_page_cmds:
            embed.add_field(
                name=cmd.name,
                value=f"> {cmd.short_doc or 'No description'}",
                inline=False,
            )

    return embed
prev_button_callback(interaction: discord.Interaction) -> None async

Handle previous page button press.

Source code in tux/ui/help_components.py
Python
async def prev_button_callback(self, interaction: discord.Interaction) -> None:
    """Handle previous page button press."""
    await interaction.response.defer()

    if self.current_page > 0:
        self.current_page -= 1

        # Update button states
        self.prev_button.disabled = self.current_page == 0
        self.next_button.disabled = False

        embed = await self.get_embed()
        if interaction.message:
            await interaction.message.edit(embed=embed, view=self)
next_button_callback(interaction: discord.Interaction) -> None async

Handle next page button press.

Source code in tux/ui/help_components.py
Python
async def next_button_callback(self, interaction: discord.Interaction) -> None:
    """Handle next page button press."""
    await interaction.response.defer()

    if self.current_page < len(self.pages) - 1:
        self.current_page += 1

        # Update button states
        self.prev_button.disabled = False
        self.next_button.disabled = self.current_page == len(self.pages) - 1

        embed = await self.get_embed()
        if interaction.message:
            await interaction.message.edit(embed=embed, view=self)
close_button_callback(interaction: discord.Interaction) -> None async

Handle close button press.

Source code in tux/ui/help_components.py
Python
async def close_button_callback(self, interaction: discord.Interaction) -> None:
    """Handle close button press."""
    if interaction.message:
        await interaction.message.delete()