UNPKG

@zeix/ui-element

Version:

UIElement - a HTML-first library for reactive Web Components

712 lines 51.1 kB
<!doctype html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Data Flow – UIElement Docs</title>
		<meta name="description" content="Passing state, events, context" />
		<link rel="stylesheet" href="./assets/main.css" />
		<script type="module" src="./assets/main.js"></script>
	</head>
	<body class="">
		<context-router>
			<header class="content-grid">
				<h1 class="content">
					UIElement Docs <small>Version 0.13.3</small>
				</h1>
				
<section-menu>
	<nav>
		<h2 class="visually-hidden">Main Menu</h2>
		<ol>
			
				<li>
					<a href="index.html">
						<span class="icon">📖</span>
						<strong>Introduction</strong>
						<small>Overview and key benefits of UIElement</small>
					</a>
				</li>

				<li>
					<a href="getting-started.html">
						<span class="icon">🚀</span>
						<strong>Getting Started</strong>
						<small>Installation, setup, and first steps</small>
					</a>
				</li>

				<li>
					<a href="components.html">
						<span class="icon">🏗️</span>
						<strong>Components</strong>
						<small>Anatomy, lifecycle, signals, effects</small>
					</a>
				</li>

				<li>
					<a href="styling.html">
						<span class="icon">🎨</span>
						<strong>Styling</strong>
						<small>Scoped styles, CSS custom properties</small>
					</a>
				</li>

				<li>
					<a href="data-flow.html">
						<span class="icon">🔄</span>
						<strong>Data Flow</strong>
						<small>Passing state, events, context</small>
					</a>
				</li>

				<li>
					<a href="examples.html">
						<span class="icon">🍽️</span>
						<strong>Examples</strong>
						<small>Common use cases and demos</small>
					</a>
				</li>

				<li>
					<a href="blog.html">
						<span class="icon">📜</span>
						<strong>Blog</strong>
						<small>Latest articles and updates</small>
					</a>
				</li>

				<li>
					<a href="api.html">
						<span class="icon">📚</span>
						<strong>API Reference</strong>
						<small>Functions, types, and constants</small>
					</a>
				</li>

				<li>
					<a href="about.html">
						<span class="icon">🤝</span>
						<strong>About</strong>
						<small>License, versioning, getting involved</small>
					</a>
				</li>
		</ol>
	</nav>
</section-menu>
				<card-callout class="content danger" hidden>
					<p class="error" role="alert" aria-live="polite"></p>
				</card-callout>
			</header>
			<main class="content-grid"><section-hero>

<h1 id="data-flow">
                <a name="data-flow" class="anchor" href="#data-flow">
	                <span class="permalink">🔗</span>
                </a>
                🔄 Data Flow
            </h1>
<div>
  <p class="lead"><strong>Learn how UIElement components can work together seamlessly.</strong> Start with simple parent-child relationships, then explore advanced patterns like custom events and shared state. Build modular, loosely coupled components that communicate efficiently.</p>
  
<module-toc>
	<nav>
		<h2>In this Page</h2>
		<ol>
			<li><a href="#component-coordination">Component Coordination</a></li>
			<li><a href="#custom-events">Custom Events</a></li>
			<li><a href="#providing-context">Providing Context</a></li>
			<li><a href="#consuming-context">Consuming Context</a></li>
			<li><a href="#next-steps">Next Steps</a></li>
		</ol>
	</nav>
</module-toc>
</div>
</section-hero>

<section>

<h2 id="component-coordination">
                <a name="component-coordination" class="anchor" href="#component-coordination">
	                <span class="permalink">🔗</span>
                </a>
                Component Coordination
            </h2>
<p>Let&#39;s consider a <strong>product catalog</strong> where users can add items to a shopping cart. We have <strong>three independent components</strong> that work together:</p>
<ul>
<li><code>ModuleCatalog</code> <strong>(Parent)</strong>:<ul>
<li><strong>Tracks all <code>SpinButton</code> components</strong> in its subtree and calculates the total count of items in the shopping cart.</li>
<li><strong>Passes that total</strong> to a <code>BasicButton</code>.</li>
</ul>
</li>
<li><code>BasicButton</code> <strong>(Child)</strong>:<ul>
<li>Displays a <strong>badge</strong> in the top-right corner when the <code>badge</code> property is set.</li>
<li><strong>Does not track any state</strong> – it simply renders whatever value is passed to it.</li>
</ul>
</li>
<li><code>FormSpinbutton</code> <strong>(Child)</strong>:<ul>
<li>Displays an <strong>Add to Cart</strong> button initially.</li>
<li>When an item is added, it transforms into a <strong>stepper</strong> (increment/decrement buttons).</li>
</ul>
</li>
</ul>
<p>Although <code>BasicButton</code> and <code>FormSpinbutton</code> are completely independent, they need to work together. So <code>ModuleCatalog</code> <strong>coordinates the data flow between them</strong>.</p>
<h3 id="parent-component-modulecatalog">
                <a name="parent-component-modulecatalog" class="anchor" href="#parent-component-modulecatalog">
	                <span class="permalink">🔗</span>
                </a>
                Parent Component: ModuleCatalog
            </h3>
