Skip to content

Commit

Permalink
EuiResizableContainer (#2701)
Browse files Browse the repository at this point in the history
* Create a resizable_container

* Tune styles, add props

* Add vertical container, scrollable panel

* Use several panels, update docs

* added styles + resizeble resizer example

* added styles + resizeble resizer example

* license headers

* rename all the things

* new badge

* flex-shrink resizer button

* docs

* type adjustments

* tests

* touch support

* type update

* docs copyedit

* handle mouse leave

* cancel dragging when keyboard in use

* prevent resizer position overlap and resulting jank

* keyboard scrollable panels

* focus state cleanup

* sass cleanup

* some aria wording

* remove scrollbar mixin maagic

* scrollable default

* resizer focus on click

* safari animation fix

* respect minSize

* CL

* stricter context access; static getPanelMinSize; clean up

* deregister panel on clean up

Co-authored-by: Henry Harding <henry.harding@elastic.co>
Co-authored-by: Greg Thompson <thompson.glowe@gmail.com>
Co-authored-by: Dave Snider <dave.snider@gmail.com>
  • Loading branch information
4 people authored Apr 30, 2020
1 parent 357a8a9 commit 2b9eca6
Show file tree
Hide file tree
Showing 24 changed files with 1,798 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Added `closeButtonProps` to `EuiCollapsibleNav` ([#3398](https://github.com/elastic/eui/pull/3398))
- Added `buffer` prop to `EuiPopover` for altering minimum distance to container edges ([#3398](https://github.com/elastic/eui/pull/3398))
- Allowed `search` prop changes to update `EuiInMemoryTable` internal query state ([#3371](https://github.com/elastic/eui/pull/3371))
- Added `EuiResizableContainer` component ([#2701](https://github.com/elastic/eui/pull/2701))

**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 @@ -172,6 +172,8 @@ import { TreeViewExample } from './views/tree_view/tree_view_example';

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

import { ResizableContainerExample } from './views/resizable_container/resizable_container_example';

import { ResponsiveExample } from './views/responsive/responsive_example';

import { SearchBarExample } from './views/search_bar/search_bar_example';
Expand Down Expand Up @@ -328,6 +330,7 @@ const navigation = [
PageExample,
PanelExample,
PopoverExample,
ResizableContainerExample,
SpacerExample,
].map(example => createExample(example)),
},
Expand Down
29 changes: 29 additions & 0 deletions src-docs/src/views/resizable_container/lorem.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Lorem ipsum dolor sit amet, omnis omittam patrioque eam ad, eum
discere efficiantur ut. Ei duo sale melius discere, per animal
equidem rationibus at. Maiestatis mnesarchum per ea, te eum option
petentium repudiandae. Ne summo dicam timeam vis, duo etiam primis
maiestatis ex. Per detraxit mediocrem ad. Ei vix postulant
aliquando, has ei epicurei quaerendum necessitatibus. No vis idque
nihil ancillae, ea nostrud incorrupte interesset mel. Ex vim paulo
docendi, docendi omittam complectitur ne quo, ea nam mundi
salutatus. An detraxit splendide sed, ridens rationibus cu has. In
nam tota meliore torquatos, stet detracto insolens cu his. Quidam
pericula cum ei, modus essent vis an, mea ut veri placerat. Ne cum
fugit dolor aeterno. No augue audiam consequuntur quo. Case
detraxit reprehendunt ad qui, vis autem possim eu, vel ut duis
erroribus. At accusata delicatissimi vis, ad eam eruditi ceteros
pertinacia, at mandamus quaerendum vis. Ut simul omittam menandri
his, quodsi vituperata et his, ut eum melius tractatos petentium.
Nec illud molestie an. Te sed dolor ridens atomorum, quem eirmod
sed id. Sea iusto dicant populo an. Ius aeque fuisset et, duo id
amet invenire. Ad duo appareat rationibus sadipscing, nullam
verterem vix no. Ut melius cetero pertinax usu, ei sententiae
reprimique eam. Eu usu ferri graeco. Ei qui paulo latine
rationibus, dico dicat tempor usu ad. Ut eligendi interesset mel,
ius ut modus animal propriae, justo epicurei no his. Ea sit enim
sale omittantur, quot malorum intellegat pro ad, ocurreret
salutatus vel cu. Brute quaeque facilisis in nec. His velit
percipitur eu, libris possim convenire nec no. Ad mel exerci
explicari, vidit brute percipitur an vim, phaedrum volutpat
consequuntur mea ad. Ei sed adhuc mentitum consetetur, ea justo
perpetua pro, cetero lucilius sententiae eos eu.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

import { EuiText, EuiResizableContainer } from '../../../../src';

const text = require('!!raw-loader!./lorem.txt');

export default () => (
<EuiResizableContainer style={{ height: '400px' }}>
{(EuiResizablePanel, EuiResizableButton) => (
<>
<EuiResizablePanel initialSize={50} minSize="30%">
<EuiText>
<p>{text}</p>
<a href="">Hello world</a>
</EuiText>
</EuiResizablePanel>

<EuiResizableButton />

<EuiResizablePanel initialSize={50} minSize="200px">
<EuiText>
<p>{text}</p>
</EuiText>
</EuiResizablePanel>
</>
)}
</EuiResizableContainer>
);
242 changes: 242 additions & 0 deletions src-docs/src/views/resizable_container/resizable_container_example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import React, { Fragment } from 'react';

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

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

import {
EuiCallOut,
EuiCode,
EuiLink,
EuiResizableContainer,
EuiSpacer,
EuiText,
} from '../../../../src/components';
import { EuiResizablePanel } from '../../../../src/components/resizable_container/resizable_panel';
import { EuiResizableButton } from '../../../../src/components/resizable_container/resizable_button';

import ResizableContainerBasic from './resizable_container_basic';
import ResizableContainerVertical from './resizable_container_vertical';
import ResizableContainerThreePanels from './resizable_container_three_panels';
import ResizableContainerResetValues from './resizable_container_reset_values';
import ResizableResizerSize from './resizable_resizer_size';

const ResizableContainerSource = require('!!raw-loader!./resizable_container_basic');
const ResizableContainerVericalSource = require('!!raw-loader!./resizable_container_vertical');
const ResizableContainerThreePanelsSource = require('!!raw-loader!./resizable_container_three_panels');
const ResizableContainerResetValuesSource = require('!!raw-loader!./resizable_container_reset_values');
const ResizableResizerSizeSource = require('!!raw-loader!./resizable_resizer_size');

const ResizableContainerHtml = renderToHtml(ResizableContainerBasic);
const ResizableContainerVericalHtml = renderToHtml(ResizableContainerVertical);
const ResizableContainerThreePanelsHtml = renderToHtml(
ResizableContainerThreePanels
);
const ResizableContainerResetValuesHtml = renderToHtml(
ResizableContainerResetValues
);
const ResizableResizerSizeHtml = renderToHtml(ResizableResizerSize);

const snippet = `<EuiResizableContainer style={{ height: '400px' }}>
{(EuiResizablePanel, EuiResizableButton) => (
<>
<EuiResizablePanel initialSize={50} minSize="200px">
<EuiText>
<p>{text}</p>
</EuiText>
</EuiResizablePanel>
<EuiResizableButton />
<EuiResizablePanel initialSize={50} minSize="200px">
<EuiText>
<p>{text}</p>
</EuiText>
</EuiResizablePanel>
</>
)}
</EuiResizableContainer>`;

export const ResizableContainerExample = {
title: 'Resizable container',
isNew: true,
intro: (
<Fragment>
<EuiCallOut title="Consuming" color="warning">
<EuiText size="s">
<p>
This component is handy for various resizable containers.{' '}
<strong>EuiResizableContainer</strong> uses the{' '}
<EuiLink
href="https://reactjs.org/docs/render-props.html#using-props-other-than-render"
external>
React Render Props
</EuiLink>{' '}
technique to provide <strong>EuiResizablePanel</strong> and{' '}
<strong>EuiResizableButton</strong> components for you layout. Wrap
parts of your content with the <strong>EuiResizablePanel</strong>{' '}
component and put the <strong>EuiResizableButton</strong> component
between.
</p>
</EuiText>
</EuiCallOut>

<EuiSpacer size="l" />
</Fragment>
),
sections: [
{
source: [
{
type: GuideSectionTypes.JS,
code: ResizableContainerSource,
},
{
type: GuideSectionTypes.HTML,
code: ResizableContainerHtml,
},
],
title: 'Horizontal resizing',
text: (
<div>
<p>
Simple resizable container with two panels and a resizer between.
This is the most common case you&#39;ll need in your app. Just drag{' '}
<strong>the resizer</strong> button between two panels to
increase/decrease panel size. You could also use arrow keys{' '}
<strong>&#x2190;</strong>|<strong>&#x2192;</strong> on{' '}
<strong>the focused resizer</strong> button to change panel size.
</p>
<ul>
<li>
add <EuiCode>initialSize</EuiCode> in percents to each panel to
specify the initial size of it. Other calculations will be
incapsulated, you don&#39;t worry about it.
</li>
<li>
add <EuiCode>scrollable=false</EuiCode> prop to a panel to
eliminate overflow scrolling
</li>
</ul>
</div>
),
props: { EuiResizableContainer, EuiResizablePanel, EuiResizableButton },
snippet,
demo: <ResizableContainerBasic />,
},
{
source: [
{
type: GuideSectionTypes.JS,
code: ResizableContainerResetValuesSource,
},
{
type: GuideSectionTypes.HTML,
code: ResizableContainerResetValuesHtml,
},
],
title: 'Horizontal resizing with controlled widths',
text: (
<div>
<p>
Sometimes it&#39;s necessary to control panel sizes from the
outside. For example to store sizes in{' '}
<EuiCode>localStorage</EuiCode> or change the layout with predefined
sizes. Here is the <EuiCode>onPanelWidthChange</EuiCode> and{' '}
<EuiCode>size</EuiCode> props for help. If you use such an approach,
you have to specify an <EuiCode>id</EuiCode> prop for each panel to
track their sizes.
</p>

<EuiCallOut title="Required properties" color="warning">
<EuiText size="s">
<p>
Either <EuiCode>initialSize</EuiCode> or <EuiCode>size</EuiCode>{' '}
must be specified. The <EuiCode>size</EuiCode> prop is for cases
where a parent component will control sizing updates.
</p>
</EuiText>
</EuiCallOut>
</div>
),
props: { EuiResizableContainer, EuiResizablePanel, EuiResizableButton },
demo: <ResizableContainerResetValues />,
},
{
source: [
{
type: GuideSectionTypes.JS,
code: ResizableContainerThreePanelsSource,
},
{
type: GuideSectionTypes.HTML,
code: ResizableContainerThreePanelsHtml,
},
],
title: 'Horizontal resizing with three panels',
text: (
<p>
The <strong>EuiResizablePanel</strong> and{' '}
<strong>EuiResizableButton</strong> components can each be used
multiple times to create a more complex layout.
</p>
),
props: { EuiResizableContainer, EuiResizablePanel, EuiResizableButton },
demo: <ResizableContainerThreePanels />,
},
{
source: [
{
type: GuideSectionTypes.JS,
code: ResizableContainerVericalSource,
},
{
type: GuideSectionTypes.HTML,
code: ResizableContainerVericalHtml,
},
],
title: 'Vertical resizing',
text: (
<p>
Set <EuiCode>direction=vertical</EuiCode> on{' '}
<strong>EuiResizableContainer</strong> to set a vertical orientation
of the resizable panels.
</p>
),
props: { EuiResizableContainer, EuiResizablePanel, EuiResizableButton },
demo: (
<div className="guideDemo__highlightSpacer">
<ResizableContainerVertical />
</div>
),
},
{
source: [
{
type: GuideSectionTypes.JS,
code: ResizableResizerSizeSource,
},
{
type: GuideSectionTypes.HTML,
code: ResizableResizerSizeHtml,
},
],
title: 'Resizable button spacing',
text: (
<div>
<p>
You can control the space between panels by modifying the{' '}
<EuiCode>size</EuiCode> prop of the{' '}
<strong>EuiResizableButton</strong> component. The available sizes
are <EuiCode>xl</EuiCode>, <EuiCode>l</EuiCode>,{' '}
<EuiCode>m</EuiCode>, and <EuiCode>s</EuiCode>. You should avoid
using different sizes within the same{' '}
<strong>EuiResizableContainer</strong>, as shown in the demo below.
</p>
</div>
),
props: { EuiResizableContainer, EuiResizablePanel, EuiResizableButton },
demo: <ResizableResizerSize />,
},
],
};
Loading

0 comments on commit 2b9eca6

Please sign in to comment.