Skip to content

Commit d127eee

Browse files
committed
feat: add a clear button to FilterPicker, Select, ComboBox * 3
1 parent 5e64940 commit d127eee

File tree

3 files changed

+37
-21
lines changed

3 files changed

+37
-21
lines changed

src/components/fields/ComboBox/ComboBox.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ const TriggerElement = tasty({
9595

9696
const ClearButton = tasty(Button, {
9797
icon: <CloseIcon />,
98+
type: 'neutral',
9899
styles: {
99100
height: '($size - 1x)',
100101
width: '($size - 1x)',
@@ -330,9 +331,11 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
330331

331332
// Clear function
332333
let clearValue = useEvent(() => {
334+
// Always clear input value in state so UI resets to placeholder
335+
state.setInputValue('');
336+
// Notify external input value only when custom value mode is enabled
333337
if (props.allowsCustomValue) {
334338
props.onInputChange?.('');
335-
state.setInputValue('');
336339
}
337340
props.onSelectionChange?.(null);
338341
state.setSelectedKey(null);
@@ -497,7 +500,6 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
497500
{showClearButton && (
498501
<ClearButton
499502
size={size}
500-
type={validationState === 'invalid' ? 'clear' : 'neutral'}
501503
theme={validationState === 'invalid' ? 'danger' : undefined}
502504
qa="ComboBoxClearButton"
503505
data-no-trigger={hideTrigger ? '' : undefined}

src/components/fields/FilterPicker/FilterPicker.tsx

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -581,25 +581,6 @@ export const FilterPicker = forwardRef(function FilterPicker<T extends object>(
581581
const selectedLabels = getSelectedLabels();
582582
const hasSelection = selectedLabels.length > 0;
583583

584-
// Clear button logic
585-
let showClearButton =
586-
isClearable && hasSelection && !isDisabled && !props.isReadOnly;
587-
588-
// Clear function
589-
let clearValue = useEvent(() => {
590-
if (selectionMode === 'multiple') {
591-
if (!isControlledMultiple) {
592-
setInternalSelectedKeys([]);
593-
}
594-
onSelectionChange?.([]);
595-
} else {
596-
if (!isControlledSingle) {
597-
setInternalSelectedKey(null);
598-
}
599-
onSelectionChange?.(null);
600-
}
601-
});
602-
603584
// Always keep the latest selection in a ref (with normalized keys) so that we can read it synchronously in the popover close effect.
604585
const latestSelectionRef = useRef<{
605586
single: string | null;
@@ -976,6 +957,33 @@ export const FilterPicker = forwardRef(function FilterPicker<T extends object>(
976957
setShouldUpdatePosition(!state.isOpen);
977958
}, [state.isOpen]);
978959

960+
// Clear button logic
961+
let showClearButton =
962+
isClearable && hasSelection && !isDisabled && !props.isReadOnly;
963+
964+
// Clear function
965+
let clearValue = useEvent(() => {
966+
if (selectionMode === 'multiple') {
967+
if (!isControlledMultiple) {
968+
setInternalSelectedKeys([]);
969+
}
970+
onSelectionChange?.([]);
971+
} else {
972+
if (!isControlledSingle) {
973+
setInternalSelectedKey(null);
974+
}
975+
onSelectionChange?.(null);
976+
}
977+
978+
if (state.isOpen) {
979+
state.close();
980+
}
981+
982+
triggerRef?.current?.focus?.();
983+
984+
return false;
985+
});
986+
979987
return (
980988
<ItemButton
981989
ref={triggerRef as any}

src/components/fields/Select/Select.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,12 @@ function Select<T extends object>(
355355
let clearValue = useEvent(() => {
356356
props.onSelectionChange?.(null);
357357
state.setSelectedKey(null);
358+
// Close the popup if it's open
359+
if (state.isOpen) {
360+
state.close();
361+
}
362+
// Return focus to the trigger for better UX
363+
triggerRef.current?.focus?.();
358364
});
359365

360366
let triggerWidth = triggerRef?.current?.offsetWidth;

0 commit comments

Comments
 (0)