<p>The <strong>parent component (<code>ModuleCatalog</code>) knows about its children</strong>, meaning it can <strong>read state from and pass state to</strong> them.</p>
<p>First, we need to observe the quantities of all <code>FormSpinbutton</code> components. For this, we create a signal of all children matching the <code>form-spinbutton</code> selector:</p>
<module-codeblock collapsed language="js" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
	<p class="meta">
		
		<span class="language">js</span>
	</p>
	<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#A6E22E">component</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">  'module-catalog'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">  {</span></span>
<span class="line"><span style="color:#F8F8F2">    total: </span><span style="color:#A6E22E">fromDescendants</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">      'form-spinbutton'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">      (</span><span style="color:#FD971F;font-style:italic">sum</span><span style="color:#F8F8F2">, </span><span style="color:#FD971F;font-style:italic">item</span><span style="color:#F8F8F2">) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> sum </span><span style="color:#F92672">+</span><span style="color:#F8F8F2"> item.value,</span></span>
<span class="line"><span style="color:#AE81FF">      0</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">    ),</span></span>
<span class="line"><span style="color:#F8F8F2">  },</span></span>
<span class="line"><span style="color:#F8F8F2">  () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> [],</span></span>
<span class="line"><span style="color:#F8F8F2">)</span></span>
<span class="line"></span></code></pre>
	<basic-button class="copy">
		<button type="button" class="secondary small">
			<span class="label">Copy</span>
		</button>
	</basic-button>
	<button type="button" class="overlay">Expand</button>
</module-codeblock>
<p>The <code>fromDescendants()</code> function returns a signal of the reduced array of all matching elements. In contrast to a static <code>querySelectorAll()</code> call, the <code>fromDescendants()</code> function is reactive and updates whenever new elements are added or removed from the DOM.</p>
<p>Then, we need to convert the total of all product quantities to a string and pass it on to the <code>BasicButton</code> component. In UIElement we use the <code>pass()</code> function to share state across components:</p>
<module-codeblock collapsed language="js" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
	<p class="meta">
		
		<span class="language">js</span>
	</p>
	<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#A6E22E">component</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">  'module-catalog'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">  {</span></span>
<span class="line"><span style="color:#F8F8F2">    total: </span><span style="color:#A6E22E">fromDescendants</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">      'form-spinbutton'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">      (</span><span style="color:#FD971F;font-style:italic">sum</span><span style="color:#F8F8F2">, </span><span style="color:#FD971F;font-style:italic">item</span><span style="color:#F8F8F2">) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> sum </span><span style="color:#F92672">+</span><span style="color:#F8F8F2"> item.value,</span></span>
<span class="line"><span style="color:#AE81FF">      0</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">    ),</span></span>
<span class="line"><span style="color:#F8F8F2">  },</span></span>
<span class="line"><span style="color:#F8F8F2">  (</span><span style="color:#FD971F;font-style:italic">el</span><span style="color:#F8F8F2">, { </span><span style="color:#FD971F;font-style:italic">first</span><span style="color:#F8F8F2"> }) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> [</span></span>
<span class="line"><span style="color:#A6E22E">    first</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">      'basic-button'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#A6E22E">      pass</span><span style="color:#F8F8F2">({</span></span>
<span class="line"><span style="color:#A6E22E">        badge</span><span style="color:#F8F8F2">: () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> (el.total </span><span style="color:#F92672">></span><span style="color:#AE81FF"> 0</span><span style="color:#F92672"> ?</span><span style="color:#A6E22E"> String</span><span style="color:#F8F8F2">(el.total) </span><span style="color:#F92672">:</span><span style="color:#E6DB74"> ''</span><span style="color:#F8F8F2">),</span></span>
<span class="line"><span style="color:#A6E22E">        disabled</span><span style="color:#F8F8F2">: () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F92672"> !</span><span style="color:#F8F8F2">el.total,</span></span>
<span class="line"><span style="color:#F8F8F2">      }),</span></span>
<span class="line"><span style="color:#F8F8F2">    ),</span></span>
<span class="line"><span style="color:#F8F8F2">  ],</span></span>
<span class="line"><span style="color:#F8F8F2">)</span></span>
<span class="line"></span></code></pre>
	<basic-button class="copy">
		<button type="button" class="secondary small">
			<span class="label">Copy</span>
		</button>
	</basic-button>
	<button type="button" class="overlay">Expand</button>
