Dogfood BareDOM components in demo gallery#2
Merged
Conversation
The "Library demo" title relied on inherited color from body through the x-theme slot boundary, which did not update when themes switched. Set color explicitly from --page-fg so applyThemeToPage rewrites reach the h1 the same way they reach header p and .header-eyebrow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hand-rolled demo chrome in demo/x-alert.html with library components so the demo gallery starts using the library it showcases: - <h1>/<h2> -> <x-typography variant="h1"|"overline"> - demo control <button> -> <x-button> (press event) - enum <select> -> <x-select> with select-change echo to keep .value live - text/number <input> -> <x-form-field> - .log div -> <x-card variant="filled"> wrapping <pre> Drop the now-unused .row button / .row select / .row input / h2 / .log CSS rules from the inline <style>. Wrap each control in an inline-flex <label> so x-form-field (block) and x-select (inline-block) line up consistently in the Spawn row. This file is the reference template for rolling the same swaps across the other ~80 demos in subsequent phases. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fold the x-alert pilot's local alignment fix into the shared demo stylesheet so future dogfooded demos inherit it automatically: - .row/.panel/.controls/.control-group label => inline-flex, so the label text sits beside the control regardless of whether the control is inline-block (x-select, x-switch, x-button) or block (x-form-field). - .row/.panel/.controls/.control-group/.field x-form-field => inline-block, so a form-field dropped into a horizontal row does not force its inline <label> onto a new line. This is Phase 2 step 0 of the demo dogfooding rollout. Local overrides in demo/x-alert.html remain for now as a safety net and will be removed in a cleanup commit once the shared rules are proven across several demos. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2 category (2) of the demo dogfooding rollout. Every demo page
used a hand-rolled "h2 { font-size:13px; text-transform:uppercase; ... }"
eyebrow pattern for section dividers; x-typography already has an
"overline" variant (0.625rem, uppercase, 0.1em tracking) that matches,
so this is a pure markup swap with no JS changes.
Scope:
- 482 h2 tags across 79 demo files rewritten to
<x-typography variant="overline">.
- demo/x-typography.html is intentionally skipped: it showcases the
h1-h6 variants and still needs a real h2 element.
- The dead "h2 { ... }" CSS rules in each file are left in place for
this commit and will be removed in a follow-up CSS-cleanup pass so
the diff here stays focused on markup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After swapping demo section <h2> elements to <x-typography variant="overline">, the pages looked visibly crammed: native <h2> had UA default top/bottom margins, but x-typography is purely presentational and renders with zero margin. Add the same rule the x-alert.html pilot uses locally (display:block; margin:32px 0 10px) to the shared demo stylesheet so every demo inherits the old vertical rhythm automatically. The local override in demo/x-alert.html stays as a safety net for now. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2 category (1) of the demo dogfooding rollout. Every demo page used a bare native <h1>"x-foo demo"</h1> as its page title; swap to <x-typography variant="h1"> so the page title is themed and styled by the library itself. Scope: - 81 <h1> tags across 81 demo files rewritten. - demo/x-typography.html is intentionally skipped (showcases the h1-h6 variants so must keep a real <h1>). - Add a shared margin rule for x-typography[variant="h1"] in demo-responsive.css so the dogfooded title preserves the old bottom spacing the native <h1> had. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2 category (3) of the demo dogfooding rollout. Every demo page
used hand-rolled native <button> elements (with inline
".row button { background:#1d4ed8; ... }" styling) for reset, spawn,
and control-panel actions; swap to <x-button> so the demo gallery
uses the library's own button component.
Scope:
- 238 native <button> tags across 39 demo files rewritten.
- demo/x-button.html never contained any native <button> (it already
showcases <x-button> exclusively), so no files are intentionally
skipped in this sweep.
- Pure HTML swap: no JS handler changes. x-button has a native
<button> inside open shadow DOM, so native "click" events bubble
out naturally and every existing click handler keeps working.
Moving to the idiomatic "press" event is a possible follow-up.
- Dead ".row button { ... }" CSS rules in each file are left in
place for this commit and will be removed in a follow-up CSS
cleanup pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Follow-up to the Phase 2 button sweep: six demos had hand-rolled
class="secondary" / class="danger" / class="modal-close" / class="btn
btn-primary" hooks that styled native <button> elements. After the
mechanical swap they all rendered as default primary, so the visual
hierarchy (cancel, close, destructive actions) was lost.
Fixes:
- x-modal.html: close X and Cancel -> variant="ghost"; Clear log ->
variant="secondary". Close button uses label="Close" for a11y.
- x-drawer.html: same treatment as x-modal.
- x-toaster.html: "With progress" / "With heading" -> variant="secondary";
"Spam x 8" -> variant="danger".
- x-notification-center.html: info/success/warning quick-push buttons ->
variant="secondary"; error quick-push and Clear All -> variant="danger".
- x-form.html: drop dead "btn btn-primary" class (primary is default),
"btn btn-secondary" -> variant="secondary", inline font/padding hacks
-> size="sm". x-button type="submit" cannot find the shadow <form>
owned by x-form via closest("form"), so wire Sign in / Send / Reset /
Clear via onclick="document.getElementById('...').submit()|.reset()".
- x-search-field.html: same treatment for the submit row inside x-form.
Native <form> submits in x-switch.html and x-radio.html keep working
via type="submit" and are not touched.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Follow-up to the Phase 2 button sweep: four demos used native <button> with dedicated CSS class hooks as non-action visual elements. The mechanical swap produced <x-button> everywhere and broke their layouts because the class-based styling no longer matched a native <button> element. Reverts: - x-dropdown.html: 23 <x-button class="menu-item"> (incl. the "danger" variant) back to native <button>. These are stacked menu rows inside <x-dropdown>, not action buttons; the local .menu-item CSS styles them as menu entries. - x-liquid-dock.html: 6 <x-button class="dock-icon"> back to native <button>. Custom dock styling. - x-menu.html: 8 <x-button slot="trigger" class="trigger-btn"> back to native <button>. Trigger buttons carry a <span class= "chevron"> child and rely on the local .trigger-btn CSS to match the x-menu visual. - x-splash.html: 1 <x-button class="demo-close-btn"> back to native <button>. Custom absolutely-positioned close. Legit action buttons in these files (e.g. x-dropdown's .demo-btn control panel) are left as <x-button>. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Follow-up to the Phase 2 button sweep: seven demos used hand-rolled class hooks (demo-btn, ctrl, action, action-btn, toggle-btn) that originally targeted "button.foo" selectors — outlined neutral control buttons. After the swap to <x-button> those selectors no longer matched and the buttons rendered as default primary. Map the dead class hooks to the closest semantic variant: - demo-btn / ctrl / action / action-btn / toggle-btn -> variant="secondary" (33 instances across 7 files) Also fix x-popover.html, which had two extra class hooks not in the original sweep list and produced an orange-inside-a-frame look: - 2x trigger-btn (Delete item / No footer) -> variant="secondary" - pop-footer-btn (Cancel / Close) -> variant="ghost" - pop-footer-btn.primary (Confirm) -> default primary The original .demo-btn / .ctrl / .trigger-btn / .pop-footer-btn CSS rules in each file's inline <style> are now dead and will be removed in the follow-up CSS cleanup pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2 category (4) of the demo dogfooding rollout.
Markup sweep:
- 124 native <select> elements across 60 demo files rewritten to
<x-select>. demo/x-select.html is intentionally skipped.
- For every swapped element, a value="..." attribute is added with
the explicit <option selected> value if present, otherwise the
first <option>'s value, so the dogfooded select renders with the
same default selection that native <select> had.
Shared compat shim (demo-theme.js):
- A document-level select-change listener echoes detail.value back
to the host's value attribute (because x-select does not auto-set
it on user interaction) and re-dispatches a synthetic native
"change" event. That keeps every existing demo handler working
unchanged: el.value reads the live selection, and listeners
registered with addEventListener("change", ...) still fire.
Shared layout (demo-responsive.css):
- Grid/panel/controls/control-group/field x-select gets width:100%
+ a compact md size override (--x-select-height-md: 2rem;
--x-select-font-size-md: 0.8125rem;) to recreate the footprint
the original native <select> had via the demos' inline CSS.
- Narrow the .row label inline-flex rule down to .row only. The
earlier broader selector list (.row, .panel, .controls,
.control-group) overreached: .controls is used inconsistently
across demos (x-form treats it as a flex row, x-toast treats it
as a CSS grid with column-stacked labels), so blanket inline-flex
centering broke the stacked layouts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2 category (5) of the demo dogfooding rollout.
Markup sweep:
- 112 native <input type="checkbox"> elements across 54 demo files
rewritten to <x-switch>. demo/x-checkbox.html and demo/x-switch.html
are intentionally skipped.
- demo/x-fieldset.html "Notification preferences" toggles converted
back to <x-checkbox>: those are multi-select preferences (Email
updates / SMS alerts / Weekly digest), semantically checkboxes, not
on/off settings.
Compat shims (demo-theme.js):
- x-switch-change -> synthetic native "change" event so existing
addEventListener("change", ...) handlers fire transparently.
- x-checkbox-change -> same shim, mirrors x-switch.
querySelector fixes:
- 23 demos used querySelectorAll(".controls input, .controls select")
to wire up live controls. After the sweep, those selectors silently
skipped the new <x-switch> / <x-select> elements (they aren't <input>
or <select>). Extend each query to also include ".controls x-switch"
and ".controls x-select" so the change handlers actually attach.
Shared layout (demo-responsive.css):
- x-switch is 24px tall (much taller than the native 16px checkbox it
replaced), so flex labels with align-items:center end up with text
glyphs sitting visually below the switch midline. Force all labels
containing a direct x-switch child to display:inline-flex with
min-height:24px and line-height:1, so the switch and the surrounding
text label sit on the same visual midline.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 2 housekeeping. The earlier sweeps swapped native <h1>, <h2>, <button>, <select>, and <input type="checkbox"> elements to library components, but left the original local CSS rules behind as dead selectors that no longer matched anything. Walk every demo's inline <style> block and remove any rule whose selector is fully dead — i.e. every comma-separated part targets a type that no longer appears anywhere in the file's body. Conservative rules: - only single-purpose selectors are removed (rules whose every part targets the now-dead type, evaluated by the rightmost compound) - rules that combine dead and live selectors (e.g. "input, select") are left alone - @media / @supports blocks are recursed into - demo/x-typography.html keeps its h1 / h2 rules because that demo intentionally still uses native heading elements Total: 207 dead rules removed across 81 files. No layout changes intended — every remaining rule still matches a live element. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The earlier .controls x-select { width: 100% } rule was added to
satisfy x-toast.html, where labels are intentionally flex-column and
the dogfooded select needs to fill its grid cell. But .controls is
used inconsistently across demos: x-avatar-group (and others) use
.controls as a flex row with default-inline labels, where stretching
the select to 100% pushed the select onto its own line below the
label text and broke alignment with the other inline controls in
the row.
Narrow the width:100% to .grid only (which is unambiguously a stacked
grid layout). Keep the compact size override (--x-select-height-md /
--x-select-font-size-md) on all the common control containers — that
one is safe everywhere.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Post-sweep polish: several demos still carried leftover class hooks
or inline "style" attributes from their native-element days, which
rendered as duplicate host-level frames / colors on top of the
dogfooded x-button / x-select chrome.
Inline style leftovers on x-select (host border/background/padding
copied from the original native <select>):
- x-form.html ctrl-autocomplete
- x-form-field.html ctrl-type
- x-search-field.html ctrl-autocomplete
Inline style leftovers on x-button (padding/background/color copied
from a native <button>):
- x-form-field.html Submit / Reset (kept only align-self:flex-start)
Dead / conflicting class="btn*" hooks on x-button:
- x-currency-field.html class="btn btn-primary" / "btn btn-secondary"
-> variant="secondary" + onclick (inside <x-form>, closest("form")
can't see the shadow form so type="submit" doesn't work).
- x-stepper.html class="btn" dropped, Previous -> secondary
- x-toast.html dead class="btn-primary" dropped
Dead / conflicting class="secondary|danger|primary|..." hooks:
- x-toaster.html class="secondary"|"danger" -> variant=secondary|danger
- x-sidebar.html dead class="primary" dropped (primary is default)
- x-popover.html disabled trigger class="trigger-btn" -> variant=secondary
Live trigger-button CSS that integrates with the surrounding custom
element (same approach as the earlier x-menu.html revert): revert
<x-button class="..."> back to native <button class="...">:
- x-navbar.html 10x ghost-btn / primary-btn / menu-btn
- x-menu-item.html 4x trigger-btn
- x-context-menu.html 7x trigger-btn
x-button.html's class="brand" is intentional (theming example).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The demo wired up Card/Detail/Next/Prev/Welcome/Profile/Done/etc.
action buttons via "document.querySelectorAll('button[data-stack]')",
but after the Phase 2 sweep those elements are <x-button>, not
<button>, so the selector returned nothing and no click listeners
attached. Narrow the selector to "x-button[data-stack]".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Follow-up polish: several more demos still had inline "style=...padding/background/border/color..." attributes on their x-button elements, copied straight from the native <button> they replaced. Those styles applied to the x-button HOST and rendered as duplicate frames on top of x-button's own shadow-DOM chrome. Fixes: - x-slider.html Submit/Reset: strip leftover style; Reset -> variant=secondary - x-color-picker.html Submit/Reset: strip padding/border-radius/cursor, keep width:fit-content; Reset -> variant=secondary - x-timeline-item.html Approve/Reject: strip full styling, use size=sm + variant=secondary on Reject - x-liquid-glass.html "Try clicking" inside liquid-glass: strip custom bg/border, keep margin-top, use variant=ghost so the button sits visibly on the frosted surface - x-sidebar.html Event-log Clear button: strip font-size/padding, use size=sm Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The .amber / .indigo / .emerald variants in the x-soft-body demo only set background, border, and shadow CSS variables but no text color, so the slotted <h3>/<p> content inherited "color: var(--page-fg)" from body. In dark mode that resolves to near-white, leaving the text invisible on the hardcoded light card backgrounds. Pin an explicit dark text color on all three variants so they remain readable regardless of OS color scheme or x-theme preset. Latent bug that predates the dogfooding sweep; caught during spot-checks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… x-switch control panel
- x-spacer.html: Docs / Sign in / Settings nav-demo x-buttons now
render as variant=secondary to read like nav links rather than
primary calls-to-action.
- x-switch.html: switch the four control-panel x-button handlers
from addEventListener("click") to addEventListener("press"). The
"Next toggle: cancel" button was not firing its handler via click
— presumably because the native click from x-button's internal
<button> doesn't bubble out cleanly in this specific wiring — but
"press" (the documented canonical x-button event) works reliably.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The sticky theme-picker bar in demo-theme.js was z-index:9999, which covered every overlay component (x-drawer at 1000/1001, x-sidebar at 999/1000, x-toaster at 9000, x-modal/x-popover/x-dropdown similar), making those demos hard to test because the picker obscured them. Drop the picker to z-index:100 so every component overlay naturally stacks above it. The picker is still above regular scrolled content (default auto/0), so its sticky behaviour is unchanged — it only yields to intentional overlays. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Apr 13, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the hand-rolled scaffolding in every
demo/*.htmlpage with the library's own components. Every demo already loads the full dev bundle, so the swap is free at runtime. The value is consistency (one visual language across 80+ pages), dogfooding (demos are the best place to find ergonomics / a11y / theming bugs in our own components), and ~541 fewer lines of repeated inline CSS.86 files changed · +1436 / −1979 (net −543 lines) · 20 commits
What was swapped
<h2>→<x-typography variant="overline">x-typography.html<h1>→<x-typography variant="h1">x-typography.html<button>→<x-button>x-button.html; reverted 38 in 4 files where native class hooks were load-bearing<select>→<x-select>x-select.html<input type="checkbox">→<x-switch>(or<x-checkbox>for multi-select preferences)x-checkbox.html/x-switch.htmlDeferred per plan: category 6 (text/number
<input>→<x-form-field>) and category 7 (event log.log→<x-card>+<pre>) are intentionally out of scope — form-field is block-level with a built-in label and would be invasive; event-log panels have lower visual impact and await<x-code>.Shared infrastructure changes
demo/demo-responsive.css— shared alignment rules for.row label/.row x-form-field, line-height fix for<x-switch>inside labels, compact size tokens for<x-select>inside grid layouts, and margin rules so<x-typography variant="h1"|"overline">has the same vertical rhythm as native<h1>/<h2>.demo/demo-theme.js— three compat shims:select-change/x-switch-change/x-checkbox-changeare each re-dispatched as nativechangeevents andx-select's value attribute is echoed back on change, so existing demo JS that reads.valueand listens forchangekeeps working without per-file edits. Theme-picker bar z-index also dropped from 9999 to 100 so overlay components render above it.CSS cleanup
One dedicated commit walks every demo's inline
<style>block and removes rules whose selector targets a type that no longer appears in the file (conservative: only single-selector rules where every comma-separated part is dead, @media blocks recursed into,x-typography.htmlpreserved because it still uses real headings). 207 dead rules stripped across 81 files.Commit log
3526bbef565011x-alert.html99e9139e14f252de4964a488a8699701a6759f49ff52f448a6360c60ba881adc7ea9ec93c320acc79c8f1a41fe79d0a83647056457832247de3e4345d2a8bcAudit scans (all clean)
style=\"...\"attributes on dogfooded componentsclass=\"...\"on<x-button>(only the intentionalclass=\"brand\"in x-button.html)querySelectorAll('.controls input/select')call extended to also matchx-switch/x-select<h1>/<h2>only inx-typography.html; native<select>only inx-select.html<button>only in 7 demos where live class CSS targets native buttons (intentional reverts)Known residuals (cosmetic, non-blocking)
demo/x-alert.htmlstill carries a localx-typography[variant=\"overline\"] { ... }override that duplicates the identical rule now indemo-responsive.css. Harmless (identical declarations). Can fold into a one-line cleanup later.input[type=\"checkbox\"] { ... }CSS rules remain in x-timeline-item / x-scroll-parallax / x-pagination / x-neural-glow (the cleanup script skipped compound selectors). They target no element and don't affect rendering.Follow-ups for separate PRs
[part=cell]needsheight: 100%so cellborder-bottomlines connect across columns with uneven intrinsic heights. Exists on main; caught during spot-checks.Test plan
npx shadow-cljs watch appand openhttp://localhost:8000/demo/index.html, browse the gallerydemo/x-alert.html— spawn alerts with varying attributes, confirm the event log populatesdemo/x-modal.html,demo/x-carousel.html,demo/x-table.html,demo/x-fieldset.html,demo/x-form.html,demo/x-notification-center.html?theme=ocean/?theme=forest/?theme=aurorato the URL and confirm the dogfooded chrome re-themes in lockstep with the target componentdemo/x-drawer.html,demo/x-sidebar.html,demo/x-toaster.htmldemo/x-typography.html(intentional skips — native h1/h2 preserved)🤖 Generated with Claude Code