API Reference
Protocols
Section titled “Protocols”RenderableProtocol
Section titled “RenderableProtocol”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.
Classes
Section titled “Classes”Alert component for notifications and messages.
Badge component for status indicators.
Breadcrumbs
Section titled “Breadcrumbs”Breadcrumb navigation component with home icon.
| Parameter | Type | Description |
|---|---|---|
| `items` | List of dicts with 'label' and 'url' |
Component
Section titled “Component”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.
Lifecycle hook called when component is instantiated.
Lifecycle hook called when component is being destroyed.
def add(*children: Any) -> Component
Fluent API to add children to this component.
Element
Section titled “Element”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.
ErrorCategory
Section titled “ErrorCategory”Categories of errors with different handling strategies.
ErrorResponse
Section titled “ErrorResponse”Standardized error response for HTMX.
Render as a toast notification.
Render as an OOB flash message targeting the flash container.
Render field errors for form validation.
Render as a full error state component.
FieldError
Section titled “FieldError”Error for a specific form field.
Icon atom that wraps `get_icon` for consistent usage in templates.
| Parameter | Type | Description |
|---|---|---|
| `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). |
A FAANG-level modal dialog powered by Alpine.js.
Pagination
Section titled “Pagination”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.
| Parameter | Type | Description |
|---|---|---|
| `page` | int | Current page number (1-based). |
| `total` | int | Total number of items. |
| `per_page` | int | Number of items per page. |
| `base_url` | str | Base URL for page links (page/per_page appended as query params). |
| `show_summary` | bool | Whether to show the "Showing X to Y of Z" summary. |
Total number of pages.
RawHTML
Section titled “RawHTML”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.
Spinner
Section titled “Spinner”Circular loading spinner with size variants.
| Parameter | Type | Description |
|---|---|---|
| `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...") |
SwapMode
Section titled “SwapMode”Valid HTMX swap modes.
A responsive tabbed interface component with smooth animations and client-side switching.
| Parameter | Type | Description |
|---|---|---|
| `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 |
Toast notification component with auto-dismiss and optional action button.
| Parameter | Type | Description |
|---|---|---|
| `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. |
UIComponentRenderedHook
Section titled “UIComponentRenderedHook”Payload fired after a UI component completes rendering.
Attributes: component_name: Qualified name of the component class that rendered.
UIContext
Section titled “UIContext”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.
UIModule
Section titled “UIModule”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): passdef configure( cls, config: Any | None = None, **kwargs: Any ) -> DynamicModule
Create a UIModule with explicit configuration.
| Parameter | Type | Description |
|---|---|---|
| `config` | Any | None | UIConfig or ``None`` to use defaults. **kwargs: Additional keyword arguments forwarded to UIProvider. |
| Type | Description |
|---|---|
| DynamicModule | A 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.
| Type | Description |
|---|---|
| DynamicModule | A DynamicModule with default UI configuration. |
UIProvider
Section titled “UIProvider”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: trueRegistered services:
UIConfig(singleton) — resolved UI configuration.
async def register(container: ContainerRegistrarProtocol) -> None
Register UI services in the DI container.
| Parameter | Type | Description |
|---|---|---|
| `container` | ContainerRegistrarProtocol | The DI container registrar. |
async def boot(container: ContainerResolverProtocol) -> None
No boot-time initialisation required for the UI module.
No shutdown work required for the UI module.
Check provider health.
| Parameter | Type | Description |
|---|---|---|
| `timeout` | float | Maximum seconds to wait for health check response. |
| Type | Description |
|---|---|
| HealthCheckResult | HealthCheckResult with status and component details. |
UITemplateRenderedHook
Section titled “UITemplateRenderedHook”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
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.
Functions
Section titled “Functions”
Create a simple Tailwind-styled button while keeping btn class for compatibility.
Usage: Button(“Save”, color=“indigo”, size=“sm”) ->
component
Section titled “component”
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.
| Parameter | Type | Description |
|---|---|---|
| `name` | str | None | Logical component name used for registration and cache keys. Defaults to the decorated function's ``__name__``. |
| `cacheable` | bool | When ``True``, signals that the component's rendered output may be cached by the render pipeline. Defaults to ``False``. |
| Type | Description |
|---|---|
| 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}))
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.
get_icon
Section titled “get_icon”
Render a Lucide icon by name.
get_ui_context
Section titled “get_ui_context”
def get_ui_context() -> UIContext | None
Return the current request-scoped UIContext, or None outside a request.
| Type | Description |
|---|---|
| UIContext | None | The active UIContext set by set_ui_context, or ``None`` if called outside of a request (e.g. during startup). |
htmx_error_response
Section titled “htmx_error_response”
def htmx_error_response( error: ErrorResponse, include_flash: bool = True ) -> tuple[str, int, dict]
Build an HTMX-compatible error response.
not_found_error
Section titled “not_found_error”
def not_found_error(message: str = 'The requested resource was not found.') -> ErrorResponse
Create a not found error response (404).
permission_error
Section titled “permission_error”
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
render_to_string
Section titled “render_to_string”
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.
render_validation_errors
Section titled “render_validation_errors”
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.
reset_ui_context
Section titled “reset_ui_context”
def reset_ui_context(token: contextvars.Token[UIContext | None]) -> None
Restore the previous UI context using the token returned by set_ui_context.
| Parameter | Type | Description |
|---|---|---|
| `token` | contextvars.Token[UIContext | None] | The token returned by set_ui_context. |
server_error
Section titled “server_error”
def server_error( message: str = 'An unexpected error occurred. Please try again.', retry_url: str | None = None ) -> ErrorResponse
Create a server error response (500).
set_ui_context
Section titled “set_ui_context”
Bind ctx as the active UI context for the current async task.
| Type | Description |
|---|---|
| contextvars.Token[UIContext | None] | A Token that can be passed to reset_ui_context to restore the previous value. |
timeout_error
Section titled “timeout_error”
def timeout_error( message: str = 'The request timed out. Please try again.', retry_url: str | None = None ) -> ErrorResponse
Create a timeout error response (504).
validation_error
Section titled “validation_error”
def validation_error( message: str = 'Please correct the errors below.', field_errors: list[FieldError] | None = None ) -> ErrorResponse
Create a validation error response (422).
Exceptions
Section titled “Exceptions”UIError
Section titled “UIError”Base exception for all UI-domain errors.