</module-codeblock>
<p>Allright, that&#39;s it!</p>
<ul>
<li>Whenever one of the <code>value</code> signals of a <code>&lt;form-spinbutton&gt;</code> updates, the total in the badge of <code>&lt;basic-button&gt;</code> automatically updates.</li>
<li>No need for event listeners or manual updates!</li>
</ul>
<h3 id="child-component-basicbutton">
                <a name="child-component-basicbutton" class="anchor" href="#child-component-basicbutton">
	                <span class="permalink">🔗</span>
                </a>
                Child Component: BasicButton
            </h3>
<p>The <code>BasicButton</code> component <strong>displays a badge when needed</strong> – it does not know about any other component nor track state itself. It just exposes a reactive properties <code>badge</code> of type <code>string</code> and <code>disabled</code> of type <code>boolean</code> and has effects to react to state changes that updates the DOM subtree.</p>
<module-codeblock collapsed language="js" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
	<p class="meta">
		
		<span class="language">js</span>
	</p>
	<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#A6E22E">component</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">  'basic-button'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">  {</span></span>
<span class="line"><span style="color:#F8F8F2">    disabled: </span><span style="color:#A6E22E">asBoolean</span><span style="color:#F8F8F2">(),</span></span>
<span class="line"><span style="color:#F8F8F2">    badge: </span><span style="color:#A6E22E">asString</span><span style="color:#F8F8F2">(),</span></span>
<span class="line"><span style="color:#F8F8F2">  },</span></span>
<span class="line"><span style="color:#F8F8F2">  (</span><span style="color:#FD971F;font-style:italic">_</span><span style="color:#F8F8F2">, { </span><span style="color:#FD971F;font-style:italic">first</span><span style="color:#F8F8F2"> }) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> [</span></span>
<span class="line"><span style="color:#A6E22E">    first</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'button'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">setProperty</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'disabled'</span><span style="color:#F8F8F2">)),</span></span>
<span class="line"><span style="color:#A6E22E">    first</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'.badge'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">setText</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'badge'</span><span style="color:#F8F8F2">)),</span></span>
<span class="line"><span style="color:#F8F8F2">  ],</span></span>
<span class="line"><span style="color:#F8F8F2">)</span></span>
<span class="line"></span></code></pre>
	<basic-button class="copy">
		<button type="button" class="secondary small">
			<span class="label">Copy</span>
		</button>
	</basic-button>
	<button type="button" class="overlay">Expand</button>
</module-codeblock>
<ul>
<li>Whenever the <code>disabled</code> property is updated by a parent component, the button is disabled or enabled.</li>
<li>Whenever the <code>badge</code> property is updated by a parent component, the badge text updates.</li>
<li>If <code>badge</code> is an empty string, the badge indicator is hidden (via CSS).</li>
</ul>
<h3 id="child-component-formspinbutton">
                <a name="child-component-formspinbutton" class="anchor" href="#child-component-formspinbutton">
	                <span class="permalink">🔗</span>
                </a>
                Child Component: FormSpinbutton
            </h3>
<p>The <code>FormSpinbutton</code> component reacts to user interactions and exposes a reactive property <code>value</code> of type <code>number</code>. It updates its own internal DOM subtree, but doesn&#39;t know about any other component nor where the value is used.</p>
<module-codeblock collapsed language="js" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
	<p class="meta">
		
		<span class="language">js</span>
	</p>
	<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#A6E22E">component</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">  'form-spinbutton'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">  {</span></span>
