Skip to content

Commit 53af7fa

Browse files
authored
Move hold prop to the Combobox Options (#1109)
* move `hold` prop to the `Combobox Options` * update changelog
1 parent 0bf325d commit 53af7fa

File tree

5 files changed

+32
-27
lines changed

5 files changed

+32
-27
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818

1919
### Added
2020

21-
- Add `Combobox` component ([#1047](https://github.com/tailwindlabs/headlessui/pull/1047), [#1099](https://github.com/tailwindlabs/headlessui/pull/1099), [#1101](https://github.com/tailwindlabs/headlessui/pull/1101), [#1104](https://github.com/tailwindlabs/headlessui/pull/1104))
21+
- Add `Combobox` component ([#1047](https://github.com/tailwindlabs/headlessui/pull/1047), [#1099](https://github.com/tailwindlabs/headlessui/pull/1099), [#1101](https://github.com/tailwindlabs/headlessui/pull/1101), [#1104](https://github.com/tailwindlabs/headlessui/pull/1104), [#1109](https://github.com/tailwindlabs/headlessui/pull/1109))
2222

2323
## [Unreleased - @headlessui/vue]
2424

@@ -32,7 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3232

3333
### Added
3434

35-
- Add `Combobox` component ([#1047](https://github.com/tailwindlabs/headlessui/pull/1047), [#1099](https://github.com/tailwindlabs/headlessui/pull/1099), [#1101](https://github.com/tailwindlabs/headlessui/pull/1101), [#1104](https://github.com/tailwindlabs/headlessui/pull/1104), [#1106](https://github.com/tailwindlabs/headlessui/pull/1106))
35+
- Add `Combobox` component ([#1047](https://github.com/tailwindlabs/headlessui/pull/1047), [#1099](https://github.com/tailwindlabs/headlessui/pull/1099), [#1101](https://github.com/tailwindlabs/headlessui/pull/1101), [#1104](https://github.com/tailwindlabs/headlessui/pull/1104), [#1106](https://github.com/tailwindlabs/headlessui/pull/1106), [#1109](https://github.com/tailwindlabs/headlessui/pull/1109))
3636

3737
## [@headlessui/react@v1.4.3] - 2022-01-14
3838

packages/@headlessui-react/src/components/combobox/combobox.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4269,10 +4269,10 @@ describe('Mouse interactions', () => {
42694269
'should be possible to hold the last active option',
42704270
suppressConsoleLogs(async () => {
42714271
render(
4272-
<Combobox value="test" onChange={console.log} hold>
4272+
<Combobox value="test" onChange={console.log}>
42734273
<Combobox.Input onChange={NOOP} />
42744274
<Combobox.Button>Trigger</Combobox.Button>
4275-
<Combobox.Options>
4275+
<Combobox.Options hold>
42764276
<Combobox.Option value="a">Option A</Combobox.Option>
42774277
<Combobox.Option value="b">Option B</Combobox.Option>
42784278
<Combobox.Option value="c">Option C</Combobox.Option>

packages/@headlessui-react/src/components/combobox/combobox.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ interface StateDefinition {
5353
comboboxPropsRef: MutableRefObject<{
5454
value: unknown
5555
onChange(value: unknown): void
56-
hold: boolean
5756
}>
5857
inputPropsRef: MutableRefObject<{
5958
displayValue?(item: unknown): string
6059
}>
6160
optionsPropsRef: MutableRefObject<{
6261
static: boolean
62+
hold: boolean
6363
}>
6464
labelRef: MutableRefObject<HTMLLabelElement | null>
6565
inputRef: MutableRefObject<HTMLInputElement | null>
@@ -230,22 +230,23 @@ let ComboboxRoot = forwardRefWithAs(function Combobox<
230230
TTag extends ElementType = typeof DEFAULT_COMBOBOX_TAG,
231231
TType = string
232232
>(
233-
props: Props<TTag, ComboboxRenderPropArg<TType>, 'value' | 'onChange' | 'disabled' | 'hold'> & {
233+
props: Props<TTag, ComboboxRenderPropArg<TType>, 'value' | 'onChange' | 'disabled'> & {
234234
value: TType
235235
onChange(value: TType): void
236236
disabled?: boolean
237-
hold?: boolean
238237
},
239238
ref: Ref<TTag>
240239
) {
241-
let { value, onChange, disabled = false, hold = false, ...passThroughProps } = props
240+
let { value, onChange, disabled = false, ...passThroughProps } = props
242241

243242
let comboboxPropsRef = useRef<StateDefinition['comboboxPropsRef']['current']>({
244243
value,
245244
onChange,
246-
hold,
247245
})
248-
let optionsPropsRef = useRef<StateDefinition['optionsPropsRef']['current']>({ static: false })
246+
let optionsPropsRef = useRef<StateDefinition['optionsPropsRef']['current']>({
247+
static: false,
248+
hold: false,
249+
})
249250
let inputPropsRef = useRef<StateDefinition['inputPropsRef']['current']>({
250251
displayValue: undefined,
251252
})
@@ -272,9 +273,6 @@ let ComboboxRoot = forwardRefWithAs(function Combobox<
272273
useIsoMorphicEffect(() => {
273274
comboboxPropsRef.current.onChange = onChange
274275
}, [onChange, comboboxPropsRef])
275-
useIsoMorphicEffect(() => {
276-
comboboxPropsRef.current.hold = hold
277-
}, [hold, comboboxPropsRef])
278276

279277
useIsoMorphicEffect(() => dispatch({ type: ActionTypes.SetDisabled, disabled }), [disabled])
280278

@@ -710,6 +708,7 @@ interface OptionsRenderPropArg {
710708
type OptionsPropsWeControl =
711709
| 'aria-activedescendant'
712710
| 'aria-labelledby'
711+
| 'hold'
713712
| 'id'
714713
| 'onKeyDown'
715714
| 'role'
@@ -721,9 +720,12 @@ let Options = forwardRefWithAs(function Options<
721720
TTag extends ElementType = typeof DEFAULT_OPTIONS_TAG
722721
>(
723722
props: Props<TTag, OptionsRenderPropArg, OptionsPropsWeControl> &
724-
PropsForFeatures<typeof OptionsRenderFeatures>,
723+
PropsForFeatures<typeof OptionsRenderFeatures> & {
724+
hold?: boolean
725+
},
725726
ref: Ref<HTMLUListElement>
726727
) {
728+
let { hold = false, ...passthroughProps } = props
727729
let [state] = useComboboxContext('Combobox.Options')
728730
let { optionsPropsRef } = state
729731

@@ -743,6 +745,9 @@ let Options = forwardRefWithAs(function Options<
743745
useIsoMorphicEffect(() => {
744746
optionsPropsRef.current.static = props.static ?? false
745747
}, [optionsPropsRef, props.static])
748+
useIsoMorphicEffect(() => {
749+
optionsPropsRef.current.hold = hold
750+
}, [hold, optionsPropsRef])
746751

747752
useTreeWalker({
748753
container: state.optionsRef.current,
@@ -774,7 +779,6 @@ let Options = forwardRefWithAs(function Options<
774779
id,
775780
ref: optionsRef,
776781
}
777-
let passthroughProps = props
778782

779783
return render({
780784
props: { ...passthroughProps, ...propsWeControl },
@@ -880,7 +884,7 @@ function Option<
880884
let handleLeave = useCallback(() => {
881885
if (disabled) return
882886
if (!active) return
883-
if (state.comboboxPropsRef.current.hold) return
887+
if (state.optionsPropsRef.current.hold) return
884888
dispatch({ type: ActionTypes.GoToOption, focus: Focus.Nothing })
885889
}, [disabled, active, dispatch, state.comboboxState, state.comboboxPropsRef])
886890

packages/@headlessui-vue/src/components/combobox/combobox.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4491,10 +4491,10 @@ describe('Mouse interactions', () => {
44914491
suppressConsoleLogs(async () => {
44924492
renderTemplate({
44934493
template: html`
4494-
<Combobox v-model="value" hold>
4494+
<Combobox v-model="value">
44954495
<ComboboxInput />
44964496
<ComboboxButton>Trigger</ComboboxButton>
4497-
<ComboboxOptions>
4497+
<ComboboxOptions hold>
44984498
<ComboboxOption value="a">Option A</ComboboxOption>
44994499
<ComboboxOption value="b">Option B</ComboboxOption>
45004500
<ComboboxOption value="c">Option C</ComboboxOption>

packages/@headlessui-vue/src/components/combobox/combobox.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,9 @@ type StateDefinition = {
3737
// State
3838
comboboxState: Ref<ComboboxStates>
3939
value: ComputedRef<unknown>
40-
hold: ComputedRef<Boolean>
4140

4241
inputPropsRef: Ref<{ displayValue?: (item: unknown) => string }>
43-
optionsPropsRef: Ref<{ static: boolean }>
42+
optionsPropsRef: Ref<{ static: boolean; hold: boolean }>
4443

4544
labelRef: Ref<HTMLLabelElement | null>
4645
inputRef: Ref<HTMLInputElement | null>
@@ -85,7 +84,6 @@ export let Combobox = defineComponent({
8584
as: { type: [Object, String], default: 'template' },
8685
disabled: { type: [Boolean], default: false },
8786
modelValue: { type: [Object, String, Number, Boolean] },
88-
hold: { type: [Boolean], default: false },
8987
},
9088
setup(props, { slots, attrs, emit }) {
9189
let comboboxState = ref<StateDefinition['comboboxState']['value']>(ComboboxStates.Closed)
@@ -97,17 +95,16 @@ export let Combobox = defineComponent({
9795
) as StateDefinition['optionsRef']
9896
let optionsPropsRef = ref<StateDefinition['optionsPropsRef']['value']>({
9997
static: false,
98+
hold: false,
10099
}) as StateDefinition['optionsPropsRef']
101100
let options = ref<StateDefinition['options']['value']>([])
102101
let activeOptionIndex = ref<StateDefinition['activeOptionIndex']['value']>(null)
103102

104103
let value = computed(() => props.modelValue)
105-
let hold = computed(() => props.hold)
106104

107105
let api = {
108106
comboboxState,
109107
value,
110-
hold,
111108
inputRef,
112109
labelRef,
113110
buttonRef,
@@ -260,7 +257,7 @@ export let Combobox = defineComponent({
260257
}
261258

262259
return render({
263-
props: omit(props, ['modelValue', 'onUpdate:modelValue', 'disabled', 'hold']),
260+
props: omit(props, ['modelValue', 'onUpdate:modelValue', 'disabled']),
264261
slot,
265262
slots,
266263
attrs,
@@ -545,12 +542,16 @@ export let ComboboxOptions = defineComponent({
545542
as: { type: [Object, String], default: 'ul' },
546543
static: { type: Boolean, default: false },
547544
unmount: { type: Boolean, default: true },
545+
hold: { type: [Boolean], default: false },
548546
},
549547
setup(props, { attrs, slots }) {
550548
let api = useComboboxContext('ComboboxOptions')
551549
let id = `headlessui-combobox-options-${useId()}`
552550
watchEffect(() => {
553-
api.optionsPropsRef.value.static = props.static ?? false
551+
api.optionsPropsRef.value.static = props.static
552+
})
553+
watchEffect(() => {
554+
api.optionsPropsRef.value.hold = props.hold
554555
})
555556
let usesOpenClosedState = useOpenClosed()
556557
let visible = computed(() => {
@@ -586,7 +587,7 @@ export let ComboboxOptions = defineComponent({
586587
ref: api.optionsRef,
587588
role: 'listbox',
588589
}
589-
let passThroughProps = props
590+
let passThroughProps = omit(props, ['hold'])
590591

591592
return render({
592593
props: { ...passThroughProps, ...propsWeControl },
@@ -667,7 +668,7 @@ export let ComboboxOption = defineComponent({
667668
function handleLeave() {
668669
if (props.disabled) return
669670
if (!active.value) return
670-
if (api.hold.value) return
671+
if (api.optionsPropsRef.value.hold) return
671672
api.goToOption(Focus.Nothing)
672673
}
673674

0 commit comments

Comments
 (0)