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] Added option.prepend and option.append support #6953

Merged
merged 11 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
80 changes: 64 additions & 16 deletions src-docs/src/views/combo_box/combo_box_example.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Fragment } from 'react';
import React from 'react';

import { Link } from 'react-router-dom';

Expand Down Expand Up @@ -49,6 +49,27 @@ const colorsSnippet = `<EuiComboBox
isClearable={true}
/>`;

import OptionPrependAppend from './option_prepend_append';
const optionPrependAppendSource = require('!!raw-loader!./option_prepend_append');
const optionsPrependAppendSnippet = `<EuiComboBox
aria-label="Accessible screen reader label"
placeholder="Select or create options"
options={[
{
label: 'Titan',
prepend: <EuiIcon type="bell" size="s" />,
},
{
label: 'Mimas',
append: '(5)',
},
]}
selectedOptions={selectedOptions}
onChange={onChange}
onCreateOption={onCreateOption}
isClearable={true}
/>`;

import RenderOption from './render_option';
const renderOptionSource = require('!!raw-loader!./render_option');
const renderOptionSnippet = `<EuiComboBox
Expand Down Expand Up @@ -224,7 +245,7 @@ const labelledbySnippet = `<EuiComboBox
export const ComboBoxExample = {
title: 'Combo box',
intro: (
<Fragment>
<>
<EuiText>
<p>
Use a <strong>EuiComboBox</strong> when the input has so many options
Expand All @@ -248,7 +269,7 @@ export const ComboBoxExample = {
<EuiCode>aria-labelledby</EuiCode> prop.
</EuiCallOut>
</EuiText>
</Fragment>
</>
),
sections: [
{
Expand Down Expand Up @@ -364,33 +385,60 @@ export const ComboBoxExample = {
},
{
title: 'Option rendering',
text: (
<p>
There are two object properties you can add to enhance the content of
your options, <EuiCode>option.prepend</EuiCode> and{' '}
<EuiCode>option.append</EuiCode>. These will add nodes before and
after the option label respectively, to both the dropdown option and
selected pill. They will not be included in the searchable content as
this only matches against the label property.
</p>
),
props: { EuiComboBox, EuiComboBoxOptionOption },
snippet: optionsPrependAppendSnippet,
demo: <OptionPrependAppend />,
source: [
{
type: GuideSectionTypes.JS,
code: renderOptionSource,
code: optionPrependAppendSource,
},
],
},
{
text: (
<Fragment>
<>
<h3 id="renderOption">Custom dropdown content</h3>
<p>
While it is best to stick to the <EuiCode>option.label</EuiCode>,{' '}
<EuiCode>option.append</EuiCode>, and{' '}
<EuiCode>option.prepend</EuiCode> props, you can pass a custom{' '}
<EuiCode>renderOption</EuiCode> function which will pass back the
single option <EuiCode>option</EuiCode> and the{' '}
<EuiCode>searchValue</EuiCode> to use for highlighting.
</p>
<p>
You can provide a <EuiCode>renderOption</EuiCode> prop which will
accept <EuiCode>option</EuiCode> and <EuiCode>searchValue</EuiCode>{' '}
arguments. Use the <EuiCode>value</EuiCode> prop of the{' '}
You can use the <EuiCode>value</EuiCode> prop of the{' '}
<EuiCode>option</EuiCode> object to store metadata about the option
for use in this callback.
</p>

<p>
<strong>Note:</strong> virtualization (above) requires that each
option have the same height. Ensure that you render the options so
that wrapping text is truncated instead of causing the height of the
option to change.
</p>
</Fragment>
</>
),
props: { EuiComboBox, EuiComboBoxOptionOption },
snippet: renderOptionSnippet,
demo: <RenderOption />,
source: [
{
type: GuideSectionTypes.JS,
code: renderOptionSource,
},
],
},
{
title: 'Groups',
Expand Down Expand Up @@ -419,7 +467,7 @@ export const ComboBoxExample = {
},
],
text: (
<Fragment>
<>
<p>
To only allow the user to select a single option, provide the{' '}
<EuiCode>singleSelection</EuiCode> prop. You may want to render the
Expand All @@ -428,7 +476,7 @@ export const ComboBoxExample = {
{'singleSelection={{ asPlainText: true }}'}
</EuiCode>
</p>
</Fragment>
</>
),
props: { EuiComboBox, EuiComboBoxOptionOption },
snippet: singleSelectionSnippet,
Expand All @@ -443,7 +491,7 @@ export const ComboBoxExample = {
},
],
text: (
<Fragment>
<>
<p>
<EuiCode>append</EuiCode> and <EuiCode>prepend</EuiCode> props only
work if
Expand All @@ -452,7 +500,7 @@ export const ComboBoxExample = {
height greater than that of <EuiCode>append</EuiCode> and{' '}
<EuiCode>prepend</EuiCode>.
</p>
</Fragment>
</>
),
props: { EuiComboBox, EuiComboBoxOptionOption },
snippet: singleSelectionPrependSnippet,
Expand All @@ -467,7 +515,7 @@ export const ComboBoxExample = {
},
],
text: (
<Fragment>
<>
<p>
You can allow the user to select a single option and also allow the
creation of custom options. To do that, use the{' '}
Expand All @@ -480,7 +528,7 @@ export const ComboBoxExample = {
available. You can also customize the custom option text by passing
a text to <EuiCode>customOptionText</EuiCode> prop.
</p>
</Fragment>
</>
),
props: { EuiComboBox, EuiComboBoxOptionOption },
snippet: singleSelectionCustomOptionsSnippet,
Expand Down
76 changes: 76 additions & 0 deletions src-docs/src/views/combo_box/option_prepend_append.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState, useMemo } from 'react';

import {
EuiComboBox,
EuiIcon,
EuiSwitch,
EuiSpacer,
} from '../../../../src/components';

const options = [
{
label: 'Titan',
'data-test-subj': 'titanOption',
prepend: <EuiIcon size="s" type="bell" />,
},
{
label: 'Enceladus',
prepend: <EuiIcon size="s" type="bolt" />,
},
{
label: 'Mimas',
prepend: <EuiIcon size="s" type="bug" />,
},
{
label:
"Pandora is one of Saturn's moons, named for a Titaness of Greek mythology",
prepend: <EuiIcon size="s" type="discuss" />,
append: '(10)',
},
{
label: 'Iapetus',
prepend: <EuiIcon size="s" type="flag" color="danger" />,
append: '(2)',
},
{
label: 'Phoebe',
prepend: <EuiIcon size="s" type="tag" color="success" />,
append: '(5)',
},
];

export default () => {
const [selectedOptions, setSelected] = useState([options[0], options[5]]);
const [singleSelection, setSingleSelection] = useState(false);

const singleSelectedOption = useMemo(() => {
return selectedOptions.length ? [selectedOptions[0]] : [];
}, [selectedOptions]);

const onChange = (selectedOptions) => {
setSelected(selectedOptions);
};

return (
<>
<EuiSwitch
checked={singleSelection}
onChange={() => setSingleSelection(!singleSelection)}
label="Single selection"
/>
<EuiSpacer />
<EuiComboBox
aria-label="Combo box demo with option prepend/append nodes"
options={options}
onChange={onChange}
singleSelection={singleSelection ? { asPlainText: true } : false}
selectedOptions={
singleSelection ? singleSelectedOption : selectedOptions
}
placeholder={`Select one ${
singleSelection ? 'option' : 'or more options'
}`}
/>
</>
);
};
Loading