Skip to content

chore(rfc): create rfc for adding form elements to ToggleButton - #10836

Closed
travisrcory wants to merge 1 commit into
adobe:mainfrom
travisrcory:rfc-toggle-button-form-elements
Closed

travisrcory wants to merge 1 commit into
adobe:mainfrom
travisrcory:rfc-toggle-button-form-elements

Conversation

@travisrcory

@travisrcory travisrcory commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Introduces RFC for adding form elements into ToggleButton. I am capable of implementing the feature, just following the correct patterns for the library!

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices
  • I understand every change in this PR and can explain why it's there.
  • If AI-assisted, I followed our AI contribution guidance and pointed my assistant at AGENTS.md.

📝 Test Instructions:

Looking for feedback for RFC before implementing this feature

🧢 Your Project:

https://github.com/Grow-Therapy-Team/sprout-ui

@nwidynski

Copy link
Copy Markdown
Contributor

Another possibility is a bespoke radio or checkbox with the toggle button UX. For simplicity, our team decided to explore building on top of the toggle button and propose building it into the core component.

What exactly was your team missing from these components?

Update ToggleButton.tsx so that in addition to the button that is rendered a hidden input is also rendered

The button role is marked children presentational, which means it can only take phrasing (non-interactive) content as its children. A nested hidden input tag would thereby be an a11y violation.

@travisrcory

Copy link
Copy Markdown
Contributor Author

Another possibility is a bespoke radio or checkbox with the toggle button UX. For simplicity, our team decided to explore building on top of the toggle button and propose building it into the core component.

What exactly was your team missing from these components?

Update ToggleButton.tsx so that in addition to the button that is rendered a hidden input is also rendered

The button role is marked children presentational, which means it can only take phrasing (non-interactive) content as its children. A nested hidden input tag would thereby be an a11y violation.

Thanks for the feedback!

For our team it is mostly a semantic naming of using a Toggle Button UX, but as a form element. Basically a limited checkbox or radio without an indicator, and without the ability to provide a description.

In my own custom implementation, I've been rendering it like this:

    <>
      <RACToggleButton
        id={id}
        isDisabled={isDisabled}
        defaultSelected={defaultSelected} // currently copying the internal pattern of using react-stately for computing this value
        isSelected={isSelected} // currently copying the internal pattern of using react-stately for computing this value
        onChange={onChange} // currently copying the internal pattern of using react-stately for computing this value
      >
        {children}
      </RACToggleButton>

      <input
        readOnly // so that it can be controlled by toggle button
        tabIndex={-1}
        aria-hidden
        className='invisible hidden' // tailwind class
        name={name} // passed to ToggleButton or inherited from ToggleButtonGroup
        form={form} // passed to ToggleButton or inherited from ToggleButtonGroup
        checked={isSelected} // currently copying the internal pattern of using react-stately for computing this value
        value={value} // either a custom value or the id passed to ToggleButton
        type={type} // computed based on the selectionMode from toggle button group
      />
    </>

The idea being that the input is not presentational, but is hidden to sighted users and screen readers. It is rendered as a sibling of the button to avoid accessibility violations

@snowystinger

snowystinger commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Could you use a Checkbox and style it to look like a button (I see that's briefly mentioned in "Alternatives")? Seems like that would announce better.

ToggleButton doesn't carry any aria attributes that would indicate selection other than aria-pressed which may be unexpected that it's included in a form submission.

@travisrcory

travisrcory commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Could you use a Checkbox and style it to look like a button (I see that's briefly mentioned in "Alternatives")? Seems like that would announce better.

ToggleButton doesn't carry any aria attributes that would indicate selection other than aria-pressed which may be unexpected that it's included in a form submission.

True, thinking out loud, if ToggleButton is the semantic name our org wants to use for the component we could always choose to render a Checkbox or Radio contextually if the consumer passes name or form to indicate its usage in a form

Thank you both for your input, I'll circle back with my team and think through how we want to do this

@travisrcory

Copy link
Copy Markdown
Contributor Author

I've updated my teams ToggleButton to render the actual form elements (RadioGroup, CheckboxGroup, CheckboxField, RadioField) based on the form props being passed.

This isn't needed anymore!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants