Skip to content

Commit

Permalink
Improves Focus Management of RadioGroups
Browse files Browse the repository at this point in the history
RadioGroups are now focusable even is there is no option selected yet. If that is the case, only the first option becomes active and can be selected by pressing Space.

If there is one option selected, the component behaves the same way as before.

This fixes issue #770
  • Loading branch information
christian.hausknecht authored and Lysander committed Feb 5, 2024
1 parent 318435b commit b2e92f8
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ class RadioGroup<C : HTMLElement, T>(tag: Tag<C>, private val explicitId: String
private var toggle: Tag<HTMLElement>? = null
private var label: Tag<HTMLElement>? = null
private var descriptions: MutableList<Tag<HTMLElement>> = mutableListOf()
private var isFirst = false

private val toggleId = "$optionId-toggle"

Expand Down Expand Up @@ -170,8 +171,11 @@ class RadioGroup<C : HTMLElement, T>(tag: Tag<C>, private val explicitId: String
content()
attr("role", Aria.Role.radio)
attr(Aria.checked, selected.asString())
attr("tabindex", selected.map { if (it) "0" else "-1" })
var toggleEvent: Listener<*, *> = clicks
tabIndex(combine(selected, value.data) { sel, data ->
if (sel || (data == null && isFirst)) 0 else -1
})
var toggleEvent: Flow<*> =
if (isFirst) merge(clicks, keydowns.filter { shortcutOf(it) == Keys.Space }) else clicks
if (domNode is HTMLInputElement) {
if (domNode.getAttribute("name") == null) {
attr("name", componentId)
Expand Down Expand Up @@ -269,6 +273,7 @@ class RadioGroup<C : HTMLElement, T>(tag: Tag<C>, private val explicitId: String

init {
options.add(option)
isFirst = options.size == 1
}
}

Expand Down
11 changes: 7 additions & 4 deletions www/src/pages/headless/radioGroup.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ radioGroup<HTMLFieldSetElement, Plan?>(tag = RenderContext::fieldset) {

## Styling the active Element

A RadioGroup also provides information about which option is currently active, i.e. has the focus.
A RadioGroup also provides information about which option is currently active, i.e. has the focus. If no option is
selected yet, the first option can get the focus. If an option is selected, the corresponding `radioGroupOptionToggle`
will be active.

For this purpose, the scope of `radioGroupOption` offers the Boolean data stream `active`. This one can (and should)
be used to provide a specific style for the `true` state.
Expand Down Expand Up @@ -195,9 +197,10 @@ previously selected option.

## Keyboard Interaction

| Command | Description |
|------------------------------------------------|-------------------------------------------------|
| [[]] [[]] when an option-toggle is focused | (Reverse) Cyclic selection through all options. |
| Command | Description |
|------------------------------------------------------|-------------------------------------------------|
| [[]] [[]] when an option-toggle is focused | (Reverse) Cyclic selection through all options. |
| [[Space]] when focused and no option is selected yet | Selects first option. |

## API

Expand Down

0 comments on commit b2e92f8

Please sign in to comment.