fix theme editor radio buttons: accessibility and double dots

Wrap logo mode radios in fieldset/legend for screen reader grouping.
Hide native radio input properly (was using nonexistent .hidden class),
add aria-hidden on decorative dot spans, focus-visible ring on cards,
and IDs on each input.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey 2026-03-04 00:14:57 +00:00
parent 2e5217b010
commit 1a2a6f5d56
3 changed files with 62 additions and 45 deletions

View File

@ -103,7 +103,7 @@ On-site editing overlay for admins: browse the real shop with a sidebar for them
| # | Task | Est | Status |
|---|---|---|---|
| 1 | Fix double radio button dots in theme editor | 30m | planned |
| 1 | Fix double radio button dots in theme editor | 30m | done |
### Platform site

View File

@ -4024,7 +4024,14 @@
}
/* Radio card selector (logo mode picker) */
.theme-radio-fieldset {
border: none;
padding: 0;
margin: 0;
}
.theme-radio-card {
position: relative;
display: flex;
align-items: center;
gap: 0.75rem;
@ -4037,6 +4044,17 @@
&:hover {
border-color: var(--admin-text-ghost);
}
&:has(:focus-visible) {
outline: 2px solid var(--t-accent);
outline-offset: 2px;
}
}
.theme-radio-input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.theme-radio-card-active {

View File

@ -90,52 +90,51 @@
<!-- Branding Section -->
<div class="theme-panel">
<label class="theme-section-label">Logo & header</label>
<!-- Logo Mode Radio Cards -->
<div class="admin-stack admin-stack-sm theme-field">
<%= for {value, title, desc} <- [
{"text-only", "Shop name only", "Your name in the heading font"},
{"logo-text", "Logo + shop name", "Your logo image with name beside it"},
{"logo-only", "Logo only", "Just your logo (with text built in)"}
] do %>
<label class={[
"theme-radio-card",
if(@theme_settings.logo_mode == value,
do: "theme-radio-card-active",
else: ""
)
]}>
<input
type="radio"
name="logo_mode"
value={value}
checked={@theme_settings.logo_mode == value}
phx-click="update_setting"
phx-value-field="logo_mode"
phx-value-setting_value={value}
class="hidden"
/>
<span class={[
"theme-radio-dot",
@theme_settings.logo_mode == value && "theme-radio-dot-active"
<fieldset class="theme-radio-fieldset">
<legend class="theme-section-label">Logo & header</legend>
<div class="admin-stack admin-stack-sm theme-field">
<%= for {value, title, desc} <- [
{"text-only", "Shop name only", "Your name in the heading font"},
{"logo-text", "Logo + shop name", "Your logo image with name beside it"},
{"logo-only", "Logo only", "Just your logo (with text built in)"}
] do %>
<label class={[
"theme-radio-card",
@theme_settings.logo_mode == value && "theme-radio-card-active"
]}>
<span class={[
"theme-radio-dot-inner",
if(@theme_settings.logo_mode == value,
do: "theme-radio-dot-inner-active",
else: ""
)
]}>
<input
type="radio"
id={"logo-mode-#{value}"}
name="logo_mode"
value={value}
checked={@theme_settings.logo_mode == value}
phx-click="update_setting"
phx-value-field="logo_mode"
phx-value-setting_value={value}
class="theme-radio-input"
/>
<span
class={[
"theme-radio-dot",
@theme_settings.logo_mode == value && "theme-radio-dot-active"
]}
aria-hidden="true"
>
<span class={[
"theme-radio-dot-inner",
@theme_settings.logo_mode == value && "theme-radio-dot-inner-active"
]}>
</span>
</span>
</span>
<div class="admin-fill">
<div class="theme-radio-title">{title}</div>
<div class="admin-text-secondary">{desc}</div>
</div>
</label>
<% end %>
</div>
<div class="admin-fill">
<div class="theme-radio-title">{title}</div>
<div class="admin-text-secondary">{desc}</div>
</div>
</label>
<% end %>
</div>
</fieldset>
<!-- Logo Upload (for logo-text and logo-only modes) -->
<%= if @theme_settings.logo_mode in ["logo-text", "logo-only"] do %>