Skip to content

Commit

Permalink
add frozen state to Combobox component
Browse files Browse the repository at this point in the history
Once you choose an option, the `selected` state remains on the "old"
value until the combobox is fully closed. This way the potential visual
indicators such as a check mark doesn't move around while the Combobox
is closing (when using transitions)

Same as the `Listbox`, this is purely about visual state and exposed
data from the `ComboboxOptions` component and down that tree. The
top-level `Combobox` and `ComboboxInput` components still know the
correct (new) value and will update the `aria-activedescendant`
correctly.

This is achieved by storing the old data (only in single value mode),
and overriding the `isSelected` check function via context provided by
the `ComboboxOptions` component.
  • Loading branch information
RobinMalfait committed Apr 24, 2024
1 parent 4263180 commit 1fb72da
Showing 1 changed file with 28 additions and 10 deletions.
38 changes: 28 additions & 10 deletions packages/@headlessui-react/src/components/combobox/combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1646,17 +1646,35 @@ function OptionsFn<TTag extends ElementType = typeof DEFAULT_OPTIONS_TAG>(
})
}

// Frozen state, the selected value will only update visually when the user re-opens the <Combobox />
let [frozenValue, setFrozenValue] = useState(data.value)
if (
data.value !== frozenValue &&
data.comboboxState === ComboboxState.Open &&
data.mode !== ValueMode.Multi
) {
setFrozenValue(data.value)
}

let isSelected = useEvent((compareValue: unknown) => {
return data.compare(frozenValue, compareValue)
})

return (
<Portal enabled={visible && portal}>
{render({
ourProps,
theirProps,
slot,
defaultTag: DEFAULT_OPTIONS_TAG,
features: OptionsRenderFeatures,
visible,
name: 'Combobox.Options',
})}
<ComboboxDataContext.Provider
value={data.mode === ValueMode.Multi ? data : { ...data, isSelected }}
>
{render({
ourProps,
theirProps,
slot,
defaultTag: DEFAULT_OPTIONS_TAG,
features: OptionsRenderFeatures,
visible,
name: 'Combobox.Options',
})}
</ComboboxDataContext.Provider>
</Portal>
)
}
Expand Down Expand Up @@ -1796,7 +1814,7 @@ function OptionFn<
}

if (data.mode === ValueMode.Single) {
requestAnimationFrame(() => actions.closeCombobox())
actions.closeCombobox()
}
})

Expand Down

0 comments on commit 1fb72da

Please sign in to comment.