diff --git a/packages/@headlessui-react/src/components/listbox/listbox.test.tsx b/packages/@headlessui-react/src/components/listbox/listbox.test.tsx
index 45feef66d..cd0b90b1e 100644
--- a/packages/@headlessui-react/src/components/listbox/listbox.test.tsx
+++ b/packages/@headlessui-react/src/components/listbox/listbox.test.tsx
@@ -456,6 +456,30 @@ describe('Rendering', () => {
})
)
})
+
+ it(
+ 'null should be a valid value for the Listbox',
+ suppressConsoleLogs(async () => {
+ render(
+
+ Trigger
+
+ Option A
+ Option B
+ Option C
+
+
+ )
+
+ assertListboxButton({ state: ListboxState.InvisibleUnmounted })
+ assertListbox({ state: ListboxState.InvisibleUnmounted })
+
+ await click(getListboxButton())
+
+ assertListboxButton({ state: ListboxState.Visible })
+ assertListbox({ state: ListboxState.Visible })
+ })
+ )
})
describe('Listbox.Label', () => {
diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md
index dae8f18c6..9f14ec1b9 100644
--- a/packages/@headlessui-vue/CHANGELOG.md
+++ b/packages/@headlessui-vue/CHANGELOG.md
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improve syncing of the `ComboboxInput` value ([#2042](https://github.com/tailwindlabs/headlessui/pull/2042))
- Fix crash when using `multiple` mode without `value` prop (uncontrolled) for `Listbox` and `Combobox` components ([#2058](https://github.com/tailwindlabs/headlessui/pull/2058))
- Allow passing in your own `id` prop ([#2060](https://github.com/tailwindlabs/headlessui/pull/2060))
+- Add `null` as a valid type for Listbox and Combobox in Vue ([#2064](https://github.com/tailwindlabs/headlessui/pull/2064))
## [1.7.4] - 2022-11-03
diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.ts b/packages/@headlessui-vue/src/components/combobox/combobox.ts
index 2e5b12f85..aac75d26a 100644
--- a/packages/@headlessui-vue/src/components/combobox/combobox.ts
+++ b/packages/@headlessui-vue/src/components/combobox/combobox.ts
@@ -118,7 +118,12 @@ export let Combobox = defineComponent({
as: { type: [Object, String], default: 'template' },
disabled: { type: [Boolean], default: false },
by: { type: [String, Function], default: () => defaultComparator },
- modelValue: { type: [Object, String, Number, Boolean], default: undefined },
+ modelValue: {
+ type: [Object, String, Number, Boolean] as PropType<
+ object | string | number | boolean | null
+ >,
+ default: undefined,
+ },
defaultValue: { type: [Object, String, Number, Boolean], default: undefined },
name: { type: String },
nullable: { type: Boolean, default: false },
diff --git a/packages/@headlessui-vue/src/components/listbox/listbox.test.tsx b/packages/@headlessui-vue/src/components/listbox/listbox.test.tsx
index 0a5360a96..def8f8691 100644
--- a/packages/@headlessui-vue/src/components/listbox/listbox.test.tsx
+++ b/packages/@headlessui-vue/src/components/listbox/listbox.test.tsx
@@ -495,6 +495,33 @@ describe('Rendering', () => {
})
)
})
+
+ it(
+ 'null should be a valid value for the Listbox',
+ suppressConsoleLogs(async () => {
+ renderTemplate({
+ template: html`
+
+ Trigger
+
+ alice
+ bob
+ charlie
+
+
+ `,
+ setup: () => ({ value: null }),
+ })
+
+ assertListboxButton({ state: ListboxState.InvisibleUnmounted })
+ assertListbox({ state: ListboxState.InvisibleUnmounted })
+
+ await click(getListboxButton())
+
+ assertListboxButton({ state: ListboxState.Visible })
+ assertListbox({ state: ListboxState.Visible })
+ })
+ )
})
describe('ListboxLabel', () => {
diff --git a/packages/@headlessui-vue/src/components/listbox/listbox.ts b/packages/@headlessui-vue/src/components/listbox/listbox.ts
index 30d1c828c..01b6dbc64 100644
--- a/packages/@headlessui-vue/src/components/listbox/listbox.ts
+++ b/packages/@headlessui-vue/src/components/listbox/listbox.ts
@@ -18,6 +18,7 @@ import {
InjectionKey,
Ref,
UnwrapNestedRefs,
+ PropType,
} from 'vue'
import { Features, render, omit, compact } from '../../utils/render'
@@ -119,7 +120,12 @@ export let Listbox = defineComponent({
disabled: { type: [Boolean], default: false },
by: { type: [String, Function], default: () => defaultComparator },
horizontal: { type: [Boolean], default: false },
- modelValue: { type: [Object, String, Number, Boolean], default: undefined },
+ modelValue: {
+ type: [Object, String, Number, Boolean] as PropType<
+ object | string | number | boolean | null
+ >,
+ default: undefined,
+ },
defaultValue: { type: [Object, String, Number, Boolean], default: undefined },
name: { type: String, optional: true },
multiple: { type: [Boolean], default: false },