<span class="line"><span style="color:#F8F8F2">    value: </span><span style="color:#A6E22E">asInteger</span><span style="color:#F8F8F2">(),</span></span>
<span class="line"><span style="color:#F8F8F2">  },</span></span>
<span class="line"><span style="color:#F8F8F2">  (</span><span style="color:#FD971F;font-style:italic">el</span><span style="color:#F8F8F2">, { </span><span style="color:#FD971F;font-style:italic">all</span><span style="color:#F8F8F2">, </span><span style="color:#FD971F;font-style:italic">first</span><span style="color:#F8F8F2"> }) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">    const</span><span style="color:#F8F8F2"> zeroLabel </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> el.</span><span style="color:#A6E22E">getAttribute</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'zero-label'</span><span style="color:#F8F8F2">) </span><span style="color:#F92672">||</span><span style="color:#E6DB74"> 'Add to Cart'</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">    const</span><span style="color:#F8F8F2"> incrementLabel </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> el.</span><span style="color:#A6E22E">getAttribute</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'increment-label'</span><span style="color:#F8F8F2">) </span><span style="color:#F92672">||</span><span style="color:#E6DB74"> 'Increment'</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">    const</span><span style="color:#F8F8F2"> max </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> asInteger</span><span style="color:#F8F8F2">(</span><span style="color:#AE81FF">9</span><span style="color:#F8F8F2">)(el, el.</span><span style="color:#A6E22E">getAttribute</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'max'</span><span style="color:#F8F8F2">))</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">    const</span><span style="color:#A6E22E"> nonZero</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> el.value </span><span style="color:#F92672">!==</span><span style="color:#AE81FF"> 0</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F92672">    return</span><span style="color:#F8F8F2"> [</span></span>
<span class="line"><span style="color:#A6E22E">      first</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'.value'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">setText</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'value'</span><span style="color:#F8F8F2">), </span><span style="color:#A6E22E">show</span><span style="color:#F8F8F2">(nonZero)),</span></span>
<span class="line"><span style="color:#A6E22E">      first</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">        '.decrement'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#A6E22E">        show</span><span style="color:#F8F8F2">(nonZero),</span></span>
<span class="line"><span style="color:#A6E22E">        on</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'click'</span><span style="color:#F8F8F2">, () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F8F8F2">          el.value</span><span style="color:#F92672">--</span></span>
<span class="line"><span style="color:#F8F8F2">        }),</span></span>
<span class="line"><span style="color:#F8F8F2">      ),</span></span>
<span class="line"><span style="color:#A6E22E">      first</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">        '.increment'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#A6E22E">        setText</span><span style="color:#F8F8F2">(() </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> (</span><span style="color:#A6E22E">nonZero</span><span style="color:#F8F8F2">() </span><span style="color:#F92672">?</span><span style="color:#E6DB74"> '+'</span><span style="color:#F92672"> :</span><span style="color:#F8F8F2"> zeroLabel)),</span></span>
<span class="line"><span style="color:#A6E22E">        setProperty</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'ariaLabel'</span><span style="color:#F8F8F2">, () </span><span style="color:#66D9EF;font-style:italic">=></span></span>
<span class="line"><span style="color:#A6E22E">          nonZero</span><span style="color:#F8F8F2">() </span><span style="color:#F92672">?</span><span style="color:#F8F8F2"> incrementLabel </span><span style="color:#F92672">:</span><span style="color:#F8F8F2"> zeroLabel,</span></span>
<span class="line"><span style="color:#F8F8F2">        ),</span></span>
<span class="line"><span style="color:#A6E22E">        setProperty</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'disabled'</span><span style="color:#F8F8F2">, () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> el.value </span><span style="color:#F92672">>=</span><span style="color:#F8F8F2"> max),</span></span>
<span class="line"><span style="color:#A6E22E">        on</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'click'</span><span style="color:#F8F8F2">, () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F8F8F2">          el.value</span><span style="color:#F92672">++</span></span>
<span class="line"><span style="color:#F8F8F2">        }),</span></span>
<span class="line"><span style="color:#F8F8F2">      ),</span></span>
<span class="line"><span style="color:#A6E22E">      all</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">        'button'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#A6E22E">        on</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'keydown'</span><span style="color:#F8F8F2">, </span><span style="color:#FD971F;font-style:italic">e</span><span style="color:#66D9EF;font-style:italic"> =></span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">          const</span><span style="color:#F8F8F2"> { key } </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> e</span></span>
<span class="line"><span style="color:#F92672">          if</span><span style="color:#F8F8F2"> ([</span><span style="color:#E6DB74">'ArrowUp'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'ArrowDown'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'-'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'+'</span><span style="color:#F8F8F2">].</span><span style="color:#A6E22E">includes</span><span style="color:#F8F8F2">(key)) {</span></span>
<span class="line"><span style="color:#F8F8F2">            e.</span><span style="color:#A6E22E">stopPropagation</span><span style="color:#F8F8F2">()</span></span>
<span class="line"><span style="color:#F8F8F2">            e.</span><span style="color:#A6E22E">preventDefault</span><span style="color:#F8F8F2">()</span></span>
<span class="line"><span style="color:#F92672">            if</span><span style="color:#F8F8F2"> (key </span><span style="color:#F92672">===</span><span style="color:#E6DB74"> 'ArrowDown'</span><span style="color:#F92672"> ||</span><span style="color:#F8F8F2"> key </span><span style="color:#F92672">===</span><span style="color:#E6DB74"> '-'</span><span style="color:#F8F8F2">) el.value</span><span style="color:#F92672">--</span></span>
<span class="line"><span style="color:#F92672">            if</span><span style="color:#F8F8F2"> (key </span><span style="color:#F92672">===</span><span style="color:#E6DB74"> 'ArrowUp'</span><span style="color:#F92672"> ||</span><span style="color:#F8F8F2"> key </span><span style="color:#F92672">===</span><span style="color:#E6DB74"> '+'</span><span style="color:#F8F8F2">) el.value</span><span style="color:#F92672">++</span></span>
<span class="line"><span style="color:#F8F8F2">          }</span></span>
<span class="line"><span style="color:#F8F8F2">        }),</span></span>
<span class="line"><span style="color:#F8F8F2">      ),</span></span>
<span class="line"><span style="color:#F8F8F2">    ]</span></span>
<span class="line"><span style="color:#F8F8F2">  },</span></span>
<span class="line"><span style="color:#F8F8F2">)</span></span>
<span class="line"></span></code></pre>
	<basic-button class="copy">
		<button type="button" class="secondary small">
			<span class="label">Copy</span>
		</button>
	</basic-button>
	<button type="button" class="overlay">Expand</button>
