Radio button
Radio buttons (COMPONENT_SPEC §23; Compose RadioButton) on native <input type="radio">s: a 48dp target around a 20dp ring. Selecting grows the dot on the fast spatial spring, which overshoots under the expressive motion scheme, while the ring and dot fade to primary; the radio that loses the selection shrinks its dot the same way. Radios that share a name inside a role="radiogroup" (or a fieldset) need no JavaScript: arrow keys move the selection and wrap, Tab enters the group at the selected radio, Space selects.
Static (m3e-css)
<label class="m3e-radio-button"> around the .m3e-radio-button__input, the __icon ring (its dot is drawn by CSS), the __state circle and an optional __label, inside a .m3e-radio-group. The label selects the radio and shows its hover and press, as in Compose's radio group sample, whose option rows are 56dp high. The ripple needs @kyralabs/m3e-elements/ripple.js (this section uses attachAutoRipple).
Element
There is no <m3e-radio-button>: native radios already select one at a time, take part in forms and move the selection with arrow keys, so the plain markup above is the element-layer API. Load @kyralabs/m3e-elements/ripple.js for the press ripple.
React
<RadioGroup value defaultValue onChange orientation isDisabled isReadOnly isRequired name aria-label> around <Radio value isDisabled> (React Aria useRadioGroup / useRadio); the same DOM as the static markup. Below, Compose's radio group sample and a horizontal group with a disable switch.