<input-radiogroup value="other">
<fieldset>
<legend>Gender</legend>
<label>
<input type="radio" name="gender" value="female">
<span>Female</span>
</label>
<label>
<input type="radio" name="gender" value="male">
<span>Male</span>
</label>
<label class="selected">
<input type="radio" name="gender" value="other" checked>
<span>Other</span>
</label>
</fieldset>
</input-radiogroup>
<input-radiogroup value="all" class="split-button">
<fieldset>
<legend class="visually-hidden">Filter</legend>
<label class="selected">
<input type="radio" class="visually-hidden" name="filter" value="all" checked>
<span>All</span>
</label>
<label>
<input type="radio" class="visually-hidden" name="filter" value="active">
<span>Active</span>
</label>
<label>
<input type="radio" class="visually-hidden" name="filter" value="completed">
<span>Completed</span>
</label>
</fieldset>
</input-radiogroup>
input-radiogroup {
display: inline-block;
> fieldset {
display: flex;
gap: var(--space-m);
border: none;
margin: 0;
padding: var(--space-xs) 0 var(--space-s);
}
& legend,
& label {
font-size: var(--font-size-s);
}
& label {
border-radius: var(--space-xs);
&:focus-within {
box-shadow: 0 0 var(--space-xxs) 2px var(--color-selection);
}
& input:focus {
outline: none;
box-shadow: none;
}
}
&.split-button {
& fieldset {
gap: 0;
padding: 0;
}
& label {
display: inline-block;
box-sizing: border-box;
height: var(--input-height);
min-width: var(--input-height);
border: 1px solid var(--color-border);
border-radius: 0;
border-left-width: 0;
background-color: var(--color-secondary);
color: var(--color-text);
padding: var(--space-xs) var(--space-s);
cursor: pointer;
line-height: var(--line-height-s);
opacity: var(--opacity-dimmed);
transition: opacity var(--transition-short) var(--easing-inout);
&:hover {
background-color: var(--color-secondary-hover);
opacity: var(--opacity-solid);
}
&:active {
background-color: var(--color-secondary-active);
}
&.selected {
color: var(--color-text-inverted);
background-color: var(--color-primary);
border-color: var(--color-primary-active);
&:hover {
background-color: var(--color-primary-hover);
}
&:active {
background-color: var(--color-primary-active);
}
}
}
& legend + label {
border-radius: var(--space-xs) 0 0 var(--space-xs);
border-left-width: 1px;
}
& label:last-child {
border-radius: 0 var(--space-xs) var(--space-xs) 0;
}
}
}
import {
type Component,
all,
asString,
component,
on,
setAttribute,
toggleClass,
} from "../../../";
export type InputRadiogroupProps = {
value: string;
};
export default component(
"input-radiogroup",
{
value: asString(),
},
(el) => [
setAttribute("value"),
all(
"input",
on("change", (e: Event) => {
el.value = (e.target as HTMLInputElement)?.value;
}),
),
all(
"label",
toggleClass(
"selected",
(target) => el.value === target.querySelector("input")?.value,
),
),
],
);
declare global {
interface HTMLElementTagNameMap {
"input-radiogroup": Component<InputRadiogroupProps>;
}
}