duck.html.components

This module defines HTML components that can be inserted into HTML pages or used to dynamically generate HTML.

These components can be embedded in templates or directly manipulated in Python code.


Template Usage Examples

Jinja2 Template:

{{ Button(
      id="btn",
      text="Hello world",
    )
}}

{# Alternatively: #}

{{ Button(
      inner_html="Hello world",
      props={
         "id": "btn",
      },
    )
}}

Django Template:

{% Button %}
    id="btn",
    text="Hello world",
{% endButton %}

{# Alternatively: #}

{% Button %}
    inner_html="Hello world",
    props={
        "id": "btn",
    },
{% endButton %}

To leverage these components, ensure the setting ENABLE_COMPONENT_SYSTEM is set to True.


Direct Usage Example

from duck.html.components.button import Button
from duck.html.components.page import Page
from duck.html.core.websocket import LivelyWebSocketView
from duck.html.core.exceptions import JSExecutionError, JSExecutionTimedOut


async def on_click(btn: Button, event: str, value: str, websocket: LivelyWebSocketView):
    '''
    Button onclick event.

    Args:
        btn (Button): Button component which received the event.
        event (str): The event name.
        value (str): The current button value.
        websocket (LivelyWebSocketView): The current active websocket connection.
    '''
    # This handler can also be either asynchronous or synchronous.
    if btn.bg_color != "red":
        btn.bg_color = "red"
    else:
        btn.bg_color = "green"

    # You can also execute JS on client side like so.
    # but the execution will execute first before button changes color.
    try:
        await websocket.execute_js(
            code='alert(`Javascript execution success`);',
            timeout=2,
            wait_for_result=True, # This will wait for feedback on execution.
        ) # or you can use get_js_result() for retrieving a variable result after code execution.
    except (JSExecutionTimedOut, JSExecutionError):
        # JS execution timed out or the code raised an error on client side.
        pass

def home(request):
    page = Page(request)
    btn = Button(
        id="some-id",
        text="Hello world",
        bg_color="green",
        color="white",
    )

    # Add button to body
    page.add_to_body(btn)

    # Bind an event handler to the button
    btn.bind("click", on_click)

    print(btn.render())  # Outputs the corresponding HTML

    # Return component or ComponentResponee
    return page

You can render this component in a template or use it anywhere HTML output is needed.


Defining Your Own Component

Subclassing the component class allows you to create custom components easily.

# This example uses a component that accepts an inner body.
# Use `NoInnerComponent` if you don’t need inner content.

from duck.html.components import InnerComponent
from duck.html.components.button import Button
from duck.shortcuts import to_response

class MyComponent(InnerComponent):
    def get_element(self):
        # Return the HTML tag name
        return "div"

    def on_create(self):
        # Called after initialization
        super().on_create()  # Useful for extending base behavior, don't leave this out

        # You can access provided extra keyword arguments provided to the component by
        # accessing `self.kwargs`

        # Do some operations
        self.add_child(Button(text="Hi there"))

# In views.py
def home(request):
    comp = MyComponent(request=request) # you can provide extra keyword arguments here.
    print("request" in comp.kwargs) # Outputs: True
    response = to_response(comp)  # More control than just returning comp
    return response

# Instead of using to_response, you can use duck.http.response.ComponentResponse instead.

Subpackages

Submodules

Package Contents

Classes

HtmlComponent

Base class for all HTML components.

InnerHtmlComponent

This is the HTML component with Inner Body presence.

NoInnerHtmlComponent

This is the HTML component with no Inner Body.

Theme

Default Duck theme.

Functions

quote

Returns an html component quoting the provided html as its body.

to_component

Returns an html component quoting the provided html as its body. (Same as quote function).

Data

Component

ComponentError

ELEMENT_PATTERN

InnerComponent

NoInnerComponent

API

duck.html.components.Component

None

duck.html.components.ComponentError

None

duck.html.components.ELEMENT_PATTERN

‘compile(…)’

class duck.html.components.HtmlComponent(element: Optional[str] = None, accept_inner_html: bool = False, inner_html: Optional[Union[str, int, float]] = None, properties: Optional[Dict[str, str]] = None, props: Optional[Dict[str, str]] = None, style: Optional[Dict[str, str]] = None, **kwargs)[source]

Base class for all HTML components.

This class provides the foundational structure for defining HTML-based UI components in the Lively component system.

Notes:

  • If the Lively Component System is active, each component is lazily registered. A component is only added to the component registry after render() or to_string() has been called.

  • To improve performance and reduce re-rendering overhead, heavy components can be pre-rendered. Once pre-rendered, subsequent renders are faster due to internal caching. You can do this by using method pre_render.

  • All Lively components are validated before any event is sent to the server, this is disabled by adding prop data-validate=false in props. Empty props without data-validate=false, default is validation. You can even toggle this by using method toggle_validation.

Initialization

Initialize an HTML component.

Parameters:
  • element – The HTML element tag name (e.g., textarea, input, button). Can be None, but make sure element is returned by get_element method.

  • accept_inner_html – Whether the HTML component accepts an inner body (e.g., inner-body-here).

  • inner_html – Inner html to add to the HTML component. Defaults to None.

  • properties – Dictionary for properties to initialize the component with.

  • props – Just same as properties argument (added for simplicity).

  • style – Dictionary for style to initialize the component with.

  • **kwargs – Extra keyword arguments

Raises:

HtmlComponentError – If ‘element’ is not a string or ‘inner_html’ is set but ‘accept_inner_html’ is False.

__copy__()[source]
__repr__() str[source]
__setattr__(key: str, value: Any)[source]

Custom attribute setter that protects component references from being overwritten.

Parameters:
  • key – The attribute name.

  • value – The value to set.

Raises:

ComponentAttributeProtection – If protected component attribute is being modified.

__str__

None

_copy(shallow: bool = False) duck.html.components.HtmlComponent[source]

Returns a copy of the component.

Notes:

  • Props, style, children are copied.

  • Iterative copy avoids recursion depth issues.

  • Shallow copy allowed only on frozen components.

_get_raw_props()[source]

Returns the component properties.

_on_mutation(mutation: duck.html.components.core.mutation.Mutation)[source]

Private entry method to on_mutation event.

_on_render_done()[source]

Internal callback triggered at the end of component rendering.

_on_render_start()[source]

Internal callback triggered at the beginning of component rendering.

static assign_component_uids(root_component: duck.html.components.Component, base_uid: str = '0', force: bool = False) None[source]

Assigns deterministic UIDs to the entire component tree using a non-recursive traversal.

Parameters:
  • root_component – The root component to start from.

  • base_uid – The base UID for the root (default is “0”).

  • force – Whether to force assign component uid’s. By default, if no children structure mutation has happened, no uid assignment is done. This argument overrides this behavior. Defaults to False.

async async_load()[source]

Load the component asynchronously.

async async_render() str[source]

Asynchronously render component.

async async_to_vdom() duck.html.components.core.vdom.VDomNode[source]

Asynchronously convert component to VDOMNode.

async async_wait_for_load(interval: float = 0.01)[source]

This asynchronously waits for the component to complete loading (if component is already being loaded somewhere).

bind(event: str, event_handler: Callable, force_bind: bool = False, update_targets: Optional[List[duck.html.components.HtmlComponent]] = None, update_self: bool = True) None[source]

Bind an event handler to this component for the specified event type.

Parameters:
  • event – The name of the event to bind (e.g., “click”, “input”).

  • event_handler – A callable (preferably async) that handles the event.

  • force_bind – If True, binds the event even if it’s not in the recognized set.

  • update_targets – Other components whose state may be modified when this event is triggered. Defaults to None.

  • update_self – Whether this component’s state may change as a result of the event. If False, only other components will be considered for DOM updates. Defaults to True.

Raises:
  • UnknownEventError – If the event is not recognized and force_bind is False.

  • AssertionError – If the event handler is not a callable.

  • RedundantUpdate – If any component pair in update_targets share the same root/parent.

  • EventAlreadyBound – If event is already bound before.

… admonition:: Notes

  • If update_self is False and no update_targets are provided, no DOM patch will be sent to the client.

  • This method requires the Lively Component System to be active (i.e., running within a WebSocket context).

check_component_system_active(inactive_msg: str = None)[source]

Checks if the component system responsible for WebSocket communication with the client is active.

… admonition:: Notes

The component system sends DOM patches to client using WebSocket protocol. It also receives component events so that they can be executed on the server. Sends signals to perform an action to the JS client WebSocket.

copied_from() Optional[duck.html.components.HtmlComponent][source]

Returns the original component that this component was copied from (if applicable else None).

copy(shallow: bool = False) duck.html.components.HtmlComponent[source]

Returns a copy of the component.

Notes:

  • Props, style, children are copied.

  • Iterative copy avoids recursion depth issues.

  • Shallow copy allowed only on frozen components.

ensure_freeze(*args, **kwargs)[source]

This works just like freeze() but does not raise an exception if component is not yet loaded.

It ensures that freeze is called whenever the component is loaded (if not already loaded) or just freeze the component right away if component is already loaded.

force_set_component_attr(key: str, value: Any)[source]

Forcefully sets an attribute on the component, bypassing attribute protection.

Parameters:
  • key – The attribute name to set.

  • value – The value to assign to the attribute.

This method temporarily disables component attribute protection, allowing internal code to set or overwrite protected attributes.

freeze()[source]

Freeze the component.

get_children_string(childs: duck.html.components.core.children.ChildrenList) str[source]

Renders and joins the HTML strings of child components.

Parameters:

childs – The child components to render.

Returns:

The rendered HTML string of all children.

Return type:

str

get_component_system_data_props() Dict[str, str][source]

Returns the data-* properties for events, actions, and other attributes used internally by the Lively component system (e.g., for client-server sync via WebSocket).

This typically includes:

  • data-uid: The stable component ID or unique ID if a component is a root component.

  • data-events: A comma-separated list of bound event names. (if available)

  • data-validate: Boolean on whether validation must be applied.

Returns:

A dictionary of data-* attributes and their corresponding values.

Return type:

Dict[str, str]

get_css_string(style: duck.html.components.core.props.StyleStore[str, str], add_to_prev_states: bool = True) str[source]

Returns a CSS style string from a dictionary of style attributes.

Parameters:
  • style – The style attributes (e.g., StyleStore({“color”: “red”, “font-size”: “12px”}) ).

  • add_to_prev_states – If True, the resulting style string is cached in the component’s previous state.

Returns:

The computed CSS string.

Return type:

str

abstractmethod get_element()[source]

Fallback method to retrieve the html element tag.

get_event_info(event: str) Tuple[Callable, Set[duck.html.components.HtmlComponent]][source]

Returns the event info in form: (event_handler, update_targets).

get_partial_string()[source]

Returns the partial string containing the style, props & inner body (if applicable).

get_props_string(props: duck.html.components.core.props.PropertyStore[str, str], add_to_prev_states: bool = True) str[source]

Returns an HTML property string from a dictionary of attributes.

Parameters:
  • props – HTML attributes (e.g., PropertyStore({“id”: “main”, “class”: “container”}) ).

  • add_to_prev_states – If True, the resulting style string is cached in the component’s previous state.

Returns:

A string of HTML element properties.

Return type:

str

get_raw_root() duck.html.components.Component[source]

Returns the raw root reference without evaluation, even if the root is self (unlike the root property).

has_local_updates()[source]

Checks if the component itself has local updates excluding those of the children.

… admonition:: Notes

This doesn’t look for any changes to the children but only itself.

property inner_html: str

Returns the inner body (innerHTML) for the component.

is_a_copy() bool[source]

Returns a boolean on whether this component is a copy from another component.

is_from_cache() bool[source]

Returns a boolean on whether this component has been retrieved from cache.

is_frozen() bool[source]

Returns boolean on whether if the component is frozen or not.

is_loaded() bool[source]

Returns a boolean on whether if the component is loaded.

is_loading() bool[source]

Returns a boolean on whether if the component is loading or not.

isroot() bool[source]

Returns a boolean on whether if the component is a root component.

load()[source]

Load the component, pack all descendants (if available).

Raises:

ComponentError – If this method is used on non-root component or if component is_loading() is True.

on_create()[source]

Called on component creation or initialization

on_mutation(mutation: duck.html.components.core.mutation.Mutation)[source]

This is called on component mutation. Either from props, style or children.

Notes:

  • This is only called if the component itself is a root component

on_parent(parent: duck.html.components.Component)[source]

Called when the component has got a parent attached.

on_root_finalized(root: duck.html.components.Component)[source]

Called when the component’s root element is permanently assigned.

This method is invoked once the component is fully integrated into its final root within the application’s structure, and this root will not change for the lifetime of the component. Use this hook to perform any final setup or initialization that requires access to the fully realized root element, such as registering with the root’s event system, performing final layout adjustments, or establishing contextual relationships within the application.

Parameters:

root – The root element to which this component is now permanently attached. This is the final root and will not be reassigned.

property parent: Optional[duck.html.components.Component]

Returns the parent for the html component. This is only resolved if this html component has been added to some html component children.

pre_render() None[source]

Pre-renders this component and optionally its children to optimize future rendering.

property properties

Returns the properties store for the HTML component.

Returns:

The properties store for the HTML component.

Return type:

PropertyStore

property props

Returns the properties store for the HTML component. (same as properties property)

Returns:

The properties store for the HTML component.

Return type:

PropertyStore

raise_if_not_loaded(message: str)[source]

Decorator which raises an exception if component is not loaded.

Parameters:

message – A custom error message for the exception.

Raises:

ComponentNotLoadedError – Raised if component is not loaded.

render() str[source]

Render the component to produce html.

property root: Optional[duck.html.components.Component]

Returns the root html component.

set_mutation_callbacks()[source]

This sets the callbacks that will be executed on prop/style mutation.

property style

Returns the style store for the HTML component.

Returns:

The style store for the HTML component.

Return type:

PropertyStore

to_string()[source]

Returns the string representation of the HTML component.

Returns:

The string representation of the HTML component.

Return type:

str

to_vdom() duck.html.components.core.vdom.VDomNode[source]

Converts the HtmlComponent into a virtual DOM node.

Returns:

A virtual DOM representation of the HTML component.

Return type:

VDomNode

toggle_validation(must_validate: bool)[source]

Whether to enable/disable validation on component before server receives an event.

Notes:

  • Validation is only applied if the JS element has both checkValidity and reportValidity.

traverse(func: callable, algorithm: str = 'depth_first_search', reverse: bool = False, include_self: bool = True) None[source]

Traverses the component tree and executes a callable on each node.

Parameters:
  • func – Function to execute on each component (takes the component as argument).

  • algorithm – ‘depth_first_search’ or ‘breadth_first_search’.

  • reverse – If True, DFS visits children from last to first.

  • include_self – If True, traversal starts at self; otherwise, starts at children.

… admonition:: Notes

  • Iterative traversal is used to avoid recursion limits.

  • BFS ignores reverse.

  • func can read or modify nodes.

traverse_ancestors(func: callable, include_self: bool = True) None[source]

Traverses upward from this component to the root, executing a callable on each ancestor.

Parameters:
  • func – A function that takes a single argument (the component) and executes logic.

  • include_self – If True, starts at the current component; if False, starts at the parent.

Notes:

  • Stops when the root component (no parent) is reached.

  • Useful for propagating mutations, marking caches dirty, or other upward operations.

property uid: str

Returns the UID for the component based on the component position.

Returns:

An assigned component UID based on component position in component tree or a random string.

Return type:

str

Notes:

  • This will be auto-assigned on render or when to_vdom is called. These methods call assign_component_uids for assigning determinable UID’s.

  • If a component is a root component, a unique ID will be generated whenever the uid property is accessed.

unbind(event: str, failsafe: bool = True)[source]

Remove/unbind an event from this component.

Parameters:
  • event – The event name to unbind.

  • failsafe – If True (default), silently ignore if the event was never bound. If False, raise UnknownEventError if the event does not exist.

Raises UnknownEventError: If failsafe is False and the event is not bound.

static vdom_diff(old: duck.html.components.core.vdom.VDomNode, new: duck.html.components.core.vdom.VDomNode) List[list][source]

Compute a minimal set of patches to transform one virtual DOM tree into another.

This method performs key-based diffing on children and emits compact patch lists using vdom.PatchCodes. Each patch is a list optimized for fast encoding with MessagePack.

Parameters:
  • old – The previous virtual DOM node.

  • new – The updated virtual DOM node.

Returns:

A list of compact patch operations (lists) in the format: [opcode, key, …data]

Return type:

List[list]

async static vdom_diff_and_act(action: Callable, old: duck.html.components.core.vdom.VDomNode, new: duck.html.components.core.vdom.VDomNode) None[source]

Compute a minimal set of patches to transform one virtual DOM tree into another.

This method performs key-based diffing on children and emits compact patch lists using PatchCode. Each patch is a list optimized for fast encoding with MessagePack.

This method diffs and perform an action on every patch rather than returning a list of all computed patches.

Parameters:
  • action – A synchronous/asynchronous callable to perform on every patch. The first argument to this must be the patch.

  • old – The previous virtual DOM node.

  • new – The updated virtual DOM node.

Returns:

Nothing to return.

Return type:

None

wait_for_load(interval: float = 0.01)[source]

This waits for the component to complete loading (if component is already being loaded somewhere).

duck.html.components.InnerComponent

None

class duck.html.components.InnerHtmlComponent(element: Optional[str] = None, properties: Optional[Dict[str, str]] = None, props: Optional[Dict[str, str]] = None, style: Optional[Dict[str, str]] = None, inner_html: Optional[Union[str, str, float]] = None, children: Optional[List[duck.html.components.HtmlComponent]] = None, **kwargs)[source]

Bases: duck.html.components.extensions.BasicExtension, duck.html.components.extensions.StyleCompatibilityExtension, duck.html.components.HtmlComponent

This is the HTML component with Inner Body presence.

Form:

<mytag>Text here</mytag>

Example:

<p>Text here</p>
<h2>Text here</h2>
<ol>List elements here</ol>

Notes:

  • The html components that fall in this category are usually basic HTML elements.

Initialization

Initialize an HTML component.

Parameters:
  • element – The HTML element tag name (e.g., textarea, input, button). Can be None, but make sure element is returned by get_element method.

  • accept_inner_html – Whether the HTML component accepts an inner body (e.g., inner-body-here).

  • inner_html – Inner html to add to the HTML component. Defaults to None.

  • properties – Dictionary for properties to initialize the component with.

  • props – Just same as properties argument (added for simplicity).

  • style – Dictionary for style to initialize the component with.

  • **kwargs – Extra keyword arguments

Raises:

HtmlComponentError – If ‘element’ is not a string or ‘inner_html’ is set but ‘accept_inner_html’ is False.

add_child(child: duck.html.components.HtmlComponent)[source]

Adds a child component to this HTML component.

Parameters:

child – The child component to add.

add_children(children: List[duck.html.components.HtmlComponent])[source]

Adds multiple child components to this HTML component.

Parameters:

children – The list of child components to add.

property children: duck.html.components.core.children.ChildrenList[duck.html.components.HtmlComponent]

Returns the component children.

clear_children()[source]

Clears all component’s children.

remove_child(child: duck.html.components.HtmlComponent)[source]

Removes a child component from this HTML component.

Parameters:

child – The child component to remove.

remove_children(children: List[duck.html.components.HtmlComponent])[source]

Removes multiple child components to this HTML component.

Parameters:

children – The list of child components to remove.

duck.html.components.NoInnerComponent

None

class duck.html.components.NoInnerHtmlComponent(element: Optional[str] = None, properties: Dict[str, str] = None, props: Dict[str, str] = None, style: Dict[str, str] = None, **kwargs)[source]

Bases: duck.html.components.extensions.BasicExtension, duck.html.components.extensions.StyleCompatibilityExtension, duck.html.components.HtmlComponent

This is the HTML component with no Inner Body.

Example:

<input> <!--Input element does not accept inner html (inner body)-->
<b/> <!--Same applies with the bold tag-->

Notes:

  • The html components that fall in this category are usually HTML Input elements.

Initialization

Initialize an HTML component.

Parameters:
  • element – The HTML element tag name (e.g., textarea, input, button). Can be None, but make sure element is returned by get_element method.

  • accept_inner_html – Whether the HTML component accepts an inner body (e.g., inner-body-here).

  • inner_html – Inner html to add to the HTML component. Defaults to None.

  • properties – Dictionary for properties to initialize the component with.

  • props – Just same as properties argument (added for simplicity).

  • style – Dictionary for style to initialize the component with.

  • **kwargs – Extra keyword arguments

Raises:

HtmlComponentError – If ‘element’ is not a string or ‘inner_html’ is set but ‘accept_inner_html’ is False.

class duck.html.components.Theme[source]

Default Duck theme.

background_color

‘#FFFFFF’

border_radius

‘15px’

button_style

None

font_family

‘Arial, sans-serif’

normal_font_size

‘16px’

padding

‘10px’

primary_color

‘#4B4E75’

secondary_color

‘#A6B48B’

text_color

‘#333333’

duck.html.components.quote(html: Optional[str] = None, element: str = 'span', no_closing_tag: bool = False, **kwargs) Union[InnerComponent, NoInnerComponent][source]

Returns an html component quoting the provided html as its body.

Parameters:
  • html – The html to quote, to set as the new html component body.

  • element – Element to quote with, Defaults to span.

  • no_closing_tag – Whether the returned html component does not need a closing tag.

  • **kwargs – Keyword arguments to parse to component

Returns:

The html component with closing tags. NoInnerComponent: The html component with no closing tags.

Return type:

InnerComponent

duck.html.components.to_component(html: Optional[str] = None, tag: str = 'span', no_closing_tag: bool = False, **kwargs)[source]

Returns an html component quoting the provided html as its body. (Same as quote function).

Parameters:
  • html – The html to quote, to set as the new html component body.

  • tag – HTML tag to quote with, Defaults to span.

  • no_closing_tag – Whether the returned html component does not need a closing tag.

  • **kwargs – Keyword arguments to parse to the component.

Returns:

The html component with closing tags. NoInnerComponent: The html component with no closing tags.

Return type:

InnerComponent