Skip to content
Merged
2 changes: 2 additions & 0 deletions changelogs/upcoming/7388.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- `EuiSelectable` now allows configurable text truncation via `listProps.truncationProps`
- `EuiTextTruncate` now supports a new `calculationDelayMs` prop for working around font loading or layout shifting scenarios
2 changes: 1 addition & 1 deletion src-docs/src/views/combo_box/combo_box_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ export const ComboBoxExample = {
By default, <strong>EuiComboBox</strong> truncates long option text at
the end of the string. You can use <EuiCode>truncationProps</EuiCode>{' '}
and almost any prop that{' '}
<Link to="/utilities/text-truncate">
<Link to="/utilities/text-truncation">
<strong>EuiTextTruncate</strong>
</Link>{' '}
accepts to configure this behavior. This can be configured at the{' '}
Expand Down
51 changes: 51 additions & 0 deletions src-docs/src/views/selectable/selectable_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
EuiSelectable,
EuiSelectableMessage,
EuiText,
EuiTextTruncate,
EuiCallOut,
EuiLink,
} from '../../../../src';
Expand Down Expand Up @@ -38,6 +39,9 @@ const selectableMessagesSource = require('!!raw-loader!./selectable_messages');
import SelectableSizing from './selectable_sizing';
const selectableSizingSource = require('!!raw-loader!./selectable_sizing');

import Truncation from './selectable_truncation';
const truncationSource = require('!!raw-loader!./selectable_truncation');

import SelectableCustomRender from './selectable_custom_render';
const selectableCustomRenderSource = require('!!raw-loader!./selectable_custom_render');

