@zeix/ui-element
Version:
UIElement - minimal reactive framework based on Web Components
672 lines (606 loc) • 96 kB
HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Examples & Recipes – UIElement Docs</title>
<meta name="description" content="Common use cases and demos" />
<base href="./examples-recipes.html" />
<link rel="stylesheet" href="assets/main.css" />
<script type="module" src="assets/main.js"></script>
</head>
<body>
<header class="content-grid">
<h1 class="content">
UIElement Docs <small>Version 0.12.2</small>
</h1>
<nav class="breakout">
<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="building-components.html">
<span class="icon">🏗️</span>
<strong>Building Components</strong>
<small>Anatomy, lifecycle, signals, effects</small>
</a>
</li>
<li>
<a href="styling-components.html">
<span class="icon">🎨</span>
<strong>Styling Components</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="patterns-techniques.html">
<span class="icon">💡</span>
<strong>Patterns & Techniques</strong>
<small>Composition, scheduling, best practices</small>
</a>
</li>
<li>
<a href="examples-recipes.html" class="active">
<span class="icon">🍽️</span>
<strong>Examples & Recipes</strong>
<small>Common use cases and demos</small>
</a>
</li>
<li>
<a href="api-reference.html">
<span class="icon">📚</span>
<strong>API Reference</strong>
<small>Detailed documentation of classes and functions</small>
</a>
</li>
<li>
<a href="about-community.html">
<span class="icon">🤝</span>
<strong>About & Community</strong>
<small>License, versioning, getting involved</small>
</a>
</li>
</ol>
</nav>
</header>
<main><section class="hero">
<h1 id="examples-amp-recipes">
<a name="examples-amp-recipes" class="anchor" href="#examples-amp-recipes">
<span class="permalink">🔗</span>
</a>
🍽️ Examples & Recipes
</h1><p class="lead">Discover practical examples and patterns for building reactive, modular components with UIElement. Each example focuses on showcasing a specific feature or best practice, guiding you through real-world use cases.</p>
</section>
<section>
<h2 id="what-you39ll-learn">
<a name="what-you39ll-learn" class="anchor" href="#what-you39ll-learn">
<span class="permalink">🔗</span>
</a>
What You'll Learn
</h2><p>This collection of examples demonstrates a range of scenarios, from simple state updates in a single component to managing complex interactions across multiple components. Here's an overview of what you'll find:</p>
<ul>
<li><strong>Basic Composition</strong>: <code>TabList</code> and <code>AccordionPanel</code> - See how a parent component can control the visibility of multiple child components, showcasing state sharing and communication between components.</li>
<li><strong>Syntax Highlighting</strong>: - See how wrapping content in a <code>CodeBlock</code> component enables syntax highlighting on the client, demonstrating integration with third-party libraries.</li>
<li><strong>Fetching Data Example</strong>: <code>LazyLoad</code> - Learn how to fetch content only when needed, handling asynchronous operations and updating state reactively as data is loaded.</li>
<li><strong>Form Validation Example</strong>: <code>InputField</code> with Client-Side & Server-Side Validation - Validate input fields based on requirements passed from the server and dynamically check the validity of entries, such as checking the availability of usernames via server requests.</li>
<li><strong>Context Example</strong>: <code>MediaContext</code> - Discover how to share state globally across components using context, with practical use cases like adapting to media queries and responsive design.</li>
</ul>
<p>Whether you're getting started with a basic component or building a full-featured application, these examples will help you understand how to use <code>UIElement</code> effectively to build reactive Web Components.</p>
</section>
<section>
<h2 id="tablist-and-accordionpanel-example">
<a name="tablist-and-accordionpanel-example" class="anchor" href="#tablist-and-accordionpanel-example">
<span class="permalink">🔗</span>
</a>
TabList and AccordionPanel Example
</h2><component-demo>
<div class="preview">
<tab-list>
<menu>
<li><button type="button" aria-pressed="true">Tab 1</button></li>
<li><button type="button">Tab 2</button></li>
<li><button type="button">Tab 3</button></li>
</menu>
<accordion-panel>
<details open aria-disabled="true">
<summary class="visually-hidden">
<div class="summary">Tab 1</div>
</summary>
Content for Tab 1
</details>
</accordion-panel>
<accordion-panel>
<details aria-disabled="true">
<summary class="visually-hidden">
<div class="summary">Tab 2</div>
</summary>
Content for Tab 2
</details>
</accordion-panel>
<accordion-panel>
<details aria-disabled="true">
<summary class="visually-hidden">
<div class="summary">Tab 3</div>
</summary>
Content for Tab 3
</details>
</accordion-panel>
</tab-list>
</div>
<accordion-panel collapsible>
<details>
<summary>TabList Source Code</summary>
<lazy-load src="./examples/tab-list.html">
<p class="loading">Loading...</p>
</lazy-load>
</details>
</accordion-panel>
<accordion-panel collapsible>
<details>
<summary>AccordionPanel Source Code</summary>
<lazy-load src="./examples/accordion-panel.html">
<p class="loading">Loading...</p>
</lazy-load>
</details>
</accordion-panel>
</component-demo>
</section>
<section>
<h2 id="codeblock-example">
<a name="codeblock-example" class="anchor" href="#codeblock-example">
<span class="permalink">🔗</span>
</a>
CodeBlock Example
</h2><component-demo>
<div class="preview">
<code-block collapsed language="html" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="file">code-block.html</span>
<span class="language">html</span>
</p>
<pre class="language-html"><code><code-block collapsed language="html" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="file">code-block.html</span>
<span class="language">html</span>
</p>
<pre><code class="language-html"><code-block collapsed language="html" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="file">code-block.html</span>
<span class="language">html</span>
</p>
<pre><code class="language-html"></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">Copy</button>
</input-button>
<button type="button" class="overlay">Expand</button>
</code-block></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">Copy</button>
</input-button>
<button type="button" class="overlay">Expand</button>
</code-block></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">Copy</button>
</input-button>
<button type="button" class="overlay">Expand</button>
</code-block>
</div>
<accordion-panel collapsible>
<details>
<summary>CodeBlock Source Code</summary>
<lazy-load src="./examples/code-block.html">
<p class="loading">Loading...</p>
</lazy-load>
</details>
</accordion-panel>
<accordion-panel collapsible>
<details>
<summary>InputButton Source Code</summary>
<lazy-load src="./examples/input-button.html">
<p class="loading">Loading...</p>
</lazy-load>
</details>
</accordion-panel>
</component-demo>
</section>
<section>
<h2 id="lazyload-example">
<a name="lazyload-example" class="anchor" href="#lazyload-example">
<span class="permalink">🔗</span>
</a>
LazyLoad Example
</h2><component-demo>
<div class="preview">
<lazy-load src="./examples/snippets/snippet.html">
<p class="loading">Loading...</p>
<p class="error"></p>
</lazy-load>
</div>
<accordion-panel collapsible>
<details>
<summary>LazyLoad Source Code</summary>
<lazy-load src="./examples/lazy-load.html">
<p class="loading">Loading...</p>
</lazy-load>
</details>
</accordion-panel>
</component-demo>
</section>
<section>
<h2 id="inputfield-example">
<a name="inputfield-example" class="anchor" href="#inputfield-example">
<span class="permalink">🔗</span>
</a>
InputField Example
</h2><component-demo>
<div class="preview">
<input-field>
<label for="name-input">Name</label>
<div class="row">
<div class="group auto">
<input type="text" id="name-input" name="name" autocomplete="name" required>
</div>
</div>
<p class="error" aria-live="assertive" id="name-error"></p>
</input-field>
<input-field integer>
<label for="bday-year-input">Birthday Year</label>
<div class="row">
<div class="group short">
<input type="number" id="bday-year-input" name="bday-year" autocomplete="bday-year" required minlength="4" maxlength="4" min="1900" max="2024" step="1">
</div>
<div class="spinbutton" data-step="1">
<button type="button" class="decrement" aria-label="Decrement">−</button>
<button type="button" class="increment" aria-label="Increment">+</button>
</div>
</div>
<p class="error" aria-live="assertive" id="bday-year-error"></p>
<p class="description" aria-live="polite" id="bday-year-description"></p>
</input-field>
<input-field validate="./examples/snippets/validate.html">
<label for="username-input">Username</label>
<div class="row">
<div class="group auto">
<input type="text" id="username-input" name="username" autocomplete="username" aria-describedby="username-description" required minlength="4" maxlength="20">
</div>
</div>
<p class="error" aria-live="assertive" id="username-error"></p>
<p class="description" aria-live="polite" id="username-description" data-remaining="${x} characters remaining">Max. 20 characters</p>
</input-field>
</div>
<accordion-panel collapsible>
<details>
<summary>InputField Source Code</summary>
<lazy-load src="./examples/input-field.html">
<p class="loading">Loading...</p>
</lazy-load>
</details>
</accordion-panel>
</component-demo>
</section>
<section>
<h2 id="mediacontext-example">
<a name="mediacontext-example" class="anchor" href="#mediacontext-example">
<span class="permalink">🔗</span>
</a>
MediaContext Example
</h2><p>The <code>MediaContext</code> component provides global state to any sub-components in its DOM tree by exposing context for responsive and adaptive features. It tracks the following:
</p>
<ul>
<li><strong>Media Motion</strong> (<code>media-motion</code>): Indicates whether the user prefers reduced motion based on the <code>(prefers-reduced-motion)</code> media query.</li>
<li>*<strong>Media Theme</strong> (<code>media-theme</code>): Provides the user's preferred color scheme, such as dark mode, based on the <code>(prefers-color-scheme)</code> media query.</li>
<li><strong>Media Viewport</strong> (<code>media-viewport</code>): Indicates the current viewport size and is classified into different sizes (e.g., <code>xs</code>, <code>sm</code>, <code>md</code>, <code>lg</code>, <code>xl</code>). Custom breakpoints can be configured by setting attributes on the <code><media-context></code> element.</li>
<li><strong>Media Orientation</strong> (<code>media-orientation</code>): Tracks the device's screen orientation, switching between <code>landscape</code> and <code>portrait</code>.</li>
</ul>
<h3 id="configuring-breakpoints">
<a name="configuring-breakpoints" class="anchor" href="#configuring-breakpoints">
<span class="permalink">🔗</span>
</a>
Configuring Breakpoints
</h3><p>The viewport sizes can be customized by providing attributes on the <code><media-context></code> element:</p>
<ul>
<li><code>sm</code>: Small screen breakpoint (default: <code>32em</code>).</li>
<li><code>md</code>: Medium screen breakpoint (default: <code>48em</code>).</li>
<li><code>lg</code>: Large screen breakpoint (default: <code>72em</code>).</li>
<li><code>xl</code>: Extra large screen breakpoint (default: <code>108em</code>).</li>
</ul>
<p>For example, to set a small breakpoint at 40em and a medium breakpoint at 60em, use:</p>
<code-block language="html" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">html</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F8F8F2"><</span><span style="color:#F92672">media-context</span><span style="color:#A6E22E"> sm</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"40em"</span><span style="color:#A6E22E"> md</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"60em"</span><span style="color:#F8F8F2">></</span><span style="color:#F92672">media-context</span><span style="color:#F8F8F2">></span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
</code-block>
<p>Source code:</p>
<code-block 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:#F92672">import</span><span style="color:#F8F8F2"> { UIElement, maybe } </span><span style="color:#F92672">from</span><span style="color:#E6DB74"> '@zeix/ui-element'</span></span>
<span class="line"></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">const</span><span style="color:#F8F8F2"> VIEWPORT_XS </span><span style="color:#F92672">=</span><span style="color:#E6DB74"> 'xs'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">const</span><span style="color:#F8F8F2"> VIEWPORT_SM </span><span style="color:#F92672">=</span><span style="color:#E6DB74"> 'sm'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">const</span><span style="color:#F8F8F2"> VIEWPORT_MD </span><span style="color:#F92672">=</span><span style="color:#E6DB74"> 'md'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">const</span><span style="color:#F8F8F2"> VIEWPORT_LG </span><span style="color:#F92672">=</span><span style="color:#E6DB74"> 'lg'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">const</span><span style="color:#F8F8F2"> VIEWPORT_XL </span><span style="color:#F92672">=</span><span style="color:#E6DB74"> 'xl'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">const</span><span style="color:#F8F8F2"> ORIENTATION_LANDSCAPE </span><span style="color:#F92672">=</span><span style="color:#E6DB74"> 'landscape'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">const</span><span style="color:#F8F8F2"> ORIENTATION_PORTRAIT </span><span style="color:#F92672">=</span><span style="color:#E6DB74"> 'portrait'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">class</span><span> </span><span style="color:#A6E22E;text-decoration:underline">MediaContext</span><span style="color:#F92672"> extends</span><span> </span><span style="color:#A6E22E;font-style:italic;text-decoration:underline">UIElement</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F92672">static</span><span style="color:#F8F8F2"> providedContexts </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> [</span><span style="color:#E6DB74">'media-motion'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'media-theme'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'media-viewport'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'media-orientation'</span><span style="color:#F8F8F2">];</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6E22E">connectedCallback</span><span style="color:#F8F8F2">() {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#A6E22E"> getBreakpoints</span><span style="color:#F92672"> =</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:#A6E22E"> parseBreakpoint</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> (</span><span style="color:#FD971F;font-style:italic">breakpoint</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"> attr </span><span style="color:#F92672">=</span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">getAttribute</span><span style="color:#F8F8F2">(breakpoint)?.</span><span style="color:#A6E22E">trim</span><span style="color:#F8F8F2">();</span></span>
<span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (</span><span style="color:#F92672">!</span><span style="color:#F8F8F2">attr) </span><span style="color:#F92672">return</span><span style="color:#AE81FF"> null</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> unit </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> attr.</span><span style="color:#A6E22E">match</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">/em</span><span style="color:#F92672">$</span><span style="color:#E6DB74">/</span><span style="color:#F8F8F2">) </span><span style="color:#F92672">?</span><span style="color:#E6DB74"> 'em'</span><span style="color:#F92672"> :</span><span style="color:#E6DB74"> 'px'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> value </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> maybe</span><span style="color:#F8F8F2">(</span><span style="color:#A6E22E">parseFloat</span><span style="color:#F8F8F2">(attr)).</span><span style="color:#A6E22E">filter</span><span style="color:#F8F8F2">(Number.isFinite)[</span><span style="color:#AE81FF">0</span><span style="color:#F8F8F2">];</span></span>
<span class="line"><span style="color:#F92672"> return</span><span style="color:#F8F8F2"> value </span><span style="color:#F92672">?</span><span style="color:#F8F8F2"> value </span><span style="color:#F92672">+</span><span style="color:#F8F8F2"> unit </span><span style="color:#F92672">:</span><span style="color:#AE81FF"> null</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:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> sm </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> parseBreakpoint</span><span style="color:#F8F8F2">(VIEWPORT_SM) </span><span style="color:#F92672">||</span><span style="color:#E6DB74"> '32em'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> md </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> parseBreakpoint</span><span style="color:#F8F8F2">(VIEWPORT_MD) </span><span style="color:#F92672">||</span><span style="color:#E6DB74"> '48em'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> lg </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> parseBreakpoint</span><span style="color:#F8F8F2">(VIEWPORT_LG) </span><span style="color:#F92672">||</span><span style="color:#E6DB74"> '72em'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> xl </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> parseBreakpoint</span><span style="color:#F8F8F2">(VIEWPORT_XL) </span><span style="color:#F92672">||</span><span style="color:#E6DB74"> '108em'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#F92672"> return</span><span style="color:#F8F8F2"> { sm, md, lg, xl };</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:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> breakpoints </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> getBreakpoints</span><span style="color:#F8F8F2">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> reducedMotion </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> matchMedia</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'(prefers-reduced-motion: reduce)'</span><span style="color:#F8F8F2">);</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> darkMode </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> matchMedia</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'(prefers-color-scheme: dark)'</span><span style="color:#F8F8F2">);</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> screenSmall </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> matchMedia</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">`(min-width: </span><span style="color:#F92672">${</span><span style="color:#F8F8F2">breakpoints.sm</span><span style="color:#F92672">}</span><span style="color:#E6DB74">)`</span><span style="color:#F8F8F2">);</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> screenMedium </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> matchMedia</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">`(min-width: </span><span style="color:#F92672">${</span><span style="color:#F8F8F2">breakpoints.md</span><span style="color:#F92672">}</span><span style="color:#E6DB74">)`</span><span style="color:#F8F8F2">);</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> screenLarge </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> matchMedia</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">`(min-width: </span><span style="color:#F92672">${</span><span style="color:#F8F8F2">breakpoints.lg</span><span style="color:#F92672">}</span><span style="color:#E6DB74">)`</span><span style="color:#F8F8F2">);</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> screenXLarge </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> matchMedia</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">`(min-width: </span><span style="color:#F92672">${</span><span style="color:#F8F8F2">breakpoints.xl</span><span style="color:#F92672">}</span><span style="color:#E6DB74">)`</span><span style="color:#F8F8F2">);</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> screenOrientation </span><span style="color:#F92672">=</span><span style="color:#A6E22E"> matchMedia</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'(orientation: landscape)'</span><span style="color:#F8F8F2">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#A6E22E"> getViewport</span><span style="color:#F92672"> =</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:#F92672"> if</span><span style="color:#F8F8F2"> (screenXLarge.matches) </span><span style="color:#F92672">return</span><span style="color:#F8F8F2"> VIEWPORT_XL;</span></span>
<span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (screenLarge.matches) </span><span style="color:#F92672">return</span><span style="color:#F8F8F2"> VIEWPORT_LG;</span></span>
<span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (screenMedium.matches) </span><span style="color:#F92672">return</span><span style="color:#F8F8F2"> VIEWPORT_MD;</span></span>
<span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (screenSmall.matches) </span><span style="color:#F92672">return</span><span style="color:#F8F8F2"> VIEWPORT_SM;</span></span>
<span class="line"><span style="color:#F92672"> return</span><span style="color:#F8F8F2"> VIEWPORT_XS;</span></span>
<span class="line"><span style="color:#F8F8F2"> };</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-motion'</span><span style="color:#F8F8F2">, reducedMotion.matches);</span></span>
<span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-theme'</span><span style="color:#F8F8F2">, darkMode.matches);</span></span>
<span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-viewport'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">getViewport</span><span style="color:#F8F8F2">());</span></span>
<span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-orientation'</span><span style="color:#F8F8F2">, screenOrientation.matches </span><span style="color:#F92672">?</span><span style="color:#F8F8F2"> ORIENTATION_LANDSCAPE </span><span style="color:#F92672">:</span><span style="color:#F8F8F2"> ORIENTATION_PORTRAIT);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> reducedMotion.</span><span style="color:#A6E22E">onchange</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> (</span><span style="color:#FD971F;font-style:italic">e</span><span style="color:#F8F8F2">) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-motion'</span><span style="color:#F8F8F2">, e.matches);</span></span>
<span class="line"><span style="color:#F8F8F2"> darkMode.</span><span style="color:#A6E22E">onchange</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> (</span><span style="color:#FD971F;font-style:italic">e</span><span style="color:#F8F8F2">) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-theme'</span><span style="color:#F8F8F2">, e.matches);</span></span>
<span class="line"><span style="color:#F8F8F2"> screenSmall.</span><span style="color:#A6E22E">onchange</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-viewport'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">getViewport</span><span style="color:#F8F8F2">());</span></span>
<span class="line"><span style="color:#F8F8F2"> screenMedium.</span><span style="color:#A6E22E">onchange</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-viewport'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">getViewport</span><span style="color:#F8F8F2">());</span></span>
<span class="line"><span style="color:#F8F8F2"> screenLarge.</span><span style="color:#A6E22E">onchange</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-viewport'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">getViewport</span><span style="color:#F8F8F2">());</span></span>
<span class="line"><span style="color:#F8F8F2"> screenXLarge.</span><span style="color:#A6E22E">onchange</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-viewport'</span><span style="color:#F8F8F2">, </span><span style="color:#A6E22E">getViewport</span><span style="color:#F8F8F2">());</span></span>
<span class="line"><span style="color:#F8F8F2"> screenOrientation.</span><span style="color:#A6E22E">onchange</span><span style="color:#F92672"> =</span><span style="color:#F8F8F2"> (</span><span style="color:#FD971F;font-style:italic">e</span><span style="color:#F8F8F2">) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-orientation'</span><span style="color:#F8F8F2">, e.matches </span><span style="color:#F92672">?</span><span style="color:#F8F8F2"> ORIENTATION_LANDSCAPE </span><span style="color:#F92672">:</span><span style="color:#F8F8F2"> ORIENTATION_PORTRAIT);</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:#F8F8F2">MediaContext.</span><span style="color:#A6E22E">define</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-context'</span><span style="color:#F8F8F2">);</span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
<button type="button" class="overlay">Expand</button>
</code-block>
</section>
<section>
<h2 id="themedcomponent-example">
<a name="themedcomponent-example" class="anchor" href="#themedcomponent-example">
<span class="permalink">🔗</span>
</a>
ThemedComponent Example
</h2><!-- Live component preview wrapped in media-context -->
<media-context>
<themed-component>
This component changes its background based on the theme!
</themed-component>
</media-context>
<!-- Source code with progressive disclosure -->
<details>
<summary>Source Code</summary>
<!-- Tabs for HTML, CSS, and JavaScript -->
<tab-list>
<!-- HTML Tab Panel -->
<tab-panel label="HTML">
<h3 id="html">
<a name="html" class="anchor" href="#html">
<span class="permalink">🔗</span>
</a>
HTML
</h3><code-block language="html" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">html</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F8F8F2"><</span><span style="color:#F92672">media-context</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> <</span><span style="color:#F92672">themed-component</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> This component changes its background based on the theme!</span></span>
<span class="line"><span style="color:#F8F8F2"> </</span><span style="color:#F92672">themed-component</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"></</span><span style="color:#F92672">media-context</span><span style="color:#F8F8F2">></span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
</code-block>
</tab-panel>
<!-- CSS Tab Panel -->
<tab-panel label="CSS">
<h3 id="css">
<a name="css" class="anchor" href="#css">
<span class="permalink">🔗</span>
</a>
CSS
</h3><code-block collapsed language="css" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">css</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F92672">themed-component</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> display</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">block</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> padding</span><span style="color:#F8F8F2">: </span><span style="color:#AE81FF">20</span><span style="color:#F92672">px</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> color</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">white</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> transition</span><span style="color:#F8F8F2">: background-color </span><span style="color:#AE81FF">0.3</span><span style="color:#F92672">s</span><span style="color:#66D9EF"> ease</span><span style="color:#F8F8F2">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> &.dark {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> background-color</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">black</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:#F8F8F2"> &</span><span style="color:#A6E22E">.light</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> background-color</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">lightgray</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>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
<button type="button" class="overlay">Expand</button>
</code-block>
</tab-panel>
<!-- JavaScript Tab Panel -->
<tab-panel label="JavaScript">
<h3 id="javascript">
<a name="javascript" class="anchor" href="#javascript">
<span class="permalink">🔗</span>
</a>
JavaScript
</h3><code-block 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:#F92672">import</span><span style="color:#F8F8F2"> { UIElement, toggleClass } </span><span style="color:#F92672">from</span><span style="color:#E6DB74"> '@zeix/ui-element'</span><span style="color:#F8F8F2">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#66D9EF;font-style:italic">class</span><span> </span><span style="color:#A6E22E;text-decoration:underline">ThemedComponent</span><span style="color:#F92672"> extends</span><span> </span><span style="color:#A6E22E;font-style:italic;text-decoration:underline">UIElement</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F92672"> static</span><span style="color:#F8F8F2"> consumedContexts </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> [</span><span style="color:#E6DB74">'media-theme'</span><span style="color:#F8F8F2">];</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6E22E"> connectedCallback</span><span style="color:#F8F8F2">() {</span></span>
<span class="line"><span style="color:#88846F"> // Toggle the class based on 'media-theme' signal</span></span>
<span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.self.</span><span style="color:#A6E22E">sync</span><span style="color:#F8F8F2">(</span><span style="color:#A6E22E">toggleClass</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'dark'</span><span style="color:#F8F8F2">, () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">get</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-theme'</span><span style="color:#F8F8F2">)));</span></span>
<span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.self.</span><span style="color:#A6E22E">sync</span><span style="color:#F8F8F2">(</span><span style="color:#A6E22E">toggleClass</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'light'</span><span style="color:#F8F8F2">, () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F92672"> !</span><span style="color:#FD971F">this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">get</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'media-theme'</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">ThemedComponent.</span><span style="color:#A6E22E">define</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'themed-component'</span><span style="color:#F8F8F2">);</span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
<button type="button" class="overlay">Expand</button>
</code-block>
</tab-panel>
</tab-list>
</details>
</section>
<section>
<h2 id="animatedcomponent-example">
<a name="animatedcomponent-example" class="anchor" href="#animatedcomponent-example">
<span class="permalink">🔗</span>
</a>
AnimatedComponent Example
</h2><!-- Live component preview wrapped in media-context -->
<media-context>
<animated-component>
<div class="animated-box">Box 1</div>
<div class="animated-box">Box 2</div>
<div class="animated-box">Box 3</div>
</animated-component>
</media-context>
<!-- Source code with progressive disclosure -->
<details>
<summary>Source Code</summary>
<!-- Tabs for HTML, CSS, and JavaScript -->
<tab-list>
<!-- HTML Tab Panel -->
<tab-panel label="HTML">
<h3 id="html">
<a name="html" class="anchor" href="#html">
<span class="permalink">🔗</span>
</a>
HTML
</h3><code-block language="html" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">html</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F8F8F2"><</span><span style="color:#F92672">media-context</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> <</span><span style="color:#F92672">animated-component</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> <</span><span style="color:#F92672">div</span><span style="color:#A6E22E"> class</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"animated-box"</span><span style="color:#F8F8F2">>Box 1</</span><span style="color:#F92672">div</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> <</span><span style="color:#F92672">div</span><span style="color:#A6E22E"> class</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"animated-box"</span><span style="color:#F8F8F2">>Box 2</</span><span style="color:#F92672">div</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> <</span><span style="color:#F92672">div</span><span style="color:#A6E22E"> class</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"animated-box"</span><span style="color:#F8F8F2">>Box 3</</span><span style="color:#F92672">div</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> </</span><span style="color:#F92672">animated-component</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"></</span><span style="color:#F92672">media-context</span><span style="color:#F8F8F2">></span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
</code-block>
</tab-panel>
<!-- CSS Tab Panel -->
<tab-panel label="CSS">
<h3 id="css">
<a name="css" class="anchor" href="#css">
<span class="permalink">🔗</span>
</a>
CSS
</h3><code-block collapsed language="css" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">css</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F92672">animated-component</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> display</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">block</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> padding</span><span style="color:#F8F8F2">: </span><span style="color:#AE81FF">20</span><span style="color:#F92672">px</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> overflow</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">hidden</span><span style="color:#F8F8F2">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> .animated-box {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> width</span><span style="color:#F8F8F2">: </span><span style="color:#AE81FF">50</span><span style="color:#F92672">px</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> height</span><span style="color:#F8F8F2">: </span><span style="color:#AE81FF">50</span><span style="color:#F92672">px</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> margin</span><span style="color:#F8F8F2">: </span><span style="color:#AE81FF">10</span><span style="color:#F92672">px</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> background-color</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">lightblue</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> text-align</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">center</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> line-height</span><span style="color:#F8F8F2">: </span><span style="color:#AE81FF">50</span><span style="color:#F92672">px</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> font-weight</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">bold</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> color</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">white</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:#F8F8F2"> &</span><span style="color:#A6E22E">.no-motion</span><span style="color:#A6E22E"> .animated-box</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> opacity</span><span style="color:#F8F8F2">: </span><span style="color:#AE81FF">0</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> transition</span><span style="color:#F8F8F2">: opacity </span><span style="color:#AE81FF">1</span><span style="color:#F92672">s</span><span style="color:#66D9EF"> ease-in</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:#F8F8F2"> &</span><span style="color:#A6E22E">.motion</span><span style="color:#A6E22E"> .animated-box</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> animation</span><span style="color:#F8F8F2">: moveAndFlash </span><span style="color:#AE81FF">2</span><span style="color:#F92672">s</span><span style="color:#66D9EF"> infinite</span><span style="color:#66D9EF"> ease-in-out</span><span style="color:#66D9EF"> alternate</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span><