diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md
index 14cc2f7..1035c32 100644
--- a/packages/@headlessui-react/CHANGELOG.md
+++ b/packages/@headlessui-react/CHANGELOG.md
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `hidden` attribute to internal `` component when the `Features.Hidden` feature is used ([#2955](https://github.com/tailwindlabs/headlessui/pull/2955))
- Attempt form submission when pressing `Enter` on `Checkbox` component ([#2962](https://github.com/tailwindlabs/headlessui/pull/2962))
- Allow setting custom `tabIndex` on the `` component ([#2966](https://github.com/tailwindlabs/headlessui/pull/2966))
+- Forward `disabled` state to hidden inputs in form-like components ([#3004](https://github.com/tailwindlabs/headlessui/pull/3004))
### Changed
diff --git a/packages/@headlessui-react/src/components/checkbox/checkbox.tsx b/packages/@headlessui-react/src/components/checkbox/checkbox.tsx
index aaa7ad2..c67e965 100644
--- a/packages/@headlessui-react/src/components/checkbox/checkbox.tsx
+++ b/packages/@headlessui-react/src/components/checkbox/checkbox.tsx
@@ -173,7 +173,12 @@ function CheckboxFn
{name != null && (
-
+
)}
{render({
ourProps,
diff --git a/packages/@headlessui-react/src/components/combobox/combobox.test.tsx b/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
index 525f345..562a33e 100644
--- a/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
+++ b/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
@@ -5747,6 +5747,48 @@ describe('Form compatibility', () => {
expect(submits).toHaveBeenLastCalledWith([['delivery', 'pickup']])
})
+ it('should not submit the data if the Combobox is disabled', async () => {
+ let submits = jest.fn()
+
+ function Example() {
+ let [value, setValue] = useState('home-delivery')
+ return (
+
+ )
+ }
+
+ render()
+
+ // Open combobox
+ await click(getComboboxButton())
+
+ // Submit the form
+ await click(getByText('Submit'))
+
+ // Verify that the form has been submitted
+ expect(submits).toHaveBeenLastCalledWith([
+ ['foo', 'bar'], // The only available field
+ ])
+ })
+
it('should be possible to submit a form with a complex value object', async () => {
let submits = jest.fn()
let options = [
diff --git a/packages/@headlessui-react/src/components/combobox/combobox.tsx b/packages/@headlessui-react/src/components/combobox/combobox.tsx
index 8bfd8a7..7971322 100644
--- a/packages/@headlessui-react/src/components/combobox/combobox.tsx
+++ b/packages/@headlessui-react/src/components/combobox/combobox.tsx
@@ -907,6 +907,7 @@ function ComboboxFn
{name != null && (
{
expect(submits).toHaveBeenLastCalledWith([['delivery', 'pickup']])
})
+ it('should not submit the data if the Listbox is disabled', async () => {
+ let submits = jest.fn()
+
+ function Example() {
+ let [value, setValue] = useState('home-delivery')
+ return (
+
+ )
+ }
+
+ render()
+
+ // Open listbox
+ await click(getListboxButton())
+
+ // Submit the form
+ await click(getByText('Submit'))
+
+ // Verify that the form has been submitted
+ expect(submits).toHaveBeenLastCalledWith([
+ ['foo', 'bar'], // The only available field
+ ])
+ })
+
it('should be possible to submit a form with a complex value object', async () => {
let submits = jest.fn()
let options = [
diff --git a/packages/@headlessui-react/src/components/listbox/listbox.tsx b/packages/@headlessui-react/src/components/listbox/listbox.tsx
index 63f26e3..129dd74 100644
--- a/packages/@headlessui-react/src/components/listbox/listbox.tsx
+++ b/packages/@headlessui-react/src/components/listbox/listbox.tsx
@@ -670,7 +670,12 @@ function ListboxFn<
})}
>
{name != null && value != null && (
-
+
)}
{render({
ourProps,
diff --git a/packages/@headlessui-react/src/components/radio-group/radio-group.test.tsx b/packages/@headlessui-react/src/components/radio-group/radio-group.test.tsx
index 85f0fd4..436b2e3 100644
--- a/packages/@headlessui-react/src/components/radio-group/radio-group.test.tsx
+++ b/packages/@headlessui-react/src/components/radio-group/radio-group.test.tsx
@@ -1539,6 +1539,41 @@ describe('Form compatibility', () => {
})
)
+ it('should not submit the data if the RadioGroup is disabled', async () => {
+ let submits = jest.fn()
+
+ function Example() {
+ let [value, setValue] = useState('home-delivery')
+ return (
+
+ )
+ }
+
+ render()
+
+ // Submit the form
+ await click(getByText('Submit'))
+
+ // Verify that the form has been submitted
+ expect(submits).toHaveBeenLastCalledWith([
+ ['foo', 'bar'], // The only available field
+ ])
+ })
+
it(
'should be possible to submit a form with a complex value object',
suppressConsoleLogs(async () => {
diff --git a/packages/@headlessui-react/src/components/radio-group/radio-group.tsx b/packages/@headlessui-react/src/components/radio-group/radio-group.tsx
index 2ab3a7a..2fabaa2 100644
--- a/packages/@headlessui-react/src/components/radio-group/radio-group.tsx
+++ b/packages/@headlessui-react/src/components/radio-group/radio-group.tsx
@@ -314,6 +314,7 @@ function RadioGroupFn
{name != null && (
{
// Verify that the form has been submitted
expect(submits).toHaveBeenLastCalledWith([['fruit', 'apple']])
})
+
+ it('should not submit the data if the Switch is disabled', async () => {
+ let submits = jest.fn()
+
+ function Example() {
+ let [state, setState] = useState(true)
+ return (
+
+ )
+ }
+
+ render()
+
+ // Submit the form
+ await click(getByText('Submit'))
+
+ // Verify that the form has been submitted
+ expect(submits).toHaveBeenLastCalledWith([
+ ['foo', 'bar'], // The only available field
+ ])
+ })
})
diff --git a/packages/@headlessui-react/src/components/switch/switch.tsx b/packages/@headlessui-react/src/components/switch/switch.tsx
index 76a4ab8..eedf7a9 100644
--- a/packages/@headlessui-react/src/components/switch/switch.tsx
+++ b/packages/@headlessui-react/src/components/switch/switch.tsx
@@ -237,7 +237,12 @@ function SwitchFn(
return (
<>
{name != null && (
-
+
)}
{render({ ourProps, theirProps, slot, defaultTag: DEFAULT_SWITCH_TAG, name: 'Switch' })}
>
diff --git a/packages/@headlessui-react/src/internal/form-fields.tsx b/packages/@headlessui-react/src/internal/form-fields.tsx
index 3592c57..ab94d98 100644
--- a/packages/@headlessui-react/src/internal/form-fields.tsx
+++ b/packages/@headlessui-react/src/internal/form-fields.tsx
@@ -31,10 +31,12 @@ export function HoistFormFields({ children }: React.PropsWithChildren<{}>) {
export function FormFields({
data,
form: formId,
+ disabled,
onReset,
}: {
data: Record
form?: string
+ disabled?: boolean
onReset?: (e: Event) => void
}) {
let [form, setForm] = useState(null)
@@ -61,6 +63,7 @@ export function FormFields({
hidden: true,
readOnly: true,
form: formId,
+ disabled,
name,
value,
})}
diff --git a/packages/@headlessui-react/src/test-utils/scenarios.tsx b/packages/@headlessui-react/src/test-utils/scenarios.tsx
index 31ee14f..c576a43 100644
--- a/packages/@headlessui-react/src/test-utils/scenarios.tsx
+++ b/packages/@headlessui-react/src/test-utils/scenarios.tsx
@@ -202,6 +202,35 @@ export function commonFormScenarios(
expect(formDataMock.mock.calls[0][0].has('foo')).toBe(true)
})
+ it('should not submit the data if the control is disabled', async () => {
+ let submits = jest.fn()
+
+ function Example() {
+ return (
+
+ )
+ }
+
+ render()
+
+ // Submit the form
+ await click(screen.getByText('Submit'))
+
+ // Verify that the form has been submitted
+ expect(submits).toHaveBeenLastCalledWith([
+ ['foo', 'bar'], // The only available field
+ ])
+ })
+
it(
'should reset the control when the form is reset',
suppressConsoleLogs(async () => {
diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md
index 25b14de..044bbd1 100644
--- a/packages/@headlessui-vue/CHANGELOG.md
+++ b/packages/@headlessui-vue/CHANGELOG.md
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Don’t override explicit `disabled` prop for components inside `