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

useInnerText; Fix EuiListGroupItem title attrs #2100

Merged
merged 18 commits into from
Jul 15, 2019
Merged
Show file tree
Hide file tree
Changes from 9 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
3 changes: 3 additions & 0 deletions src-docs/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ import { IconExample } from './views/icon/icon_example';

import { ImageExample } from './views/image/image_example';

import { InnerTextExample } from './views/inner_text/inner_text_example';

import { KeyPadMenuExample } from './views/key_pad_menu/key_pad_menu_example';

import { LinkExample } from './views/link/link_example';
Expand Down Expand Up @@ -371,6 +373,7 @@ const navigation = [
ErrorBoundaryExample,
FocusTrapExample,
HighlightExample,
InnerTextExample,
I18nExample,
IsColorDarkExample,
MutationObserverExample,
Expand Down
61 changes: 61 additions & 0 deletions src-docs/src/views/inner_text/inner_text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react';

import { EuiInnerText } from '../../../../src/components/inner_text';

import {
EuiBadge,
EuiCode,
EuiFlexGroup,
EuiHighlight,
EuiFlexItem,
EuiHorizontalRule,
EuiPanel,
EuiText,
} from '../../../../src/components';

export default () => (
<EuiText size="s">
<h5>Example:</h5>
<EuiInnerText>
{(ref, innerText) => (
<React.Fragment>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiPanel paddingSize="s" grow={false}>
<span ref={ref} title={innerText}>
Simple string content
</span>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<h5 className="eui-displayInlineBlock">Output:</h5>{' '}
<EuiCode>{innerText}</EuiCode>
</React.Fragment>
)}
</EuiInnerText>

<EuiHorizontalRule margin="xl" />

<h5>Example:</h5>
<EuiInnerText>
{(ref, innerText) => (
<React.Fragment>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiPanel paddingSize="s" grow={false}>
<span ref={ref} title={innerText}>
<EuiHighlight search="content">
EuiHighlight content
</EuiHighlight>
<EuiBadge>with EuiBadge</EuiBadge>
cchaos marked this conversation as resolved.
Show resolved Hide resolved
</span>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
<h5 className="eui-displayInlineBlock">Output:</h5>{' '}
<EuiCode>{innerText}</EuiCode>
</React.Fragment>
)}
</EuiInnerText>
</EuiText>
);
73 changes: 73 additions & 0 deletions src-docs/src/views/inner_text/inner_text_example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react';

import { renderToHtml } from '../../services';

import { GuideSectionTypes } from '../../components';

import { EuiCode, EuiSpacer, EuiText } from '../../../../src/components';

import InnerText from './inner_text';
const innerTextSource = require('!!raw-loader!./inner_text');
const innerTextHtml = renderToHtml(InnerText);
const useInnerTextSnippet = `// useInnerText
cchaos marked this conversation as resolved.
Show resolved Hide resolved
const [ref, innerText] = useInnerText();
<span ref={ref} title={innerText}>
Content
</span>`;
const euiInnerTextSnippet = `// EuiInnerText
<EuiInnerText>
{(ref, innerText) => (
<span ref={ref} title={innerText}>
Content
</span>
)}
</EuiInnerText>`;

export const InnerTextExample = {
title: 'Inner Text',
intro: (
<React.Fragment>
<EuiText>
<p>
For instances where accessing the text content of a component that may
be wrapped or interspersed with other components, two utilities are
available:
</p>
<ul>
<li>
<EuiCode>useInnerText</EuiCode> - A custom React hook, usable in
function components
</li>
<li>
<EuiCode>EuiInnerText</EuiCode> - A higher order{' '}
<EuiCode>useInnerText</EuiCode> component for use in class
components
</li>
</ul>
<p>
Both utilities make available a <EuiCode>ref</EuiCode> reference to
add to the target DOM element, and the resulting{' '}
<EuiCode>innerText</EuiCode> value to use as needed.
</p>
</EuiText>
<EuiSpacer />
</React.Fragment>
),
sections: [
{
title: 'Rendered',
source: [
{
type: GuideSectionTypes.JS,
code: innerTextSource,
},
{
type: GuideSectionTypes.HTML,
code: innerTextHtml,
},
],
demo: <InnerText />,
snippet: [useInnerTextSnippet, euiInnerTextSnippet],
},
],
};
2 changes: 1 addition & 1 deletion src-docs/src/views/list_group/list_group.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default class extends Component {

<EuiSpacer size="l" />

<EuiListGroup flush={flushWidth} bordered={showBorder} showToolTips>
<EuiListGroup flush={flushWidth} bordered={showBorder}>
<EuiListGroupItem label="First item" />

<EuiListGroupItem label="Second item" />
Expand Down
26 changes: 26 additions & 0 deletions src-docs/src/views/list_group/list_group_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import ListGroupLinkActions from './list_group_link_actions';
const listGroupLinkActionsSource = require('!!raw-loader!./list_group_link_actions');
const listGroupLinkActionsHtml = renderToHtml(ListGroupLinkActions);

import ListGroupExtra from './list_group_extra';
const listGroupExtraSource = require('!!raw-loader!./list_group_extra');
const listGroupExtraHtml = renderToHtml(ListGroupExtra);

export const ListGroupExample = {
title: 'List Group',
sections: [
Expand Down Expand Up @@ -95,5 +99,27 @@ export const ListGroupExample = {
),
demo: <ListGroupLinkActions />,
},
{
title: 'Text wrapping and tooltips',
source: [
{
type: GuideSectionTypes.JS,
code: listGroupExtraSource,
},
{
type: GuideSectionTypes.HTML,
code: listGroupExtraHtml,
},
],
text: (
<p>
Optional props <EuiCode>showToolTip</EuiCode> and{' '}
<EuiCode>wrapLines</EuiCode> can be used to augment the display of
list items. Use these when lists are inside small containers where it
is likely that the content will be truncated.
</p>
),
demo: <ListGroupExtra />,
},
],
};
55 changes: 55 additions & 0 deletions src-docs/src/views/list_group/list_group_extra.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { Fragment } from 'react';

import {
EuiListGroup,
EuiListGroupItem,
EuiSpacer,
} from '../../../../src/components';

export default () => (
<Fragment>
<EuiListGroup>
thompsongl marked this conversation as resolved.
Show resolved Hide resolved
<EuiListGroupItem label="We use defaults" />

<EuiListGroupItem
label={
<span>
A very, very long item that <strong>will surely</strong> force
truncation
</span>
}
/>
</EuiListGroup>

<EuiSpacer />

<EuiListGroup>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these other two can be combined into one group even though it will still show a tooltip on the wrapped lines one.

  • First item
  • Second item
  • Third very, very long item that will surely force truncation
  • Fourth very, very long item with wrapping enabled that will not force truncation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TY! Just one more thing, I promise...

Can you add two snippets for this example?

<EuiListGroup showToolTips>...</EuiListGroup>
<EuiListGroupItem
  wrapText
  label={label}
/>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thompsongl Did you see my last comment on here? ^^

<EuiListGroupItem wrapText label="We wrap lines" />

<EuiListGroupItem
wrapText
label={
<span>
A very, very long item that <strong>will surely</strong> force
wrapping
</span>
}
/>
</EuiListGroup>

<EuiSpacer />

<EuiListGroup showToolTips>
<EuiListGroupItem label="We use tooltips" />

<EuiListGroupItem
label={
<span>
A very, very long item that <strong>will surely</strong> force
truncation
</span>
}
/>
</EuiListGroup>
</Fragment>
);
8 changes: 6 additions & 2 deletions src/components/filter_group/filter_button.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { COLORS, ICON_SIDES, EuiButtonEmpty } from '../button/button_empty';

import { IconPropType } from '../icon';

import { useInnerText } from '../inner_text';

export const EuiFilterButton = ({
children,
className,
Expand Down Expand Up @@ -53,12 +55,14 @@ export const EuiFilterButton = ({
dataText = children;
}

const [ref, innerText] = useInnerText();
const buttonContents = (
<Fragment>
<span
ref={ref}
className="euiFilterButton__textShift"
data-text={dataText}
title={dataText}>
data-text={dataText || innerText}
title={dataText || innerText}>
{children}
</span>

Expand Down
2 changes: 2 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ export { ICON_TYPES, EuiIcon } from './icon';

export { EuiImage } from './image';

export { useInnerText, EuiInnerText } from './inner_text';

export { EuiI18n, EuiI18nNumber } from './i18n';

export {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EuiInnerText is rendered 1`] = `
<span>
Test
</span>
`;
1 change: 1 addition & 0 deletions src/components/inner_text/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useInnerText, EuiInnerText } from './inner_text';
43 changes: 43 additions & 0 deletions src/components/inner_text/inner_text.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import {
render,
// mount
} from 'enzyme';
import {
// findTestSubject,
requiredProps,
} from '../../test';

import { EuiInnerText } from './inner_text';

describe('EuiInnerText', () => {
test('is rendered', () => {
const component = render(
<EuiInnerText {...requiredProps}>
{(ref, innerText) => (
<span ref={ref} title={innerText}>
Test
</span>
)}
</EuiInnerText>
);

expect(component).toMatchSnapshot();
});

// test('uses innerText', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working on getting these types of tests to run

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still stumped. I'm not actually sure if Enzyme can handle it.

// const text = 'Test';
// const component = mount(
// <EuiInnerText {...requiredProps}>
// {(ref, innerText) => (
// <span ref={ref} title={innerText} data-test-subj="span">
// {text}
// </span>
// )}
// </EuiInnerText>
// );
//
// const span = findTestSubject(component, 'span');
// expect(span.props().title).toBe(text);
// });
});
30 changes: 30 additions & 0 deletions src/components/inner_text/inner_text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
FunctionComponent,
ReactElement,
Ref,
RefObject,
useEffect,
useRef,
useState,
} from 'react';

export function useInnerText(
innerTextFallback?: string
): [RefObject<HTMLElement>, string | undefined] {
const ref = useRef<HTMLElement>(null);
const [innerText, setInnerText] = useState(innerTextFallback);
useEffect(() => {
if (ref && ref.current) {
setInnerText(ref.current.innerText);
}
}, [ref.current]);

return [ref, innerText];
}

export const EuiInnerText: FunctionComponent<{
children: (ref?: Ref<HTMLElement>, innerText?: string) => ReactElement;
}> = ({ children }) => {
const [ref, innerText] = useInnerText();
return children(ref, innerText);
};
Loading