mirror of
https://github.com/grafana/grafana.git
synced 2026-02-03 20:49:50 -05:00
Combobox: Customize custom value description (#117291)
Combobox: Make custom value description customizable via prop Add a new optional `customValueDescription` prop to Combobox and MultiCombobox components that allows customizing the description text shown for custom values. The existing "Use custom value" translation remains as the default.
This commit is contained in:
parent
ec0104d1ed
commit
b980c80d0b
4 changed files with 33 additions and 5 deletions
|
|
@ -32,6 +32,11 @@ interface ComboboxStaticProps<T extends string | number>
|
|||
* Allows the user to set a value which is not in the list of options.
|
||||
*/
|
||||
createCustomValue?: boolean;
|
||||
/**
|
||||
* Custom description text for the "create custom value" option.
|
||||
* Defaults to "Use custom value".
|
||||
*/
|
||||
customValueDescription?: string;
|
||||
/**
|
||||
* Custom container for rendering the dropdown menu via Portal
|
||||
*/
|
||||
|
|
@ -133,6 +138,7 @@ export const Combobox = <T extends string | number>(props: ComboboxProps<T>) =>
|
|||
placeholder: placeholderProp,
|
||||
isClearable, // this should be default false, but TS can't infer the conditional type if you do
|
||||
createCustomValue = false,
|
||||
customValueDescription,
|
||||
id,
|
||||
width,
|
||||
minWidth,
|
||||
|
|
@ -158,7 +164,7 @@ export const Combobox = <T extends string | number>(props: ComboboxProps<T>) =>
|
|||
updateOptions,
|
||||
asyncLoading,
|
||||
asyncError,
|
||||
} = useOptions(props.options, createCustomValue);
|
||||
} = useOptions(props.options, createCustomValue, customValueDescription);
|
||||
const isAsync = typeof allOptions === 'function';
|
||||
|
||||
const selectedItemIndex = useMemo(() => {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export const MultiCombobox = <T extends string | number>(props: MultiComboboxPro
|
|||
maxWidth,
|
||||
isClearable,
|
||||
createCustomValue = false,
|
||||
customValueDescription,
|
||||
'aria-labelledby': ariaLabelledBy,
|
||||
'data-testid': dataTestId,
|
||||
portalContainer,
|
||||
|
|
@ -80,7 +81,7 @@ export const MultiCombobox = <T extends string | number>(props: MultiComboboxPro
|
|||
updateOptions,
|
||||
asyncLoading,
|
||||
asyncError,
|
||||
} = useOptions(props.options, createCustomValue);
|
||||
} = useOptions(props.options, createCustomValue, customValueDescription);
|
||||
const options = useMemo(() => {
|
||||
// Only add the 'All' option if there's more than 1 option
|
||||
const addAllOption = enableAllOption && baseOptions.length > 1;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,23 @@ describe('useOptions', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should use custom description when provided', () => {
|
||||
const options = [
|
||||
{ label: 'Apple', value: 'apple' },
|
||||
{ label: 'Carrot', value: 'carrot' },
|
||||
];
|
||||
const { result } = renderHook(() => useOptions(options, true, 'Create new item'));
|
||||
|
||||
act(() => {
|
||||
result.current.updateOptions('car');
|
||||
});
|
||||
|
||||
expect(result.current.options).toEqual([
|
||||
{ label: 'car', value: 'car', description: 'Create new item' },
|
||||
{ label: 'Carrot', value: 'carrot' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not add a custom value if it already exists', () => {
|
||||
const options = [
|
||||
{ label: 'Apple', value: 'apple' },
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@ export const DEBOUNCE_TIME_MS = 200;
|
|||
* - function to call when user types (to filter, or call async fn)
|
||||
* - loading and error states
|
||||
*/
|
||||
export function useOptions<T extends string | number>(rawOptions: AsyncOptions<T>, createCustomValue: boolean) {
|
||||
export function useOptions<T extends string | number>(
|
||||
rawOptions: AsyncOptions<T>,
|
||||
createCustomValue: boolean,
|
||||
customValueDescription?: string
|
||||
) {
|
||||
const isAsync = typeof rawOptions === 'function';
|
||||
|
||||
const loadOptions = useLatestAsyncCall(isAsync ? rawOptions : asyncNoop);
|
||||
|
|
@ -76,13 +80,13 @@ export function useOptions<T extends string | number>(rawOptions: AsyncOptions<T
|
|||
currentOptions.unshift({
|
||||
label: userTypedSearch,
|
||||
value: userTypedSearch as T,
|
||||
description: t('combobox.custom-value.description', 'Use custom value'),
|
||||
description: customValueDescription ?? t('combobox.custom-value.description', 'Use custom value'),
|
||||
});
|
||||
}
|
||||
}
|
||||
return currentOptions;
|
||||
},
|
||||
[createCustomValue, userTypedSearch]
|
||||
[createCustomValue, customValueDescription, userTypedSearch]
|
||||
);
|
||||
|
||||
const updateOptions = useCallback(
|
||||
|
|
|
|||
Loading…
Reference in a new issue