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.0.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.0-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: dpy_layout_builder-1.1.0.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.0.tar.gz
Algorithm Hash digest
SHA256 6a49a5ed3d054aff10c2cb5d57107678102ad4bb821e00e65c6077037f27069e
MD5 3748f4874c8fb98b240450cbafefa05c
BLAKE2b-256 4ddc26a017cc84764dd6c49f5770b60ebf298d76e421e9da35943e7d881b5599

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for dpy_layout_builder-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c497737afd6ff22f2ce793a5150c21d9cf1dbbc17871efb1a3528af3da8b9db5
MD5 9f351b94a21783e693104c68b1db5674
BLAKE2b-256 50cabf8f0e3497a5ceadd12134223c6bc2f4e38d8ec65a5be916351928f2b586

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