Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiComboBox] add support for option tooltips #7700

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
34153a7
feat(EuiToolTip): add controlled isOpen support
mgadewoll Apr 18, 2024
63721a9
feat(EuiComboBox): add EuiToolTip support on option
mgadewoll Apr 18, 2024
0734902
test(EuiComboBox): add tests for toolTipContent and toolTipProps
mgadewoll Apr 18, 2024
5813c35
fix(EuiComboBox): fix isLoading layout for mobile
mgadewoll Apr 18, 2024
c3e19f8
docs(storybook): add separate tooltip story for ComboBox
mgadewoll Apr 18, 2024
7615fa1
test(EuiComboBox): update input options placement
mgadewoll Apr 18, 2024
ad0a3c5
refactor(EuiComboBox): prevent tooltip props from being applied on input
mgadewoll Apr 18, 2024
3c66b43
docs(EuiComboBox): add EuiDocs example
mgadewoll Apr 18, 2024
7b5236c
chore: add changelog
mgadewoll Apr 18, 2024
664dc88
refactor: revert adding isOpen on EuiToolTip and use ref API for show…
mgadewoll May 2, 2024
ffc84a9
refactor: use remove tooltip wrapper in favor of using anchorProps fo…
mgadewoll May 2, 2024
90197c5
chore: add PR feedback
mgadewoll May 2, 2024
fee66ff
docs: update EuiComboBox tooltip docs example
mgadewoll May 2, 2024
67a9db7
chore: cleanup wrongly removed type check
mgadewoll May 2, 2024
b8ebf61
chore: add comment
mgadewoll May 2, 2024
7e48f0a
Fix Firefox behavior by checking for `scrollTarget.contains`
cee-chen May 2, 2024
aa016c1
Update/add Cypress tests
cee-chen May 2, 2024
dbd8866
test(VRT): add base snapshots for EuiComboBox
mgadewoll May 3, 2024
8c1b693
feat: Add `optionMatcher` prop to `EuiSelectable` and `EuiComboBox` c…
tkajtoch Apr 29, 2024
c50b604
docs(storybook): add separate tooltip story for ComboBox
mgadewoll Apr 18, 2024
9929c3e
chore: cleanup
mgadewoll May 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions changelogs/upcoming/7700.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- Updated `EuiComboBox`'s `options` to support including tooltip details for selectable options. Use `toolTipContent` to render tooltip information, and `toolTipProps` to optionally customize the tooltip rendering behavior

**Bug fixes**

- Fixed a visual layout bug for `EuiComboBox` with `isLoading` in mobile views

1 change: 1 addition & 0 deletions changelogs/upcoming/7709.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Added a new, optional `optionMatcher` prop to `EuiSelectable` and `EuiComboBox` allowing passing a custom option matcher function to these components and controlling option filtering for given search string
39 changes: 39 additions & 0 deletions src-docs/src/views/combo_box/combo_box_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,26 @@ const renderOptionSnippet = `<EuiComboBox
renderOption={renderOption}
/>`;

import ToolTips from './tool_tips';
const toolTipsSource = require('!!raw-loader!./tool_tips');
const toolTipsSnippet = `<EuiComboBox
aria-label="Accessible screen reader label"
placeholder="Select or create options"
options={[
{
label: 'option 1',
tooltipContent: 'tooltip 1',
tooltipProps: {
position: 'bottom'
'data-test-subj': 'optionTooltip',
}
}
]}
onChange={onChange}
onCreateOption={onCreateOption}
isClearable={true}
/>`;

