diff --git a/packages/@headlessui-react/src/test-utils/interactions.ts b/packages/@headlessui-react/src/test-utils/interactions.ts
index 784d021..a742a94 100644
--- a/packages/@headlessui-react/src/test-utils/interactions.ts
+++ b/packages/@headlessui-react/src/test-utils/interactions.ts
@@ -234,6 +234,7 @@ export async function click(
) {
try {
if (element === null) return expect(element).not.toBe(null)
+ if (element.disabled) return
let options = { button }
diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md
index b9a8057..9df9b89 100644
--- a/packages/@headlessui-vue/CHANGELOG.md
+++ b/packages/@headlessui-vue/CHANGELOG.md
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix getting Vue dom elements ([#1610](https://github.com/tailwindlabs/headlessui/pull/1610))
- Ensure `CMD`+`Backspace` works in nullable mode for `Combobox` component ([#1617](https://github.com/tailwindlabs/headlessui/pull/1617))
+- Properly merge incoming props with own props ([#1651](https://github.com/tailwindlabs/headlessui/pull/1651))
## [1.6.5] - 2022-06-20
diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.test.ts b/packages/@headlessui-vue/src/components/combobox/combobox.test.ts
index 77c9eb3..fafa583 100644
--- a/packages/@headlessui-vue/src/components/combobox/combobox.test.ts
+++ b/packages/@headlessui-vue/src/components/combobox/combobox.test.ts
@@ -4832,7 +4832,7 @@ describe('Mouse interactions', () => {
Trigger
alice
- bob
+ bob
charlie
@@ -4849,7 +4849,7 @@ describe('Mouse interactions', () => {
// We should not be able to focus the first option
await focus(options[1])
- assertNoActiveComboboxOption()
+ assertNotActiveComboboxOption(options[1])
})
)
diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.ts b/packages/@headlessui-vue/src/components/combobox/combobox.ts
index 18d0bcd..df95ff8 100644
--- a/packages/@headlessui-vue/src/components/combobox/combobox.ts
+++ b/packages/@headlessui-vue/src/components/combobox/combobox.ts
@@ -439,7 +439,7 @@ export let Combobox = defineComponent({
)
return () => {
- let { name, modelValue, disabled, ...incomingProps } = props
+ let { name, modelValue, disabled, ...theirProps } = props
let slot = {
open: comboboxState.value === ComboboxStates.Open,
disabled,
@@ -466,10 +466,11 @@ export let Combobox = defineComponent({
)
: []),
render({
- props: {
+ theirProps: {
...attrs,
- ...omit(incomingProps, ['nullable', 'multiple', 'onUpdate:modelValue', 'by']),
+ ...omit(theirProps, ['nullable', 'multiple', 'onUpdate:modelValue', 'by']),
},
+ ourProps: {},
slot,
slots,
attrs,
@@ -500,9 +501,11 @@ export let ComboboxLabel = defineComponent({
}
let ourProps = { id, ref: api.labelRef, onClick: handleClick }
+ let theirProps = props
return render({
- props: { ...props, ...ourProps },
+ ourProps,
+ theirProps,
slot,
attrs,
slots,
@@ -601,9 +604,11 @@ export let ComboboxButton = defineComponent({
onKeydown: handleKeydown,
onClick: handleClick,
}
+ let theirProps = props
return render({
- props: { ...props, ...ourProps },
+ ourProps,
+ theirProps,
slot,
attrs,
slots,
@@ -755,10 +760,11 @@ export let ComboboxInput = defineComponent({
tabIndex: 0,
ref: api.inputRef,
}
- let incomingProps = omit(props, ['displayValue'])
+ let theirProps = omit(props, ['displayValue'])
return render({
- props: { ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps,
slot,
attrs,
slots,
@@ -827,10 +833,11 @@ export let ComboboxOptions = defineComponent({
ref: api.optionsRef,
role: 'listbox',
}
- let incomingProps = omit(props, ['hold'])
+ let theirProps = omit(props, ['hold'])
return render({
- props: { ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps,
slot,
attrs,
slots,
@@ -937,8 +944,11 @@ export let ComboboxOption = defineComponent({
onMouseleave: handleLeave,
}
+ let theirProps = props
+
return render({
- props: { ...props, ...ourProps },
+ ourProps,
+ theirProps,
slot,
attrs,
slots,
diff --git a/packages/@headlessui-vue/src/components/description/description.ts b/packages/@headlessui-vue/src/components/description/description.ts
index 65ab4d0..99f1dc7 100644
--- a/packages/@headlessui-vue/src/components/description/description.ts
+++ b/packages/@headlessui-vue/src/components/description/description.ts
@@ -78,7 +78,7 @@ export let Description = defineComponent({
return () => {
let { name = 'Description', slot = ref({}), props = {} } = context
- let incomingProps = myProps
+ let theirProps = myProps
let ourProps = {
...Object.entries(props).reduce(
(acc, [key, value]) => Object.assign(acc, { [key]: unref(value) }),
@@ -88,7 +88,8 @@ export let Description = defineComponent({
}
return render({
- props: { ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps,
slot: slot.value,
attrs,
slots,
diff --git a/packages/@headlessui-vue/src/components/dialog/dialog.ts b/packages/@headlessui-vue/src/components/dialog/dialog.ts
index 90181f6..76f82fe 100644
--- a/packages/@headlessui-vue/src/components/dialog/dialog.ts
+++ b/packages/@headlessui-vue/src/components/dialog/dialog.ts
@@ -280,7 +280,7 @@ export let Dialog = defineComponent({
'aria-labelledby': titleId.value,
'aria-describedby': describedby.value,
}
- let { open: _, initialFocus, ...incomingProps } = props
+ let { open: _, initialFocus, ...theirProps } = props
let slot = { open: dialogState.value === DialogStates.Open }
@@ -302,7 +302,8 @@ export let Dialog = defineComponent({
},
() =>
render({
- props: { ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps,
slot,
attrs,
slots,
@@ -344,10 +345,11 @@ export let DialogOverlay = defineComponent({
'aria-hidden': true,
onClick: handleClick,
}
- let incomingProps = props
+ let theirProps = props
return render({
- props: { ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps,
slot: { open: api.dialogState.value === DialogStates.Open },
attrs,
slots,
@@ -381,7 +383,7 @@ export let DialogBackdrop = defineComponent({
})
return () => {
- let incomingProps = props
+ let theirProps = props
let ourProps = {
id,
ref: internalBackdropRef,
@@ -391,7 +393,8 @@ export let DialogBackdrop = defineComponent({
return h(ForcePortalRoot, { force: true }, () =>
h(Portal, () =>
render({
- props: { ...attrs, ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps: { ...attrs, ...theirProps },
slot: { open: api.dialogState.value === DialogStates.Open },
attrs,
slots,
@@ -426,10 +429,11 @@ export let DialogPanel = defineComponent({
ref: api.panelRef,
onClick: handleClick,
}
- let incomingProps = props
+ let theirProps = props
return render({
- props: { ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps,
slot: { open: api.dialogState.value === DialogStates.Open },
attrs,
slots,
@@ -457,10 +461,11 @@ export let DialogTitle = defineComponent({
return () => {
let ourProps = { id }
- let incomingProps = props
+ let theirProps = props
return render({
- props: { ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps,
slot: { open: api.dialogState.value === DialogStates.Open },
attrs,
slots,
diff --git a/packages/@headlessui-vue/src/components/disclosure/disclosure.ts b/packages/@headlessui-vue/src/components/disclosure/disclosure.ts
index 46adf52..49f8a4d 100644
--- a/packages/@headlessui-vue/src/components/disclosure/disclosure.ts
+++ b/packages/@headlessui-vue/src/components/disclosure/disclosure.ts
@@ -118,9 +118,16 @@ export let Disclosure = defineComponent({
)
return () => {
- let { defaultOpen: _, ...incomingProps } = props
+ let { defaultOpen: _, ...theirProps } = props
let slot = { open: disclosureState.value === DisclosureStates.Open, close: api.close }
- return render({ props: incomingProps, slot, slots, attrs, name: 'Disclosure' })
+ return render({
+ theirProps,
+ ourProps: {},
+ slot,
+ slots,
+ attrs,
+ name: 'Disclosure',
+ })
}
},
})
@@ -223,7 +230,8 @@ export let DisclosureButton = defineComponent({
}
return render({
- props: { ...props, ...ourProps },
+ ourProps,
+ theirProps: props,
slot,
attrs,
slots,
@@ -263,7 +271,8 @@ export let DisclosurePanel = defineComponent({
let ourProps = { id: api.panelId, ref: api.panel }
return render({
- props: { ...props, ...ourProps },
+ ourProps,
+ theirProps: props,
slot,
attrs,
slots,
diff --git a/packages/@headlessui-vue/src/components/focus-trap/focus-trap.ts b/packages/@headlessui-vue/src/components/focus-trap/focus-trap.ts
index b488b4e..d9d5b34 100644
--- a/packages/@headlessui-vue/src/components/focus-trap/focus-trap.ts
+++ b/packages/@headlessui-vue/src/components/focus-trap/focus-trap.ts
@@ -103,7 +103,7 @@ export let FocusTrap = Object.assign(
return () => {
let slot = {}
let ourProps = { 'data-hi': 'container', ref: container }
- let { features, initialFocus, containers: _containers, ...incomingProps } = props
+ let { features, initialFocus, containers: _containers, ...theirProps } = props
return h(Fragment, [
Boolean(features & Features.TabLock) &&
@@ -114,7 +114,8 @@ export let FocusTrap = Object.assign(
features: HiddenFeatures.Focusable,
}),
render({
- props: { ...attrs, ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps: { ...attrs, ...theirProps },
slot,
attrs,
slots,
diff --git a/packages/@headlessui-vue/src/components/label/label.ts b/packages/@headlessui-vue/src/components/label/label.ts
index 623b75f..7edb1b9 100644
--- a/packages/@headlessui-vue/src/components/label/label.ts
+++ b/packages/@headlessui-vue/src/components/label/label.ts
@@ -77,7 +77,7 @@ export let Label = defineComponent({
return () => {
let { name = 'Label', slot = {}, props = {} } = context
- let { passive, ...incomingProps } = myProps
+ let { passive, ...theirProps } = myProps
let ourProps = {
...Object.entries(props).reduce(
(acc, [key, value]) => Object.assign(acc, { [key]: unref(value) }),
@@ -85,14 +85,19 @@ export let Label = defineComponent({
),
id,
}
- let allProps = { ...incomingProps, ...ourProps }
- // @ts-expect-error props are dynamic via context, some components will
- // provide an onClick then we can delete it.
- if (passive) delete allProps['onClick']
+ if (passive) {
+ // @ts-expect-error props are dynamic via context, some components will provide an onClick
+ // then we can delete it.
+ delete ourProps['onClick']
+ // @ts-expect-error props are dynamic via context, some components will provide an onClick
+ // then we can delete it.
+ delete theirProps['onClick']
+ }
return render({
- props: allProps,
+ ourProps,
+ theirProps,
slot,
attrs,
slots,
diff --git a/packages/@headlessui-vue/src/components/listbox/listbox.ts b/packages/@headlessui-vue/src/components/listbox/listbox.ts
index 5bd9062..4c08c10 100644
--- a/packages/@headlessui-vue/src/components/listbox/listbox.ts
+++ b/packages/@headlessui-vue/src/components/listbox/listbox.ts
@@ -323,7 +323,7 @@ export let Listbox = defineComponent({
)
return () => {
- let { name, modelValue, disabled, ...incomingProps } = props
+ let { name, modelValue, disabled, ...theirProps } = props
let slot = { open: listboxState.value === ListboxStates.Open, disabled }
@@ -346,9 +346,10 @@ export let Listbox = defineComponent({
)
: []),
render({
- props: {
+ ourProps: {},
+ theirProps: {
...attrs,
- ...omit(incomingProps, ['onUpdate:modelValue', 'horizontal', 'multiple', 'by']),
+ ...omit(theirProps, ['onUpdate:modelValue', 'horizontal', 'multiple', 'by']),
},
slot,
slots,
@@ -381,7 +382,8 @@ export let ListboxLabel = defineComponent({
let ourProps = { id, ref: api.labelRef, onClick: handleClick }
return render({
- props: { ...props, ...ourProps },
+ ourProps,
+ theirProps: props,
slot,
attrs,
slots,
@@ -480,7 +482,8 @@ export let ListboxButton = defineComponent({
}
return render({
- props: { ...props, ...ourProps },
+ ourProps,
+ theirProps: props,
slot,
attrs,
slots,
@@ -604,10 +607,11 @@ export let ListboxOptions = defineComponent({
tabIndex: 0,
ref: api.optionsRef,
}
- let incomingProps = props
+ let theirProps = props
return render({
- props: { ...incomingProps, ...ourProps },
+ ourProps,
+ theirProps,
slot,
attrs,
slots,
@@ -753,7 +757,8 @@ export let ListboxOption = defineComponent({
}
return render({
- props: { ...omit(props, ['value', 'disabled']), ...ourProps },
+ ourProps,
+ theirProps: omit(props, ['value', 'disabled']),
slot,
attrs,
slots,
diff --git a/packages/@headlessui-vue/src/components/menu/menu.test.tsx b/packages/@headlessui-vue/src/components/menu/menu.test.tsx
index 4ef874c..201fa2b 100644
--- a/packages/@headlessui-vue/src/components/menu/menu.test.tsx
+++ b/packages/@headlessui-vue/src/components/menu/menu.test.tsx
@@ -317,16 +317,16 @@ describe('Rendering', () => {
'',
'The current component is rendering a "template".',
'However we need to passthrough the following props:',
- ' - disabled',
- ' - ref',
- ' - id',
- ' - type',
- ' - aria-haspopup',
' - aria-controls',
' - aria-expanded',
+ ' - aria-haspopup',
+ ' - disabled',
+ ' - id',
+ ' - onClick',
' - onKeydown',
' - onKeyup',
- ' - onClick',
+ ' - ref',
+ ' - type',
'',
'You can apply a few solutions:',
' - Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".',
@@ -518,9 +518,9 @@ describe('Rendering', () => {
' - id',
' - onKeydown',
' - onKeyup',
+ ' - ref',
' - role',
' - tabIndex',
- ' - ref',
'',
'You can apply a few solutions:',
' - Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".',
@@ -680,18 +680,18 @@ describe('Rendering', () => {
'',
'The current component is rendering a "template".',
'However we need to passthrough the following props:',
+ ' - aria-disabled',
' - disabled',
' - id',
+ ' - onClick',
+ ' - onFocus',
+ ' - onMouseleave',
+ ' - onMousemove',
+ ' - onPointerleave',
+ ' - onPointermove',
' - ref',
' - role',
' - tabIndex',
- ' - aria-disabled',
- ' - onClick',
- ' - onFocus',
- ' - onPointermove',
- ' - onMousemove',
- ' - onPointerleave',
- ' - onMouseleave',
'',
'You can apply a few solutions:',
' - Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".',
@@ -3452,11 +3452,11 @@ describe('Mouse interactions', () => {