diff --git a/packages/grafana-ui/src/components/Combobox/Combobox.tsx b/packages/grafana-ui/src/components/Combobox/Combobox.tsx index 04b0e076fe1..148c9e61cd3 100644 --- a/packages/grafana-ui/src/components/Combobox/Combobox.tsx +++ b/packages/grafana-ui/src/components/Combobox/Combobox.tsx @@ -5,6 +5,7 @@ import { debounce } from 'lodash'; import { ReactNode, useCallback, useId, useMemo, useState } from 'react'; import { useStyles2 } from '../../themes'; +import { logOptions } from '../../utils'; import { t, Trans } from '../../utils/i18n'; import { Icon } from '../Icon/Icon'; import { AutoSizeInput } from '../Input/AutoSizeInput'; @@ -48,6 +49,8 @@ interface ComboboxBaseProps width?: number | 'auto'; } +const RECOMMENDED_ITEMS_AMOUNT = 100_000; + type AutoSizeConditionals = | { width: 'auto'; @@ -123,7 +126,7 @@ export const Combobox = (props: ComboboxProps) => const setItems = useCallback( (items: Array>, inputValue: string | undefined) => { let itemsToSet = items; - + logOptions(itemsToSet.length, RECOMMENDED_ITEMS_AMOUNT, id, ariaLabelledBy); if (inputValue && createCustomValue) { const optionMatchingInput = items.find( (opt) => opt.label === 'Custom value: ' + inputValue || opt.value === inputValue @@ -146,7 +149,7 @@ export const Combobox = (props: ComboboxProps) => baseSetItems(itemsToSet); }, - [createCustomValue] + [createCustomValue, id, ariaLabelledBy] ); const selectedItemIndex = useMemo(() => { diff --git a/packages/grafana-ui/src/utils/index.ts b/packages/grafana-ui/src/utils/index.ts index be52f2352c0..20d5a6c3cff 100644 --- a/packages/grafana-ui/src/utils/index.ts +++ b/packages/grafana-ui/src/utils/index.ts @@ -18,5 +18,6 @@ export { createLogger } from './logger'; export { attachDebugger } from './debug'; export * from './nodeGraph'; export { fuzzyMatch } from './fuzzy'; +export { logOptions } from './logOptions'; export { ReactUtils }; diff --git a/packages/grafana-ui/src/utils/logOptions.test.ts b/packages/grafana-ui/src/utils/logOptions.test.ts new file mode 100644 index 00000000000..06e2ff8acc4 --- /dev/null +++ b/packages/grafana-ui/src/utils/logOptions.test.ts @@ -0,0 +1,30 @@ +import { logOptions } from './logOptions'; + +const RECOMMENDED_AMOUNT = 10; + +describe('logOptions', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should not log anything if amount is less than or equal to recommendedAmount', () => { + console.warn = jest.fn(); + + logOptions(5, RECOMMENDED_AMOUNT, 'test-id', 'test-aria'); + + expect(console.warn).not.toHaveBeenCalled(); + }); + + it('should log a warning if amount exceeds recommendedAmount', () => { + console.warn = jest.fn(); + + logOptions(15, RECOMMENDED_AMOUNT, 'test-id', 'test-aria'); + + expect(console.warn).toHaveBeenCalledWith('[Combobox] Items exceed the recommended amount 10.', { + itemsCount: '15', + recommendedAmount: '10', + 'aria-labelledby': 'test-aria', + id: 'test-id', + }); + }); +}); diff --git a/packages/grafana-ui/src/utils/logOptions.ts b/packages/grafana-ui/src/utils/logOptions.ts new file mode 100644 index 00000000000..b1a749c22a3 --- /dev/null +++ b/packages/grafana-ui/src/utils/logOptions.ts @@ -0,0 +1,23 @@ +/** + * This function logs a warning if the amount of items exceeds the recommended amount. + * + * @param amount + * @param id + * @param ariaLabelledBy + */ +export function logOptions( + amount: number, + recommendedAmount: number, + id: string | undefined, + ariaLabelledBy: string | undefined +): void { + if (amount > recommendedAmount) { + const msg = `[Combobox] Items exceed the recommended amount ${recommendedAmount}.`; + console.warn(msg, { + itemsCount: '' + amount, + recommendedAmount: '' + recommendedAmount, + 'aria-labelledby': ariaLabelledBy ?? '', + id: id ?? '', + }); + } +}