Skip to content

Commit

Permalink
[Feature] Added EuiCollapsibleNav component (#2977)
Browse files Browse the repository at this point in the history
* Setting up file structure

* Added EuiFlyout to render, moved to left, and added docking

* mock euioverlaymask

* Better docs for EuiCollapsibleNav

* Cleanup css

* Adding responsive behavior

* No longer using EuiFlyout directly

*  added a `close` button
  • Loading branch information
cchaos authored and cchaos committed Mar 18, 2020
1 parent 72eef0e commit b98fd5a
Show file tree
Hide file tree
Showing 13 changed files with 405 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src-docs/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ import { CodeEditorExample } from './views/code_editor/code_editor_example';

import { CodeExample } from './views/code/code_example';

import { CollapsibleNavExample } from './views/collapsible_nav/collapsible_nav_example';

import { ColorPickerExample } from './views/color_picker/color_picker_example';

import { ComboBoxExample } from './views/combo_box/combo_box_example';
Expand Down Expand Up @@ -321,6 +323,7 @@ const navigation = [
items: [
BreadcrumbsExample,
ButtonExample,
CollapsibleNavExample,
ContextMenuExample,
ControlBarExample,
FacetExample,
Expand Down
36 changes: 36 additions & 0 deletions src-docs/src/views/collapsible_nav/collapsible_nav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useState } from 'react';

import { EuiCollapsibleNav } from '../../../../src/components/collapsible_nav';
import { EuiButton, EuiButtonToggle } from '../../../../src/components/button';
import { EuiTitle } from '../../../../src/components/title';
import { EuiSpacer } from '../../../../src/components/spacer';

export default () => {
const [navIsOpen, setNavIsOpen] = useState(false);
const [navIsDocked, setNavIsDocked] = useState(false);

return (
<>
<EuiButton onClick={() => setNavIsOpen(!navIsOpen)}>Toggle nav</EuiButton>
{navIsOpen && (
<EuiCollapsibleNav
docked={navIsDocked}
onClose={() => setNavIsOpen(false)}>
<div style={{ padding: 16 }}>
<EuiTitle>
<h2>I am some nav</h2>
</EuiTitle>
<EuiSpacer />
<EuiButtonToggle
label={`Docked: ${navIsDocked ? 'on' : 'off'}`}
fill={navIsDocked}
onChange={() => {
setNavIsDocked(!navIsDocked);
}}
/>
</div>
</EuiCollapsibleNav>
)}
</>
);
};
69 changes: 69 additions & 0 deletions src-docs/src/views/collapsible_nav/collapsible_nav_example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import { Link } from 'react-router';

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

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

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

import CollapsibleNav from './collapsible_nav';
const collapsibleNavSource = require('!!raw-loader!./collapsible_nav');
const collapsibleNavHtml = renderToHtml(CollapsibleNav);

export const CollapsibleNavExample = {
title: 'Collapsible nav',
intro: (
<EuiText>
<p>
This is a high level component that creates a flyout-style navigational
pane. It is the next evolution of{' '}
<Link to="/layout/nav-drawer">
<strong>EuiNavDrawer</strong>
</Link>{' '}
which will be deprecated in the coming months.
</p>
<EuiSpacer size="m" />
</EuiText>
),
sections: [
{
source: [
{
type: GuideSectionTypes.JS,
code: collapsibleNavSource,
},
{
type: GuideSectionTypes.HTML,
code: collapsibleNavHtml,
},
],
text: (
<>
<p>
<strong>EuiCollapsibleNav</strong> is a similar implementation to{' '}
<Link to="/layout/flyout">
<strong>EuiFlyout</strong>
</Link>
; the visibility of which must be maintained by the consuming
application. An extra feature that it provides is the ability to{' '}
<EuiCode>dock</EuiCode> the flyout. This affixes the flyout to the
window and pushes the body content by adding left side padding.
</p>
<EuiCallOut
iconType="tableOfContents"
title="Docking is not possible on small screens because it would force less real estate for the page content."
/>
</>
),
props: { EuiCollapsibleNav },
demo: <CollapsibleNav />,
},
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EuiCollapsibleNav can be docked 1`] = `
<div>
<div
data-focus-guard="true"
style="width:1px;height:0px;padding:0;overflow:hidden;position:fixed;top:1px;left:1px"
tabindex="-1"
/>
<div
data-focus-guard="true"
style="width:1px;height:0px;padding:0;overflow:hidden;position:fixed;top:1px;left:1px"
tabindex="-1"
/>
<div
data-focus-lock-disabled="disabled"
>
<nav
class="euiCollapsibleNav euiCollapsibleNav--isDocked"
>
<button
class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--xSmall euiCollapsibleNav__closeButton"
type="button"
>
<span
class="euiButtonEmpty__content"
>
<div
aria-hidden="true"
class="euiButtonEmpty__icon"
data-euiicon-type="cross"
/>
<span
class="euiButtonEmpty__text"
>
close
</span>
</span>
</button>
</nav>
</div>
<div
data-focus-guard="true"
style="width:1px;height:0px;padding:0;overflow:hidden;position:fixed;top:1px;left:1px"
tabindex="-1"
/>
</div>
`;

exports[`EuiCollapsibleNav is rendered 1`] = `
Array [
<div />,
<div>
<div
data-focus-guard="true"
style="width:1px;height:0px;padding:0;overflow:hidden;position:fixed;top:1px;left:1px"
tabindex="0"
/>
<div
data-focus-guard="true"
style="width:1px;height:0px;padding:0;overflow:hidden;position:fixed;top:1px;left:1px"
tabindex="1"
/>
<div
data-focus-lock-disabled="false"
>
<nav
aria-label="aria-label"
class="euiCollapsibleNav testClass1 testClass2"
data-test-subj="test subject string"
>
<button
class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--xSmall euiCollapsibleNav__closeButton"
type="button"
>
<span
class="euiButtonEmpty__content"
>
<div
aria-hidden="true"
class="euiButtonEmpty__icon"
data-euiicon-type="cross"
/>
<span
class="euiButtonEmpty__text"
>
close
</span>
</span>
</button>
</nav>
</div>
<div
data-focus-guard="true"
style="width:1px;height:0px;padding:0;overflow:hidden;position:fixed;top:1px;left:1px"
tabindex="0"
/>
</div>,
]
`;
52 changes: 52 additions & 0 deletions src/components/collapsible_nav/_collapsible_nav.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Extends euiFlyout
@use '../flyout/flyout';

.euiCollapsibleNav {
@extend %eui-flyout;
right: auto;
left: 0;
width: $euiCollapsibleNavWidth;
max-width: 80vw;

&:not(.euiCollapsibleNav--isDocked) {
animation: euiCollapsibleNavIn $euiAnimSpeedNormal $euiAnimSlightResistance;
}
}

.euiCollapsibleNav__closeButton {
position: absolute;
right: 0;
top: $euiSize;
margin-right: -25%;
}

@include euiBreakpoint('l', 'xl') {
// The addition of this class is handled through JS as well
// but adding under the breakpoint mixin is an additional fail-safe
.euiCollapsibleNav.euiCollapsibleNav--isDocked {
@include euiBottomShadowMedium;

.euiCollapsibleNav__closeButton {
display: none;
}
}

.euiBody--collapsibleNavIsDocked {
// Shrink the content from the left so it's no longer overlapped by the nav drawer (ALWAYS)
padding-left: $euiCollapsibleNavWidth !important; // sass-lint:disable-line no-important
transition: padding $euiAnimSpeedFast $euiAnimSlightResistance;
}
}

// Specific keyframes so in comes in from the left
@keyframes euiCollapsibleNavIn {
0% {
opacity: 0;
transform: translateX(-100%);
}

75% {
opacity: 1;
transform: translateX(0%);
}
}
2 changes: 2 additions & 0 deletions src/components/collapsible_nav/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import 'variables';
@import 'collapsible_nav';
2 changes: 2 additions & 0 deletions src/components/collapsible_nav/_variables.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Sizing
$euiCollapsibleNavWidth: $euiSize * 20; // ~ 320px
27 changes: 27 additions & 0 deletions src/components/collapsible_nav/collapsible_nav.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { render } from 'enzyme';
import { requiredProps } from '../../test/required_props';

import { EuiCollapsibleNav } from './collapsible_nav';

jest.mock('../overlay_mask', () => ({
EuiOverlayMask: (props: any) => <div {...props} />,
}));

describe('EuiCollapsibleNav', () => {
test('is rendered', () => {
const component = render(
<EuiCollapsibleNav onClose={() => {}} {...requiredProps} />
);

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

test('can be docked', () => {
const component = render(
<EuiCollapsibleNav docked={true} onClose={() => {}} />
);

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

0 comments on commit b98fd5a

Please sign in to comment.