From 976cfcbf4f39df2f9aefb5be5cbb8a41102eb832 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:59:58 +0100 Subject: [PATCH] Combobox: Add description support (#98593) * Support multiple sizes * Add support for multi * add a longer description to test clipping --------- Co-authored-by: joshhunt --- .../components/Combobox/Combobox.story.tsx | 20 ++++++++++++++++--- .../src/components/Combobox/Combobox.tsx | 4 ++-- .../src/components/Combobox/MultiCombobox.tsx | 4 ++-- .../components/Combobox/getComboboxStyles.ts | 5 +++-- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/grafana-ui/src/components/Combobox/Combobox.story.tsx b/packages/grafana-ui/src/components/Combobox/Combobox.story.tsx index 53e1a2c0276..e6c239f5bc5 100644 --- a/packages/grafana-ui/src/components/Combobox/Combobox.story.tsx +++ b/packages/grafana-ui/src/components/Combobox/Combobox.story.tsx @@ -30,8 +30,17 @@ const meta: Meta = { isClearable: false, placeholder: 'Select an option...', options: [ - { label: 'Apple', value: 'apple' }, - { label: 'Banana', value: 'banana' }, + { + label: 'Apple', + value: 'apple', + description: 'Apples are a great source of fiber and vitamin C.', + }, + { + label: 'Banana', + value: 'banana', + description: + 'Bananas are a great source of potassium, fiber, and vitamin C. They are also a great snack for on the go.', + }, { label: 'Carrot', value: 'carrot' }, // Long label to test overflow { @@ -44,7 +53,12 @@ const meta: Meta = { { label: 'Fennel', value: 'fennel' }, { label: 'Grape', value: 'grape' }, { label: 'Honeydew', value: 'honeydew' }, - { label: 'Iceberg Lettuce', value: 'iceberg-lettuce' }, + { + label: 'Iceberg Lettuce', + value: 'iceberg-lettuce', + description: + 'this is a very long description that should be longer than the longest option label which should make it clip to only one line. It is a bit tough to estimate the width of the descriptions because the font size is smaller, but this should be enough.', + }, { label: 'Jackfruit', value: 'jackfruit' }, ], value: 'banana', diff --git a/packages/grafana-ui/src/components/Combobox/Combobox.tsx b/packages/grafana-ui/src/components/Combobox/Combobox.tsx index 4022e98a48e..6a338006b08 100644 --- a/packages/grafana-ui/src/components/Combobox/Combobox.tsx +++ b/packages/grafana-ui/src/components/Combobox/Combobox.tsx @@ -15,7 +15,7 @@ import { Stack } from '../Layout/Stack/Stack'; import { Portal } from '../Portal/Portal'; import { ScrollContainer } from '../ScrollContainer/ScrollContainer'; -import { getComboboxStyles, MENU_OPTION_HEIGHT } from './getComboboxStyles'; +import { getComboboxStyles, MENU_OPTION_HEIGHT, MENU_OPTION_HEIGHT_DESCRIPTION } from './getComboboxStyles'; import { useComboboxFloat } from './useComboboxFloat'; import { StaleResultError, useLatestAsyncCall } from './useLatestAsyncCall'; @@ -215,7 +215,7 @@ export const Combobox = (props: ComboboxProps) => const virtualizerOptions = { count: items.length, getScrollElement: () => scrollRef.current, - estimateSize: () => MENU_OPTION_HEIGHT, + estimateSize: (index: number) => (items[index].description ? MENU_OPTION_HEIGHT_DESCRIPTION : MENU_OPTION_HEIGHT), overscan: VIRTUAL_OVERSCAN_ITEMS, }; diff --git a/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx b/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx index e511ee0b032..0af00d221e2 100644 --- a/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx +++ b/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx @@ -22,7 +22,7 @@ import { } from './Combobox'; import { OptionListItem } from './OptionListItem'; import { ValuePill } from './ValuePill'; -import { getComboboxStyles, MENU_OPTION_HEIGHT } from './getComboboxStyles'; +import { getComboboxStyles, MENU_OPTION_HEIGHT, MENU_OPTION_HEIGHT_DESCRIPTION } from './getComboboxStyles'; import { getMultiComboboxStyles } from './getMultiComboboxStyles'; import { useComboboxFloat } from './useComboboxFloat'; import { useMeasureMulti } from './useMeasureMulti'; @@ -150,7 +150,7 @@ export const MultiCombobox = (props: MultiComboboxPro const virtualizerOptions = { count: items.length, getScrollElement: () => scrollRef.current, - estimateSize: () => MENU_OPTION_HEIGHT, + estimateSize: (index: number) => (items[index].description ? MENU_OPTION_HEIGHT_DESCRIPTION : MENU_OPTION_HEIGHT), overscan: VIRTUAL_OVERSCAN_ITEMS, }; diff --git a/packages/grafana-ui/src/components/Combobox/getComboboxStyles.ts b/packages/grafana-ui/src/components/Combobox/getComboboxStyles.ts index 665d24cea4f..a9c6d51c91c 100644 --- a/packages/grafana-ui/src/components/Combobox/getComboboxStyles.ts +++ b/packages/grafana-ui/src/components/Combobox/getComboboxStyles.ts @@ -11,6 +11,7 @@ export const MENU_ITEM_LINE_HEIGHT = 1.5; // Used with Downshift to get the height of each item export const MENU_OPTION_HEIGHT = MENU_ITEM_PADDING * 2 + MENU_ITEM_FONT_SIZE * MENU_ITEM_LINE_HEIGHT; +export const MENU_OPTION_HEIGHT_DESCRIPTION = MENU_OPTION_HEIGHT + MENU_ITEM_LINE_HEIGHT * MENU_ITEM_FONT_SIZE; export const POPOVER_MAX_HEIGHT = MENU_OPTION_HEIGHT * 8.5; export const getComboboxStyles = (theme: GrafanaTheme2) => { @@ -67,7 +68,7 @@ export const getComboboxStyles = (theme: GrafanaTheme2) => { }), optionDescription: css({ label: 'combobox-option-description', - fontWeight: 'normal', + fontWeight: theme.typography.fontWeightRegular, fontSize: theme.typography.bodySmall.fontSize, color: theme.colors.text.secondary, lineHeight: MENU_ITEM_LINE_HEIGHT, @@ -89,7 +90,7 @@ export const getComboboxStyles = (theme: GrafanaTheme2) => { borderRadius: theme.shape.radius.default, content: '" "', display: 'block', - height: MENU_OPTION_HEIGHT, + height: '100%', position: 'absolute', width: theme.spacing(0.5), left: 0,