Skip to main content

A fluent builder pattern for creating Discord UI LayoutViews with containers.

Project description

dpy-layout-builder

A fluent builder pattern for creating Discord UI LayoutViews with containers in discord.py.

Stop wrestling with nested Container, ActionRow, Section, and TextDisplay calls - chain a few methods and .build().

PyPI Python License: MIT discord.py

Installation

pip install dpy-layout-builder

Quick Start

import discord
from dpy_layout_builder import LayoutViewBuilder

async def my_callback(interaction: discord.Interaction):
    await interaction.response.send_message("Clicked!", ephemeral=True)

view = (
    LayoutViewBuilder()
    .set_accent_color(discord.Color.blurple())
    .add_header("# Welcome!")
    .add_separator()
    .add_text("Thanks for checking out the server.")
    .add_separator()
    .add_button("Get Started", style=discord.ButtonStyle.primary, callback=my_callback)
    .build()
)

await interaction.response.send_message(view=view)

Features

Method Description
.set_accent_color(color) Set the container accent color
.set_spoiler(True) Mark the container as a spoiler
.add_header(text) Add a heading (use # markdown)
.add_text(text) Add a text block
.add_separator() Add a visual divider
.add_section(text, ...) Add a section with optional thumbnail or button accessory
.add_button(label, ...) Add a button (auto-grouped into ActionRows, max 5 per row)
.add_select(placeholder, options, ...) Add a dropdown select menu
.add_media_gallery(*urls) Add an image gallery (up to 10)
.add_file(url, ...) Add a file display
.add_raw_item(item) Escape hatch - add any discord.ui component
.build(timeout=180) Build the final LayoutView

Examples

Section with Thumbnail

view = (
    LayoutViewBuilder()
    .set_accent_color(discord.Color.green())
    .add_header("# User Profile")
    .add_separator()
    .add_section(
        "**Username:** Strasse\n**Level:** 42\n**Joined:** 2024",
        thumbnail_url="https://example.com/avatar.png",
    )
    .build()
)

Section with Button Accessory

from dpy_layout_builder import LayoutViewBuilder, ButtonConfig

view = (
    LayoutViewBuilder()
    .add_section(
        "Click the button to claim your reward!",
        button=ButtonConfig(
            label="Claim",
            style=discord.ButtonStyle.success,
            callback=claim_callback,
        ),
    )
    .build()
)

Multiple Buttons

view = (
    LayoutViewBuilder()
    .set_accent_color(discord.Color.red())
    .add_text("Choose an action:")
    .add_separator()
    .add_button("Approve", style=discord.ButtonStyle.success, callback=approve)
    .add_button("Deny", style=discord.ButtonStyle.danger, callback=deny)
    .add_button("Skip", style=discord.ButtonStyle.secondary, callback=skip)
    .build()
)

Select Menu

Using SelectOptionConfig for rich options with descriptions:

from dpy_layout_builder import LayoutViewBuilder, SelectOptionConfig

async def on_role_selected(interaction: discord.Interaction):
    values = interaction.data.get("values", [])
    selected = values[0] if values else None
    await interaction.response.send_message(f"You picked: {selected}", ephemeral=True)

ROLE_OPTIONS = [
    SelectOptionConfig(label="Announcements", value="announcements", description="Get pinged for announcements"),
    SelectOptionConfig(label="Events", value="events", description="Get pinged for events"),
    SelectOptionConfig(label="Giveaways", value="giveaways", description="Get pinged for giveaways"),
]

view = (
    LayoutViewBuilder()
    .add_text("Pick a notification role:")
    .add_separator()
    .add_select(
        placeholder="Select a role...",
        options=ROLE_OPTIONS,
        callback=on_role_selected,
    )
    .build()
)

You can also pass plain strings for simple options:

view = (
    LayoutViewBuilder()
    .add_text("Pick your favorite color:")
    .add_select("Choose a color...", ["Red", "Green", "Blue"], callback=on_color)
    .build()
)

Multiple Containers

from dpy_layout_builder import LayoutViewBuilder, MultiContainerLayoutViewBuilder

view = (
    MultiContainerLayoutViewBuilder()
    .add_container(
        LayoutViewBuilder()
        .set_accent_color(discord.Color.red())
        .add_header("# Warnings")
        .add_text("You have 2 active warnings.")
    )
    .add_container(
        LayoutViewBuilder()
        .set_accent_color(discord.Color.green())
        .add_header("# Rewards")
        .add_text("You earned 500 XP today!")
    )
    .build()
)

Quick Helpers

from dpy_layout_builder import quick_info_view, quick_confirm_view

# Simple info display
info = quick_info_view(
    "# Server Rules",
    "1. Be respectful\n2. No spam\n3. Have fun!",
    color=discord.Color.gold(),
    footer="*Last updated: March 2026*",
)

# Confirmation dialog
confirm = quick_confirm_view(
    "Are you sure you want to reset your progress?",
    on_confirm=handle_confirm,
    on_cancel=handle_cancel,
)

Build Safety

The builder is safe to call .build() multiple times - it snapshots internal state without mutating, so you can reuse a configured builder to produce multiple views.

Requirements

  • Python 3.10+
  • discord.py 2.7.1+ (with LayoutView / Components V2 support)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dpy_layout_builder-1.1.1.tar.gz (8.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dpy_layout_builder-1.1.1-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

File details

Details for the file dpy_layout_builder-1.1.1.tar.gz.

File metadata

  • Download URL: dpy_layout_builder-1.1.1.tar.gz
  • Upload date:
  • Size: 8.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for dpy_layout_builder-1.1.1.tar.gz
Algorithm Hash digest
SHA256 57319804e40a60d87a8cfeef690574716fef699cb5435f11d67c8bec176f06c6
MD5 d252453713afeb19c4af70ca3c198cf1
BLAKE2b-256 f96fbde1493bdd3667355b2eef3a604dffb39a50f8e2c61eed40ef3103d08e82

See more details on using hashes here.

File details

Details for the file dpy_layout_builder-1.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for dpy_layout_builder-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f6cb1180446fcc83be44e0361c3f54cd4a73216a30bf7c09f77a96e55104b4ed
MD5 fb60f1698827f33fd95a0ee39489ae9b
BLAKE2b-256 29eb0bd97244436901409a5c8460139358641252332a121c459b67cb9ab30963

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page