Sticky top bar with three named slots: brand, nav, actions. At narrow viewports the slots stack vertically; no hamburger menu in v2.
<script type="module" src=".../dist/components/sa-header.js"></script>
<sa-header>
<a slot="brand" href="/">acme.example</a>
<nav slot="nav">
<a href="/docs">Docs</a>
<a href="/blog">Blog</a>
<a href="/pricing">Pricing</a>
</nav>
<a slot="actions" href="/login">Sign in</a>
</sa-header>
| Kind | Name | Notes |
|---|---|---|
| slot | brand | Logo or wordmark, usually inside an <a>. |
| slot | nav | A <nav> with 2–5 links. |
| slot | actions | One or two CTA links (sign-in, GitHub, …). |
| part | container | The outer <header>. |
| part | brand | Wrapper around the brand slot. |
| part | nav | Wrapper around the nav slot. |
| part | actions | Wrapper around the actions slot. |
Splash block parameterized by attributes. Optional media slot promotes the layout to two columns on wide viewports. CTA renders only when both cta-href and cta-label are set.
<script type="module" src=".../dist/components/sa-hero.js"></script>
<sa-hero
eyebrow="Foundation v0.1.0"
title="Compose your site from blocks"
subtitle="A small kit of tokens, typography, and web components."
cta-href="/docs/quickstart"
cta-label="Get started">
<img slot="media" src="/img/illustration.svg" alt="">
</sa-hero>
| Kind | Name | Notes |
|---|---|---|
| attribute | title | Required. Renders as the H1. |
| attribute | subtitle | Optional supporting paragraph. |
| attribute | eyebrow | Optional small label above the title. |
| attribute | cta-href | CTA link target. Renders only with cta-label. |
| attribute | cta-label | CTA link text. Renders only with cta-href. |
| attribute | align | "left" (default) or "center". |
| slot | media | Optional. With align="left", promotes layout to two columns. |
| part | container | Outer wrapper. |
| part | eyebrow / title / subtitle / cta / media | Each individually styleable. |
Bottom-of-page chrome with three named slots: brand, links, copyright. Top row stacks at narrow viewports.
Compose your site from blocks.
<script type="module" src=".../dist/components/sa-footer.js"></script>
<sa-footer>
<div slot="brand">
<strong>acme.example</strong>
<p>Compose your site from blocks.</p>
</div>
<nav slot="links">
<a href="/docs">Docs</a>
<a href="/blog">Blog</a>
<a href="/pricing">Pricing</a>
</nav>
<span slot="copyright">© 2026 Acme.</span>
</sa-footer>
| Kind | Name | Notes |
|---|---|---|
| slot | brand | Logo + optional tagline. Pinned to top-row left. |
| slot | links | One or more <nav> blocks. Top-row right, flex-wraps. |
| slot | copyright | Single line in the bottom row. |
| part | container | The outer <footer>. |
| part | top | Top row (brand + links). |
| part | brand / links / bottom / copyright | Each individually styleable. |
Auto-fitting CSS grid (minmax(280px, 1fr)). Children typically <sa-feature> instances but anything works — the grid doesn't introspect children.
Each component is a single ES module under dist/components/. A page imports only what it uses; nothing else loads.
Override --sa-accent on :root and every component picks it up automatically through CSS-custom-property inheritance.
Slots collapse cleanly when nothing is provided. This card has no icon slot — the layout adjusts without empty space.
<script type="module" src=".../dist/components/sa-feature-grid.js"></script>
<script type="module" src=".../dist/components/sa-feature.js"></script>
<sa-feature-grid>
<sa-feature title="Drop-in modules">
<svg slot="icon" viewBox="0 0 24 24" fill="currentColor">...</svg>
<p>Each component is a single ES module under dist/components/.</p>
</sa-feature>
<sa-feature title="Themed once">
<span slot="icon">🎨</span>
<p>Override --sa-accent and every component picks it up.</p>
</sa-feature>
<sa-feature title="Optional slots">
<p>Slots collapse cleanly when not provided.</p>
</sa-feature>
</sa-feature-grid>
| Kind | Name | Notes |
|---|---|---|
| slot | (default) | Any children. <sa-feature> is typical but not required. |
| part | container | The CSS Grid container. Override to change column min-width or gap. |
| Kind | Name | Notes |
|---|---|---|
| attribute | title | Required. Renders as the H3. |
| slot | icon | Optional. SVG (will inherit accent via currentColor) or emoji span. |
| slot | (default) | Body description. Typically a paragraph or short prose. |
| part | container | The card itself. |
| part | icon / title / body | Each individually styleable. |
Two-region layout for chat surfaces: scrollable messages on top, pinned composer on the bottom. Both regions are slot-only — the kit owns layout (max-width, sizing, hairline divider, padding via tokens), the consumer owns the appearance of individual messages and composer controls.
Hi — drop your composer in the composer slot, your messages container in the messages slot. The kit handles the layout.
What stays in light DOM?
Your slotted children. Selectors like #messages and #user-input stay queryable from your app code.
<script type="module" src=".../dist/components/sa-chat.js"></script>
<sa-chat>
<div slot="messages" id="messages">
<!-- consumer's app code appends message nodes here -->
</div>
<form slot="composer" id="composer">
<textarea id="user-input" placeholder="Ask anything…"></textarea>
<button type="submit">Send</button>
</form>
</sa-chat>
| Kind | Name | Notes |
|---|---|---|
| slot | messages | Container for the messages list. Stays in light DOM so app code can query and mutate it directly. |
| slot | composer | The composer (typically a <form>). Stays in light DOM for the same reason. |
| part | messages | The scrollable wrapper around the messages slot. Override padding / scroll behavior here. |
| part | composer | The composer wrapper. Override padding / divider / background here. |
| var | --sa-chat-max-width | Container width. Defaults to 880px. |