From c9ca26966eca9182520523913539e2b78bbd4b92 Mon Sep 17 00:00:00 2001 From: cchaos Date: Fri, 30 Aug 2019 15:16:50 -0400 Subject: [PATCH 01/20] Adding a shared component for the different states of each form control --- src-docs/src/routes.js | 2 +- .../src/views/form_controls/field_number.js | 74 +------ .../src/views/form_controls/field_password.js | 59 +---- .../src/views/form_controls/field_search.js | 61 +----- .../src/views/form_controls/field_text.js | 60 +----- .../src/views/form_controls/file_picker.js | 59 +++-- .../form_controls/form_controls_example.js | 20 +- src-docs/src/views/form_controls/select.js | 49 +---- src-docs/src/views/form_controls/shared.js | 202 ++++++++++++++++++ src-docs/src/views/form_controls/text_area.js | 38 +--- 10 files changed, 271 insertions(+), 353 deletions(-) create mode 100644 src-docs/src/views/form_controls/shared.js diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js index f3c8c27dfbc..b642934373e 100644 --- a/src-docs/src/routes.js +++ b/src-docs/src/routes.js @@ -326,8 +326,8 @@ const navigation = [ { name: 'Forms', items: [ - FormLayoutsExample, FormControlsExample, + FormLayoutsExample, FormValidationExample, SuperSelectExample, ComboBoxExample, diff --git a/src-docs/src/views/form_controls/field_number.js b/src-docs/src/views/form_controls/field_number.js index ebfc39dfd18..698ea3ac9c3 100644 --- a/src-docs/src/views/form_controls/field_number.js +++ b/src-docs/src/views/form_controls/field_number.js @@ -1,6 +1,7 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; -import { EuiFieldNumber, EuiSpacer, EuiText } from '../../../../src/components'; +import { EuiFieldNumber } from '../../../../src/components'; +import { Switches } from './shared'; export default class extends Component { constructor(props) { @@ -20,79 +21,14 @@ export default class extends Component { render() { return ( - + - - - - - - - - - - - - - - - - - - - - - - - - - % - - } - placeholder="0 - 100" - value={this.state.value} - onChange={this.onChange} - aria-label="Use aria labels when no actual label is in use" - /> - + ); } } diff --git a/src-docs/src/views/form_controls/field_password.js b/src-docs/src/views/form_controls/field_password.js index 89ef106d4ba..41ff291a855 100644 --- a/src-docs/src/views/form_controls/field_password.js +++ b/src-docs/src/views/form_controls/field_password.js @@ -1,6 +1,7 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; -import { EuiFieldPassword, EuiSpacer } from '../../../../src/components'; +import { EuiFieldPassword } from '../../../../src/components'; +import { Switches } from './shared'; export default class extends Component { constructor(props) { @@ -19,64 +20,14 @@ export default class extends Component { render() { return ( - + - - - - - - - - - - - - - - - - - - - - - + ); } } diff --git a/src-docs/src/views/form_controls/field_search.js b/src-docs/src/views/form_controls/field_search.js index 2224b22e9a1..0967a908955 100644 --- a/src-docs/src/views/form_controls/field_search.js +++ b/src-docs/src/views/form_controls/field_search.js @@ -1,6 +1,7 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; -import { EuiFieldSearch, EuiSpacer } from '../../../../src/components'; +import { EuiFieldSearch } from '../../../../src/components'; +import { Switches } from './shared'; export default class extends Component { constructor(props) { @@ -19,64 +20,14 @@ export default class extends Component { render() { return ( - + - - - - - - - - - - - - - - - - - - - - - + ); } } diff --git a/src-docs/src/views/form_controls/field_text.js b/src-docs/src/views/form_controls/field_text.js index 125dc557928..681a9bda121 100644 --- a/src-docs/src/views/form_controls/field_text.js +++ b/src-docs/src/views/form_controls/field_text.js @@ -1,6 +1,7 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; -import { EuiFieldText, EuiSpacer } from '../../../../src/components'; +import { EuiFieldText } from '../../../../src/components'; +import { Switches } from './shared'; export default class extends Component { constructor(props) { @@ -19,64 +20,15 @@ export default class extends Component { render() { return ( - + - - - - - - - - - - - - - - - - - - - - - + ); } } diff --git a/src-docs/src/views/form_controls/file_picker.js b/src-docs/src/views/form_controls/file_picker.js index 68f7acd2799..c7366daa435 100644 --- a/src-docs/src/views/form_controls/file_picker.js +++ b/src-docs/src/views/form_controls/file_picker.js @@ -1,4 +1,5 @@ import React, { Component, Fragment } from 'react'; +import { Switches } from './shared'; import { EuiFilePicker, @@ -6,6 +7,7 @@ import { EuiFlexItem, EuiText, EuiSpacer, + EuiSwitch, } from '../../../../src/components'; export class FilePicker extends Component { @@ -13,6 +15,7 @@ export class FilePicker extends Component { super(props); this.state = { files: {}, + large: true, }; } @@ -45,15 +48,29 @@ export class FilePicker extends Component { return ( - - { - this.onChange(files); - }} - /> + + { + this.setState({ large: e.target.checked }); + }} + />, + ]}> + { + this.onChange(files); + }} + display={this.state.large ? 'large' : 'default'} + /> + + @@ -62,30 +79,6 @@ export class FilePicker extends Component { - - - - - - - - { - this.onChange(files); - }} - /> - - - - { - this.onChange(files); - }} - /> ); } diff --git a/src-docs/src/views/form_controls/form_controls_example.js b/src-docs/src/views/form_controls/form_controls_example.js index 9d186929cd1..1bd1ead5519 100644 --- a/src-docs/src/views/form_controls/form_controls_example.js +++ b/src-docs/src/views/form_controls/form_controls_example.js @@ -87,38 +87,38 @@ export const FormControlsExample = { title: 'Form controls', sections: [ { - title: 'Search field', + title: 'Text field', source: [ { type: GuideSectionTypes.JS, - code: fieldSearchSource, + code: fieldTextSource, }, { type: GuideSectionTypes.HTML, - code: fieldSearchHtml, + code: fieldTextHtml, }, ], props: { - EuiFieldSearch, + EuiFieldText, }, - demo: , + demo: , }, { - title: 'Text field', + title: 'Search field', source: [ { type: GuideSectionTypes.JS, - code: fieldTextSource, + code: fieldSearchSource, }, { type: GuideSectionTypes.HTML, - code: fieldTextHtml, + code: fieldSearchHtml, }, ], props: { - EuiFieldText, + EuiFieldSearch, }, - demo: , + demo: , }, { title: 'Number field', diff --git a/src-docs/src/views/form_controls/select.js b/src-docs/src/views/form_controls/select.js index 1c7774d55c5..71a092c0f80 100644 --- a/src-docs/src/views/form_controls/select.js +++ b/src-docs/src/views/form_controls/select.js @@ -1,6 +1,7 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; -import { EuiSelect, EuiSpacer } from '../../../../src/components'; +import { EuiSelect } from '../../../../src/components'; +import { Switches } from './shared'; export default class extends Component { constructor(props) { @@ -25,54 +26,14 @@ export default class extends Component { render() { return ( - + - - - - - - - - - - - - - - - - - + ); } } diff --git a/src-docs/src/views/form_controls/shared.js b/src-docs/src/views/form_controls/shared.js new file mode 100644 index 00000000000..5ad8eab1c72 --- /dev/null +++ b/src-docs/src/views/form_controls/shared.js @@ -0,0 +1,202 @@ +import React, { cloneElement, Component, Fragment } from 'react'; +import { Link } from 'react-router'; +import PropTypes from 'prop-types'; + +import { + EuiFlexGroup, + EuiSwitch, + EuiHorizontalRule, + EuiFlexItem, + EuiToolTip, + EuiIcon, + EuiButtonEmpty, + EuiFormLabel, +} from '../../../../src/components'; + +export class Switches extends Component { + constructor(props) { + super(props); + + this.state = { + disabled: false, + readOnly: false, + loading: false, + compressed: false, + fullWidth: false, + prepend: undefined, + append: undefined, + }; + } + + render() { + const { + canDisabled, + canReadOnly, + canLoading, + canCompressed, + canFullWidth, + canPrepend, + canAppend, + canInvalid, + children, + extras, + } = this.props; + + const canProps = {}; + if (canDisabled) canProps.disabled = this.state.disabled; + if (canReadOnly) canProps.readOnly = this.state.readOnly; + if (canLoading) canProps.isLoading = this.state.loading; + if (canFullWidth) canProps.fullWidth = this.state.fullWidth; + if (canCompressed) canProps.compressed = this.state.compressed; + if (canPrepend && this.state.prepend) + canProps.prepend = Prepend; + if (canAppend && this.state.append) + canProps.append = Append; + if (canInvalid) canProps.isInvalid = this.state.invalid; + + return ( + + {cloneElement(children, canProps)} + + + {canDisabled && ( + + { + this.setState({ disabled: e.target.checked }); + }} + /> + + )} + {canReadOnly && ( + + { + this.setState({ readOnly: e.target.checked }); + }} + /> + + )} + {canLoading && ( + + { + this.setState({ loading: e.target.checked }); + }} + /> + + )} + {canFullWidth && ( + + { + this.setState({ fullWidth: e.target.checked }); + }} + /> + + )} + {canCompressed && ( + + + compressed{' '} + + + + + + + } + checked={this.state.compressed} + onChange={e => { + this.setState({ compressed: e.target.checked }); + }} + /> + + )} + {canPrepend && ( + + { + this.setState({ + prepend: e.target.checked, + }); + }} + /> + + )} + {canAppend && ( + + { + this.setState({ + append: e.target.checked, + }); + }} + /> + + )} + {canInvalid && ( + + { + this.setState({ + invalid: e.target.checked, + }); + }} + /> + + )} + {extras && + extras.map((extra, index) => { + return ( + + {extra} + + ); + })} + + + ); + } +} + +Switches.propTypes = { + canDisabled: PropTypes.bool, + canReadOnly: PropTypes.bool, + canLoading: PropTypes.bool, + canCompressed: PropTypes.bool, + canFullWidth: PropTypes.bool, + canFullWidth: PropTypes.bool, + canPrepend: PropTypes.bool, + canAppend: PropTypes.bool, + canInvalid: PropTypes.bool, + extras: PropTypes.arrayOf(PropTypes.node), +}; + +Switches.defaultProps = { + canDisabled: true, + canReadOnly: true, + canLoading: true, + canCompressed: true, + canFullWidth: true, + canInvalid: true, + canPrepend: false, + canAppend: false, +}; diff --git a/src-docs/src/views/form_controls/text_area.js b/src-docs/src/views/form_controls/text_area.js index 43f04395d50..1288c5d277e 100644 --- a/src-docs/src/views/form_controls/text_area.js +++ b/src-docs/src/views/form_controls/text_area.js @@ -1,6 +1,7 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; -import { EuiTextArea, EuiSpacer } from '../../../../src/components'; +import { EuiTextArea } from '../../../../src/components'; +import { Switches } from './shared'; export default class extends Component { constructor(props) { @@ -19,43 +20,14 @@ export default class extends Component { render() { return ( - + - - - - - - - - - - - - - + ); } } From 665207aa66213e1a07552bf8d8d7bdad69278e4f Mon Sep 17 00:00:00 2001 From: cchaos Date: Fri, 30 Aug 2019 16:51:28 -0400 Subject: [PATCH 02/20] Move toggles to popover --- src-docs/src/views/form_controls/shared.js | 265 +++++++++++---------- 1 file changed, 145 insertions(+), 120 deletions(-) diff --git a/src-docs/src/views/form_controls/shared.js b/src-docs/src/views/form_controls/shared.js index 5ad8eab1c72..f339a087b4b 100644 --- a/src-docs/src/views/form_controls/shared.js +++ b/src-docs/src/views/form_controls/shared.js @@ -1,16 +1,17 @@ -import React, { cloneElement, Component, Fragment } from 'react'; +import React, { cloneElement, Component } from 'react'; import { Link } from 'react-router'; import PropTypes from 'prop-types'; import { EuiFlexGroup, EuiSwitch, - EuiHorizontalRule, EuiFlexItem, EuiToolTip, EuiIcon, EuiButtonEmpty, EuiFormLabel, + EuiPopover, + EuiButtonIcon, } from '../../../../src/components'; export class Switches extends Component { @@ -23,11 +24,20 @@ export class Switches extends Component { loading: false, compressed: false, fullWidth: false, - prepend: undefined, - append: undefined, + prepend: false, + append: false, + isPopoverOpen: false, + invalid: false, }; } + updateProperty = (checked, property) => { + const currentState = { ...this.state }; + currentState[property] = checked; + this.setState(currentState); + this.props.onUpdate && this.props.onUpdate(currentState); + }; + render() { const { canDisabled, @@ -40,6 +50,8 @@ export class Switches extends Component { canInvalid, children, extras, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + onUpdate, } = this.props; const canProps = {}; @@ -55,124 +67,136 @@ export class Switches extends Component { if (canInvalid) canProps.isInvalid = this.state.invalid; return ( - - {cloneElement(children, canProps)} - - - {canDisabled && ( - - { - this.setState({ disabled: e.target.checked }); - }} - /> - - )} - {canReadOnly && ( - - { - this.setState({ readOnly: e.target.checked }); - }} - /> - - )} - {canLoading && ( - - { - this.setState({ loading: e.target.checked }); - }} - /> - - )} - {canFullWidth && ( - - { - this.setState({ fullWidth: e.target.checked }); - }} - /> - - )} - {canCompressed && ( - - - compressed{' '} - - - - - - - } - checked={this.state.compressed} - onChange={e => { - this.setState({ compressed: e.target.checked }); - }} - /> - - )} - {canPrepend && ( - - { - this.setState({ - prepend: e.target.checked, - }); - }} - /> - - )} - {canAppend && ( - - { - this.setState({ - append: e.target.checked, - }); - }} - /> - - )} - {canInvalid && ( - - { - this.setState({ - invalid: e.target.checked, - }); + + + { + this.setState({ isPopoverOpen: false }); + }} + button={ + { + this.setState({ isPopoverOpen: !this.state.isPopoverOpen }); }} /> - - )} - {extras && - extras.map((extra, index) => { - return ( - - {extra} - - ); - })} - - + }> +
+ + {canDisabled && ( + + + this.updateProperty(e.target.checked, 'disabled') + } + /> + + )} + {canReadOnly && ( + + + this.updateProperty(e.target.checked, 'readOnly') + } + /> + + )} + {canLoading && ( + + + this.updateProperty(e.target.checked, 'loading') + } + /> + + )} + {canInvalid && ( + + + this.updateProperty(e.target.checked, 'invalid') + } + /> + + )} + {canFullWidth && ( + + + this.updateProperty(e.target.checked, 'fullWidth') + } + /> + + )} + {canCompressed && ( + + + compressed{' '} + + + + + + + } + checked={this.state.compressed} + onChange={e => + this.updateProperty(e.target.checked, 'compressed') + } + /> + + )} + {canPrepend && ( + + + this.updateProperty(e.target.checked, 'prepend') + } + /> + + )} + {canAppend && ( + + + this.updateProperty(e.target.checked, 'append') + } + /> + + )} + {extras && + extras.map((extra, index) => { + return ( + + {extra} + + ); + })} + +
+ + + {cloneElement(children, canProps)} + ); } } @@ -188,6 +212,7 @@ Switches.propTypes = { canAppend: PropTypes.bool, canInvalid: PropTypes.bool, extras: PropTypes.arrayOf(PropTypes.node), + onUpdate: PropTypes.func, }; Switches.defaultProps = { From 36d48b7e0d7cce1b5ea1a65d68d8ba957c94d304 Mon Sep 17 00:00:00 2001 From: cchaos Date: Tue, 3 Sep 2019 14:09:16 -0400 Subject: [PATCH 03/20] Rename and place toggles beneath control --- .../src/views/form_controls/field_number.js | 7 +- .../src/views/form_controls/field_password.js | 7 +- .../src/views/form_controls/field_search.js | 7 +- .../src/views/form_controls/field_text.js | 7 +- .../src/views/form_controls/file_picker.js | 7 +- src-docs/src/views/form_controls/select.js | 7 +- src-docs/src/views/form_controls/shared.js | 269 +++++++++--------- src-docs/src/views/form_controls/text_area.js | 7 +- 8 files changed, 162 insertions(+), 156 deletions(-) diff --git a/src-docs/src/views/form_controls/field_number.js b/src-docs/src/views/form_controls/field_number.js index 698ea3ac9c3..aaf2d2b0126 100644 --- a/src-docs/src/views/form_controls/field_number.js +++ b/src-docs/src/views/form_controls/field_number.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { EuiFieldNumber } from '../../../../src/components'; -import { Switches } from './shared'; +import { DisplayToggles } from './shared'; export default class extends Component { constructor(props) { @@ -21,14 +21,15 @@ export default class extends Component { render() { return ( - + /* DisplayToggles wrapper for Docs only */ + - + ); } } diff --git a/src-docs/src/views/form_controls/field_password.js b/src-docs/src/views/form_controls/field_password.js index 41ff291a855..53ecc6cc04f 100644 --- a/src-docs/src/views/form_controls/field_password.js +++ b/src-docs/src/views/form_controls/field_password.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { EuiFieldPassword } from '../../../../src/components'; -import { Switches } from './shared'; +import { DisplayToggles } from './shared'; export default class extends Component { constructor(props) { @@ -20,14 +20,15 @@ export default class extends Component { render() { return ( - + /* DisplayToggles wrapper for Docs only */ + - + ); } } diff --git a/src-docs/src/views/form_controls/field_search.js b/src-docs/src/views/form_controls/field_search.js index 0967a908955..23530845ae8 100644 --- a/src-docs/src/views/form_controls/field_search.js +++ b/src-docs/src/views/form_controls/field_search.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { EuiFieldSearch } from '../../../../src/components'; -import { Switches } from './shared'; +import { DisplayToggles } from './shared'; export default class extends Component { constructor(props) { @@ -20,14 +20,15 @@ export default class extends Component { render() { return ( - + /* DisplayToggles wrapper for Docs only */ + - + ); } } diff --git a/src-docs/src/views/form_controls/field_text.js b/src-docs/src/views/form_controls/field_text.js index 681a9bda121..d7e0fbd03cf 100644 --- a/src-docs/src/views/form_controls/field_text.js +++ b/src-docs/src/views/form_controls/field_text.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { EuiFieldText } from '../../../../src/components'; -import { Switches } from './shared'; +import { DisplayToggles } from './shared'; export default class extends Component { constructor(props) { @@ -20,7 +20,8 @@ export default class extends Component { render() { return ( - + /* DisplayToggles wrapper for Docs only */ + - + ); } } diff --git a/src-docs/src/views/form_controls/file_picker.js b/src-docs/src/views/form_controls/file_picker.js index c7366daa435..e5d04f3df54 100644 --- a/src-docs/src/views/form_controls/file_picker.js +++ b/src-docs/src/views/form_controls/file_picker.js @@ -1,5 +1,5 @@ import React, { Component, Fragment } from 'react'; -import { Switches } from './shared'; +import { DisplayToggles } from './shared'; import { EuiFilePicker, @@ -49,7 +49,8 @@ export class FilePicker extends Component { - - + diff --git a/src-docs/src/views/form_controls/select.js b/src-docs/src/views/form_controls/select.js index 71a092c0f80..2d34596abab 100644 --- a/src-docs/src/views/form_controls/select.js +++ b/src-docs/src/views/form_controls/select.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { EuiSelect } from '../../../../src/components'; -import { Switches } from './shared'; +import { DisplayToggles } from './shared'; export default class extends Component { constructor(props) { @@ -26,14 +26,15 @@ export default class extends Component { render() { return ( - + /* DisplayToggles wrapper for Docs only */ + - + ); } } diff --git a/src-docs/src/views/form_controls/shared.js b/src-docs/src/views/form_controls/shared.js index f339a087b4b..e1eef7e3936 100644 --- a/src-docs/src/views/form_controls/shared.js +++ b/src-docs/src/views/form_controls/shared.js @@ -1,4 +1,4 @@ -import React, { cloneElement, Component } from 'react'; +import React, { cloneElement, Component, Fragment } from 'react'; import { Link } from 'react-router'; import PropTypes from 'prop-types'; @@ -11,10 +11,10 @@ import { EuiButtonEmpty, EuiFormLabel, EuiPopover, - EuiButtonIcon, + EuiSpacer, } from '../../../../src/components'; -export class Switches extends Component { +export class DisplayToggles extends Component { constructor(props) { super(props); @@ -67,141 +67,140 @@ export class Switches extends Component { if (canInvalid) canProps.isInvalid = this.state.invalid; return ( - - - { - this.setState({ isPopoverOpen: false }); - }} - button={ - { - this.setState({ isPopoverOpen: !this.state.isPopoverOpen }); - }} - /> - }> -
- - {canDisabled && ( - - - this.updateProperty(e.target.checked, 'disabled') - } - /> - - )} - {canReadOnly && ( - - - this.updateProperty(e.target.checked, 'readOnly') - } - /> - - )} - {canLoading && ( - - - this.updateProperty(e.target.checked, 'loading') - } - /> - - )} - {canInvalid && ( - - - this.updateProperty(e.target.checked, 'invalid') - } - /> - - )} - {canFullWidth && ( - - - this.updateProperty(e.target.checked, 'fullWidth') - } - /> - - )} - {canCompressed && ( - - - compressed{' '} - - - - - - - } - checked={this.state.compressed} - onChange={e => - this.updateProperty(e.target.checked, 'compressed') - } - /> - - )} - {canPrepend && ( - - - this.updateProperty(e.target.checked, 'prepend') - } - /> - - )} - {canAppend && ( - - - this.updateProperty(e.target.checked, 'append') - } - /> - - )} - {extras && - extras.map((extra, index) => { - return ( - - {extra} - - ); - })} - -
-
-
- {cloneElement(children, canProps)} -
+ + {cloneElement(children, canProps)} + + { + this.setState({ isPopoverOpen: false }); + }} + button={ + { + this.setState({ isPopoverOpen: !this.state.isPopoverOpen }); + }}> + Display toggles + + }> +
+ + {canDisabled && ( + + + this.updateProperty(e.target.checked, 'disabled') + } + /> + + )} + {canReadOnly && ( + + + this.updateProperty(e.target.checked, 'readOnly') + } + /> + + )} + {canLoading && ( + + + this.updateProperty(e.target.checked, 'loading') + } + /> + + )} + {canInvalid && ( + + + this.updateProperty(e.target.checked, 'invalid') + } + /> + + )} + {canFullWidth && ( + + + this.updateProperty(e.target.checked, 'fullWidth') + } + /> + + )} + {canCompressed && ( + + + compressed{' '} + + + + + + + } + checked={this.state.compressed} + onChange={e => + this.updateProperty(e.target.checked, 'compressed') + } + /> + + )} + {canPrepend && ( + + + this.updateProperty(e.target.checked, 'prepend') + } + /> + + )} + {canAppend && ( + + + this.updateProperty(e.target.checked, 'append') + } + /> + + )} + {extras && + extras.map((extra, index) => { + return ( + + {extra} + + ); + })} + +
+
+
); } } -Switches.propTypes = { +DisplayToggles.propTypes = { canDisabled: PropTypes.bool, canReadOnly: PropTypes.bool, canLoading: PropTypes.bool, @@ -215,7 +214,7 @@ Switches.propTypes = { onUpdate: PropTypes.func, }; -Switches.defaultProps = { +DisplayToggles.defaultProps = { canDisabled: true, canReadOnly: true, canLoading: true, diff --git a/src-docs/src/views/form_controls/text_area.js b/src-docs/src/views/form_controls/text_area.js index 1288c5d277e..de91dc9d559 100644 --- a/src-docs/src/views/form_controls/text_area.js +++ b/src-docs/src/views/form_controls/text_area.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { EuiTextArea } from '../../../../src/components'; -import { Switches } from './shared'; +import { DisplayToggles } from './shared'; export default class extends Component { constructor(props) { @@ -20,14 +20,15 @@ export default class extends Component { render() { return ( - + /* DisplayToggles wrapper for Docs only */ + - + ); } } From 3a9daac464dad3c9020b37ceb2a02902483d9870 Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 4 Sep 2019 11:30:10 -0400 Subject: [PATCH 04/20] cleanup --- .../src/views/form_controls/checkbox_group.js | 15 ----- .../src/views/form_controls/file_picker.js | 2 +- .../form_controls/form_controls_example.js | 56 +++++++++---------- .../src/views/form_controls/radio_group.js | 15 ----- .../src/views/form_layouts/inline_sizing.js | 2 +- 5 files changed, 30 insertions(+), 60 deletions(-) diff --git a/src-docs/src/views/form_controls/checkbox_group.js b/src-docs/src/views/form_controls/checkbox_group.js index 20679cdd113..9edfd40f885 100644 --- a/src-docs/src/views/form_controls/checkbox_group.js +++ b/src-docs/src/views/form_controls/checkbox_group.js @@ -72,21 +72,6 @@ export default class extends Component { onChange={this.onChange} disabled /> - - - - -

Compressed

-
- - - -
); } diff --git a/src-docs/src/views/form_controls/file_picker.js b/src-docs/src/views/form_controls/file_picker.js index e5d04f3df54..a02e7ec35af 100644 --- a/src-docs/src/views/form_controls/file_picker.js +++ b/src-docs/src/views/form_controls/file_picker.js @@ -49,7 +49,7 @@ export class FilePicker extends Component { - /* DisplayToggles wrapper for Docs only */ + {/* DisplayToggles wrapper for Docs only */} , }, + { + title: 'Select', + source: [ + { + type: GuideSectionTypes.JS, + code: selectSource, + }, + { + type: GuideSectionTypes.HTML, + code: selectHtml, + }, + ], + text: ( +

+ This component renders a basic HTML <select>{' '} + element. If you need more customization for how the options and/or + selected values render, use the{' '} + EuiSuperSelect. Another option is + to use the EuiComboBox, which has + search and multi-select capabilities, but also has restrictions on how + items are rendered. +

+ ), + props: { + EuiSelect, + }, + demo: , - }, { title: 'Checkbox', source: [ diff --git a/src-docs/src/views/form_controls/radio_group.js b/src-docs/src/views/form_controls/radio_group.js index 1e4cfb4f672..e727f684893 100644 --- a/src-docs/src/views/form_controls/radio_group.js +++ b/src-docs/src/views/form_controls/radio_group.js @@ -60,21 +60,6 @@ export default class extends Component { onChange={this.onChange} disabled /> - - - - -

Compressed

-
- - - -
); } diff --git a/src-docs/src/views/form_layouts/inline_sizing.js b/src-docs/src/views/form_layouts/inline_sizing.js index d66e8da3c98..56f70f5bc54 100644 --- a/src-docs/src/views/form_layouts/inline_sizing.js +++ b/src-docs/src/views/form_layouts/inline_sizing.js @@ -29,7 +29,7 @@ export default () => ( - Save + Save From f92b383397ab8818f2e5f01eb537f3ebcbd3854b Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 4 Sep 2019 12:16:44 -0400 Subject: [PATCH 05/20] New docs section for compressed --- src-docs/src/routes.js | 3 + src-docs/src/views/focus_trap/focus_trap.js | 2 +- .../views/form_compressed/form_compressed.js | 168 ++++++++++++++++ .../form_compressed_example.js | 102 ++++++++++ .../views/form_compressed/form_horizontal.js | 157 +++++++++++++++ .../src/views/form_layouts/form_compressed.js | 181 ------------------ .../form_layouts/form_layouts_example.js | 47 ----- 7 files changed, 431 insertions(+), 229 deletions(-) create mode 100644 src-docs/src/views/form_compressed/form_compressed.js create mode 100644 src-docs/src/views/form_compressed/form_compressed_example.js create mode 100644 src-docs/src/views/form_compressed/form_horizontal.js delete mode 100644 src-docs/src/views/form_layouts/form_compressed.js diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js index b642934373e..831fc73a7b7 100644 --- a/src-docs/src/routes.js +++ b/src-docs/src/routes.js @@ -96,6 +96,8 @@ import { FormControlsExample } from './views/form_controls/form_controls_example import { FormLayoutsExample } from './views/form_layouts/form_layouts_example'; +import { FormCompressedExample } from './views/form_compressed/form_compressed_example'; + import { FormValidationExample } from './views/form_validation/form_validation_example'; import { HeaderExample } from './views/header/header_example'; @@ -328,6 +330,7 @@ const navigation = [ items: [ FormControlsExample, FormLayoutsExample, + FormCompressedExample, FormValidationExample, SuperSelectExample, ComboBoxExample, diff --git a/src-docs/src/views/focus_trap/focus_trap.js b/src-docs/src/views/focus_trap/focus_trap.js index 9cb3fa0e2a5..f3da7d38146 100644 --- a/src-docs/src/views/focus_trap/focus_trap.js +++ b/src-docs/src/views/focus_trap/focus_trap.js @@ -9,7 +9,7 @@ import { EuiText, } from '../../../../src/components'; -import FormExample from '../form_layouts/form_compressed'; +import FormExample from '../form_compressed/form_compressed'; export default class extends Component { constructor(props) { diff --git a/src-docs/src/views/form_compressed/form_compressed.js b/src-docs/src/views/form_compressed/form_compressed.js new file mode 100644 index 00000000000..c14c69c6648 --- /dev/null +++ b/src-docs/src/views/form_compressed/form_compressed.js @@ -0,0 +1,168 @@ +import React, { Component } from 'react'; + +import { + EuiCheckboxGroup, + EuiComboBox, + EuiFieldText, + EuiFormRow, + EuiFilePicker, + EuiRange, + EuiSelect, + EuiSwitch, + EuiPanel, +} from '../../../../src/components'; + +import makeId from '../../../../src/components/form/form_row/make_id'; + +export default class extends Component { + constructor(props) { + super(props); + + const idPrefix = makeId(); + + this.state = { + isSwitchChecked: false, + checkboxes: [ + { + id: `${idPrefix}0`, + label: 'Option one', + }, + { + id: `${idPrefix}1`, + label: 'Option two is checked by default', + }, + { + id: `${idPrefix}2`, + label: 'Option three', + }, + ], + checkboxIdToSelectedMap: { + [`${idPrefix}1`]: true, + }, + radios: [ + { + id: `${idPrefix}4`, + label: 'Option one', + }, + { + id: `${idPrefix}5`, + label: 'Option two is selected by default', + }, + { + id: `${idPrefix}6`, + label: 'Option three', + }, + ], + radioIdSelected: `${idPrefix}5`, + comboBoxSelectionOptions: [], + value: '20', + }; + } + + onRangeChange = e => { + this.setState({ + value: e.target.value, + }); + }; + + onSwitchChange = () => { + this.setState({ + isSwitchChecked: !this.state.isSwitchChecked, + }); + }; + + onCheckboxChange = optionId => { + const newCheckboxIdToSelectedMap = { + ...this.state.checkboxIdToSelectedMap, + ...{ + [optionId]: !this.state.checkboxIdToSelectedMap[optionId], + }, + }; + + this.setState({ + checkboxIdToSelectedMap: newCheckboxIdToSelectedMap, + }); + }; + + onRadioChange = optionId => { + this.setState({ + radioIdSelected: optionId, + }); + }; + + render() { + return ( + + + + + + + + + + + + + + + + this.setState({ comboBoxSelectionOptions }) + } + /> + + + + + + + + + + + + + + + ); + } +} diff --git a/src-docs/src/views/form_compressed/form_compressed_example.js b/src-docs/src/views/form_compressed/form_compressed_example.js new file mode 100644 index 00000000000..42fbf691f1b --- /dev/null +++ b/src-docs/src/views/form_compressed/form_compressed_example.js @@ -0,0 +1,102 @@ +import React, { Fragment } from 'react'; + +import { renderToHtml } from '../../services'; + +import { GuideSectionTypes } from '../../components'; + +import { EuiCode, EuiFormRow } from '../../../../src/components'; + +import FormCompressed from './form_compressed'; +const formCompressedSource = require('!!raw-loader!./form_compressed'); +const formCompressedHtml = renderToHtml(FormCompressed); + +import FormHorizontal from './form_horizontal'; +const formHorizontalSource = require('!!raw-loader!./form_horizontal'); +const formHorizontalHtml = renderToHtml(FormHorizontal); + +export const FormCompressedExample = { + title: 'Compressed forms', + sections: [ + { + // title: 'Compressed and horizontal', + source: [ + { + type: GuideSectionTypes.JS, + code: formCompressedSource, + }, + { + type: GuideSectionTypes.HTML, + code: formCompressedHtml, + }, + ], + text: ( + +

+ Also known as Editor Style Controls, compressed + forms and controls were specifically created for use when space is + at a premium. They are not intended for use when the form is the + main objective of the page. They are best used for applications that + are of the editor style and the form controls are used to create + something else on the page. +

+

+ + Do no use compressed and non-compressed form controls in the same + form. + +

+

+ Pass display="rowCompressed" to the{' '} + EuiFormRows but you will also need to pass{' '} + compressed=true to the form controls themselves. +

+
+ ), + props: { + EuiFormRow, + }, + demo: , + snippet: [ + ` + +`, + ], + }, + { + title: 'Horizontal layout', + source: [ + { + type: GuideSectionTypes.JS, + code: formHorizontalSource, + }, + { + type: GuideSectionTypes.HTML, + code: formHorizontalHtml, + }, + ], + text: ( +

+ Editor style controls can be displayed horizontally for even better + use of limited space, just pass{' '} + display="columnCompressed" to align the + labels and inputs horizontally. +

+ ), + props: { + EuiFormRow, + }, + demo: , + snippet: [ + ` + +`, + ], + }, + ], +}; diff --git a/src-docs/src/views/form_compressed/form_horizontal.js b/src-docs/src/views/form_compressed/form_horizontal.js new file mode 100644 index 00000000000..05424cbb670 --- /dev/null +++ b/src-docs/src/views/form_compressed/form_horizontal.js @@ -0,0 +1,157 @@ +import React, { Component } from 'react'; + +import { + EuiComboBox, + EuiFieldText, + EuiFormRow, + EuiFilePicker, + EuiRange, + EuiSelect, + EuiSwitch, + EuiPanel, +} from '../../../../src/components'; + +import makeId from '../../../../src/components/form/form_row/make_id'; + +export default class extends Component { + constructor(props) { + super(props); + + const idPrefix = makeId(); + + this.state = { + isSwitchChecked: false, + checkboxes: [ + { + id: `${idPrefix}0`, + label: 'Option one', + }, + { + id: `${idPrefix}1`, + label: 'Option two is checked by default', + }, + { + id: `${idPrefix}2`, + label: 'Option three', + }, + ], + checkboxIdToSelectedMap: { + [`${idPrefix}1`]: true, + }, + radios: [ + { + id: `${idPrefix}4`, + label: 'Option one', + }, + { + id: `${idPrefix}5`, + label: 'Option two is selected by default', + }, + { + id: `${idPrefix}6`, + label: 'Option three', + }, + ], + radioIdSelected: `${idPrefix}5`, + comboBoxSelectionOptions: [], + value: '20', + }; + } + + onRangeChange = e => { + this.setState({ + value: e.target.value, + }); + }; + + onSwitchChange = () => { + this.setState({ + isSwitchChecked: !this.state.isSwitchChecked, + }); + }; + + onCheckboxChange = optionId => { + const newCheckboxIdToSelectedMap = { + ...this.state.checkboxIdToSelectedMap, + ...{ + [optionId]: !this.state.checkboxIdToSelectedMap[optionId], + }, + }; + + this.setState({ + checkboxIdToSelectedMap: newCheckboxIdToSelectedMap, + }); + }; + + onRadioChange = optionId => { + this.setState({ + radioIdSelected: optionId, + }); + }; + + render() { + return ( + + + + + + + + + + + + + + + + this.setState({ comboBoxSelectionOptions }) + } + /> + + + + + + + + + + + ); + } +} diff --git a/src-docs/src/views/form_layouts/form_compressed.js b/src-docs/src/views/form_layouts/form_compressed.js deleted file mode 100644 index 8ab9ba27cb8..00000000000 --- a/src-docs/src/views/form_layouts/form_compressed.js +++ /dev/null @@ -1,181 +0,0 @@ -import React, { Component } from 'react'; - -import { - EuiButton, - EuiCheckboxGroup, - EuiComboBox, - EuiFieldText, - EuiForm, - EuiFormRow, - EuiFilePicker, - EuiRange, - EuiSelect, - EuiSpacer, - EuiSwitch, - EuiPanel, -} from '../../../../src/components'; - -import makeId from '../../../../src/components/form/form_row/make_id'; - -export default class extends Component { - constructor(props) { - super(props); - - const idPrefix = makeId(); - - this.state = { - isSwitchChecked: false, - checkboxes: [ - { - id: `${idPrefix}0`, - label: 'Option one', - }, - { - id: `${idPrefix}1`, - label: 'Option two is checked by default', - }, - { - id: `${idPrefix}2`, - label: 'Option three', - }, - ], - checkboxIdToSelectedMap: { - [`${idPrefix}1`]: true, - }, - radios: [ - { - id: `${idPrefix}4`, - label: 'Option one', - }, - { - id: `${idPrefix}5`, - label: 'Option two is selected by default', - }, - { - id: `${idPrefix}6`, - label: 'Option three', - }, - ], - radioIdSelected: `${idPrefix}5`, - comboBoxSelectionOptions: [], - value: '20', - }; - } - - onRangeChange = e => { - this.setState({ - value: e.target.value, - }); - }; - - onSwitchChange = () => { - this.setState({ - isSwitchChecked: !this.state.isSwitchChecked, - }); - }; - - onCheckboxChange = optionId => { - const newCheckboxIdToSelectedMap = { - ...this.state.checkboxIdToSelectedMap, - ...{ - [optionId]: !this.state.checkboxIdToSelectedMap[optionId], - }, - }; - - this.setState({ - checkboxIdToSelectedMap: newCheckboxIdToSelectedMap, - }); - }; - - onRadioChange = optionId => { - this.setState({ - radioIdSelected: optionId, - }); - }; - - render() { - return ( - - - - - - - - - - - - - - - - - this.setState({ comboBoxSelectionOptions }) - } - /> - - - - - - - - - - - - - - - - - - Save form - - - - ); - } -} diff --git a/src-docs/src/views/form_layouts/form_layouts_example.js b/src-docs/src/views/form_layouts/form_layouts_example.js index 47bb218318a..75570fda683 100644 --- a/src-docs/src/views/form_layouts/form_layouts_example.js +++ b/src-docs/src/views/form_layouts/form_layouts_example.js @@ -35,10 +35,6 @@ import InlinePopover from './inline_popover'; const inlinePopoverSource = require('!!raw-loader!./inline_popover'); const inlinePopoverHtml = renderToHtml(InlinePopover); -import FormCompressed from './form_compressed'; -const formCompressedSource = require('!!raw-loader!./form_compressed'); -const formCompressedHtml = renderToHtml(FormCompressed); - export const FormLayoutsExample = { title: 'Form layouts', sections: [ @@ -107,49 +103,6 @@ export const FormLayoutsExample = { `, }, - { - title: 'Compressed and horizontal', - source: [ - { - type: GuideSectionTypes.JS, - code: formCompressedSource, - }, - { - type: GuideSectionTypes.HTML, - code: formCompressedHtml, - }, - ], - text: ( -

- If the particular form is in an area with a small amount of real - estate, you can pass{' '} - display="rowCompressed" to the{' '} - EuiFormRows but you will also need to pass{' '} - compressed=true to the form controls themselves. - For editor style controls, pass{' '} - display="columnCompressed" to align the - labels and inputs horizontally. -

- ), - props: { - EuiFormRow, - }, - demo: , - snippet: [ - ` - -`, - ` - -`, - ], - }, { title: 'Described form groups', source: [ From 91209a7a0b5ec47efcee8a748741a0b2ec7f1508 Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 4 Sep 2019 14:30:36 -0400 Subject: [PATCH 06/20] Added `columnCompressedSwitch` to display type of EuiFormRow For better alignment of switch style controls --- .../form_compressed_example.js | 19 ++++++++++++------ .../views/form_compressed/form_horizontal.js | 2 +- .../__snapshots__/form_row.test.js.snap | 15 ++++++++++++++ src/components/form/form_row/_form_row.scss | 20 +++++++++++++++++++ src/components/form/form_row/form_row.js | 4 ++++ 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src-docs/src/views/form_compressed/form_compressed_example.js b/src-docs/src/views/form_compressed/form_compressed_example.js index 42fbf691f1b..55462872c5d 100644 --- a/src-docs/src/views/form_compressed/form_compressed_example.js +++ b/src-docs/src/views/form_compressed/form_compressed_example.js @@ -78,12 +78,19 @@ export const FormCompressedExample = { }, ], text: ( -

- Editor style controls can be displayed horizontally for even better - use of limited space, just pass{' '} - display="columnCompressed" to align the - labels and inputs horizontally. -

+ +

+ Editor style controls can be displayed horizontally for even better + use of limited space, just pass{' '} + display="columnCompressed" to align the + labels and inputs horizontally. +

+

+ EuiSwitches are a special case in which so you must + pass columnCompressedSwitch as the display + property. +

+
), props: { EuiFormRow, diff --git a/src-docs/src/views/form_compressed/form_horizontal.js b/src-docs/src/views/form_compressed/form_horizontal.js index 05424cbb670..63f00966b13 100644 --- a/src-docs/src/views/form_compressed/form_horizontal.js +++ b/src-docs/src/views/form_compressed/form_horizontal.js @@ -144,7 +144,7 @@ export default class extends Component { /> - + `; +exports[`EuiFormRow props display type columnCompressedSwitch is rendered 1`] = ` +
+
+ +
+
+`; + exports[`EuiFormRow props display type row is rendered 1`] = `
Date: Wed, 4 Sep 2019 15:13:25 -0400 Subject: [PATCH 07/20] Add help section --- .../form_compressed_example.js | 35 ++++++++++ .../form_compressed/form_horizontal_help.js | 68 +++++++++++++++++++ src-docs/src/views/form_controls/shared.js | 2 +- 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src-docs/src/views/form_compressed/form_horizontal_help.js diff --git a/src-docs/src/views/form_compressed/form_compressed_example.js b/src-docs/src/views/form_compressed/form_compressed_example.js index 55462872c5d..3c232daae75 100644 --- a/src-docs/src/views/form_compressed/form_compressed_example.js +++ b/src-docs/src/views/form_compressed/form_compressed_example.js @@ -1,4 +1,5 @@ import React, { Fragment } from 'react'; +import { Link } from 'react-router'; import { renderToHtml } from '../../services'; @@ -14,6 +15,10 @@ import FormHorizontal from './form_horizontal'; const formHorizontalSource = require('!!raw-loader!./form_horizontal'); const formHorizontalHtml = renderToHtml(FormHorizontal); +import FormHelp from './form_horizontal_help'; +const formHelpSource = require('!!raw-loader!./form_horizontal_help'); +const formHelpHtml = renderToHtml(FormHelp); + export const FormCompressedExample = { title: 'Compressed forms', sections: [ @@ -105,5 +110,35 @@ export const FormCompressedExample = { `, ], }, + { + title: 'Contextual help', + source: [ + { + type: GuideSectionTypes.JS, + code: formHelpSource, + }, + { + type: GuideSectionTypes.HTML, + code: formHelpHtml, + }, + ], + text: ( + +

+ When using compressed form styles, it is best not to overload the UI + with expansive help text. If it's short and part of the + validation, use the helpText. However, if + it's an explanation of the control, consider wrapping the whole + form row in an EuiToolTip with a + long delay. +

+
+ ), + props: { + EuiFormRow, + }, + demo: , + snippet: [''], + }, ], }; diff --git a/src-docs/src/views/form_compressed/form_horizontal_help.js b/src-docs/src/views/form_compressed/form_horizontal_help.js new file mode 100644 index 00000000000..b5deb5c378a --- /dev/null +++ b/src-docs/src/views/form_compressed/form_horizontal_help.js @@ -0,0 +1,68 @@ +import React, { Component } from 'react'; + +import { + EuiFieldText, + EuiFormRow, + EuiSelect, + EuiSwitch, + EuiPanel, +} from '../../../../src/components'; + +export default class extends Component { + constructor(props) { + super(props); + + this.state = { + isSwitchChecked: false, + value: '20', + }; + } + + onSwitchChange = () => { + this.setState({ + isSwitchChecked: !this.state.isSwitchChecked, + }); + }; + + render() { + return ( + + + + + + + + + + Only accepts zeros and ones.}> + + + + ); + } +} diff --git a/src-docs/src/views/form_controls/shared.js b/src-docs/src/views/form_controls/shared.js index e1eef7e3936..f130611eaf9 100644 --- a/src-docs/src/views/form_controls/shared.js +++ b/src-docs/src/views/form_controls/shared.js @@ -149,7 +149,7 @@ export class DisplayToggles extends Component { compressed{' '} - + From 8f358a7f8c29d2b95921f869a081c522f3bba3bc Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 4 Sep 2019 15:38:45 -0400 Subject: [PATCH 08/20] Account for tooltips as pre/appends --- .../form/form_control_layout/_form_control_layout.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/form/form_control_layout/_form_control_layout.scss b/src/components/form/form_control_layout/_form_control_layout.scss index db4b0a93d0f..961cad44ff9 100644 --- a/src/components/form/form_control_layout/_form_control_layout.scss +++ b/src/components/form/form_control_layout/_form_control_layout.scss @@ -85,6 +85,13 @@ } } + // In case a tooltip was passed as a pre/append + // The cloned element's classname would have been passed to the tooltip not the anchor + .euiToolTipAnchor { + padding: $euiSizeXS; + background-color: $euiFormInputGroupLabelBackground; + } + // // Borders From 854ec6d7cf1cd1e61ff2fdbae025f1e030ea0b31 Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 4 Sep 2019 15:48:56 -0400 Subject: [PATCH 09/20] Finalize help section --- .../form_compressed_example.js | 35 ++++++++++++++----- .../form_compressed/form_horizontal_help.js | 31 ++++++---------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src-docs/src/views/form_compressed/form_compressed_example.js b/src-docs/src/views/form_compressed/form_compressed_example.js index 3c232daae75..80025bceecb 100644 --- a/src-docs/src/views/form_compressed/form_compressed_example.js +++ b/src-docs/src/views/form_compressed/form_compressed_example.js @@ -5,7 +5,7 @@ import { renderToHtml } from '../../services'; import { GuideSectionTypes } from '../../components'; -import { EuiCode, EuiFormRow } from '../../../../src/components'; +import { EuiCode, EuiFormRow, EuiToolTip } from '../../../../src/components'; import FormCompressed from './form_compressed'; const formCompressedSource = require('!!raw-loader!./form_compressed'); @@ -125,20 +125,39 @@ export const FormCompressedExample = { text: (

