Skip to content
GitHubDiscord

API Reference

Any object that can render to an HTML string.

Implemented by Component, Element, and any custom renderable in lexigram-ui. Export this protocol from the UIModule so that other packages can accept UI objects without importing from lexigram-ui implementation modules.


Alert component for notifications and messages.
def __init__(
    message: str,
    variant: AlertVariant = 'info',
    dismissible: bool = False,
    **props
) -> None
def render() -> Any

Badge component for status indicators.
def __init__(
    text: str,
    variant: BadgeVariant = 'default',
    **props
) -> None
def render() -> Any

Breadcrumb navigation component with home icon.
Parameters
ParameterTypeDescription
`items`List of dicts with 'label' and 'url'
def __init__(
    items: list[dict[str, str]],
    **props
) -> Any
def render() -> Any

Base UI Component for lexigram-admin (HTPy-backed).

Subclasses implement render() which returns either a string or an htpy element. render_to_string converts to HTML.

Components support Streamlit-style with usage via context manager methods: entering the context makes the component the current parent for subsequent calls to add_child_to_current or manual appends.

def __init__(
    *children: Any,
    **props: Any
) -> None
def on_mount() -> None

Lifecycle hook called when component is instantiated.

def on_unmount() -> None

Lifecycle hook called when component is being destroyed.

def add(*children: Any) -> Component

Fluent API to add children to this component.

def render() -> str | Any

A lightweight, structured HTML element compatible with htpy.

This provides a small subset of behaviour we need: HTML attribute escaping, boolean attributes, self-closing tag handling and a stable __html__/__str__ API so our render_to_string function can consistently produce HTML regardless of whether htpy is present.

def __init__(
    tag: str,
    *children: Any,
    **attrs: Any
) -> None

Categories of errors with different handling strategies.

Standardized error response for HTMX.
def to_toast_html() -> str

Render as a toast notification.

def to_flash_html() -> str

Render as an OOB flash message targeting the flash container.

def to_inline_errors_html() -> str

Render field errors for form validation.

def to_error_state_html() -> str

Render as a full error state component.


Error for a specific form field.

Icon atom that wraps `get_icon` for consistent usage in templates.
Parameters
ParameterTypeDescription
`name`icon name (string or raw node)
`size`Tailwind size classes for icon (default: 'w-5 h-5')
`class_name`extra classes to apply to the icon
`aria_hidden`When True (default), marks icon as decorative with aria-hidden="true". Set to False for meaningful icons and supply an aria_label.
`aria_label`Accessible label for meaningful icons (used when aria_hidden=False).
def __init__(
    name: str | Any,
    size: str = 'w-5 h-5',
    class_name: str = '',
    aria_hidden: bool = True,
    aria_label: str | None = None,
    **props
) -> None
def render() -> Any

A FAANG-level modal dialog powered by Alpine.js.
def __init__(
    title: str,
    trigger: str | Any = None,
    footer: list[Any] | None = None,
    is_open: bool = False,
    render_trigger: bool = True,
    max_width: str | None = None,
    max_height: str | None = None,
    **props
) -> None
def render() -> Any

Simple prev/next pagination for any URL-based page navigation.

Renders summary text and previous/next page links using plain anchor tags. For HTMX-enhanced pagination with zone targeting, use the admin-specific Pagination in lexigram.admin.ui.

def __init__(
    page: int = 1,
    total: int = 0,
    per_page: int = 20,
    base_url: str = '',
    show_summary: bool = True,
    **props: Any
) -> None

Initialize the pagination component.

Parameters
ParameterTypeDescription
`page`intCurrent page number (1-based).
`total`intTotal number of items.
`per_page`intNumber of items per page.
`base_url`strBase URL for page links (page/per_page appended as query params).
`show_summary`boolWhether to show the "Showing X to Y of Z" summary.
property total_pages() -> int

Total number of pages.

def render() -> Any

Wrapper for raw HTML strings that should be included verbatim.

Instances implement __html__ so they are detected as htpy-like elements and their contents are not escaped when inserted as children.

def __init__(value: str) -> None

Circular loading spinner with size variants.
Parameters
ParameterTypeDescription
`size`Size variant (sm=16px, md=24px, lg=32px, xl=48px)
`color`Tailwind color class (e.g., 'indigo', 'blue', 'gray')
`aria_label`Accessible label announced to screen readers (default: "Loading...")
def __init__(
    size: Literal['sm', 'md', 'lg', 'xl'] = 'md',
    color: str = 'indigo',
    aria_label: str = 'Loading...',
    **props
) -> None
def render() -> Any

Valid HTMX swap modes.

