From f5f82c6123f7f5c7059d5d1df24f071b02f7cee5 Mon Sep 17 00:00:00 2001 From: cchaos Date: Tue, 26 Jun 2018 16:28:07 -0400 Subject: [PATCH 01/21] Updating filter buttons and group styles --- .../src/views/filter_group/filter_group.js | 17 +++- .../filter_group/_filter_button.scss | 85 ++++++++----------- .../filter_group/_filter_group.scss | 10 +-- src/components/filter_group/filter_button.js | 17 ++-- src/components/form/_mixins.scss | 4 +- src/components/form/_variables.scss | 2 + 6 files changed, 66 insertions(+), 69 deletions(-) diff --git a/src-docs/src/views/filter_group/filter_group.js b/src-docs/src/views/filter_group/filter_group.js index 48a0a2b2f21..8003787cd26 100644 --- a/src-docs/src/views/filter_group/filter_group.js +++ b/src-docs/src/views/filter_group/filter_group.js @@ -21,9 +21,16 @@ export default class extends Component { this.state = { isPopoverOpen: false, + isFilterOn: false, }; } + toggleFilter = () => { + this.setState({ + isFilterOn: !this.state.isFilterOn, + }); + } + onButtonClick() { this.setState({ isPopoverOpen: !this.state.isPopoverOpen, @@ -66,6 +73,7 @@ export default class extends Component { onClick={this.onButtonClick.bind(this)} isSelected={this.state.isPopoverOpen} hasActiveFilters={true} + className="euiFilterButton--wide" > Composers @@ -73,11 +81,11 @@ export default class extends Component { return ( - - Filter on + + Filter - - Filter off + + Filter Disabled diff --git a/src/components/filter_group/_filter_button.scss b/src/components/filter_group/_filter_button.scss index c0c73b4733c..93cb2729bda 100644 --- a/src/components/filter_group/_filter_button.scss +++ b/src/components/filter_group/_filter_button.scss @@ -1,26 +1,50 @@ +@import '../form/variables'; +@import '../form/mixins'; + /** - * 1. We don't want any of the animations that come inherited from the mixin. - * These should act like normal links instead. + * 1. Only add the border style drop shadow */ + .euiFilterButton { - @include euiButton; - line-height: 40px; - border-color: transparent; - background-color: transparent; - box-shadow: none; - transform: none !important; // 1 - animation: none !important; // 1 + @include euiFormControlStyle(); + width: auto; + max-width: none; + box-shadow: inset 0 0 0 1px $euiFormBorderColor; /* 1 */ + text-align: center; + + &:hover:not(:disabled) { + .euiFilterButton__textShift { + text-decoration: underline; + } + } + + &:focus { + background-color: $euiFormBackgroundColor; + box-shadow: inset 0 0 0 1px $euiFormBorderColor; /* 1 */ + } + + &:disabled { + box-shadow: inset 0 0 0 1px $euiFormBorderColor--disabled; /* 1 */ + } + + &.euiFilterButton--wide { + width: 100%; + text-align: left; + } .euiFilterButton__content { @include euiButtonContent; + } - padding: 0 $euiSizeS; - + &.euiFilterButton--iconRight { + .euiFilterButton__content { + @include euiButtonContent($isReverse: true); + justify-content: space-between; + } } .euiFilterButton__textShift { - text-align: center; display: inline-block; &::after { @@ -33,31 +57,6 @@ } } - &.euiFilterButton--iconRight { - .euiFilterButton__content { - @include euiButtonContent($isReverse: true); - } - } - - &:disabled { - color: $euiButtonColorDisabled; - pointer-events: none; - - .euiFilterButton__content { - pointer-events: auto; - cursor: not-allowed; - } - - .euiFilterButton__icon { - fill: $euiButtonColorDisabled; - } - - &:hover, &:focus { - background-color: $euiColorEmptyShade; - text-decoration: none; - } - } - &.euiFilterButton-isSelected { text-decoration: underline; } @@ -80,17 +79,5 @@ $buttonTypes: ( @each $name, $color in $buttonTypes { .euiFilterButton--#{$name} { color: $color; - - .euiFilterButton__icon { - fill: $color; - } - - &:hover { - background-color: transparent; - - @if ($name == 'disabled') { - cursor: not-allowed; - } - } } } diff --git a/src/components/filter_group/_filter_group.scss b/src/components/filter_group/_filter_group.scss index 31f1cff9aac..ecf62398131 100644 --- a/src/components/filter_group/_filter_group.scss +++ b/src/components/filter_group/_filter_group.scss @@ -1,12 +1,10 @@ .euiFilterGroup { - @include euiFormControlStyle; - height: 40px; - padding: 0px; - width: auto; - display: inline-block; + display: flex; + // Match just the regular box-shadow of inputs + box-shadow: 0 3px 2px -2px rgba($euiShadowColor, 0.2); > * + * { - border-left: $euiBorderThin; + margin-left: -1px; } } diff --git a/src/components/filter_group/filter_button.js b/src/components/filter_group/filter_button.js index 7050f750934..ee60119f433 100644 --- a/src/components/filter_group/filter_button.js +++ b/src/components/filter_group/filter_button.js @@ -67,6 +67,13 @@ export const EuiFilterButton = ({ ); } + const buttonContents = ( + + {buttonIcon} + {children} + + ); + if (href) { const secureRel = getSecureRelForTarget(target, rel); @@ -78,10 +85,7 @@ export const EuiFilterButton = ({ rel={secureRel} {...rest} > - - {buttonIcon} - {children} - + {buttonContents} ); } else { @@ -92,10 +96,7 @@ export const EuiFilterButton = ({ type={type} {...rest} > - - {buttonIcon} - {children} - + {buttonContents} ); } diff --git a/src/components/form/_mixins.scss b/src/components/form/_mixins.scss index 4d76dc6bc89..dd93f5cb29c 100644 --- a/src/components/form/_mixins.scss +++ b/src/components/form/_mixins.scss @@ -39,7 +39,7 @@ @mixin euiFormControlDefaultShadow { box-shadow: 0 3px 2px -2px rgba($euiShadowColor, 0.2), - inset 0 0 0 1px transparentize($euiColorFullShade, .9), + inset 0 0 0 1px $euiFormBorderColor, inset #{-$euiFormMaxWidth} 0 0 0 $euiFormBackgroundColor; } @@ -63,7 +63,7 @@ @mixin euiFormControlDisabledStyle { cursor: not-allowed; background: darken($euiColorLightestShade, 2%); - box-shadow: inset 0 0 0 1px transparentize($euiColorFullShade, .92); + box-shadow: inset 0 0 0 1px $euiFormBorderColor--disabled; color: $euiFormControlDisabledColor; &::placeholder { diff --git a/src/components/form/_variables.scss b/src/components/form/_variables.scss index 86c5fbf6714..8702a7a987f 100644 --- a/src/components/form/_variables.scss +++ b/src/components/form/_variables.scss @@ -1,5 +1,7 @@ $euiFormMaxWidth: 400px; $euiFormBackgroundColor: tintOrShade($euiColorLightestShade, 60%, 25%); +$euiFormBorderColor: transparentize($euiColorFullShade, .9); +$euiFormBorderColor--disabled: transparentize($euiColorFullShade, .92); $euiFormCustomControlDisabledIconColor: shadeOrTint($euiColorMediumShade, 38%, 48.5%); // exact 508c foreground for $euiColorLightShade $euiRadioSize: $euiSize; From 8c01c9603e7a7de7bd8426908e1cf3d71769b1a9 Mon Sep 17 00:00:00 2001 From: cchaos Date: Tue, 26 Jun 2018 18:21:55 -0400 Subject: [PATCH 02/21] Using form layout and notifications --- .../src/views/filter_group/filter_group.js | 5 +- .../__snapshots__/filter_button.test.js.snap | 6 +- .../filter_select_item.test.js.snap | 2 +- .../filter_group/_filter_button.scss | 63 ++++++++++--------- .../filter_group/_filter_group.scss | 5 ++ src/components/filter_group/filter_button.js | 47 ++++++++------ .../filter_group/filter_select_item.js | 1 + .../header/_header_notification.scss | 1 + .../field_value_selection_filter.test.js.snap | 4 ++ .../field_value_toggle_filter.test.js.snap | 4 ++ ...eld_value_toggle_group_filter.test.js.snap | 8 +++ .../__snapshots__/is_filter.test.js.snap | 1 + 12 files changed, 93 insertions(+), 54 deletions(-) diff --git a/src-docs/src/views/filter_group/filter_group.js b/src-docs/src/views/filter_group/filter_group.js index 8003787cd26..1ac38609570 100644 --- a/src-docs/src/views/filter_group/filter_group.js +++ b/src-docs/src/views/filter_group/filter_group.js @@ -73,7 +73,8 @@ export default class extends Component { onClick={this.onButtonClick.bind(this)} isSelected={this.state.isPopoverOpen} hasActiveFilters={true} - className="euiFilterButton--wide" + numFilters={2} + grow={true} > Composers @@ -96,7 +97,7 @@ export default class extends Component { panelPaddingSize="none" withTitle panelClassName="euiFilterGroup__popoverPanel" - style={{ flexGrow: '1', fontSize: '0' }} + style={{ fontSize: '0' }} > diff --git a/src/components/filter_group/__snapshots__/filter_button.test.js.snap b/src/components/filter_group/__snapshots__/filter_button.test.js.snap index 320e2570a0d..5443a25e5ad 100644 --- a/src/components/filter_group/__snapshots__/filter_button.test.js.snap +++ b/src/components/filter_group/__snapshots__/filter_button.test.js.snap @@ -7,12 +7,12 @@ exports[`EuiFilterButton is rendered 1`] = ` data-test-subj="test subject string" type="button" > - - + `; diff --git a/src/components/filter_group/__snapshots__/filter_select_item.test.js.snap b/src/components/filter_group/__snapshots__/filter_select_item.test.js.snap index 10494b47fc4..78de8ac186d 100644 --- a/src/components/filter_group/__snapshots__/filter_select_item.test.js.snap +++ b/src/components/filter_group/__snapshots__/filter_select_item.test.js.snap @@ -8,7 +8,7 @@ exports[`EuiFilterSelectItem is rendered 1`] = ` type="button" >
* { + // defaults to growing children though filter buttons don't grow by default + flex-grow: 1; + } + > * + * { margin-left: -1px; } diff --git a/src/components/filter_group/filter_button.js b/src/components/filter_group/filter_button.js index ee60119f433..70480ae7a55 100644 --- a/src/components/filter_group/filter_button.js +++ b/src/components/filter_group/filter_button.js @@ -3,10 +3,11 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { getSecureRelForTarget } from '../../services'; +import { EuiFormControlLayout } from '../form/form_control_layout'; +import { EuiHeaderNotification } from '../header/header_notification'; import { ICON_TYPES, - EuiIcon, } from '../icon'; const colorToClassNameMap = { @@ -33,12 +34,14 @@ export const EuiFilterButton = ({ iconSide, color, hasActiveFilters, + numFilters, isDisabled, isSelected, href, target, rel, type, + grow, ...rest }) => { @@ -49,29 +52,28 @@ export const EuiFilterButton = ({ { 'euiFilterButton-isSelected': isSelected, 'euiFilterButton-hasActiveFilters': hasActiveFilters, + 'euiFilterButton-grow': grow, }, className, ); - // Add an icon to the button if one exists. - let buttonIcon; - - if (iconType) { - buttonIcon = ( -
diff --git a/src/components/combo_box/_combo_box.scss b/src/components/combo_box/_combo_box.scss index 12d59569efb..d448f90bbb4 100644 --- a/src/components/combo_box/_combo_box.scss +++ b/src/components/combo_box/_combo_box.scss @@ -8,7 +8,7 @@ * 3. The height on combo can be larger than normal text inputs. */ .euiComboBox__inputWrap { - @include euiFormControlStyle($includeStates: false); + @include euiFormControlStyle($includeStates: false, $includeSizes:false); @include euiFormControlWithIcon($isIconOptional: true); @include euiFormControlSize(auto); /* 3 */ diff --git a/src/components/filter_group/__snapshots__/filter_button.test.js.snap b/src/components/filter_group/__snapshots__/filter_button.test.js.snap index 634d5d4a558..9efa815d161 100644 --- a/src/components/filter_group/__snapshots__/filter_button.test.js.snap +++ b/src/components/filter_group/__snapshots__/filter_button.test.js.snap @@ -10,9 +10,13 @@ exports[`EuiFilterButton is rendered 1`] = `
- +
+ +
`; diff --git a/src/components/form/_mixins.scss b/src/components/form/_mixins.scss index cde9ea7e398..aa6aaaeb610 100644 --- a/src/components/form/_mixins.scss +++ b/src/components/form/_mixins.scss @@ -12,10 +12,24 @@ * 1. Ensure the icon padding remains when in readOnly mode */ -@mixin euiFormControlSize($height: $euiFormControlHeight) { +@mixin euiFormControlSize( + $height: $euiFormControlHeight, + $includeAlternates: false +) { + // Default max-width: $euiFormMaxWidth; width: 100%; height: $height; + + @if ($includeAlternates) { + &--fullWidth { + max-width: 100%; + } + + &--compressed { + height: $euiFormControlCompressedHeight; + } + } } @mixin euiFormControlWithIcon($isIconOptional: false, $side: "left") { @@ -110,9 +124,9 @@ * 2. Override invalid state with focus state. */ -@mixin euiFormControlStyle($borderOnly: false, $includeStates: true) { - @include euiFormControlSize; - @include euiFormControlDefaultShadow($borderOnly); +@mixin euiFormControlStyle($borderOnly: false, $includeStates: true, $includeSizes: true) { + @include euiFormControlSize($includeAlternates: $includeSizes); + @include euiFormControlDefaultShadow(); border: none; font-size: $euiFontSizeS; @@ -122,14 +136,11 @@ color: $euiTextColor; border-radius: 0; - &--fullWidth { - max-width: 100%; - } - - &--compressed { - padding-top: $euiFormControlCompressedPadding; - padding-bottom: $euiFormControlCompressedPadding; - height: $euiFormControlCompressedHeight; + @if ($includeSizes) { + &--compressed { + padding-top: $euiFormControlCompressedPadding; + padding-bottom: $euiFormControlCompressedPadding; + } } @if ($includeStates) { @@ -138,7 +149,7 @@ } &:focus { /* 2 */ - @include euiFormControlFocusStyle($borderOnly); + @include euiFormControlFocusStyle(); } &:disabled { @@ -149,7 +160,6 @@ @include euiFormControlReadOnlyStyle; } } - } // Custom styles and states for checkboxes and radios diff --git a/src/components/form/form_control_layout/__snapshots__/form_control_layout.test.js.snap b/src/components/form/form_control_layout/__snapshots__/form_control_layout.test.js.snap index 4f106845a78..9de76c91e2b 100644 --- a/src/components/form/form_control_layout/__snapshots__/form_control_layout.test.js.snap +++ b/src/components/form/form_control_layout/__snapshots__/form_control_layout.test.js.snap @@ -6,7 +6,11 @@ exports[`EuiFormControlLayout is rendered 1`] = ` class="euiFormControlLayout testClass1 testClass2" data-test-subj="test subject string" > - +
+ +
`; @@ -15,34 +19,38 @@ exports[`EuiFormControlLayout props clear onClick is rendered 1`] = ` class="euiFormControlLayout" >
- + + +
`; @@ -50,7 +58,11 @@ exports[`EuiFormControlLayout props clear onClick is rendered 1`] = ` exports[`EuiFormControlLayout props fullWidth is rendered 1`] = `
+> +
+
`; exports[`EuiFormControlLayout props icon is rendered as a string 1`] = ` @@ -58,32 +70,36 @@ exports[`EuiFormControlLayout props icon is rendered as a string 1`] = ` class="euiFormControlLayout" >
- - - + + + + + + +
`; @@ -93,33 +109,37 @@ exports[`EuiFormControlLayout props icon is rendered as an object 1`] = ` class="euiFormControlLayout" >
- - - + + + + + + +
`; @@ -129,32 +149,36 @@ exports[`EuiFormControlLayout props icon side left is rendered 1`] = ` class="euiFormControlLayout" >
- - - + + + + + + +
`; @@ -164,32 +188,36 @@ exports[`EuiFormControlLayout props icon side right is rendered 1`] = ` class="euiFormControlLayout" >
- - - + + + + + + +
`; @@ -199,11 +227,85 @@ exports[`EuiFormControlLayout props isLoading is rendered 1`] = ` class="euiFormControlLayout" >
+ class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right" + > +
+
`; + +exports[`EuiFormControlLayout props multiple appends are rendered 1`] = ` +
+
+ + 1 + + + 2 + +
+`; + +exports[`EuiFormControlLayout props multiple prepends are rendered 1`] = ` +
+ + 1 + + + 2 + +
+
+`; + +exports[`EuiFormControlLayout props one append is rendered 1`] = ` +
+
+ + 1 + +
+`; + +exports[`EuiFormControlLayout props one prepend is rendered 1`] = ` +
+ + 1 + +
+
+`; 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 22a959acb08..23d81f4a71c 100644 --- a/src/components/form/form_control_layout/_form_control_layout.scss +++ b/src/components/form/form_control_layout/_form_control_layout.scss @@ -2,37 +2,38 @@ .euiFormControlLayout { // Let the height expand as needed - @include euiFormControlSize(auto); - - display: inline-block; - position: relative; + @include euiFormControlSize(auto, $includeAlternates: true); } -.euiFormControlLayout--fullWidth { - width: 100%; - max-width: 100%; +.euiFormControlLayout__childrenWrapper { + position: relative; } -// If it contains any inline labels, -// make the whole layout have the form control style +/** + * 1. Account for inner box-shadow style border + */ -.euiFormControlLayout--hasLabel { - // Match just the regular box-shadow of inputs - @include euiFormControlStyle(); +.euiFormControlLayout--group { + // Match just the regular drop shadow of inputs + @include euiFormControlDefaultShadow(); display: flex; padding: 1px; /* 1 */ - .euiFormControlLayout__child--noStyle { + .euiFormControlLayout__childrenWrapper { flex-grow: 1; + } + + // Change the height and remove drop shadow of the input + .euiFormControlLayout__child--noStyle { height: $euiFormControlHeight - 2px; /* 1 */ box-shadow: none !important; } - .euiFormControlLayout__inlineLabel { + .euiFormControlLayout__prepend, + .euiFormControlLayout__append { flex-shrink: 0; height: $euiFormControlHeight - 2px; /* 1 */ line-height: $euiFontSize; - border-right: 1px solid $euiFormBorderColor; &:disabled { background-color: $euiFormBackgroundDisabledColor; @@ -49,9 +50,36 @@ background-color: $euiFormBackgroundDisabledColor; line-height: $euiFontSize; } + } - &.euiText { - line-height: 1em; + // + // Borders + + .euiFormControlLayout__prepend { + border-right: 1px solid $euiFormBorderColor; + } + + .euiFormControlLayout__append { + border-left: 1px solid $euiFormBorderColor; + } + + // + // Compressed alterations + + &.euiFormControlLayout--compressed { + .euiFormControlLayout__child--noStyle { + height: $euiFormControlCompressedHeight - 2px; /* 1 */ + } + + .euiFormControlLayout__prepend, + .euiFormControlLayout__append { + height: $euiFormControlCompressedHeight - 2px; /* 1 */ + + &.euiFormLabel, + &.euiText { + padding-top: $euiFormControlCompressedPadding; + padding-bottom: $euiFormControlCompressedPadding; + } } } } diff --git a/src/components/form/form_control_layout/_form_control_layout_clear_button.scss b/src/components/form/form_control_layout/_form_control_layout_clear_button.scss index a0830685fea..0dc57d56668 100644 --- a/src/components/form/form_control_layout/_form_control_layout_clear_button.scss +++ b/src/components/form/form_control_layout/_form_control_layout_clear_button.scss @@ -1,10 +1,3 @@ .euiFormControlLayoutClearButton { @include euiFormControlLayoutClearIcon('.euiFormControlLayoutClearButton__icon'); } - -// The 1px padding throws off the times icon -.euiFormControlLayout--hasLabel { - .euiFormControlLayoutClearButton .euiFormControlLayoutClearButton__icon { - top: -1px; - } -} diff --git a/src/components/form/form_control_layout/form_control_layout.js b/src/components/form/form_control_layout/form_control_layout.js index 029f6b95c08..8a09f79f8c6 100644 --- a/src/components/form/form_control_layout/form_control_layout.js +++ b/src/components/form/form_control_layout/form_control_layout.js @@ -1,49 +1,117 @@ -import React from 'react'; +import React, { + cloneElement, + Component, +} from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { EuiFormControlLayoutIcons } from './form_control_layout_icons'; -import { EuiFormControlLayoutChildren } from './form_control_layout_children'; export const ICON_SIDES = ['left', 'right']; -export const LABEL_SIDES = ['left', 'right']; - -export const EuiFormControlLayout = ({ - children, - icon, - clear, - fullWidth, - isLoading, - compressed, - className, - inlineLabel, - ...rest -}) => { - const classes = classNames( - 'euiFormControlLayout', - { - 'euiFormControlLayout--fullWidth': fullWidth, - 'euiFormControlLayout--compressed': compressed, - 'euiFormControlLayout--hasLabel': inlineLabel, - }, - className - ); - - return ( -
- - - -
- ); -}; + +export class EuiFormControlLayout extends Component { + render() { + const { + children, + icon, + clear, + fullWidth, + isLoading, + compressed, + className, + prepend, + append, + ...rest + } = this.props; + + const classes = classNames( + 'euiFormControlLayout', + { + 'euiFormControlLayout--fullWidth': fullWidth, + 'euiFormControlLayout--compressed': compressed, + 'euiFormControlLayout--group': prepend || append, + }, + className + ); + + const prependNodes = this.renderPrepends(); + const appendNodes = this.renderAppends(); + + let clonedChildren; + if ((prepend || append) && children) { + clonedChildren = cloneElement(children, { + className: `${children.props.className} euiFormControlLayout__child--noStyle`, + }); + } + + return ( +
+ {prependNodes} +
+ {clonedChildren || children} + + +
+ {appendNodes} +
+ ); + } + + renderPrepends() { + const { prepend } = this.props; + + if (!prepend) { + return; + } + + let prependNodes; + + if (Array.isArray(prepend)) { + prependNodes = prepend.map((item, index) => { + return this.createSideNode(item, 'prepend', index); + }); + } + + else { + prependNodes = this.createSideNode(prepend, 'prepend'); + } + + return prependNodes; + } + + renderAppends() { + const { append } = this.props; + + if (!append) { + return; + } + + let appendNodes; + + if (Array.isArray(append)) { + appendNodes = append.map((item, index) => { + return this.createSideNode(item, 'append', index); + }); + } + + else { + appendNodes = this.createSideNode(append, 'append'); + } + + return appendNodes; + } + + createSideNode(node, side, key) { + return cloneElement(node, { + className: `euiFormControlLayout__${side}`, + key: key + }); + } +} EuiFormControlLayout.propTypes = { children: PropTypes.node, @@ -63,14 +131,18 @@ EuiFormControlLayout.propTypes = { className: PropTypes.string, compressed: PropTypes.bool, /** - * Creates an input group with an inline label + * Creates an input group with element(s) coming before children */ - inlineLabel: PropTypes.oneOfType([ + prepend: PropTypes.oneOfType([ PropTypes.node, - PropTypes.shape({ - label: PropTypes.node, - side: PropTypes.oneOf(LABEL_SIDES), - }), + PropTypes.arrayOf(PropTypes.node), + ]), + /** + * Creates an input group with element(s) coming after children + */ + append: PropTypes.oneOfType([ + PropTypes.node, + PropTypes.arrayOf(PropTypes.node), ]), }; diff --git a/src/components/form/form_control_layout/form_control_layout.test.js b/src/components/form/form_control_layout/form_control_layout.test.js index 33749c6677d..08afabf4d58 100644 --- a/src/components/form/form_control_layout/form_control_layout.test.js +++ b/src/components/form/form_control_layout/form_control_layout.test.js @@ -135,5 +135,51 @@ describe('EuiFormControlLayout', () => { expect(component).toMatchSnapshot(); }); + + test('one prepend is rendered', () => { + const component = render( + 1} + /> + ); + + expect(component).toMatchSnapshot(); + }); + + test('one append is rendered', () => { + const component = render( + 1} + /> + ); + + expect(component).toMatchSnapshot(); + }); + + test('multiple prepends are rendered', () => { + const component = render( + 1, + 2 + ]} + /> + ); + + expect(component).toMatchSnapshot(); + }); + + test('multiple appends are rendered', () => { + const component = render( + 1, + 2 + ]} + /> + ); + + expect(component).toMatchSnapshot(); + }); }); }); diff --git a/src/components/form/form_control_layout/form_control_layout_children.js b/src/components/form/form_control_layout/form_control_layout_children.js deleted file mode 100644 index 4a5a1a9223a..00000000000 --- a/src/components/form/form_control_layout/form_control_layout_children.js +++ /dev/null @@ -1,56 +0,0 @@ -import React, { - cloneElement, - Fragment, -} from 'react'; -import PropTypes from 'prop-types'; - -export const LABEL_SIDES = ['left', 'right']; - -export const EuiFormControlLayoutChildren = ({ - children, - inlineLabel, -}) => { - - const labelSide = inlineLabel && inlineLabel.side ? inlineLabel.side : 'left'; - - let leftLabel; - let rightLabel; - let clonedChildren; - - if (inlineLabel) { - const labelNode = inlineLabel.node ? inlineLabel.node : inlineLabel; - const labelClone = cloneElement(labelNode, { - className: 'euiFormControlLayout__inlineLabel' - }); - - if (labelSide === 'left') { - leftLabel = labelClone; - } - else if (labelSide === 'right') { - rightLabel = labelClone; - } - - clonedChildren = cloneElement(children, { - className: `${children.props.className} euiFormControlLayout__child--noStyle`, - }); - } - - - return ( - - {leftLabel} - {clonedChildren || children} - {rightLabel} - - ); -}; - -EuiFormControlLayoutChildren.propTypes = { - inlineLabel: PropTypes.oneOfType([ - PropTypes.node, - PropTypes.shape({ - label: PropTypes.node, - side: PropTypes.oneOf(LABEL_SIDES), - }), - ]), -}; From 88b2fdd960853f002ae5fc21dac46dc4c91d06dc Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 28 Jun 2018 17:32:41 -0400 Subject: [PATCH 12/21] Adding options to select, text, and number controls --- .../src/views/form_controls/field_number.js | 12 ++++++++++++ .../form_controls/form_control_layout.js | 6 +++--- src/components/form/_mixins.scss | 13 +++++++++++++ .../form/field_number/field_number.js | 19 +++++++++++++++++++ src/components/form/field_text/field_text.js | 19 +++++++++++++++++++ .../_form_control_layout.scss | 13 ++----------- src/components/form/select/_select.scss | 8 ++++++++ src/components/form/select/select.js | 19 +++++++++++++++++++ 8 files changed, 95 insertions(+), 14 deletions(-) diff --git a/src-docs/src/views/form_controls/field_number.js b/src-docs/src/views/form_controls/field_number.js index b74aa14b487..307cfc119a8 100644 --- a/src-docs/src/views/form_controls/field_number.js +++ b/src-docs/src/views/form_controls/field_number.js @@ -6,6 +6,7 @@ import React, { import { EuiFieldNumber, EuiSpacer, + EuiText, } from '../../../../src/components'; export default class extends Component { @@ -83,6 +84,17 @@ export default class extends Component { onChange={this.onChange} compressed /> + + + + %} + 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/form_control_layout.js b/src-docs/src/views/form_controls/form_control_layout.js index 724d70dea9c..cc0022853f8 100644 --- a/src-docs/src/views/form_controls/form_control_layout.js +++ b/src-docs/src/views/form_controls/form_control_layout.js @@ -115,7 +115,7 @@ export default () => ( Label} > - + @@ -123,7 +123,7 @@ export default () => ( %} > - + @@ -133,7 +133,7 @@ export default () => ( clear={{ onClick: () => {} }} prepend={Button} > - + ); diff --git a/src/components/form/_mixins.scss b/src/components/form/_mixins.scss index aa6aaaeb610..8b217c53862 100644 --- a/src/components/form/_mixins.scss +++ b/src/components/form/_mixins.scss @@ -10,6 +10,7 @@ /** * 1. Ensure the icon padding remains when in readOnly mode + * 2. Account for inner box-shadow style border when in group */ @mixin euiFormControlSize( @@ -29,6 +30,14 @@ &--compressed { height: $euiFormControlCompressedHeight; } + + &--inGroup { + height: $euiFormControlHeight - 2px; /* 2 */ + } + + &--inGroup#{&}--compressed { + height: $euiFormControlCompressedHeight - 2px; /* 2 */ + } } } @@ -141,6 +150,10 @@ padding-top: $euiFormControlCompressedPadding; padding-bottom: $euiFormControlCompressedPadding; } + + &--inGroup { + box-shadow: none !important; + } } @if ($includeStates) { diff --git a/src/components/form/field_number/field_number.js b/src/components/form/field_number/field_number.js index a75471e455a..352ec8bd026 100644 --- a/src/components/form/field_number/field_number.js +++ b/src/components/form/field_number/field_number.js @@ -23,12 +23,15 @@ export const EuiFieldNumber = ({ fullWidth, isLoading, compressed, + prepend, + append, ...rest }) => { const classes = classNames('euiFieldNumber', className, { 'euiFieldNumber--withIcon': icon, 'euiFieldNumber--fullWidth': fullWidth, 'euiFieldNumber--compressed': compressed, + 'euiFieldNumber--inGroup': prepend || append, 'euiFieldNumber-isLoading': isLoading, }); @@ -38,6 +41,8 @@ export const EuiFieldNumber = ({ fullWidth={fullWidth} isLoading={isLoading} compressed={compressed} + prepend={prepend} + append={append} > { const classes = classNames('euiFieldText', className, { 'euiFieldText--withIcon': icon, 'euiFieldText--fullWidth': fullWidth, 'euiFieldText--compressed': compressed, + 'euiFieldText--inGroup': prepend || append, 'euiFieldText-isLoading': isLoading, }); @@ -37,6 +40,8 @@ export const EuiFieldText = ({ fullWidth={fullWidth} isLoading={isLoading} compressed={compressed} + prepend={prepend} + append={append} > { const classes = classNames( @@ -30,6 +32,7 @@ export const EuiSelect = ({ { 'euiSelect--fullWidth': fullWidth, 'euiSelect--compressed': compressed, + 'euiSelect--inGroup': prepend || append, 'euiSelect-isLoading': isLoading, }, className @@ -60,6 +63,8 @@ export const EuiSelect = ({ fullWidth={fullWidth} isLoading={isLoading} compressed={compressed} + prepend={prepend} + append={append} > +
+
+
+
+ +
+
+
+ + → + +
+ + +
+
+
+
+
+ +
+
+
+
+
+
+
+ +`; diff --git a/src/components/date_picker/_date_picker_range.scss b/src/components/date_picker/_date_picker_range.scss new file mode 100644 index 00000000000..8c931a14db5 --- /dev/null +++ b/src/components/date_picker/_date_picker_range.scss @@ -0,0 +1,34 @@ +@import '../form/variables'; +@import '../form/mixins'; + +/** + * 1. Account for inner box-shadow style border + */ + + .euiDatePickerRange { + @include euiFormControlSize(auto, $includeAlternates: true); + // Match just the regular drop shadow of inputs + @include euiFormControlDefaultShadow(); + display: flex; + align-items: center; + padding: 1px; /* 1 */ + + > span { + flex-grow: 1; + } + + .euiDatePicker { + box-shadow: none !important; // including all states + text-align: center; + } +} + +.euiDatePickerRange__icon { + padding-left: $euiFormControlPadding; + padding-right: $euiFormControlPadding; +} + +.euiDatePickerRange__delimeter { + padding-left: $euiFormControlPadding/2; + padding-right: $euiFormControlPadding/2; +} diff --git a/src/components/date_picker/_index.scss b/src/components/date_picker/_index.scss index f44d6770ed1..65219322767 100644 --- a/src/components/date_picker/_index.scss +++ b/src/components/date_picker/_index.scss @@ -1,2 +1,3 @@ // Uses some form mixins @import 'date_picker'; +@import 'date_picker_range'; diff --git a/src/components/date_picker/date_picker.js b/src/components/date_picker/date_picker.js index 332e74ed4c4..bb279fd8ec9 100644 --- a/src/components/date_picker/date_picker.js +++ b/src/components/date_picker/date_picker.js @@ -49,6 +49,7 @@ export class EuiDatePicker extends Component { selected, shadow, shouldCloseOnSelect, + showIcon, showTimeSelect, showTimeSelectOnly, timeFormat, @@ -70,14 +71,14 @@ export class EuiDatePicker extends Component { { 'euiFieldText--fullWidth': fullWidth, 'euiFieldText-isLoading': isLoading, - 'euiFieldText--withIcon': !inline, + 'euiFieldText--withIcon': !inline && showIcon, 'euiFieldText-isInvalid': isInvalid, }, className ); let optionalIcon; - if (inline || customInput) { + if (inline || customInput || !showIcon) { optionalIcon = null; } else if (showTimeSelectOnly) { optionalIcon = 'clock'; @@ -268,6 +269,10 @@ EuiDatePicker.propTypes = { * Will close the popup on selection */ shouldCloseOnSelect: PropTypes.bool, + /** + * Show the icon in input + */ + showIcon: PropTypes.bool, /** * Show the time selection alongside the calendar */ @@ -288,5 +293,6 @@ EuiDatePicker.defaultProps = { isLoading: false, shadow: true, shouldCloseOnSelect: true, + showIcon: true, timeFormat: 'hh:mm A', }; diff --git a/src/components/date_picker/date_picker_range.js b/src/components/date_picker/date_picker_range.js new file mode 100644 index 00000000000..4ff4a15bcca --- /dev/null +++ b/src/components/date_picker/date_picker_range.js @@ -0,0 +1,78 @@ +import React, { + cloneElement, +} from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +import { EuiText } from '../text'; +import { + ICON_TYPES, + EuiIcon, +} from '../icon'; + +export const EuiDatePickerRange = ({ + className, + startDateControl, + endDateControl, + iconType, + ...rest +}) => { + + const classes = classNames( + 'euiDatePickerRange', + className + ); + + // Set the icon for the entire group instead of per control + let optionalIcon; + if (iconType) { + const icon = typeof iconType === 'string' ? iconType : 'calendar'; + optionalIcon = ( + + ); + } else { + optionalIcon = null; + } + + const clonedStartDate = cloneElement(startDateControl, { + showIcon: false, + }); + + const clonedEndDate = cloneElement(endDateControl, { + showIcon: false, + }); + + return ( +
+ {optionalIcon} + {clonedStartDate} + + {clonedEndDate} +
+ ); +}; + +EuiDatePickerRange.propTypes = { + /** + * The start date `EuiDatePicker` element + */ + startDateControl: PropTypes.node.isRequired, + /** + * The end date `EuiDatePicker` element + */ + endDateControl: PropTypes.node.isRequired, + /** + * Pass either an icon type or set to `false` to remove icon entirely + */ + iconType: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.oneOf(ICON_TYPES), + ]), +}; + +EuiDatePickerRange.defaultProps = { + iconType: true, +}; diff --git a/src/components/date_picker/date_picker_range.test.js b/src/components/date_picker/date_picker_range.test.js new file mode 100644 index 00000000000..72b0fea7e97 --- /dev/null +++ b/src/components/date_picker/date_picker_range.test.js @@ -0,0 +1,21 @@ +import React from 'react'; +import { render } from 'enzyme'; +import { requiredProps } from '../../test'; + +import { EuiDatePickerRange } from './date_picker_range'; +import { EuiDatePicker } from './date_picker'; + +describe('EuiDatePickerRange', () => { + test('is rendered', () => { + const component = render( + } + endDateControl={} + {...requiredProps} + /> + ); + + expect(component) + .toMatchSnapshot(); + }); +}); diff --git a/src/components/date_picker/index.js b/src/components/date_picker/index.js index a50b7176468..eb720402eec 100644 --- a/src/components/date_picker/index.js +++ b/src/components/date_picker/index.js @@ -1,3 +1,7 @@ export { EuiDatePicker, } from './date_picker'; + +export { + EuiDatePickerRange, +} from './date_picker_range'; 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 b5d655cceb5..30f6ec1c8f0 100644 --- a/src/components/form/form_control_layout/_form_control_layout.scss +++ b/src/components/form/form_control_layout/_form_control_layout.scss @@ -1,4 +1,5 @@ @import '../variables'; +@import '../mixins'; .euiFormControlLayout { // Let the height expand as needed diff --git a/src/components/index.js b/src/components/index.js index 2c41840fd58..26e939e255b 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -66,6 +66,7 @@ export { export { EuiDatePicker, + EuiDatePickerRange, } from './date_picker'; export { From 130d8720ed61472bb1077901cbdb18a01d3b5074 Mon Sep 17 00:00:00 2001 From: cchaos Date: Mon, 2 Jul 2018 16:27:22 -0400 Subject: [PATCH 19/21] Forgot to remove one more part of non-existent comp --- .../form_control_layout/_form_control_layout_children.scss | 3 --- src/components/form/form_control_layout/_index.scss | 1 - 2 files changed, 4 deletions(-) delete mode 100644 src/components/form/form_control_layout/_form_control_layout_children.scss diff --git a/src/components/form/form_control_layout/_form_control_layout_children.scss b/src/components/form/form_control_layout/_form_control_layout_children.scss deleted file mode 100644 index 50b36e8eb30..00000000000 --- a/src/components/form/form_control_layout/_form_control_layout_children.scss +++ /dev/null @@ -1,3 +0,0 @@ -.euiFormControlLayoutChildren { - -} diff --git a/src/components/form/form_control_layout/_index.scss b/src/components/form/form_control_layout/_index.scss index 83dac974b3d..f5a9b5d33bc 100644 --- a/src/components/form/form_control_layout/_index.scss +++ b/src/components/form/form_control_layout/_index.scss @@ -3,4 +3,3 @@ @import 'form_control_layout_icons'; @import 'form_control_layout_clear_button'; @import 'form_control_layout_custom_icon'; -@import 'form_control_layout_children'; From b7af0dd8fd5525b63cb5eaafa014a0d8aed2ac93 Mon Sep 17 00:00:00 2001 From: cchaos Date: Mon, 2 Jul 2018 16:39:04 -0400 Subject: [PATCH 20/21] changelog --- CHANGELOG.md | 3 +++ .../range/__snapshots__/range.test.js.snap | 26 +++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c46c5e0f3..f366daf9bba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## [`master`](https://github.com/elastic/eui/tree/master) - Added more (mainly style) options to `EuiRange` ([#932](https://github.com/elastic/eui/pull/932)) +- Added `prepend` and `append` props to `EuiFormControlLayout` ([#961](https://github.com/elastic/eui/pull/961)) +- Updated style implementation of `EuiFilterGroup` and `EuiFilterGroupButton` ([#961](https://github.com/elastic/eui/pull/961)) +- Added `EuiDatePickerRange` as a way to layout two `EuiDatePicker`s. ([#961](https://github.com/elastic/eui/pull/961)) ## [`1.0.1`](https://github.com/elastic/eui/tree/v1.0.1) diff --git a/src/components/form/range/__snapshots__/range.test.js.snap b/src/components/form/range/__snapshots__/range.test.js.snap index e9539ebbf9b..8115936460c 100644 --- a/src/components/form/range/__snapshots__/range.test.js.snap +++ b/src/components/form/range/__snapshots__/range.test.js.snap @@ -62,17 +62,21 @@ exports[`EuiRange props extra input should render 1`] = `
- +
+ +
`; From 9ba5136b09f59dbdd400f2babf4387feae7e3b66 Mon Sep 17 00:00:00 2001 From: cchaos Date: Fri, 13 Jul 2018 14:19:04 -0400 Subject: [PATCH 21/21] Addressed PR feedback --- src-docs/src/views/button/button_icon.js | 4 ++-- src-docs/src/views/date_picker/range.js | 2 ++ src/components/filter_group/filter_button.js | 22 -------------------- 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src-docs/src/views/button/button_icon.js b/src-docs/src/views/button/button_icon.js index 89a21d46f60..8fb87a60d00 100644 --- a/src-docs/src/views/button/button_icon.js +++ b/src-docs/src/views/button/button_icon.js @@ -19,8 +19,8 @@ const colors = [ export default () => ( { - colors.map((color, index) => ( - + colors.map((color) => ( + this.state.endDate} aria-label="Start date" showTimeSelect /> @@ -54,6 +55,7 @@ export default class extends Component { onChange={this.handleChangeEnd} startDate={this.state.startDate} endDate={this.state.endDate} + isInvalid={this.state.startDate > this.state.endDate} aria-label="End date" showTimeSelect /> diff --git a/src/components/filter_group/filter_button.js b/src/components/filter_group/filter_button.js index b27c7d829ff..433099ccaf2 100644 --- a/src/components/filter_group/filter_button.js +++ b/src/components/filter_group/filter_button.js @@ -24,9 +24,6 @@ export const EuiFilterButton = ({ numFilters, isDisabled, isSelected, - // href, - // target, - // rel, type, grow, noDivider, @@ -53,11 +50,6 @@ export const EuiFilterButton = ({ ); - // let secureRel; - // if (href) { - // secureRel = getSecureRelForTarget(target, rel); - // } - return ( @@ -98,18 +88,6 @@ EuiFilterButton.propTypes = { */ isSelected: PropTypes.bool, isDisabled: PropTypes.bool, - /** - * If passed, changes the button to an anchor tag - */ - href: PropTypes.string, - /** - * Used along with href - */ - target: PropTypes.string, - /** - * Used along with href - */ - rel: PropTypes.string, /** * Defines html button input type */