</module-codeblock>
<ul>
<li>Whenever the user clicks a button or presses a handled key, the value property is updated.</li>
<li>The component sets hidden and disabled states of buttons and updates the text of the <code>.value</code> element.</li>
</ul>
<h3 id="full-example">
                <a name="full-example" class="anchor" href="#full-example">
	                <span class="permalink">🔗</span>
                </a>
                Full Example
            </h3>
<p>Here&#39;s how everything comes together:</p>
<ul>
<li>Each <code>FormSpinbutton</code> tracks its own value.</li>
<li>The <code>ModuleCatalog</code> sums all quantities and passes the total to <code>BasicButton</code>.</li>
<li>The <code>BasicButton</code> displays the total if it&#39;s greater than zero.</li>
</ul>
<p><strong>No custom events are needed – state flows naturally!</strong></p>
<module-demo>
	<div class="preview">
  	<module-catalog>
  		<header>
  			<p>Shop</p>
  			<basic-button disabled>
  				<button type="button" disabled>
  					<span class="label">🛒 Shopping Cart</span>
  					<span class="badge"></span>
  				</button>
  			</basic-button>
  		</header>
  		<ul>
  			<li>
  				<p>Product 1</p>
  				<form-spinbutton
  					value="0"
  					zero-label="Add to Cart"
  					increment-label="Increment"
  				>
  					<button
  						type="button"
  						class="decrement"
  						aria-label="Decrement"
  						hidden
  					>
  						−
  					</button>
  					<p class="value" hidden>0</p>
  					<button type="button" class="increment">Add to Cart</button>
  				</form-spinbutton>
  			</li>
  			<li>
  				<p>Product 2</p>
  				<form-spinbutton
  					value="0"
  					zero-label="Add to Cart"
  					increment-label="Increment"
  				>
  					<button
  						type="button"
  						class="decrement"
  						aria-label="Decrement"
  						hidden
  					>
  						−
  					</button>
  					<p class="value" hidden>0</p>
  					<button type="button" class="increment">Add to Cart</button>
  				</form-spinbutton>
  			</li>
  			<li>
  				<p>Product 3</p>
  				<form-spinbutton
  					value="0"
  					zero-label="Add to Cart"
  					increment-label="Increment"
  				>
  					<button
  						type="button"
  						class="decrement"
  						aria-label="Decrement"
  						hidden
  					>
  						−
  					</button>
  					<p class="value" hidden>0</p>
  					<button type="button" class="increment">Add to Cart</button>
  				</form-spinbutton>
  			</li>
  		</ul>
	  </module-catalog>
	</div>
	<details>
		<summary>ModuleCatalog Source Code</summary>
		<module-lazy src="./examples/module-catalog.html">
			<card-callout>
				<p class="loading" role="status">Loading...</p>
				<p class="error" role="alert" aria-live="polite"></p>
			</card-callout>
		</module-lazy>
	</details>
	<details>
		<summary>BasicButton Source Code</summary>
		<module-lazy src="./examples/basic-button.html">
			<card-callout>
				<p class="loading" role="status">Loading...</p>
				<p class="error" role="alert" aria-live="polite"></p>
			</card-callout>
		</module-lazy>
	</details>
	<details>
		<summary>FormSpinbutton Source Code</summary>
		<module-lazy src="./examples/form-spinbutton.html">
			<card-callout>
				<p class="loading" role="status">Loading...</p>
				<p class="error" role="alert" aria-live="polite"></p>
			</card-callout>
		</module-lazy>
	</details>
</module-demo>

</section>

<section>

<h2 id="custom-events">
                <a name="custom-events" class="anchor" href="#custom-events">
	                <span class="permalink">🔗</span>
                </a>
                Custom Events
            </h2>
<p>Passing state down works well when a <strong>parent component can directly observe child state</strong>, but sometimes a <strong>child needs to notify its parent</strong> about an action <strong>without managing shared state itself</strong>.</p>
<p>Custom events are perfect for this - they allow components to communicate upward through the DOM tree without tight coupling.</p>
<h3 id="typescript-support-for-components-and-events">
                <a name="typescript-support-for-components-and-events" class="anchor" href="#typescript-support-for-components-and-events">
	                <span class="permalink">🔗</span>
                </a>
                TypeScript Support for Components and Events
            </h3>
<p>To get full TypeScript support, declare your components and custom events globally:</p>
<module-codeblock collapsed language="typescript" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
	<p class="meta">
		
		<span class="language">typescript</span>
	</p>
	<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#88846F">// In your component file</span></span>
