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

Recursive tree #2409

Merged
merged 18 commits into from
Oct 25, 2019
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## [`master`](https://github.com/elastic/eui/tree/master)

- Added new `euiTreeView` component for rendering recursive objects such as folder structures. ([#2409](https://github.com/elastic/eui/pull/2409))
- Added `euiXScrollWithShadows()` mixin and `.eui-xScrollWithShadows` utility class ([#2458](https://github.com/elastic/eui/pull/2458))

**Bug fixes**
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 @@ -151,6 +151,8 @@ import { ProgressExample } from './views/progress/progress_example';

import { RangeControlExample } from './views/range/range_example';

import { TreeViewExample } from './views/tree_view/tree_view_example';

import { ResizeObserverExample } from './views/resize_observer/resize_observer_example';

import { ResponsiveExample } from './views/responsive/responsive_example';
Expand Down Expand Up @@ -310,6 +312,7 @@ const navigation = [
KeyPadMenuExample,
LinkExample,
PaginationExample,
TreeViewExample,
SideNavExample,
StepsExample,
TabsExample,
Expand Down
96 changes: 96 additions & 0 deletions src-docs/src/views/tree_view/compressed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from 'react';

import { EuiTreeView, EuiToken } from '../../../../src/components';

export class TreeViewCompressed extends React.Component {
showAlert = () => {
alert('You squashed a bug!');
};

render() {
const items = [
{
label: 'transporter',
id: 'transporter',
icon: <EuiToken size="xs" iconType="tokenObject" />,
children: [
{
label: 'service',
id: 'service',
icon: <EuiToken size="xs" iconType="tokenString" />,
},
{
label: 'auth',
id: 'auth',
icon: <EuiToken size="xs" iconType="tokenObject" />,
children: [
{
label: 'user',
id: 'user',
icon: <EuiToken size="xs" iconType="tokenVariable" />,
},
{
label: 'pass',
id: 'pass',
icon: <EuiToken size="xs" iconType="tokenVariable" />,
},
],
},
],
},
{
label: 'getContact',
id: 'getContact',
icon: <EuiToken size="xs" iconType="tokenFunction" />,
children: [
{
label: 'render',
id: 'render',
icon: <EuiToken size="xs" iconType="tokenFunction" />,
children: [
{
label: 'title',
id: 'title',
icon: <EuiToken size="xs" iconType="tokenString" />,
},
],
},
],
},
{
label: 'postContact',
id: 'postContact',
icon: <EuiToken size="xs" iconType="tokenFunction" />,
children: [
{
label: 'errors',
id: 'errors',
icon: <EuiToken size="xs" iconType="tokenConstant" />,
},
{
label: 'mailOptions',
id: 'mailOptions',
icon: <EuiToken size="xs" iconType="tokenObject" />,
},
],
},
{
label: 'smokeMonster',
id: 'smokeMonster',
icon: <EuiToken size="xs" iconType="tokenMethod" />,
},
];

return (
<div style={{ width: '20rem' }}>
<EuiTreeView
items={items}
display="compressed"
expandByDefault
showExpansionArrows
aria-label="Document Outline"
/>
</div>
);
}
}
76 changes: 76 additions & 0 deletions src-docs/src/views/tree_view/tree_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';

import { EuiIcon, EuiTreeView, EuiToken } from '../../../../src/components';

export class TreeView extends React.Component {
showAlert = () => {
alert('You squashed a bug!');
};

render() {
const items = [
{
label: 'Item One',
id: 'item_one',
icon: <EuiIcon type="folderClosed" />,
iconWhenExpanded: <EuiIcon type="folderOpen" />,
isExpanded: true,
children: [
{
label: 'Item A',
id: 'item_a',
icon: <EuiIcon type="document" />,
},
{
label: 'Item B',
id: 'item_b',
icon: <EuiIcon type="arrowRight" />,
iconWhenExpanded: <EuiIcon type="arrowDown" />,
children: [
{
label: 'A Cloud',
id: 'item_cloud',
icon: <EuiToken iconType="tokenConstant" />,
},
{
label: "I'm a Bug",
id: 'item_bug',
icon: <EuiToken iconType="tokenEnum" />,
callback: this.showAlert,
},
],
},
{
label: 'Item C',
id: 'item_c',
icon: <EuiIcon type="arrowRight" />,
iconWhenExpanded: <EuiIcon type="arrowDown" />,
children: [
{
label: 'Another Cloud',
id: 'item_cloud2',
icon: <EuiToken iconType="tokenConstant" />,
},
{
label: 'Another Bug',
id: 'item_bug2',
icon: <EuiToken iconType="tokenEnum" />,
callback: this.showAlert,
},
],
},
],
},
{
label: 'Item Two',
id: 'item_two',
},
];

return (
<div style={{ width: '20rem' }}>
<EuiTreeView items={items} aria-label="Sample Folder Tree" />
</div>
);
}
}
97 changes: 97 additions & 0 deletions src-docs/src/views/tree_view/tree_view_example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react';

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

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

import { EuiCode, EuiTreeView } from '../../../../src/components';
import { EuiTreeViewNode } from './tree_view_props';
import { TreeView } from './tree_view';
import { TreeViewCompressed } from './compressed';

const treeViewSource = require('!!raw-loader!./tree_view');
const treeViewHtml = renderToHtml(TreeView);

const treeViewCompressedSource = require('!!raw-loader!./compressed');
const treeViewCompressedHtml = renderToHtml(TreeViewCompressed);

export const TreeViewExample = {
title: 'Tree View',
sections: [
{
source: [
{
type: GuideSectionTypes.JS,
code: treeViewSource,
},
{
type: GuideSectionTypes.HTML,
code: treeViewHtml,
},
],
text: (
<div>
<p>
<EuiCode>EuiTreeView</EuiCode> allows you to render recursive
objects, such as a file directory. The <EuiCode>chilldren</EuiCode>{' '}
prop takes an array of <EuiCode>nodes</EuiCode>.
</p>
<p>
Keyboard navigation allows users to navigate and interact with the
tree using the arrow keys, spacebar, and return.
</p>
<p>
The <EuiCode>icon</EuiCode> prop accepts <EuiCode>EuiIcon</EuiCode>{' '}
and <EuiCode>EuiToken</EuiCode> as react nodes. You can also
specifiy a different icon for the open state with the{' '}
<EuiCode>iconWhenExpanded</EuiCode> prop.
</p>
</div>
),
components: { EuiTreeView },
demo: <TreeView />,
props: { EuiTreeView, EuiTreeViewNode },
},
{
title: 'Optional styling',
source: [
{
type: GuideSectionTypes.JS,
code: treeViewCompressedSource,
},
{
type: GuideSectionTypes.HTML,
code: treeViewCompressedHtml,
},
],
text: (
<div>
<p>
<EuiCode>EuiTreeView</EuiCode> supports a compressed mode with the{' '}
<EuiCode>display=&quot;compressed&quot;</EuiCode> setting. When
using the compressed version it&apos;s highly recommended to use the
small size of <EuiCode>EuiIcon</EuiCode> and the extra small size of{' '}
<EuiCode>EuiToken</EuiCode>. This will help prevent awkard alignment
issues when used alongside the{' '}
<EuiCode>showExpansionArrows</EuiCode> prop.
</p>
<p>
The <EuiCode>showExpansionArrows</EuiCode> prop provides an
additional visual indicator. Ideal for when a tree&apos;s items use
icons that don&apos;t immediately let a user know that there are
nested nodes that may not be visible.
</p>
<p>
In some cases, you may want to automatically expand all the items
with children. In those instances, you can use the{' '}
<EuiCode>expandByDefault</EuiCode> prop, as seen in the example
below.
</p>
</div>
),
components: { EuiTreeView },
demo: <TreeViewCompressed />,
props: { EuiTreeView, EuiTreeViewNode },
},
],
};
4 changes: 4 additions & 0 deletions src-docs/src/views/tree_view/tree_view_props.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import React, { FunctionComponent } from 'react';
import { Node } from '../../../../src/components/tree_view/tree_view';

export const EuiTreeViewNode: FunctionComponent<Node> = () => <div />;
2 changes: 1 addition & 1 deletion src/components/button/button_empty/button_empty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ interface CommonEuiButtonEmptyProps extends CommonProps {
isLoading?: boolean;

type?: 'button' | 'submit';
buttonRef?: () => void;
buttonRef?: (ref: HTMLButtonElement | HTMLAnchorElement | null) => void;
/**
* Passes props to `euiButtonEmpty__content` 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 @@ -222,6 +222,8 @@ export { EuiPortal } from './portal';

export { EuiProgress } from './progress';

export { EuiTreeView } from './tree_view';

export { EuiResizeObserver } from './observer/resize_observer';

export { EuiSearchBar, Query, Ast } from './search_bar';
Expand Down
1 change: 1 addition & 0 deletions src/components/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
@import 'popover/index';
@import 'portal/index';
@import 'progress/index';
@import 'tree_view/index';
@import 'side_nav/index';
@import 'spacer/index';
@import 'search_bar/index';
Expand Down
15 changes: 15 additions & 0 deletions src/components/token/__snapshots__/token.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,18 @@ exports[`EuiToken props size s is rendered 1`] = `
/>
</div>
`;

exports[`EuiToken props size xs is rendered 1`] = `
<div
class="euiToken euiToken--tokenTint01 euiToken--circle euiToken--xsmall"
>
<svg
class="euiIcon euiIcon--medium euiIcon-isLoading"
focusable="false"
height="16"
viewBox="0 0 16 16"
width="16"
xmlns="http://www.w3.org/2000/svg"
/>
</div>
`;
9 changes: 9 additions & 0 deletions src/components/token/_token.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
border-radius: $euiBorderRadius - 1px;
}

.euiToken--xsmall {
width: $euiSizeM;
height: $euiSizeM;

&.euiToken--rectangle {
padding: 0 $euiSizeXS;
}
}

.euiToken--small {
width: $euiSize;
height: $euiSize;
Expand Down
1 change: 1 addition & 0 deletions src/components/token/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export {
EuiToken,
EuiTokenProps,
SIZES as TOKEN_SIZES,
SHAPES as TOKEN_SHAPES,
COLORS as TOKEN_COLORS,
Expand Down
Loading