Combobox: Add description support (#98593)

* Support multiple sizes

* Add support for multi

* add a longer description to test clipping

---------

Co-authored-by: joshhunt <josh@trtr.co>
This commit is contained in:
Tobias Skarhed 2025-01-07 14:59:58 +01:00 committed by GitHub
parent f9c2a5fae9
commit 976cfcbf4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 24 additions and 9 deletions

View File

@ -30,8 +30,17 @@ const meta: Meta<PropsAndCustomArgs> = {
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<PropsAndCustomArgs> = {
{ 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',

View File

@ -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 = <T extends string | number>(props: ComboboxProps<T>) =>
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,
};

View File

@ -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 = <T extends string | number>(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,
};

View File

@ -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,