<span class="line"><span style="color:#F92672">export</span><span style="color:#66D9EF;font-style:italic"> type</span><span> </span><span style="color:#A6E22E;text-decoration:underline">ProductCardProps</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F8F8F2">  productId</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> string</span></span>
<span class="line"><span style="color:#F8F8F2">  quantity</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> number</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F92672">declare</span><span style="color:#F8F8F2"> global {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">  interface</span><span> </span><span style="color:#A6E22E;text-decoration:underline">HTMLElementTagNameMap</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#E6DB74">    'product-card'</span><span style="color:#F92672">:</span><span> </span><span style="color:#A6E22E;text-decoration:underline">Component</span><span style="color:#F8F8F2">&#x3C;</span><span style="color:#A6E22E;text-decoration:underline">ProductCardProps</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#E6DB74">    'shopping-cart'</span><span style="color:#F92672">:</span><span> </span><span style="color:#A6E22E;text-decoration:underline">Component</span><span style="color:#F8F8F2">&#x3C;</span><span style="color:#A6E22E;text-decoration:underline">ShoppingCartProps</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2">  }</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">  interface</span><span> </span><span style="color:#A6E22E;text-decoration:underline">HTMLElementEventMap</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F8F8F2">    itemAdded</span><span style="color:#F92672">:</span><span> </span><span style="color:#A6E22E;text-decoration:underline">CustomEvent</span><span style="color:#F8F8F2">&#x3C;{ id</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> string</span><span style="color:#F8F8F2">; quantity</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> number</span><span style="color:#F8F8F2"> }></span></span>
<span class="line"><span style="color:#F8F8F2">    cartUpdated</span><span style="color:#F92672">:</span><span> </span><span style="color:#A6E22E;text-decoration:underline">CustomEvent</span><span style="color:#F8F8F2">&#x3C;{ total</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> number</span><span style="color:#F8F8F2"> }></span></span>
<span class="line"><span style="color:#F8F8F2">  }</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span></code></pre>
	<basic-button class="copy">
		<button type="button" class="secondary small">
			<span class="label">Copy</span>
		</button>
	</basic-button>
	<button type="button" class="overlay">Expand</button>
</module-codeblock>
<p>This enables full type checking, autocompletion, and access to UIElement component methods like <code>.getSignal()</code> and <code>.setSignal()</code>.</p>
<h3 id="example-shopping-cart-events">
                <a name="example-shopping-cart-events" class="anchor" href="#example-shopping-cart-events">
	                <span class="permalink">🔗</span>
                </a>
                Example: Shopping Cart Events
            </h3>
<p>Consider a <strong>product card</strong> that needs to notify its parent when an item is added:</p>
<module-codeblock collapsed language="js" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
	<p class="meta">
		
		<span class="language">js</span>
	</p>
	<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#88846F">// Child component dispatches custom event</span></span>
<span class="line"><span style="color:#A6E22E">component</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">  'product-card'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">  {</span></span>
<span class="line"><span style="color:#F8F8F2">    productId: </span><span style="color:#A6E22E">asString</span><span style="color:#F8F8F2">(),</span></span>
<span class="line"><span style="color:#F8F8F2">    quantity: </span><span style="color:#A6E22E">asInteger</span><span style="color:#F8F8F2">(),</span></span>
<span class="line"><span style="color:#F8F8F2">  },</span></span>
<span class="line"><span style="color:#F8F8F2">  (</span><span style="color:#FD971F;font-style:italic">el</span><span style="color:#F8F8F2">, { </span><span style="color:#FD971F;font-style:italic">first</span><span style="color:#F8F8F2"> }) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> [</span></span>
<span class="line"><span style="color:#A6E22E">    first</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">      '.add-button'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#A6E22E">      on</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'click'</span><span style="color:#F8F8F2">, () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#88846F">        // Dispatch custom event with product details</span></span>
<span class="line"><span style="color:#F8F8F2">        el.</span><span style="color:#A6E22E">dispatchEvent</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#F92672">          new</span><span style="color:#A6E22E"> CustomEvent</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'itemAdded'</span><span style="color:#F8F8F2">, {</span></span>
<span class="line"><span style="color:#F8F8F2">            detail: {</span></span>
<span class="line"><span style="color:#F8F8F2">              id: el.productId,</span></span>
<span class="line"><span style="color:#F8F8F2">              quantity: el.quantity,</span></span>
<span class="line"><span style="color:#F8F8F2">            },</span></span>
<span class="line"><span style="color:#F8F8F2">            bubbles: </span><span style="color:#AE81FF">true</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">          }),</span></span>
<span class="line"><span style="color:#F8F8F2">        )</span></span>
<span class="line"><span style="color:#F8F8F2">      }),</span></span>
<span class="line"><span style="color:#F8F8F2">    ),</span></span>
<span class="line"><span style="color:#F8F8F2">  ],</span></span>
<span class="line"><span style="color:#F8F8F2">)</span></span>
<span class="line"></span></code></pre>
	<basic-button class="copy">
		<button type="button" class="secondary small">
			<span class="label">Copy</span>
		</button>
	</basic-button>
	<button type="button" class="overlay">Expand</button>
