Skip to content

Composition

Shrd components compose through slots and nesting.

Wrapper + leaf pattern

{% component Card title="Tasks" %}
  {% component TodoList placeholder="Add a task" %}{% endcomponent %}
{% endcomponent %}
  • Wrapper (Card) — provides structure and scoped styles, accepts slots
  • Leaf (TodoList) — owns state and actions

Layout components

Multi-slot layouts organize page structure:

{% component Layout %}
  {% slot header %}<h1>Settings</h1>{% endslot %}
  <form>...</form>
  {% slot footer %}<button>Save</button>{% endslot %}
{% endcomponent %}

Rendering children from Python

Inside a component method or template:

# Python
html = self.render_child("Counter", props={"initial": 5})
{# Template #}
{% shard_child "Counter" initial=5 %}

When to nest where

Approach Best for
Slots in page template Page-specific composition
{% shard_child %} in component template Fixed child structure
render_child() in Python Dynamic children based on props/state
View data + ViewTreeComponent Data-driven layouts, mutable via actions

See View data for building layouts from structured descriptors.

Avoiding deep nesting

Three levels is usually enough:

Layout → Card → Counter

Deeper nesting works but makes slot content harder to reason about. Consider flattening or using page templates for complex layouts.

Shared styles

Each component scopes its own CSS. Wrappers don't style slot content unless you use deep selectors (avoid this). Let leaf components own their appearance.

Props drilling

Pass props explicitly at each level:

{% component Card title="Counter" %}
  {% component Counter initial=3 step=2 %}{% endcomponent %}
{% endcomponent %}

There's no automatic prop forwarding. This keeps data flow explicit and debuggable.