Skip to content

Commit

Permalink
Merge branch 'main' into theme-css-variables
Browse files Browse the repository at this point in the history
  • Loading branch information
cee-chen committed Sep 5, 2023
2 parents 947f979 + a588a35 commit 72b509a
Show file tree
Hide file tree
Showing 35 changed files with 2,638 additions and 158 deletions.
1 change: 0 additions & 1 deletion .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const config: StorybookConfig = {
use: [
{
loader: require.resolve('babel-loader'),
options: { plugins: ['@emotion/babel-plugin'] },
},
],
});
Expand Down
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
40 changes: 11 additions & 29 deletions src-docs/src/views/accordion/accordion_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -408,26 +408,13 @@ export const AccordionExample = {
text: (
<>
<p>
Since accordions are unstyled by default, EUI also provides a few
classes you can add to parts of the EuiAccordion to give it more
style, like when using with forms.
Accordions are unstyled by default, but{' '}
<strong>EuiAccordion</strong> supports several props around padding
sizes and borders, as well as letting you pass in your own custom
CSS styles. See the snippet tab below for a quick preview of said
props, and the and the demo code tab below for custom hover and
focus CSS overrides.
</p>
<ul>
<li>
<EuiCode>.euiAccordionForm</EuiCode>: Applied to the{' '}
<EuiCode>className</EuiCode>, adds top and bottom borders
</li>
<li>
<EuiCode>.euiAccordionForm__button</EuiCode>: Applied to the{' '}
<EuiCode>buttonClassName</EuiCode>, adds extra padding to the
button for better spacing
</li>
<li>
<EuiCode>.euiAccordionForm__extraAction</EuiCode>: Applied to the
button passed to <EuiCode>extraAction</EuiCode>, will visually
hide it until hover or focus
</li>
</ul>
<p>
We also recommend creating a fieldset/legend combination for better
accessibility and DOM structure by passing{' '}
Expand All @@ -441,18 +428,13 @@ export const AccordionExample = {
),
demo: <AccordionForm />,
snippet: `<EuiAccordion
id={accordionId4}
className="euiAccordionForm"
id={accordionId}
element="fieldset"
buttonClassName="euiAccordionForm__button"
paddingSize="l"
borders="horizontal"
buttonProps={{ paddingSize: 'm' }}
buttonContent={buttonContent}
extraAction={<EuiButtonIcon
iconType="cross"
color="danger"
className="euiAccordionForm__extraAction"
aria-label="Delete"
/>}
paddingSize="l">
>
<!-- Content to show when expanded -->
</EuiAccordion>`,
},
Expand Down
38 changes: 30 additions & 8 deletions src-docs/src/views/accordion/accordion_form.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { css } from '@emotion/react';

import {
EuiAccordion,
Expand All @@ -17,6 +18,7 @@ import {
EuiButtonIcon,
} from '../../../../src/components';
import { useGeneratedHtmlId } from '../../../../src/services';
import { euiCanAnimate } from '../../../../src/global_styling';

const repeatableForm = (
<EuiForm component="form">
Expand Down Expand Up @@ -68,13 +70,33 @@ const buttonContent = (
</EuiText>
</div>
);
// Custom trigger button CSS
const buttonCss = css`
&:hover {
text-decoration: none;
}
`;

// Custom CSS to make the extra action only appear on hover or focus
// Useful if there's multiple accordions in a row to reduce visual overwhelm
const extraAction = (
<EuiButtonIcon
aria-label="Delete"
iconType="cross"
color="danger"
className="euiAccordionForm__extraAction"
aria-label="Delete"
css={({ euiTheme }) => css`
opacity: 0;
&:focus,
.euiAccordion:hover & {
opacity: 1;
}
${euiCanAnimate} {
transition: opacity ${euiTheme.animation.normal}
${euiTheme.animation.resistance};
}
`}
/>
);

Expand All @@ -89,12 +111,12 @@ export default () => {
});

return (
<div>
<>
<EuiAccordion
id={formAccordionId__1}
element="fieldset"
className="euiAccordionForm"
buttonClassName="euiAccordionForm__button"
borders="horizontal"
buttonProps={{ paddingSize: 'm', css: buttonCss }}
buttonContent={buttonContent}
extraAction={extraAction}
paddingSize="l"
Expand All @@ -105,14 +127,14 @@ export default () => {
<EuiAccordion
id={formAccordionId__2}
element="fieldset"
className="euiAccordionForm"
buttonClassName="euiAccordionForm__button"
borders="horizontal"
buttonProps={{ paddingSize: 'm', css: buttonCss }}
buttonContent={buttonContent}
extraAction={extraAction}
paddingSize="l"
>
{repeatableForm}
</EuiAccordion>
</div>
</>
);
};
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 72b509a

Please sign in to comment.