</module-codeblock>
<module-codeblock collapsed language="js" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
	<p class="meta">
		
		<span class="language">js</span>
	</p>
	<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#88846F">// Parent component listens for custom events</span></span>
<span class="line"><span style="color:#A6E22E">component</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">  'shopping-cart'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">  {</span></span>
<span class="line"><span style="color:#F8F8F2">    items: </span><span style="color:#A6E22E">fromEvent</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">      'product-card'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#E6DB74">      'itemAdded'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">      ({ </span><span style="color:#FD971F;font-style:italic">event</span><span style="color:#F8F8F2">, </span><span style="color:#FD971F;font-style:italic">source</span><span style="color:#F8F8F2">, </span><span style="color:#FD971F;font-style:italic">value</span><span style="color:#F8F8F2"> }) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#88846F">        // TypeScript knows 'source' is Component&#x3C;ProductCardProps></span></span>
<span class="line"><span style="color:#88846F">        // Can access UIElement methods like source.getSignal('quantity')</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">        const</span><span style="color:#F8F8F2"> newItem </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F8F8F2">          id: event.detail.id,</span></span>
<span class="line"><span style="color:#F8F8F2">          quantity: event.detail.quantity,</span></span>
<span class="line"><span style="color:#F8F8F2">          addedAt: Date.</span><span style="color:#A6E22E">now</span><span style="color:#F8F8F2">(),</span></span>
<span class="line"><span style="color:#F8F8F2">        }</span></span>
<span class="line"><span style="color:#F92672">        return</span><span style="color:#F8F8F2"> [</span><span style="color:#F92672">...</span><span style="color:#F8F8F2">value, newItem]</span></span>
<span class="line"><span style="color:#F8F8F2">      },</span></span>
<span class="line"><span style="color:#F8F8F2">      [],</span></span>
<span class="line"><span style="color:#F8F8F2">    ),</span></span>
<span class="line"><span style="color:#A6E22E">    total</span><span style="color:#F8F8F2">: () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> el.items.</span><span style="color:#A6E22E">reduce</span><span style="color:#F8F8F2">((</span><span style="color:#FD971F;font-style:italic">sum</span><span style="color:#F8F8F2">, </span><span style="color:#FD971F;font-style:italic">item</span><span style="color:#F8F8F2">) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> sum </span><span style="color:#F92672">+</span><span style="color:#F8F8F2"> item.quantity, </span><span style="color:#AE81FF">0</span><span style="color:#F8F8F2">),</span></span>
<span class="line"><span style="color:#F8F8F2">  },</span></span>
<span class="line"><span style="color:#F8F8F2">  (</span><span style="color:#FD971F;font-style:italic">el</span><span style="color:#F8F8F2">, { </span><span style="color:#FD971F;font-style:italic">first</span><span style="color:#F8F8F2"> }) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> [</span></span>
<span class="line"><span style="color:#A6E22E">    first</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'.cart-count'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">setText</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'total'</span><span style="color:#F8F8F2">)),</span></span>
<span class="line"><span style="color:#A6E22E">    first</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">      '.items-list'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#A6E22E">      setText</span><span style="color:#F8F8F2">(() </span><span style="color:#66D9EF;font-style:italic">=></span></span>
<span class="line"><span style="color:#F8F8F2">        el.items.</span><span style="color:#A6E22E">map</span><span style="color:#F8F8F2">(</span><span style="color:#FD971F;font-style:italic">item</span><span style="color:#66D9EF;font-style:italic"> =></span><span style="color:#E6DB74"> `</span><span style="color:#F92672">${</span><span style="color:#F8F8F2">item.id</span><span style="color:#F92672">}</span><span style="color:#E6DB74">: </span><span style="color:#F92672">${</span><span style="color:#F8F8F2">item.quantity</span><span style="color:#F92672">}</span><span style="color:#E6DB74">`</span><span style="color:#F8F8F2">).</span><span style="color:#A6E22E">join</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">', '</span><span style="color:#F8F8F2">),</span></span>
<span class="line"><span style="color:#F8F8F2">      ),</span></span>
<span class="line"><span style="color:#F8F8F2">    ),</span></span>
<span class="line"><span style="color:#F8F8F2">  ],</span></span>
<span class="line"><span style="color:#F8F8F2">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F92672">declare</span><span style="color:#F8F8F2"> global {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">  interface</span><span> </span><span style="color:#A6E22E;text-decoration:underline">HTMLElementTagNameMap</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#E6DB74">    'shopping-cart'</span><span style="color:#F92672">:</span><span> </span><span style="color:#A6E22E;text-decoration:underline">Component</span><span style="color:#F8F8F2">&#x3C;</span><span style="color:#A6E22E;text-decoration:underline">ShoppingCartProps</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2">  }</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span></code></pre>
	<basic-button class="copy">
		<button type="button" class="secondary small">
			<span class="label">Copy</span>
		</button>
	</basic-button>
	<button type="button" class="overlay">Expand</button>