- When using compressed form styles, it is best not to overload the UI - with expansive help text. If it's short and part of the - validation, use the helpText. However, if - it's an explanation of the control, consider wrapping the whole - form row in an EuiToolTip with a - long delay. + When using compressed, horizontal form styles, it is best not to + overload the UI with expansive help text. If it's short and + part of the validation, use helpText. However, if + it's an explanation of the control, consider wraping the label + with a EuiToolTip and appending + the questionInCircle icon to it.

), props: { EuiFormRow, + EuiToolTip, }, demo: , - snippet: [''], + snippet: [ + ` + +`, + ` + + Label + + + }> + +`, + ], }, ], }; diff --git a/src-docs/src/views/form_compressed/form_horizontal_help.js b/src-docs/src/views/form_compressed/form_horizontal_help.js index b5deb5c378a..9cdc912c92d 100644 --- a/src-docs/src/views/form_compressed/form_horizontal_help.js +++ b/src-docs/src/views/form_compressed/form_horizontal_help.js @@ -4,9 +4,10 @@ import { EuiFieldText, EuiFormRow, EuiSelect, - EuiSwitch, EuiPanel, + EuiIcon, } from '../../../../src/components'; +import { EuiToolTip } from '../../../../src/components/tool_tip'; export default class extends Component { constructor(props) { @@ -29,19 +30,20 @@ export default class extends Component { + label={ + + + Label + + + } + display="columnCompressed"> - - Only accepts zeros and ones.
}> - - ); } From 53d993b8fb80b575f5c8bee695358f1f433d71ea Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 4 Sep 2019 19:10:40 -0400 Subject: [PATCH 10/20] Allow passing a string as the pre/appends and it automatically wraps it in a form label --- .../form_control_layout.test.tsx.snap | 32 ++++++++++++++++++- .../form_control_layout.test.tsx | 14 +++++++- .../form_control_layout.tsx | 17 +++++++--- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/components/form/form_control_layout/__snapshots__/form_control_layout.test.tsx.snap b/src/components/form/form_control_layout/__snapshots__/form_control_layout.test.tsx.snap index 0aeb606629a..9eead0d5469 100644 --- a/src/components/form/form_control_layout/__snapshots__/form_control_layout.test.tsx.snap +++ b/src/components/form/form_control_layout/__snapshots__/form_control_layout.test.tsx.snap @@ -240,7 +240,22 @@ exports[`EuiFormControlLayout props one append is rendered 1`] = `
`; -exports[`EuiFormControlLayout props one prepend is rendered 1`] = ` +exports[`EuiFormControlLayout props one append string is rendered 1`] = ` +
+
+ +
+`; + +exports[`EuiFormControlLayout props one prepend node is rendered 1`] = `
@@ -255,6 +270,21 @@ exports[`EuiFormControlLayout props one prepend is rendered 1`] = `
`; +exports[`EuiFormControlLayout props one prepend string is rendered 1`] = ` +
+ +
+
+`; + exports[`EuiFormControlLayout props readOnly is rendered 1`] = `
{ expect(component).toMatchSnapshot(); }); - test('one prepend is rendered', () => { + test('one prepend node is rendered', () => { const component = render( 1} /> ); @@ -130,6 +130,12 @@ describe('EuiFormControlLayout', () => { expect(component).toMatchSnapshot(); }); + test('one prepend string is rendered', () => { + const component = render(); + + expect(component).toMatchSnapshot(); + }); + test('one append is rendered', () => { const component = render( 1} /> @@ -138,6 +144,12 @@ describe('EuiFormControlLayout', () => { expect(component).toMatchSnapshot(); }); + test('one append string is rendered', () => { + const component = render(); + + expect(component).toMatchSnapshot(); + }); + test('multiple prepends are rendered', () => { const component = render( 1, 2]} /> diff --git a/src/components/form/form_control_layout/form_control_layout.tsx b/src/components/form/form_control_layout/form_control_layout.tsx index b0198868c9a..76862973427 100644 --- a/src/components/form/form_control_layout/form_control_layout.tsx +++ b/src/components/form/form_control_layout/form_control_layout.tsx @@ -12,6 +12,7 @@ import { EuiFormControlLayoutIconsProps, } from './form_control_layout_icons'; import { CommonProps } from '../../common'; +import { EuiFormLabel } from '../form_label'; export { ICON_SIDES } from './form_control_layout_icons'; @@ -22,11 +23,11 @@ type EuiFormControlLayoutProps = CommonProps & /** * Creates an input group with element(s) coming before children */ - prepend?: ReactElements; + prepend?: string | ReactElements; /** * Creates an input group with element(s) coming after children */ - append?: ReactElements; + append?: string | ReactElements; children?: ReactNode; icon?: EuiFormControlLayoutIconsProps['icon']; clear?: EuiFormControlLayoutIconsProps['clear']; @@ -87,11 +88,15 @@ export class EuiFormControlLayout extends Component { ); } - renderPrepends(prepend: ReactElements | undefined | null) { + renderPrepends(prepend: string | ReactElements | undefined | null) { if (!prepend) { return; } + if (typeof prepend === 'string') { + prepend = {prepend}; + } + const prependNodes = React.Children.map(prepend, (item, index) => this.createSideNode(item, 'prepend', index) ); @@ -99,11 +104,15 @@ export class EuiFormControlLayout extends Component { return prependNodes; } - renderAppends(append: ReactElements | undefined | null) { + renderAppends(append: string | ReactElements | undefined | null) { if (!append) { return; } + if (typeof append === 'string') { + append = {append}; + } + const appendNodes = React.Children.map(append, (item, index) => this.createSideNode(item, 'append', index) ); From 067bc5e7a3137cce5f82f19ee5b022aa8c61a50d Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 5 Sep 2019 18:59:21 -0400 Subject: [PATCH 11/20] Added `DisplayToggles` for more form controls --- .../src/views/color_picker/kitchen_sink.js | 56 ++-------------- src-docs/src/views/combo_box/combo_box.js | 22 ++++--- src-docs/src/views/date_picker/states.js | 49 ++++---------- .../src/views/super_select/super_select.js | 65 ++----------------- 4 files changed, 36 insertions(+), 156 deletions(-) diff --git a/src-docs/src/views/color_picker/kitchen_sink.js b/src-docs/src/views/color_picker/kitchen_sink.js index b9cdd4d55c9..f0b9f496486 100644 --- a/src-docs/src/views/color_picker/kitchen_sink.js +++ b/src-docs/src/views/color_picker/kitchen_sink.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; -import { EuiColorPicker, EuiFormRow } from '../../../../src/components'; -import { isValidHex } from '../../../../src/services'; +import { EuiColorPicker } from '../../../../src/components'; +import { DisplayToggles } from '../form_controls/shared'; export class KitchenSink extends Component { constructor(props) { @@ -16,55 +16,11 @@ export class KitchenSink extends Component { }; render() { - const hasErrors = !isValidHex(this.state.color) && this.state.color !== ''; - const isCompressed = true; - - let errors; - if (hasErrors) { - errors = ['Provide a valid hex value']; - } - return ( - - - console.log('onBlur')} - onFocus={() => console.log('onFocus')} - compressed={isCompressed} - fullWidth={true} - popoverZIndex={10} - mode="default" - swatches={['#333', '#666', '#999', '#CCC', '#FFF']} - /> - - - - - - - - - - - - - - + /* DisplayToggles wrapper for Docs only */ + + + ); } } diff --git a/src-docs/src/views/combo_box/combo_box.js b/src-docs/src/views/combo_box/combo_box.js index 015177c6f42..560d88c8988 100644 --- a/src-docs/src/views/combo_box/combo_box.js +++ b/src-docs/src/views/combo_box/combo_box.js @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import { EuiComboBox } from '../../../../src/components'; +import { DisplayToggles } from '../form_controls/shared'; export default class extends Component { constructor(props) { @@ -82,15 +83,18 @@ export default class extends Component { render() { const { selectedOptions } = this.state; return ( - + /* DisplayToggles wrapper for Docs only */ + + + ); } } diff --git a/src-docs/src/views/date_picker/states.js b/src-docs/src/views/date_picker/states.js index b1813e50808..9ec99d552f0 100644 --- a/src-docs/src/views/date_picker/states.js +++ b/src-docs/src/views/date_picker/states.js @@ -5,6 +5,7 @@ import { EuiSpacer, EuiFormRow, } from '../../../../src/components'; +import { DisplayToggles } from '../form_controls/shared'; export default class extends Component { constructor(props) { @@ -30,15 +31,18 @@ export default class extends Component { ]; return ( + /* DisplayToggles wrapper for Docs only */
- + + + - + - - - - - - - - - - - - + /* DisplayToggles wrapper for Docs only */ + - - - - - - - - - - - - - - - - - - - - - - - - - + ); } } From 972839a769a6a2f8d342c36154c4cbad3bd8b708 Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 5 Sep 2019 18:59:57 -0400 Subject: [PATCH 12/20] Added Complex example --- .../views/form_compressed/complex_example.js | 168 ++++++++++++++++++ .../form_compressed_example.js | 31 ++++ 2 files changed, 199 insertions(+) create mode 100644 src-docs/src/views/form_compressed/complex_example.js diff --git a/src-docs/src/views/form_compressed/complex_example.js b/src-docs/src/views/form_compressed/complex_example.js new file mode 100644 index 00000000000..be8c8cf7bff --- /dev/null +++ b/src-docs/src/views/form_compressed/complex_example.js @@ -0,0 +1,168 @@ +import React, { Component } from 'react'; + +import { + EuiFieldText, + EuiFormRow, + EuiSelect, + EuiPanel, + EuiIcon, + EuiFormControlLayoutDelimited, + EuiRange, + EuiSuperSelect, + EuiColorPicker, + EuiFieldNumber, + EuiToolTip, + EuiButtonIcon, +} from '../../../../src/components'; +import makeId from '../../../../src/components/form/form_row/make_id'; + +export default class extends Component { + constructor(props) { + super(props); + const idPrefix = makeId; + + this.toggleButtons = [ + { + id: `${idPrefix}0`, + label: 'coarse', + }, + { + id: `${idPrefix}1`, + label: 'fine', + }, + { + id: `${idPrefix}2`, + label: 'finest', + }, + ]; + + this.state = { + isSwitchChecked: false, + opacityValue: '20', + buttonGroupIdSelected: `${idPrefix}1`, + color: '#DB1374', + }; + } + + onColorChange = value => { + this.setState({ color: value }); + }; + + onSwitchChange = () => { + this.setState({ + isSwitchChecked: !this.state.isSwitchChecked, + }); + }; + + onRangeChange = e => { + this.setState({ + opacityValue: e.target.value, + }); + }; + + onChange = optionId => { + this.setState({ + buttonGroupIdSelected: optionId, + }); + }; + + render() { + return ( + + + + + + + + } + endControl={ + + } + /> + + + + + + + + + Label + + + } + display="columnCompressed"> + + + + + + + + + + } + append="px" + /> + + + + + + + ); + } +} diff --git a/src-docs/src/views/form_compressed/form_compressed_example.js b/src-docs/src/views/form_compressed/form_compressed_example.js index 80025bceecb..1afd1815981 100644 --- a/src-docs/src/views/form_compressed/form_compressed_example.js +++ b/src-docs/src/views/form_compressed/form_compressed_example.js @@ -19,6 +19,10 @@ import FormHelp from './form_horizontal_help'; const formHelpSource = require('!!raw-loader!./form_horizontal_help'); const formHelpHtml = renderToHtml(FormHelp); +import ComplexExample from './complex_example'; +const ComplexExampleSource = require('!!raw-loader!./complex_example'); +const ComplexExampleHtml = renderToHtml(ComplexExample); + export const FormCompressedExample = { title: 'Compressed forms', sections: [ @@ -159,5 +163,32 @@ export const FormCompressedExample = { `, ], }, + { + title: 'Complex example', + source: [ + { + type: GuideSectionTypes.JS, + code: ComplexExampleSource, + }, + { + type: GuideSectionTypes.HTML, + code: ComplexExampleHtml, + }, + ], + text: ( + +

+ This is an example of how to combine compressed form controls with + from rows, labels, prepend and appends. +

+
+ ), + props: { + // EuiFormRow, + // EuiToolTip, + }, + demo: , + snippet: [''], + }, ], }; From 0f3af1cc6e9c0fd1cce478138f545d886f0796be Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 10 Jul 2019 13:41:24 -0400 Subject: [PATCH 13/20] Made all EuiSuperDatePicker form controls compressed (in popover) --- .../date_popover/_absolute_tab.scss | 3 + .../date_popover/_index.scss | 1 + .../date_popover/absolute_tab.js | 3 +- .../date_popover/relative_tab.js | 17 +- .../__snapshots__/quick_select.test.js.snap | 354 +++++++----------- .../quick_select_popover/quick_select.js | 68 ++-- .../quick_select_popover/refresh_interval.js | 56 ++- 7 files changed, 212 insertions(+), 290 deletions(-) create mode 100644 src/components/date_picker/super_date_picker/date_popover/_absolute_tab.scss diff --git a/src/components/date_picker/super_date_picker/date_popover/_absolute_tab.scss b/src/components/date_picker/super_date_picker/date_popover/_absolute_tab.scss new file mode 100644 index 00000000000..8fc06622454 --- /dev/null +++ b/src/components/date_picker/super_date_picker/date_popover/_absolute_tab.scss @@ -0,0 +1,3 @@ +.euiSuperDatePicker__absoluteDateFormRow { + padding: 0 $euiSizeS $euiSizeS !important; // override compressed form row +} diff --git a/src/components/date_picker/super_date_picker/date_popover/_index.scss b/src/components/date_picker/super_date_picker/date_popover/_index.scss index d8a2dc7d5a5..e184170cbc1 100644 --- a/src/components/date_picker/super_date_picker/date_popover/_index.scss +++ b/src/components/date_picker/super_date_picker/date_popover/_index.scss @@ -1,2 +1,3 @@ +@import 'absolute_tab'; @import 'date_popover_button'; @import 'date_popover_content'; diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js index 30269280f05..51f17a14514 100644 --- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js +++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js @@ -62,7 +62,7 @@ export class EuiAbsoluteTab extends Component { onChange={this.handleChange} /> = 0' : null}> - - - + @@ -113,6 +113,7 @@ export class EuiRelativeTab extends Component { /> - - - + hasNoInitialSelection={false} + isLoading={false} + onChange={[Function]} + options={ + Array [ + Object { + "text": "Last", + "value": "last", + }, + Object { + "text": "Next", + "value": "next", + }, + ] + } + value="last" + /> - - - + isLoading={false} + onChange={[Function]} + value={15} + /> - - - + hasNoInitialSelection={false} + isLoading={false} + onChange={[Function]} + options={ + Array [ + Object { + "text": "seconds", + "value": "s", + }, + Object { + "text": "minutes", + "value": "m", + }, + Object { + "text": "hours", + "value": "h", + }, + Object { + "text": "days", + "value": "d", + }, + Object { + "text": "weeks", + "value": "w", + }, + Object { + "text": "months", + "value": "M", + }, + Object { + "text": "years", + "value": "y", + }, + ] + } + value="m" + /> - - - Apply - - + Apply + - - - + hasNoInitialSelection={false} + isLoading={false} + onChange={[Function]} + options={ + Array [ + Object { + "text": "Last", + "value": "last", + }, + Object { + "text": "Next", + "value": "next", + }, + ] + } + value="Next" + /> - - - + isLoading={false} + onChange={[Function]} + value={32} + /> - - - + hasNoInitialSelection={false} + isLoading={false} + onChange={[Function]} + options={ + Array [ + Object { + "text": "seconds", + "value": "s", + }, + Object { + "text": "minutes", + "value": "m", + }, + Object { + "text": "hours", + "value": "h", + }, + Object { + "text": "days", + "value": "d", + }, + Object { + "text": "weeks", + "value": "w", + }, + Object { + "text": "months", + "value": "M", + }, + Object { + "text": "years", + "value": "y", + }, + ] + } + value="M" + /> - - - Apply - - + Apply + - - - + - - - + - - - + - - - Apply - - + + Apply + diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js index e7f5e52b1cb..4c0f5fcc7bb 100644 --- a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js +++ b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js @@ -5,7 +5,7 @@ import { timeUnits, timeUnitsPlural } from '../time_units'; import { EuiFlexGroup, EuiFlexItem } from '../../../flex'; import { EuiTitle } from '../../../title'; import { EuiSpacer } from '../../../spacer'; -import { EuiFormRow, EuiSelect, EuiFieldNumber } from '../../../form'; +import { EuiSelect, EuiFieldNumber } from '../../../form'; import { EuiButton } from '../../../button'; const refreshUnitsOptions = Object.keys(timeUnits) @@ -122,40 +122,34 @@ export class EuiRefreshInterval extends Component { - - - + - - - + - - - {this.props.isPaused ? 'Start' : 'Stop'} - - + + {this.props.isPaused ? 'Start' : 'Stop'} + From b68c29b5b716efdae8635b0cb48101a596b5ac70 Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 5 Sep 2019 22:01:28 -0400 Subject: [PATCH 14/20] Connection prepend/appends with input via `htmlFor` --- .../__snapshots__/field_number.test.js.snap | 1 + .../form/field_number/field_number.js | 3 ++- .../__snapshots__/field_text.test.js.snap | 1 + src/components/form/field_text/field_text.js | 3 ++- .../form_control_layout.test.tsx.snap | 2 +- .../form_control_layout.test.tsx | 2 +- .../form_control_layout.tsx | 23 ++++++++++++++----- .../select/__snapshots__/select.test.js.snap | 1 + src/components/form/select/select.js | 3 ++- 9 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/components/form/field_number/__snapshots__/field_number.test.js.snap b/src/components/form/field_number/__snapshots__/field_number.test.js.snap index 15a4aa9df41..ea8bcf26f2b 100644 --- a/src/components/form/field_number/__snapshots__/field_number.test.js.snap +++ b/src/components/form/field_number/__snapshots__/field_number.test.js.snap @@ -5,6 +5,7 @@ exports[`EuiFieldNumber is rendered 1`] = ` compressed="false" fullwidth="false" icon="alert" + inputid="1" isloading="false" > diff --git a/src/components/form/field_number/field_number.js b/src/components/form/field_number/field_number.js index 1adb63f0408..3509ef0dcab 100644 --- a/src/components/form/field_number/field_number.js +++ b/src/components/form/field_number/field_number.js @@ -41,7 +41,8 @@ export const EuiFieldNumber = ({ compressed={compressed} readOnly={readOnly} prepend={prepend} - append={append}> + append={append} + inputId={id}> diff --git a/src/components/form/field_text/field_text.js b/src/components/form/field_text/field_text.js index 25c240f279f..34ab574a2d7 100644 --- a/src/components/form/field_text/field_text.js +++ b/src/components/form/field_text/field_text.js @@ -39,7 +39,8 @@ export const EuiFieldText = ({ compressed={compressed} readOnly={readOnly} prepend={prepend} - append={append}> + append={append} + inputId={id}> `; -exports[`EuiFormControlLayout props one append is rendered 1`] = ` +exports[`EuiFormControlLayout props one append node is rendered 1`] = `
diff --git a/src/components/form/form_control_layout/form_control_layout.test.tsx b/src/components/form/form_control_layout/form_control_layout.test.tsx index 06abf58b864..bd3337e374a 100644 --- a/src/components/form/form_control_layout/form_control_layout.test.tsx +++ b/src/components/form/form_control_layout/form_control_layout.test.tsx @@ -136,7 +136,7 @@ describe('EuiFormControlLayout', () => { expect(component).toMatchSnapshot(); }); - test('one append is rendered', () => { + test('one append node is rendered', () => { const component = render( 1} /> ); diff --git a/src/components/form/form_control_layout/form_control_layout.tsx b/src/components/form/form_control_layout/form_control_layout.tsx index 76862973427..6e057e6f0cf 100644 --- a/src/components/form/form_control_layout/form_control_layout.tsx +++ b/src/components/form/form_control_layout/form_control_layout.tsx @@ -37,6 +37,10 @@ type EuiFormControlLayoutProps = CommonProps & className?: string; compressed?: boolean; readOnly?: boolean; + /** + * Connects the prepend and append labels to the input + */ + inputId?: string; }; export class EuiFormControlLayout extends Component { @@ -53,6 +57,7 @@ export class EuiFormControlLayout extends Component { prepend, append, readOnly, + inputId, ...rest } = this.props; @@ -68,8 +73,8 @@ export class EuiFormControlLayout extends Component { className ); - const prependNodes = this.renderPrepends(prepend); - const appendNodes = this.renderAppends(append); + const prependNodes = this.renderPrepends(prepend, inputId); + const appendNodes = this.renderAppends(append, inputId); return (
@@ -88,13 +93,16 @@ export class EuiFormControlLayout extends Component { ); } - renderPrepends(prepend: string | ReactElements | undefined | null) { + renderPrepends( + prepend: string | ReactElements | undefined | null, + inputId?: string + ) { if (!prepend) { return; } if (typeof prepend === 'string') { - prepend = {prepend}; + prepend = {prepend}; } const prependNodes = React.Children.map(prepend, (item, index) => @@ -104,13 +112,16 @@ export class EuiFormControlLayout extends Component { return prependNodes; } - renderAppends(append: string | ReactElements | undefined | null) { + renderAppends( + append: string | ReactElements | undefined | null, + inputId?: string + ) { if (!append) { return; } if (typeof append === 'string') { - append = {append}; + append = {append}; } const appendNodes = React.Children.map(append, (item, index) => diff --git a/src/components/form/select/__snapshots__/select.test.js.snap b/src/components/form/select/__snapshots__/select.test.js.snap index 230f65ef8ba..31245a34f5d 100644 --- a/src/components/form/select/__snapshots__/select.test.js.snap +++ b/src/components/form/select/__snapshots__/select.test.js.snap @@ -5,6 +5,7 @@ exports[`EuiSelect is rendered 1`] = ` compressed="false" fullwidth="false" icon="[object Object]" + inputid="id" isloading="false" > diff --git a/src/components/form/select/select.js b/src/components/form/select/select.js index 9bc45b27291..576cb4c4bf2 100644 --- a/src/components/form/select/select.js +++ b/src/components/form/select/select.js @@ -74,7 +74,8 @@ export const EuiSelect = ({ compressed={compressed} readOnly={readOnly} prepend={prepend} - append={append}> + append={append} + inputId={id}>