Expand Down Expand Up @@ -385,6 +389,53 @@ export const SelectableExample = {
{list => list}
</EuiSelectable>`,
},
{
title: 'Truncation',
source: [
{
type: GuideSectionTypes.TSX,
code: truncationSource,
},
],
text: (
<>
<p>
<strong>EuiSelectable</strong> defaults to{' '}
<EuiCode>listProps.textWrap="truncate"</EuiCode>, which truncates
long option text at the end of the string.
</p>
<p>
You can use <EuiCode>listProps.truncationProps</EuiCode> and almost
any prop that{' '}
<Link to="/utilities/text-truncation">
<strong>EuiTextTruncate</strong>
</Link>{' '}
accepts to configure this behavior. This can be configured at the{' '}
<strong>EuiSelectable</strong> level, as well as by each individual
option.
</p>
</>
),
props: {
EuiSelectableOptionsList,
EuiSelectableOptionProps,
EuiTextTruncate,
},
snippet: `<EuiSelectable
options={[]}
onChange={newOptions => setOptions(newOptions)}
listProps={{
textWrap: 'truncate',
truncationProps: {
truncation: 'start',
truncationOffset: 5,
},
}}
>
{list => list}
</EuiSelectable>`,
demo: <Truncation />,
},
{
title: 'Rendering the options',
source: [
Expand Down
153 changes: 153 additions & 0 deletions src-docs/src/views/selectable/selectable_truncation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import React, { useState } from 'react';

import {
useGeneratedHtmlId,
EuiFlexGroup,
EuiFlexItem,
EuiButtonGroup,
EuiFieldNumber,
EuiTextTruncationTypes,
EuiTitle,
EuiSpacer,
EuiSelectable,
EuiSelectableOptionsListProps,
EuiSelectableOption,
EuiPanel,
EuiIcon,
EuiText,
} from '../../../../src';

export default () => {
const [options, setOptions] = useState<EuiSelectableOption[]>([
{
label:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, lorem ispum',
checked: 'on',
},
{
label:
'Phasellus enim turpis, molestie ut nisi ut, suscipit tristique libero',
},
{
label: 'Ut sagittis interdum nisi, pellentesque laoreet arcu blandit a',
},
{
label: 'Fusce sed viverra nisl',
},
{
label: 'Donec maximus est justo, eget semper lorem lacinia nec',
},
{
label: 'Vestibulum lobortis ipsum sit amet tellus scelerisque vestibulum',
},
{
prepend: <EuiIcon type="alert" color="warning" aria-label="Note!" />,
label:
'This option has `textWrap` and `truncationProps` settings that will override the parent',
textWrap: 'truncate',
truncationProps: {
truncation: 'start',
truncationOffset: 5,
},
},
]);

type TextWrap = NonNullable<EuiSelectableOptionsListProps['textWrap']>;
const [textWrap, setTextWrap] = useState<TextWrap>('truncate');
const [truncation, setTruncation] = useState<EuiTextTruncationTypes>('end');
const [truncationOffset, setTruncationOffset] = useState(0);
const offsetId = useGeneratedHtmlId();

return (
<>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h3>Text wrap</h3>
</EuiTitle>
<EuiSpacer size="xs" />
<EuiButtonGroup
legend="Text wrap"
idSelected={textWrap}
onChange={(id) => setTextWrap(id as TextWrap)}
options={[
{ id: 'truncate', label: 'truncate' },
{ id: 'wrap', label: 'wrap' },
]}
color="primary"
/>
</EuiFlexItem>
{textWrap === 'wrap' && (
<EuiFlexItem grow={false} css={{ alignSelf: 'center' }}>
<EuiText color="danger" size="s">
<EuiIcon type="alert" /> Wrapping text requires disabling
virtualization. We do not recommend this for large (50+) amounts
of options.
</EuiText>
</EuiFlexItem>
)}
{textWrap === 'truncate' && (
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h3>Truncation type</h3>
</EuiTitle>
<EuiSpacer size="xs" />
<EuiButtonGroup
legend="Truncation type"
idSelected={truncation}
onChange={(id) => setTruncation(id as EuiTextTruncationTypes)}
options={[
{ id: 'start', label: 'start ' },
{ id: 'end', label: 'end' },
{ id: 'startEnd', label: 'startEnd' },
{ id: 'middle', label: 'middle' },
]}
color="primary"
/>
</EuiFlexItem>
)}
{textWrap === 'truncate' &&
(truncation === 'start' || truncation === 'end') && (
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h3 id={offsetId}>Truncation offset</h3>
</EuiTitle>
<EuiSpacer size="xs" />
<EuiFieldNumber
aria-labelledby={offsetId}
value={truncationOffset}
onChange={(e) => setTruncationOffset(Number(e.target.value))}
compressed
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
<EuiSpacer />
<EuiPanel
paddingSize="s"
style={{ inlineSize: 400, resize: 'horizontal', overflow: 'auto' }}
>
<EuiSelectable
searchable={true}
options={options}
onChange={(updatedOptions) => setOptions(updatedOptions)}
listProps={{
isVirtualized: textWrap !== 'wrap',
textWrap,
truncationProps: {
truncation,
truncationOffset,
},
}}
>
{(list, search) => (
<>
{search}
{list}
</>
)}
</EuiSelectable>
</EuiPanel>
</>
);
};
8 changes: 7 additions & 1 deletion src/components/auto_sizer/auto_sizer.testenv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,22 @@
* Side Public License, v 1.
*/

import React from 'react';
import React, { useEffect } from 'react';

export const EuiAutoSizer = ({
children,
defaultHeight,
defaultWidth,
onResize,
}: any) => {
const childrenParams = {
height: defaultHeight ?? 600,
width: defaultWidth ?? 600,
};

useEffect(() => {
onResize?.(childrenParams);
}, [onResize, defaultHeight, defaultWidth]); // eslint-disable-line react-hooks/exhaustive-deps

return <div data-eui="EuiAutoSizer">{children(childrenParams)}</div>;
};
2 changes: 1 addition & 1 deletion src/components/combo_box/combo_box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export interface _EuiComboBoxProps<T>
/**
* By default, EuiComboBox will truncate option labels at the end of
* the string. You can use pass in a custom truncation configuration that
* accepts any prop that [EuiTextTruncate](/#/utilities/text-truncate) prop
* accepts any [EuiTextTruncate](/#/utilities/text-truncation) prop,
* except for `text` and `children`.
*
* Note: when searching, custom truncation props are ignored. The highlighted search
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,7 @@ exports[`EuiSelectable errorMessage prop does not render the message when not de
<span
class="euiSelectableListItem__text euiSelectableListItem__text--truncate"
>
<span>
Titan
</span>
Titan
</span>
</span>
</li>
Expand All @@ -205,9 +203,7 @@ exports[`EuiSelectable errorMessage prop does not render the message when not de
<span
class="euiSelectableListItem__text euiSelectableListItem__text--truncate"
>
<span>
Enceladus
</span>
Enceladus
</span>
</span>
</li>
Expand All @@ -232,9 +228,7 @@ exports[`EuiSelectable errorMessage prop does not render the message when not de
<span
class="euiSelectableListItem__text euiSelectableListItem__text--truncate"
>
<span>
Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
</span>
Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
</span>
</span>
</li>
Expand Down
Loading