Skip to content

Commit

Permalink
Add EuiTextTruncate component (#7116)
Browse files Browse the repository at this point in the history
  • Loading branch information
cee-chen authored Sep 1, 2023
1 parent eaaa098 commit b6ecfe0
Show file tree
Hide file tree
Showing 20 changed files with 2,247 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src-docs/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ import { TabsExample } from './views/tabs/tabs_example';

import { TextDiffExample } from './views/text_diff/text_diff_example';

import { TextTruncateExample } from './views/text_truncate/text_truncate_example';

import { TextExample } from './views/text/text_example';

import { TimelineExample } from './views/timeline/timeline_example';
Expand Down Expand Up @@ -670,6 +672,7 @@ const navigation = [
ResizeObserverExample,
ScrollExample,
TextDiffExample,
TextTruncateExample,
WindowEventExample,
].map((example) => createExample(example)),
},
Expand Down
25 changes: 25 additions & 0 deletions src-docs/src/views/text_truncate/ellipsis.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';

import { EuiPanel, EuiText, EuiTextTruncate } from '../../../../src';

export default () => {
return (
<EuiText>
<EuiPanel css={{ inlineSize: '40ch', maxInlineSize: '100%' }}>
<EuiTextTruncate
text="Opinions differ as to how to render ellipses in printed material. According to The Chicago Manual of Style, it should consist of three periods, each separated from its neighbor by a non-breaking space. According to the AP Stylebook, the periods should be rendered with no space between them."
ellipsis=". . ."
/>
<EuiTextTruncate
text="In some legal writing, an ellipsis is written as three asterisks, to make it obvious that text has been omitted or to signal that the omitted text extends beyond the end of the paragraph."
ellipsis=" ***"
/>
<EuiTextTruncate
text="Brackets are often used to indicate that a quotation has been condensed for space, brevity or relevance."
truncation="middle"
ellipsis="[...]"
/>
</EuiPanel>
</EuiText>
);
};
117 changes: 117 additions & 0 deletions src-docs/src/views/text_truncate/performance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { useState, useEffect, useRef } from 'react';
import { css } from '@emotion/react';
import { throttle } from 'lodash';
import { faker } from '@faker-js/faker';
import { FixedSizeList } from 'react-window';

import {
EuiFlexGroup,
EuiPanel,
EuiText,
EuiFormRow,
EuiFieldNumber,
EuiSwitch,
EuiSpacer,
EuiTextTruncate,
} from '../../../../src';

const text = Array.from({ length: 100 }, () => faker.lorem.lines(5));

export default () => {
// Testing toggles
const [canvasRendering, setCanvasRendering] = useState(true);
const measurementRenderAPI = canvasRendering ? 'canvas' : 'dom';
const [virtualization, setVirtualization] = useState(false);
const [throttleMs, setThrottleMs] = useState(100);

// Width resize observer
const widthRef = useRef<HTMLDivElement | null>(null);
const [width, setWidth] = useState(200);

useEffect(() => {
if (!widthRef.current) return;

const onObserve = throttle((entries) => {
// Skipping a forEach as we're only observing one element
setWidth(entries[0].contentRect.width);
}, throttleMs);

const resizeObserver = new ResizeObserver(onObserve);
resizeObserver.observe(widthRef.current);

() => resizeObserver.disconnect();
}, [throttleMs]);

return (
<EuiText>
<EuiFlexGroup alignItems="center">
<EuiSwitch
label="Toggle canvas rendering"
checked={canvasRendering}
onChange={() => setCanvasRendering(!canvasRendering)}
/>
<EuiSwitch
label="Toggle virtualization"
checked={virtualization}
onChange={() => setVirtualization(!virtualization)}
/>
<EuiFormRow label="Resize throttle" display="columnCompressed">
<EuiFieldNumber
value={throttleMs}
onChange={(e) => setThrottleMs(Number(e.target.value))}
style={{ width: 100 }}
compressed
/>
</EuiFormRow>
</EuiFlexGroup>
<EuiSpacer size="m" />

<EuiPanel
panelRef={widthRef}
css={css`
overflow: auto;
resize: horizontal; /* Not all browsers support resize logical properties yet */
resize: inline;
max-inline-size: 100%;
inline-size: 600px;
block-size: 300px;
`}
>
{virtualization ? (
<FixedSizeList
width={width}
height={268}
itemCount={100}
itemSize={24}
>
{({ index, style }) => (
<EuiTextTruncate
style={style}
key={index}
text={text[index]}
truncation="middle"
width={width}
measurementRenderAPI={measurementRenderAPI}
/>
)}
</FixedSizeList>
) : (
text.map((text, i) => (
<EuiTextTruncate
key={i}
text={text}
truncation="middle"
width={width}
measurementRenderAPI={measurementRenderAPI}
/>
))
)}
</EuiPanel>
<EuiSpacer />
<p>
Drag the panel resize handle to test performance. Use the controls above
to compare the performance of different approaches.
</p>
</EuiText>
);
};
57 changes: 57 additions & 0 deletions src-docs/src/views/text_truncate/render_prop.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { useState } from 'react';

import {
EuiText,
EuiFormRow,
EuiFieldText,
EuiSpacer,
EuiPanel,
EuiHighlight,
EuiMark,
EuiTextTruncate,
} from '../../../../src';

const text =
"But the dog wasn't lazy, it was just practicing mindfulness, so it had a greater sense of life-satisfaction than that fox with all its silly jumping.";

export default () => {
const [highlight, setHighlight] = useState('');
const highlightStartPosition = text
.toLowerCase()
.indexOf(highlight.toLowerCase());
const highlightCenterPosition =
highlightStartPosition + Math.floor(highlight.length / 2);

return (
<EuiText>
<EuiFormRow label="Type to highlight text">
<EuiFieldText
value={highlight}
onChange={(e) => setHighlight(e.target.value)}
placeholder={
'For example, try typing "lazy", "mindful", "life", or "silly"'
}
/>
</EuiFormRow>
<EuiSpacer />
<EuiPanel css={{ inlineSize: '40ch', maxInlineSize: '100%' }}>
<EuiTextTruncate
text={text}
truncation="startEnd"
truncationPosition={highlightCenterPosition}
>
{(truncatedText) => (
<>
{truncatedText.length > highlight.length ? (
<EuiHighlight search={highlight}>{truncatedText}</EuiHighlight>
) : (
// Highlight everything if the search match is greater than the visible text
<EuiMark>{truncatedText}</EuiMark>
)}
</>
)}
</EuiTextTruncate>
</EuiPanel>
</EuiText>
);
};
Loading

0 comments on commit b6ecfe0

Please sign in to comment.