Axismundi · v3.5.1 · Wave 1 #1

Button — Full Spec Module

Component Full-Spec Module — baseline components.css §2 (L122–L234) is UNCHANGED at v3.5.1. This page demonstrates the five variants × Phase 1-scoped states. Animated ripple is deferred to Ripple v2 release (BACKLOG #25) per the Phase 2 pre-entry decision (Option b).
Baseline catalog: ../../style-guide.html#components-button

Static state-layer only. The five variants use has-state-layer (Pattern A: currentColor overlay scaled by opacity tokens). Animated click- position ripple is not wired at v3.5.1; it is a TARGET dependency routed to the Ripple v2 release (BACKLOG #25).

§2. Variants — label only

다섯 가지 variant — filled / tonal / elevated / outlined / text. S size (40px), corner-full radius (round). On press: corner-small morph via spatial spring. All include has-state-layer.

§3. With leading icon

Canonical icon slot per BUTTON-SPEC-AUDIT.md §8<span class="material-symbols-rounded ax-button-icon" aria-hidden translate="no" draggable="false"> + wrapped label.

§4. has-state-layer opt-out demo

Phase 1 SPEC §10 Risk 3 settled: default-ON canonical. This section demonstrates the opt-out path for completeness. Hover/ focus the two specimens to see the visual difference.

has-state-layer class applied — hover/focus shows opacity overlay (Pattern A).

has-state-layer 적용 — hover/focus 시 opacity overlay 표시 (Pattern A).

has-state-layer class omitted — expected to lack hover/focus opacity overlay. Not a bug; intentional demonstration.

has-state-layer class 생략 — hover/focus opacity overlay 없음이 정상. 버그 아님, 의도된 시연.

§5. Disabled — native attribute (Pattern A §0.8)

All five variants with native disabled attribute. Pattern A: 10% on-surface bg + 38% on-surface text + level0 box-shadow. Text variant retains transparent bg (baseline L231–L234 exception).

Native disabled — browser blocks activation + AT announces "disabled" + Pattern A visual rendering applied.
Native disabled — 브라우저가 activation 차단 + AT가 "disabled" 발화 + Pattern A 시각 렌더링 적용.

§5a. Disabled — aria-disabled (plugin-managed)

Single specimen with explicit caption. NOT a canonical replacement for native disabled.

aria-disabled="true" visually mirrors Pattern A via baseline L213 ([aria-disabled="true"]) but does NOT block click activation by itself. Use this form ONLY when the disabled state is plugin-managed (e.g., a form plugin toggles aria-disabled while the submit handler is in flight) and the plugin's own JS prevents activation. For static / theme-side disabled, prefer native disabled.

aria-disabled="true"는 baseline L213 선택자로 Pattern A 외관을 흉내내지만, 단독으로는 click activation을 막지 않는다. plugin이 disabled 상태를 동적으로 관리하면서 (예: form plugin이 submit handler 진행 중 aria-disabled를 토글), plugin JS가 activation을 직접 차단할 때만 이 형태를 사용. 정적 / theme-side disabled는 native disabled가 정답.

§6. Bare button

Rare-use base shape per SPEC §4.6. Receives base sizing + typography but no fill/color. Used for embedded contexts where styling comes from parent (split-button slave, custom block surface).

§7. Code snippets

Click each snippet to expand. Canonical markup for each variant family.

§2 Variants — label only (canonical)
<button class="ax-button is-filled has-state-layer t-label-large" type="button">Filled</button>
<button class="ax-button is-tonal has-state-layer t-label-large" type="button">Tonal</button>
<button class="ax-button is-elevated has-state-layer t-label-large" type="button">Elevated</button>
<button class="ax-button is-outlined has-state-layer t-label-large" type="button">Outlined</button>
<button class="ax-button is-text has-state-layer t-label-large" type="button">Text</button>
§3 With leading icon (canonical icon slot)
<button class="ax-button is-filled has-state-layer t-label-large" type="button">
  <span class="material-symbols-rounded notranslate ax-button-icon"
        translate="no" aria-hidden="true" draggable="false">add</span>
  <span>Add</span>
</button>
§4 has-state-layer opt-out
<!-- Default (state-layer ON) -->
<button class="ax-button is-filled has-state-layer t-label-large" type="button">With state-layer</button>

<!-- Opt-out (state-layer OFF) -->
<button class="ax-button is-filled t-label-large" type="button">Without state-layer</button>
§5 Disabled — native attribute (preferred)
<button class="ax-button is-filled has-state-layer t-label-large" type="button" disabled>Filled</button>
<!-- ... text variant retains transparent bg per baseline L231-L234 exception -->
<button class="ax-button is-text has-state-layer t-label-large" type="button" disabled>Text</button>
§5a aria-disabled — plugin-managed (use sparingly)
<!-- Plugin/JS must independently prevent activation; aria-disabled
     alone does NOT block click. -->
<button class="ax-button is-filled has-state-layer t-label-large"
        type="button" aria-disabled="true">aria-disabled</button>
§6 Bare button
<button class="ax-button has-state-layer t-label-large" type="button">Bare</button>

§8. Cross-references

Phase 0 · BUTTON-PHASE-0-REPORT.md

Phase 1 audit trio:

Phase 2 plan · BUTTON-PHASE-2-PLAN.md

Framework:

Baseline:

Animated ripple (TARGET — deferred): BACKLOG #25 — Ripple v2 contract.