Conditional Fields
stimeo--conditional-fields
Shows and hides parts of a form according to what another control is set to.
Shows and hides parts of a form according to a checkbox or a selection. Which value reveals which region is declared in your markup, and with several conditions you choose whether any or all of them must hold. While a region is hidden its inputs can be disabled, so a value nobody can see is never submitted by accident. If the region being hidden holds focus, focus retreats to the control that drives it, so the keyboard never loses its place. When the markup is swapped out, the decision is made again from the current values.
Keyboard
This component has no keyboard interactions of its own.
<%# Conditional fields demo: check the box to reveal the address fieldset. The
controller toggles hidden / aria-hidden and disables the hidden inputs (so they
drop out of submission); it listens for the change itself, so no consumer JS is
needed. This demo only styles the layout. %>
<div class="conditional-fields-demo">
<form data-controller="stimeo--conditional-fields">
<label class="conditional-fields-demo__toggle">
<input type="checkbox" data-stimeo--conditional-fields-target="trigger">
<%= t("components.conditional_fields.demo.toggle") %>
</label>
<fieldset
class="conditional-fields-demo__region"
data-stimeo--conditional-fields-target="region"
data-when-checked
hidden>
<legend><%= t("components.conditional_fields.demo.legend") %></legend>
<label class="conditional-fields-demo__field">
<span><%= t("components.conditional_fields.demo.street") %></span>
<input type="text" name="street">
</label>
<label class="conditional-fields-demo__field">
<span><%= t("components.conditional_fields.demo.city") %></span>
<input type="text" name="city">
</label>
</fieldset>
</form>
</div>
/*
* Presentation-only styles for the conditional-fields demo.
* The library toggles hidden / aria-hidden / disabled and data-visible; this CSS
* only lays out the toggle and the revealed fieldset.
*/
.conditional-fields-demo {
max-width: 28rem;
}
.conditional-fields-demo form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.conditional-fields-demo__toggle {
display: flex;
align-items: center;
gap: 0.5rem;
}
.conditional-fields-demo__region {
display: flex;
flex-direction: column;
gap: 0.75rem;
margin: 0;
padding: 1rem;
border: 1px solid var(--border);
border-radius: 0.5rem;
}
.conditional-fields-demo__field {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.conditional-fields-demo__field input {
padding: 0.5rem;
border: 1px solid var(--border);
border-radius: 0.375rem;
font: inherit;
}
This demo needs no consumer-side JS (the controller handles the behavior).
These demo styles use shared design tokens (light + dark). Copy the shared styles too, then toggle data-theme on your root element for dark mode.
The data-* attributes you add to your own HTML to wire this component. Put the data-controller below on a root element, then place its targets / values / actions inside that element.
On the root element
data-controller="stimeo--conditional-fields"
Targets
| Name | Description | Attribute |
|---|---|---|
trigger
required
|
Control(s) whose value/checked state drives the regions. | data-stimeo--conditional-fields-target="trigger" |
region
required
|
Element shown/hidden by its data-when-* condition. |
data-stimeo--conditional-fields-target="region" |
Values
| Name | Description | Attribute |
|---|---|---|
disableHidden
|
Disable inputs inside a hidden region so they are not submitted (default true). |
data-stimeo--conditional-fields-disable-hidden-value |
match
|
How multiple triggers combine: any or all (default any). |
data-stimeo--conditional-fields-match-value |
Actions
| Name | Action |
|---|---|
evaluate
|
stimeo--conditional-fields#evaluate |
Events
| Name | Description | Event |
|---|---|---|
change
|
Fires when a region's visibility changes, with detail.region / detail.visible. |
stimeo--conditional-fields:change |
reconcile
|
stimeo--conditional-fields:reconcile |
State hooks
The library only manages these ARIA/data attributes and custom properties. Your CSS reads them to render the look — selectors like [aria-selected], [aria-expanded], or var(--stimeo--…) hook into this state.
| Hook | Target | Meaning |
|---|---|---|
hidden / aria-hidden |
Region | Added while the region's condition does not hold. |
disabled |
Inputs inside a hidden region | Added (when disableHidden) so they drop out of the submission. |
data-visible |
Region | Present while the region is shown. |