</module-codeblock>
<h3 id="benefits-of-custom-events">
                <a name="benefits-of-custom-events" class="anchor" href="#benefits-of-custom-events">
	                <span class="permalink">🔗</span>
                </a>
                Benefits of Custom Events
            </h3>
<ul>
<li><strong>Decoupling</strong>: Child components don&#39;t need to know about parent implementation</li>
<li><strong>Reusability</strong>: Components can be used in different contexts</li>
<li><strong>Standard DOM</strong>: Uses native event system, works with any framework</li>
<li><strong>Bubbling</strong>: Events naturally flow up the DOM tree</li>
<li><strong>Cancellable</strong>: Parent can prevent default behavior if needed</li>
</ul>
<h3 id="when-to-use-custom-events">
                <a name="when-to-use-custom-events" class="anchor" href="#when-to-use-custom-events">
	                <span class="permalink">🔗</span>
                </a>
                When to Use Custom Events
            </h3>
<ul>
<li><strong>User Actions</strong>: Button clicks, form submissions, gestures</li>
<li><strong>State Changes</strong>: When a component&#39;s internal state affects others</li>
<li><strong>Lifecycle Events</strong>: Component initialization, destruction, errors</li>
<li><strong>Data Flow</strong>: When child needs to send data upward without direct coupling</li>
</ul>
<h3 id="component-type-safety-best-practices">
                <a name="component-type-safety-best-practices" class="anchor" href="#component-type-safety-best-practices">
	                <span class="permalink">🔗</span>
                </a>
                Component Type Safety Best Practices
            </h3>
<p>Each UIElement component should declare its own <code>HTMLElementTagNameMap</code> extension:</p>
<module-codeblock collapsed language="ts" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
	<p class="meta">
		
		<span class="language">ts</span>
	</p>
	<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#88846F">// In my-component.ts</span></span>
<span class="line"><span style="color:#F92672">export</span><span style="color:#66D9EF;font-style:italic"> type</span><span> </span><span style="color:#A6E22E;text-decoration:underline">MyComponentProps</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F8F8F2">  value</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> string</span></span>
<span class="line"><span style="color:#F8F8F2">  count</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> number</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F92672">export</span><span style="color:#F92672"> default</span><span style="color:#A6E22E"> component</span><span style="color:#F8F8F2">(</span></span>
<span class="line"><span style="color:#E6DB74">  'my-component'</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">  {</span></span>
<span class="line"><span style="color:#88846F">    /* ... */</span></span>
<span class="line"><span style="color:#F8F8F2">  },</span></span>
<span class="line"><span style="color:#F8F8F2">  () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> [],</span></span>
<span class="line"><span style="color:#F8F8F2">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F92672">declare</span><span style="color:#F8F8F2"> global {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">  interface</span><span> </span><span style="color:#A6E22E;text-decoration:underline">HTMLElementTagNameMap</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#E6DB74">    'my-component'</span><span style="color:#F92672">:</span><span> </span><span style="color:#A6E22E;text-decoration:underline">Component</span><span style="color:#F8F8F2">&#x3C;</span><span style="color:#A6E22E;text-decoration:underline">MyComponentProps</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2">  }</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span></code></pre>
	<basic-button class="copy">
		<button type="button" class="secondary small">
			<span class="label">Copy</span>
		</button>
	</basic-button>
	<button type="button" class="overlay">Expand</button>
</module-codeblock>
<p>This enables:</p>
<ul>
<li><strong>Full type safety</strong> when using signal producers like <code>fromDescendants(&#39;my-component&#39;, ...)</code></li>
<li><strong>Access to UIElement methods</strong> like <code>.getSignal()</code> and <code>.setSignal()</code></li>
<li><strong>IntelliSense</strong> for component properties and methods</li>
<li><strong>Compile-time validation</strong> of component interactions</li>
</ul>
</section>

<section>

<h2 id="providing-context">
                <a name="providing-context" class="anchor" href="#providing-context">
	                <span class="permalink">🔗</span>
                </a>
                Providing Context
            </h2>
<card-callout class="caution">

<p><strong>TODO</strong>: Add example</p>
</card-callout>

</section>

<section>

<h2 id="consuming-context">
                <a name="consuming-context" class="anchor" href="#consuming-context">
	                <span class="permalink">🔗</span>
                </a>
                Consuming Context
            </h2>
<card-callout class="caution">

<p><strong>TODO</strong>: Add example</p>
</card-callout>

</section>

<section>

<h2 id="next-steps">
                <a name="next-steps" class="anchor" href="#next-steps">
	                <span class="permalink">🔗</span>
                </a>
                Next Steps
            </h2>
</section>
</main>
			<footer class="content-grid">
				<div class="content">
					<h2 class="visually-hidden">Footer</h2>
					<p>© 2024 – 2025 Zeix AG</p>
				</div>
			</footer>
		</context-router>
	</body>
</html>