A responsive tabbed interface component with smooth animations and client-side switching.
Parameters
ParameterTypeDescription
`tabs`List of (label, id) or (label, url) tuples
`active_tab`Initially active tab ID or label
`client_side`If True, uses Alpine.js for content switching without page load
def __init__(
    tabs: list[tuple[str, str]],
    active_tab: str | None = None,
    client_side: bool = True,
    **props
)
def render() -> Any

Toast notification component with auto-dismiss and optional action button.
Parameters
ParameterTypeDescription
`message`Notification message.
`toast_type`Notification severity — ``info``, ``success``, ``warning``, ``error``.
`duration`Auto-dismiss delay in milliseconds (default 3000).
`action_label`Optional label for an inline action button.
`action_url`URL the action button links to (used as ``href`` when set). When empty the button triggers an HTMX request if ``hx_*`` attributes are passed, otherwise it is a plain button for the caller to handle.
def __init__(
    message: str,
    toast_type: str = 'info',
    duration: int = 3000,
    action_label: str = '',
    action_url: str = '',
    **props: Any
) -> None
def render() -> Any

Payload fired after a UI component completes rendering.

Attributes: component_name: Qualified name of the component class that rendered.


Immutable per-request UI rendering context.

Attributes: theme: Active theme name (e.g. "default", "dark"). locale: BCP-47 locale string (e.g. "en", "fr-FR"). user: Optional current user object; application-defined type. extra: Arbitrary extra key-value pairs for application-specific state.


HTMX/htpy component library module.

Call configure to configure and register the UI component system for injection.

Usage

from lexigram.ui.config import UIConfig
@module(
imports=[UIModule.configure(UIConfig(default_theme="default"))]
)
class AppModule(Module):
pass
def configure(
    cls,
    config: Any | None = None,
    **kwargs: Any
) -> DynamicModule

Create a UIModule with explicit configuration.

Parameters
ParameterTypeDescription
`config`Any | NoneUIConfig or ``None`` to use defaults. **kwargs: Additional keyword arguments forwarded to UIProvider.
Returns
TypeDescription
DynamicModuleA DynamicModule descriptor.
def stub(cls) -> DynamicModule

Return a no-op UIModule for testing.

Registers the UI provider with default configuration. No real rendering backends are configured.

Returns
TypeDescription
DynamicModuleA DynamicModule with default UI configuration.

Registers the lexigram-ui component system.

Bind into your application bootstrap

from lexigram.ui.di import UIProvider
app.add_provider(UIProvider())

Configuration (application.yaml)

ui:
default_theme: my-theme
debug_components: true

Registered services:

  • UIConfig (singleton) — resolved UI configuration.
def __init__(
    config: UIConfig | None = None,
    **kwargs: Any
) -> None
async def register(container: ContainerRegistrarProtocol) -> None

Register UI services in the DI container.

Parameters
ParameterTypeDescription
`container`ContainerRegistrarProtocolThe DI container registrar.
async def boot(container: ContainerResolverProtocol) -> None

No boot-time initialisation required for the UI module.

async def shutdown() -> None

No shutdown work required for the UI module.

async def health_check(timeout: float = 5.0) -> HealthCheckResult

Check provider health.

Parameters
ParameterTypeDescription
`timeout`floatMaximum seconds to wait for health check response.
Returns
TypeDescription
HealthCheckResultHealthCheckResult with status and component details.

Payload fired after a template is rendered to its final HTML output.

Attributes: template_name: Name or path of the template that was rendered.


Definition of a UI zone.

A zone represents a targetable region of the page with specific semantics for how it can be updated via HTMX.

Attributes: id: The HTML element ID for this zone description: Human-readable description of this zone’s purpose swappable: Whether this zone can be targeted by HTMX swaps swap_mode: The default HTMX swap mode for this zone preserve_alpine: Whether Alpine.js state should be preserved on swap oob_only: If True, this zone should only be updated via OOB swaps

property selector() -> str

Return the CSS selector for this zone.


Central registry of all UI zones.

This class provides a single source of truth for all targetable regions in the admin UI. Components should reference these zones rather than hardcoding IDs.

Zone Hierarchy:

TABLE (root scope)
├── TOOLBAR (switchers, header actions) - OOB only
├── SEARCH (search input) - never swap
├── FILTERS (filter bar) - OOB only
└── DATA (rows + pagination) - most common target
MODAL (global, outside table)
SLIDE_OVER (global, outside table)
FLASH (toast notifications)

Usage

from lexigram.ui.core.zones import Zones

attrs = { “hx-target”: Zones.DATA.selector, “hx-swap”: Zones.DATA.swap_mode.value, }