import Truncation from './truncation';
const truncationSource = require('!!raw-loader!./truncation');
const truncationSnippet = `<EuiComboBox
Expand Down Expand Up @@ -472,6 +492,25 @@ export const ComboBoxExample = {
},
],
},
{
title: 'Tooltips',
source: [
{
type: GuideSectionTypes.JS,
mgadewoll marked this conversation as resolved.
Show resolved Hide resolved
code: toolTipsSource,
},
],
text: (
<p>
You can add tooltips to the options by passing{' '}
<EuiCode>toolTipContent</EuiCode>. Use <EuiCode>toolTipProps</EuiCode>{' '}
to pass additional <EuiCode>EuiToolTipProps</EuiCode> to the tooltip.
</p>
),
props: { EuiComboBox, EuiComboBoxOptionOption },
snippet: toolTipsSnippet,
demo: <ToolTips />,
},
{
title: 'Truncation',
source: [
Expand Down
43 changes: 43 additions & 0 deletions src-docs/src/views/combo_box/tool_tips.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { useState } from 'react';

import {
EuiComboBox,
EuiComboBoxOptionOption,
} from '../../../../src/components';

const options: Array<EuiComboBoxOptionOption<string>> = [
{
label: 'Titan',
toolTipContent:
'Titan is the largest moon of Saturn and the second-largest in the Solar System',
},
{
label: 'Pandora',
toolTipContent:
"Pandora is one of Saturn's moons, named for a Titaness of Greek mythology",
},
{
label: 'Iapetus',
toolTipContent: "Iapetus is the outermost of Saturn's large moons",
toolTipProps: { position: 'bottom' },
},
];
export default () => {
const [selectedOptions, setSelected] = useState([options[2]]);

const onChange = (
selectedOptions: Array<EuiComboBoxOptionOption<string>>
) => {
setSelected(selectedOptions);
};

return (
<EuiComboBox
aria-label="Example of combobox options with tooltips"
options={options}
selectedOptions={selectedOptions}
onChange={onChange}
isClearable={true}
/>
);
};
92 changes: 57 additions & 35 deletions src/components/combo_box/combo_box.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ import { EuiComboBox, EuiComboBoxProps } from './combo_box';
import { EuiComboBoxOptionMatcher } from './types';
import { EuiCode } from '../code';

const toolTipProps = {
toolTipContent: 'This is a tooltip!',
toolTipProps: { position: 'left' as const },
value: 4,
};

const options = [
{ label: 'Item 1' },
{ label: 'Item 2' },
{ label: 'Item 3' },
{ label: 'Item 4' },
{ label: 'Item 4', disabled: true },
{ label: 'Item 5' },
];

Expand Down Expand Up @@ -64,41 +70,19 @@ export default meta;
type Story = StoryObj<EuiComboBoxProps<{}>>;

export const Playground: Story = {
render: function Render({ singleSelection, onCreateOption, ...args }) {
const [selectedOptions, setSelectedOptions] = useState(
args.selectedOptions
);
const onChange: EuiComboBoxProps<{}>['onChange'] = (options, ...args) => {
setSelectedOptions(options);
action('onChange')(options, ...args);
};
const _onCreateOption: EuiComboBoxProps<{}>['onCreateOption'] = (
searchValue,
...args
) => {
const createdOption = { label: searchValue };
setSelectedOptions((prevState) =>
!prevState || singleSelection
? [createdOption]
: [...prevState, createdOption]
);
action('onCreateOption')(searchValue, ...args);
};
return (
<EuiComboBox
singleSelection={
// @ts-ignore Specific to Storybook control
singleSelection === 'asPlainText'
? { asPlainText: true }
: Boolean(singleSelection)
}
{...args}
selectedOptions={selectedOptions}
onChange={onChange}
onCreateOption={onCreateOption ? _onCreateOption : undefined}
/>
);
render: (args) => <StatefulComboBox {...args} />,
};

export const WithTooltip: Story = {
parameters: {
controls: {
include: ['fullWidth', 'options', 'selectedOptions'],
},
},
args: {
options: options.map((option) => ({ ...option, ...toolTipProps })),
},
render: (args) => <StatefulComboBox {...args} />,
};

export const CustomMatcher: Story = {
Expand Down Expand Up @@ -142,3 +126,41 @@ export const CustomMatcher: Story = {
);
},
};

const StatefulComboBox = ({
singleSelection,
onCreateOption,
...args
}: EuiComboBoxProps<{}>) => {
const [selectedOptions, setSelectedOptions] = useState(args.selectedOptions);
const onChange: EuiComboBoxProps<{}>['onChange'] = (options, ...args) => {
setSelectedOptions(options);
action('onChange')(options, ...args);
};
const _onCreateOption: EuiComboBoxProps<{}>['onCreateOption'] = (
searchValue,
...args
) => {
const createdOption = { label: searchValue };
setSelectedOptions((prevState) =>
!prevState || singleSelection
? [createdOption]
: [...prevState, createdOption]
);
action('onCreateOption')(searchValue, ...args);
};
return (
<EuiComboBox
singleSelection={
// @ts-ignore Specific to Storybook control
singleSelection === 'asPlainText'
? { asPlainText: true }
: Boolean(singleSelection)
}
{...args}
selectedOptions={selectedOptions}
onChange={onChange}
onCreateOption={onCreateOption ? _onCreateOption : undefined}
/>
);
};
Loading
Loading