def all_zones(cls) -> list[Zone]

Return all registered zones.

def swappable(cls) -> list[Zone]

Return all zones that can be targeted by HTMX swaps.

def get_by_id(
    cls,
    zone_id: str
) -> Zone | None

Look up a zone by its ID.

Returns None if no zone with that ID exists.

def get_by_selector(
    cls,
    selector: str
) -> Zone | None

Look up a zone by its CSS selector.

Handles both “#zone-id” and “zone-id” formats.


def Button(
    label: str = '',
    color: str = 'indigo',
    size: str | None = None,
    **attrs
) -> Any

Create a simple Tailwind-styled button while keeping btn class for compatibility.

Usage: Button(“Save”, color=“indigo”, size=“sm”) ->


def component(
    name: str | None = None,
    *,
    cacheable: bool = False
) -> Callable[[F], F]

Mark a callable as a named UI component and attach component metadata.

Tags the decorated function with __component_name__ and __component_cacheable__ attributes so that component registries, debug tooling, and render pipelines can discover and identify components by name without relying on __qualname__.

This decorator does not register the component in any global registry by itself — registration is handled by the DI container via the UIProvider. The decorator provides the metadata that the provider reads during component discovery.

Parameters
ParameterTypeDescription
`name`str | NoneLogical component name used for registration and cache keys. Defaults to the decorated function's ``__name__``.
`cacheable`boolWhen ``True``, signals that the component's rendered output may be cached by the render pipeline. Defaults to ``False``.
Returns
TypeDescription
Callable[[F], F]Decorator that attaches component metadata to the target callable.

Example

@component("user_card", cacheable=True)
def user_card(user: User) -> str:
return render_to_string(
el("div", {"class": "card"}, user.display_name)
)
@component()
def avatar(src: str, alt: str = "") -> str:
return render_to_string(el("img", {"src": src, "alt": alt}))

def el(
    tag: str,
    *children: Any,
    **attrs: Any
) -> Any

Construct an element using htpy when available, otherwise return an Element fallback that implements __html__.

For self-closing tags we prefer our local Element to ensure consistent output (including trailing slash), even when htpy is installed.


def get_icon(
    name: str | Any,
    class_name: str = '',
    size: str = 'w-5 h-5',
    **attrs
) -> Any

Render a Lucide icon by name.


def get_ui_context() -> UIContext | None

Return the current request-scoped UIContext, or None outside a request.

Returns
TypeDescription
UIContext | NoneThe active UIContext set by set_ui_context, or ``None`` if called outside of a request (e.g. during startup).

def htmx_error_response(
    error: ErrorResponse,
    include_flash: bool = True
) -> tuple[str, int, dict]

Build an HTMX-compatible error response.


def not_found_error(message: str = 'The requested resource was not found.') -> ErrorResponse

Create a not found error response (404).


def permission_error(message: str = "You don't have permission to perform this action.") -> ErrorResponse

Create a permission error response (403).


def raw(value: str) -> RawHTML

def render_to_string(value: str | Any) -> str

Render a component or htpy element to an HTML string.

This performs a best-effort conversion: strings are returned verbatim, htpy elements are converted if they provide a renderer, iterables are flattened by rendering each child and concatenating the results, and component instances are rendered via their render() method.


def render_validation_errors(
    errors: list[FieldError] | dict[str, str | list[str]],
    field_name: str | None = None
) -> str

Render validation errors as an HTML string.


def reset_ui_context(token: contextvars.Token[UIContext | None]) -> None

Restore the previous UI context using the token returned by set_ui_context.

Parameters
ParameterTypeDescription
`token`contextvars.Token[UIContext | None]The token returned by set_ui_context.

def server_error(
    message: str = 'An unexpected error occurred. Please try again.',
    retry_url: str | None = None
) -> ErrorResponse

Create a server error response (500).


def set_ui_context(ctx: UIContext) -> contextvars.Token[UIContext | None]

Bind ctx as the active UI context for the current async task.

Parameters
ParameterTypeDescription
`ctx`UIContextThe UIContext to set as active.
Returns
TypeDescription
contextvars.Token[UIContext | None]A Token that can be passed to reset_ui_context to restore the previous value.

def timeout_error(
    message: str = 'The request timed out. Please try again.',
    retry_url: str | None = None
) -> ErrorResponse

Create a timeout error response (504).


def validation_error(
    message: str = 'Please correct the errors below.',
    field_errors: list[FieldError] | None = None
) -> ErrorResponse

Create a validation error response (422).


Base exception for all UI-domain errors.
def __init__(
    message: str,
    *,
    code: str | None = None
) -> None