From 66b3378445ba43a600cbc82fcd8d9482f9544379 Mon Sep 17 00:00:00 2001 From: Caroline Horn <549577+cchaos@users.noreply.github.com> Date: Fri, 12 Jul 2019 12:14:55 -0400 Subject: [PATCH 01/24] [Feature branch] Updated form control border color (#2114) * Updated form control border color * Slighly more transparent * change sass var name to $euiFormBorderOpaqueColor --- src/components/form/_mixins.scss | 4 ++-- src/components/form/_variables.scss | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/form/_mixins.scss b/src/components/form/_mixins.scss index 04aa4268714..9672e9a34b5 100644 --- a/src/components/form/_mixins.scss +++ b/src/components/form/_mixins.scss @@ -122,12 +122,12 @@ background-size: 100% 100%; /* 3 */ @if ($borderOnly) { - box-shadow: inset 0 0 0 1px transparentize($euiColorFullShade, .84); + box-shadow: inset 0 0 0 1px $euiFormBorderColor; } @else { box-shadow: 0 1px 1px -1px transparentize($euiShadowColor, .8), 0 4px 4px -2px transparentize($euiShadowColor, .8), - inset 0 0 0 1px transparentize($euiColorFullShade, .84); + inset 0 0 0 1px $euiFormBorderColor; } } diff --git a/src/components/form/_variables.scss b/src/components/form/_variables.scss index eae29dabd11..e42d4f02023 100644 --- a/src/components/form/_variables.scss +++ b/src/components/form/_variables.scss @@ -16,8 +16,9 @@ $euiSwitchIconHeight: $euiSize !default; // Coloring $euiFormBackgroundColor: tintOrShade($euiColorLightestShade, 60%, 40%) !default; $euiFormBackgroundDisabledColor: darken($euiColorLightestShade, 2%) !default; -$euiFormBorderColor: transparentize($euiColorFullShade, .9) !default; -$euiFormBorderDisabledColor: transparentize($euiColorFullShade, .92) !default; +$euiFormBorderOpaqueColor: shade(desaturate(adjust-hue($euiColorPrimary, 22), 22.95), 26%) !default; +$euiFormBorderColor: transparentize($euiFormBorderOpaqueColor, .9) !default; +$euiFormBorderDisabledColor: transparentize($euiFormBorderOpaqueColor, .9) !default; $euiFormCustomControlDisabledIconColor: shadeOrTint($euiColorMediumShade, 38%, 48.5%) !default; // exact 508c foreground for $euiColorLightShade $euiFormControlDisabledColor: $euiColorMediumShade !default; $euiFormControlBoxShadow: 0 1px 1px -1px transparentize($euiShadowColor, .8), 0 3px 2px -2px transparentize($euiShadowColor, .8); From eb5297a1e0a97016f26f9443550af6f9ea3d27d7 Mon Sep 17 00:00:00 2001 From: Caroline Horn <549577+cchaos@users.noreply.github.com> Date: Tue, 23 Jul 2019 10:19:49 -0400 Subject: [PATCH 02/24] [Feature branch] Added EuiFormControlLayoutDelimited component (#2117) As a layout helper component to create date and number ranges * Added Sass var for `$euiFormControlLayoutGroupInputHeight` and compressed version --- .../form_control_layout_range.js | 137 ++++++++++++++++++ .../form_controls/form_controls_example.js | 45 ++++++ .../date_picker/_date_picker_range.scss | 3 +- .../super_date_picker/_mixins.scss | 6 +- src/components/form/_index.scss | 2 - src/components/form/_mixins.scss | 7 +- src/components/form/_variables.scss | 2 +- ...orm_control_layout_delimited.test.tsx.snap | 100 +++++++++++++ .../_form_control_layout.scss | 13 +- .../_form_control_layout_range.scss | 56 +++++++ .../form/form_control_layout/_index.scss | 2 + .../form/form_control_layout/_variables.scss | 8 + .../form_control_layout.tsx | 54 +------ .../form_control_layout_delimited.test.tsx | 52 +++++++ .../form_control_layout_delimited.tsx | 56 +++++++ .../form/form_control_layout/index.ts | 2 + src/components/form/index.js | 5 +- src/components/form/select/_select.scss | 4 +- src/components/index.js | 1 + 19 files changed, 494 insertions(+), 61 deletions(-) create mode 100644 src-docs/src/views/form_controls/form_control_layout_range.js create mode 100644 src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap create mode 100644 src/components/form/form_control_layout/_form_control_layout_range.scss create mode 100644 src/components/form/form_control_layout/_variables.scss create mode 100644 src/components/form/form_control_layout/form_control_layout_delimited.test.tsx create mode 100644 src/components/form/form_control_layout/form_control_layout_delimited.tsx diff --git a/src-docs/src/views/form_controls/form_control_layout_range.js b/src-docs/src/views/form_controls/form_control_layout_range.js new file mode 100644 index 00000000000..a11d465fc05 --- /dev/null +++ b/src-docs/src/views/form_controls/form_control_layout_range.js @@ -0,0 +1,137 @@ +import React, { Fragment } from 'react'; + +import { + EuiFormControlLayoutDelimited, + EuiSpacer, + EuiFormLabel, + EuiIcon, +} from '../../../../src/components'; + +export default () => ( + + + } + endControl={ + + } + /> + + + px} + startControl={ + + } + endControl={ + + } + /> + + + + } + endControl={ + + } + /> + + + {} }} + isLoading + startControl={ + + } + endControl={ + + } + /> + + + + } + endControl={ + + } + /> + + + + } + endControl={ + + } + /> + + + + } + endControl={ + + } + /> + + + + Add} + startControl={ + + } + delimiter="+" + endControl={ + + } + /> + + + + Merge} + startControl={ + + } + delimiter={} + endControl={ + + } + /> + + + + Read only} + startControl={ + + } + endControl={ + + } + /> + +); 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 7fcdb3d04f0..9d186929cd1 100644 --- a/src-docs/src/views/form_controls/form_controls_example.js +++ b/src-docs/src/views/form_controls/form_controls_example.js @@ -18,6 +18,7 @@ import { EuiFieldText, EuiFilePicker, EuiFormControlLayout, + EuiFormControlLayoutDelimited, EuiLink, EuiRadio, EuiRadioGroup, @@ -78,6 +79,10 @@ import FormControlLayout from './form_control_layout'; const formControlLayoutSource = require('!!raw-loader!./form_control_layout'); const formControlLayoutHtml = renderToHtml(FormControlLayout); +import FormControlLayoutRange from './form_control_layout_range'; +const formControlLayoutRangeSource = require('!!raw-loader!./form_control_layout_range'); +const formControlLayoutRangeHtml = renderToHtml(FormControlLayoutRange); + export const FormControlsExample = { title: 'Form controls', sections: [ @@ -351,5 +356,45 @@ export const FormControlsExample = { }, demo: , }, + { + title: 'Form control layout delimited', + source: [ + { + type: GuideSectionTypes.JS, + code: formControlLayoutRangeSource, + }, + { + type: GuideSectionTypes.HTML, + code: formControlLayoutRangeHtml, + }, + ], + text: ( + +

+ Building block only +

+ +

+ Like EuiFormControlLayout,{' '} + EuiFormControlLayoutDelimited is generally used + internally to consistently style form controls. This component + specifically lays out two form controls with center text or icon. +

+

+ It takes all of the same props as{' '} + EuiFormControlLayout except for{' '} + children. Instead it requires both a{' '} + single startControl and a{' '} + single endControl. You can + optionally change the center content to a different string or node + (like an EuiIcon). +

+
+ ), + props: { + EuiFormControlLayoutDelimited, + }, + demo: , + }, ], }; diff --git a/src/components/date_picker/_date_picker_range.scss b/src/components/date_picker/_date_picker_range.scss index 583562cd5a3..cedeb5772b4 100644 --- a/src/components/date_picker/_date_picker_range.scss +++ b/src/components/date_picker/_date_picker_range.scss @@ -1,5 +1,6 @@ @import '../form/variables'; @import '../form/mixins'; +@import '../form/form_control_layout/variables'; /** * 1. Account for inner box-shadow style border @@ -34,7 +35,7 @@ padding: 0; .euiDatePicker { - height: $euiFormControlHeight - 2px; + height: $euiFormControlLayoutGroupInputHeight; } } diff --git a/src/components/date_picker/super_date_picker/_mixins.scss b/src/components/date_picker/super_date_picker/_mixins.scss index 02db2c4fd55..4f5a7a5e23a 100644 --- a/src/components/date_picker/super_date_picker/_mixins.scss +++ b/src/components/date_picker/super_date_picker/_mixins.scss @@ -1,10 +1,12 @@ +@import '../../form/form_control_layout/variables'; + @mixin euiSuperDatePickerText { @include euiFormControlText; display: block; width: 100%; padding: 0 $euiSizeS; - line-height: $euiFormControlHeight - 2px; - height: $euiFormControlHeight - 2px; + line-height: $euiFormControlLayoutGroupInputHeight; + height: $euiFormControlLayoutGroupInputHeight; word-break: break-all; transition: background $euiAnimSpeedFast ease-in; } diff --git a/src/components/form/_index.scss b/src/components/form/_index.scss index 689fdbb54a3..e8f451f6b3f 100644 --- a/src/components/form/_index.scss +++ b/src/components/form/_index.scss @@ -1,5 +1,3 @@ -@import 'form_control_layout/mixins'; - @import 'variables'; @import 'mixins'; diff --git a/src/components/form/_mixins.scss b/src/components/form/_mixins.scss index 9672e9a34b5..e97115c2884 100644 --- a/src/components/form/_mixins.scss +++ b/src/components/form/_mixins.scss @@ -1,3 +1,6 @@ +@import 'variables'; +@import 'form_control_layout/variables'; + @mixin euiPlaceholderPerBrowser { // sass-lint:disable-block no-vendor-prefixes // Each prefix must be it's own content block @@ -54,11 +57,11 @@ } &--inGroup:not(:read-only) { - height: $euiFormControlHeight - 2px; /* 2 */ + height: $euiFormControlLayoutGroupInputHeight; /* 2 */ } &--inGroup#{&}--compressed:not(:read-only) { - height: $euiFormControlCompressedHeight - 2px; /* 2 */ + height: $euiFormControlLayoutGroupInputCompressedHeight; /* 2 */ } } } diff --git a/src/components/form/_variables.scss b/src/components/form/_variables.scss index e42d4f02023..f192c28b9e6 100644 --- a/src/components/form/_variables.scss +++ b/src/components/form/_variables.scss @@ -16,7 +16,7 @@ $euiSwitchIconHeight: $euiSize !default; // Coloring $euiFormBackgroundColor: tintOrShade($euiColorLightestShade, 60%, 40%) !default; $euiFormBackgroundDisabledColor: darken($euiColorLightestShade, 2%) !default; -$euiFormBorderOpaqueColor: shade(desaturate(adjust-hue($euiColorPrimary, 22), 22.95), 26%) !default; +$euiFormBorderOpaqueColor: shadeOrTint(desaturate(adjust-hue($euiColorPrimary, 22), 22.95), 26%, 60%) !default; $euiFormBorderColor: transparentize($euiFormBorderOpaqueColor, .9) !default; $euiFormBorderDisabledColor: transparentize($euiFormBorderOpaqueColor, .9) !default; $euiFormCustomControlDisabledIconColor: shadeOrTint($euiColorMediumShade, 38%, 48.5%) !default; // exact 508c foreground for $euiColorLightShade diff --git a/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap b/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap new file mode 100644 index 00000000000..e42a39191cb --- /dev/null +++ b/src/components/form/form_control_layout/__snapshots__/form_control_layout_delimited.test.tsx.snap @@ -0,0 +1,100 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EuiFormControlLayoutDelimited is rendered 1`] = ` +
+
+ + start + +
+
+ → +
+
+ + end + +
+
+`; + +exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a node 1`] = ` +
+
+ + start + +
+
+ +
+
+ + end + +
+
+`; + +exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a string 1`] = ` +
+
+ + start + +
+
+ + +
+
+ + end + +
+
+`; 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 6910a59c6c8..12cfbafe776 100644 --- a/src/components/form/form_control_layout/_form_control_layout.scss +++ b/src/components/form/form_control_layout/_form_control_layout.scss @@ -28,7 +28,7 @@ .euiFormControlLayout__prepend, .euiFormControlLayout__append { flex-shrink: 0; - height: $euiFormControlHeight - 2px; /* 1 */ + height: $euiFormControlLayoutGroupInputHeight; line-height: $euiFontSize; border: none; // remove any border in case it exists @@ -66,7 +66,7 @@ &.euiFormControlLayout--compressed { .euiFormControlLayout__prepend, .euiFormControlLayout__append { - height: $euiFormControlCompressedHeight - 2px; /* 1 */ + height: $euiFormControlLayoutGroupInputCompressedHeight; &.euiFormLabel, &.euiText { @@ -76,12 +76,19 @@ } } + > .euiFormControlLayout--compressed { + height: $euiFormControlLayoutGroupInputCompressedHeight; + } + // // ReadOnly alterations &.euiFormControlLayout--readOnly { @include euiFormControlReadOnlyStyle; padding: 0; /* 1 */ - background-color: transparent; // Ensures the input and layout don't double up on background color + + input { + background-color: transparent; // Ensures the input and layout don't double up on background color + } .euiFormControlLayout__prepend, .euiFormControlLayout__append { diff --git a/src/components/form/form_control_layout/_form_control_layout_range.scss b/src/components/form/form_control_layout/_form_control_layout_range.scss new file mode 100644 index 00000000000..81c7af082c3 --- /dev/null +++ b/src/components/form/form_control_layout/_form_control_layout_range.scss @@ -0,0 +1,56 @@ +.euiFormControlLayoutDelimited { + // Match just the regular drop shadow of inputs + @include euiFormControlDefaultShadow; + padding: 1px; /* 1 */ + + > .euiFormControlLayout__childrenWrapper { + display: flex; + align-items: center; + } + + input { + height: $euiFormControlLayoutGroupInputHeight; + } + + &[class*='--compressed'] input { + height: $euiFormControlLayoutGroupInputCompressedHeight; + padding-top: 0; // Fixes IE + padding-bottom: 0; // Fixes IE + } + + &[class*='--fullWidth'] input { + max-width: none; + } + + .euiFormControlLayoutIcons { + // Absolutely positioning the icons doesn't work because they + // overlay only one of controls making the layout unbalanced + position: static; // Overrider absolute + padding-left: $euiFormControlPadding; + padding-right: $euiFormControlPadding; + flex-shrink: 0; // Fixes IE + + &:not(.euiFormControlLayoutIcons--right) { + order: -1; + } + } +} + +.euiFormControlLayoutDelimited__child--noStyle { + // sass-lint:disable-block no-important + box-shadow: none !important; + border-radius: 0 !important; +} + +.euiFormControlLayoutDelimited__child--centered { + text-align: center; +} + +.euiFormControlLayoutDelimited__delimeter { + // sass-lint:disable-block no-important + // Override EuiText line-height + line-height: 1 !important; + flex: 0 0 auto; + padding-left: $euiFormControlPadding / 2; + padding-right: $euiFormControlPadding / 2; +} diff --git a/src/components/form/form_control_layout/_index.scss b/src/components/form/form_control_layout/_index.scss index f5a9b5d33bc..d14b350f0ef 100644 --- a/src/components/form/form_control_layout/_index.scss +++ b/src/components/form/form_control_layout/_index.scss @@ -1,5 +1,7 @@ +@import 'variables'; @import 'mixins'; @import 'form_control_layout'; +@import 'form_control_layout_range'; @import 'form_control_layout_icons'; @import 'form_control_layout_clear_button'; @import 'form_control_layout_custom_icon'; diff --git a/src/components/form/form_control_layout/_variables.scss b/src/components/form/form_control_layout/_variables.scss new file mode 100644 index 00000000000..8e04c7aeba1 --- /dev/null +++ b/src/components/form/form_control_layout/_variables.scss @@ -0,0 +1,8 @@ +@import '../variables'; + +/** + * 1. Account for inner box-shadow style border + */ + +$euiFormControlLayoutGroupInputHeight: $euiFormControlHeight - 2px; /* 1 */ +$euiFormControlLayoutGroupInputCompressedHeight: $euiFormControlCompressedHeight - 2px; /* 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 aaf51f8fa70..b0198868c9a 100644 --- a/src/components/form/form_control_layout/form_control_layout.tsx +++ b/src/components/form/form_control_layout/form_control_layout.tsx @@ -17,28 +17,8 @@ export { ICON_SIDES } from './form_control_layout_icons'; type ReactElements = ReactElement | ReactElement[]; -// if `prepend` and/or `append` is specified then `children` must be undefined or a single ReactElement -interface AppendWithChildren { - append: ReactElements; - children?: ReactElement; -} -interface PrependWithChildren { - prepend: ReactElements; - children?: ReactElement; -} -type SiblingsWithChildren = AppendWithChildren | PrependWithChildren; - -type ChildrenOptions = - | SiblingsWithChildren - | { - append?: undefined | null; - prepend?: undefined | null; - children?: ReactNode; - }; - type EuiFormControlLayoutProps = CommonProps & - HTMLAttributes & - ChildrenOptions & { + HTMLAttributes & { /** * Creates an input group with element(s) coming before children */ @@ -47,6 +27,7 @@ type EuiFormControlLayoutProps = CommonProps & * Creates an input group with element(s) coming after children */ append?: ReactElements; + children?: ReactNode; icon?: EuiFormControlLayoutIconsProps['icon']; clear?: EuiFormControlLayoutIconsProps['clear']; fullWidth?: boolean; @@ -57,14 +38,6 @@ type EuiFormControlLayoutProps = CommonProps & readOnly?: boolean; }; -function isChildrenIsReactElement( - append: EuiFormControlLayoutProps['append'], - prepend: EuiFormControlLayoutProps['prepend'], - children: EuiFormControlLayoutProps['children'] -): children is ReactElement { - return (!!append || !!prepend) && children != null; -} - export class EuiFormControlLayout extends Component { render() { const { @@ -94,23 +67,14 @@ export class EuiFormControlLayout extends Component { className ); - const prependNodes = this.renderPrepends(); - const appendNodes = this.renderAppends(); - - let clonedChildren; - if (isChildrenIsReactElement(append, prepend, children)) { - clonedChildren = cloneElement(children, { - className: `${ - children.props.className - } euiFormControlLayout__child--noStyle`, - }); - } + const prependNodes = this.renderPrepends(prepend); + const appendNodes = this.renderAppends(append); return (
{prependNodes}
- {clonedChildren || children} + {children} { ); } - renderPrepends() { - const { prepend } = this.props; - + renderPrepends(prepend: ReactElements | undefined | null) { if (!prepend) { return; } @@ -137,9 +99,7 @@ export class EuiFormControlLayout extends Component { return prependNodes; } - renderAppends() { - const { append } = this.props; - + renderAppends(append: ReactElements | undefined | null) { if (!append) { return; } diff --git a/src/components/form/form_control_layout/form_control_layout_delimited.test.tsx b/src/components/form/form_control_layout/form_control_layout_delimited.test.tsx new file mode 100644 index 00000000000..22dce0c5498 --- /dev/null +++ b/src/components/form/form_control_layout/form_control_layout_delimited.test.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { render } from 'enzyme'; +import { requiredProps } from '../../../test/required_props'; + +import { EuiFormControlLayoutDelimited } from './form_control_layout_delimited'; +import { EuiIcon } from '../../icon'; + +describe('EuiFormControlLayoutDelimited', () => { + test('is rendered', () => { + const component = render( + start} + endControl={end} + {...requiredProps} + /> + ); + + expect(component).toMatchSnapshot(); + }); + + describe('props', () => { + describe('delimiter', () => { + describe('is rendered', () => { + test('as a string', () => { + const component = render( + start} + endControl={end} + delimiter="+" + /> + ); + + expect(component).toMatchSnapshot(); + }); + + test('as a node', () => { + const icon = ; + + const component = render( + start} + endControl={end} + delimiter={icon} + /> + ); + + expect(component).toMatchSnapshot(); + }); + }); + }); + }); +}); diff --git a/src/components/form/form_control_layout/form_control_layout_delimited.tsx b/src/components/form/form_control_layout/form_control_layout_delimited.tsx new file mode 100644 index 00000000000..56f3b34481a --- /dev/null +++ b/src/components/form/form_control_layout/form_control_layout_delimited.tsx @@ -0,0 +1,56 @@ +import React, { + FunctionComponent, + ReactElement, + cloneElement, + ReactNode, +} from 'react'; +import classNames from 'classnames'; + +import { EuiText } from '../../text'; +import { EuiFormControlLayout } from './form_control_layout'; + +type EuiFormControlLayoutDelimitedProps = Partial & { + /** + * Left side control + */ + startControl: ReactElement; + /** + * Right side control + */ + endControl: ReactElement; + /** + * The center content. Accepts a string to be wrapped in a subdued EuiText + * or a single ReactElement + */ + delimiter?: ReactNode; + className?: string; +}; + +export const EuiFormControlLayoutDelimited: FunctionComponent< + EuiFormControlLayoutDelimitedProps +> = ({ startControl, endControl, delimiter = '→', className, ...rest }) => { + const classes = classNames('euiFormControlLayoutDelimited', className); + + return ( + + {addClassesToControl(startControl)} + + {delimiter} + + {addClassesToControl(endControl)} + + ); +}; + +function addClassesToControl(control: ReactElement) { + return cloneElement(control, { + className: classNames( + control.props.className, + 'euiFormControlLayoutDelimited__child--noStyle', + 'euiFormControlLayoutDelimited__child--centered' + ), + }); +} diff --git a/src/components/form/form_control_layout/index.ts b/src/components/form/form_control_layout/index.ts index 79e0774a1f0..0f16df04588 100644 --- a/src/components/form/form_control_layout/index.ts +++ b/src/components/form/form_control_layout/index.ts @@ -5,3 +5,5 @@ export { export { EuiFormControlLayoutCustomIcon, } from './form_control_layout_custom_icon'; + +export { EuiFormControlLayoutDelimited } from './form_control_layout_delimited'; diff --git a/src/components/form/index.js b/src/components/form/index.js index 75310f40940..0c0d51a554b 100644 --- a/src/components/form/index.js +++ b/src/components/form/index.js @@ -6,7 +6,10 @@ export { EuiFieldSearch } from './field_search'; export { EuiFieldText } from './field_text'; export { EuiFilePicker } from './file_picker'; export { EuiForm } from './form'; -export { EuiFormControlLayout } from './form_control_layout'; +export { + EuiFormControlLayout, + EuiFormControlLayoutDelimited, +} from './form_control_layout'; export { EuiFormErrorText } from './form_error_text'; export { EuiFormHelpText } from './form_help_text'; export { EuiFormLabel } from './form_label'; diff --git a/src/components/form/select/_select.scss b/src/components/form/select/_select.scss index 9dc5e60b1a8..93e2f795623 100644 --- a/src/components/form/select/_select.scss +++ b/src/components/form/select/_select.scss @@ -20,11 +20,11 @@ } &--inGroup { - line-height: $euiFormControlHeight - 2px; /* 2 */ + line-height: $euiFormControlLayoutGroupInputHeight; /* 2 */ } &--inGroup#{&}--compressed { - line-height: $euiFormControlCompressedHeight - 2px; /* 2 */ + line-height: $euiFormControlLayoutGroupInputCompressedHeight; /* 2 */ } // Turn off linter for some MS specific bits. diff --git a/src/components/index.js b/src/components/index.js index 32923f19c17..4a8d83c490d 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -106,6 +106,7 @@ export { EuiFilePicker, EuiForm, EuiFormControlLayout, + EuiFormControlLayoutDelimited, EuiFormErrorText, EuiFormHelpText, EuiFormLabel, From 89c99666932f8c46057efe9962ab121e7e783a19 Mon Sep 17 00:00:00 2001 From: Caroline Horn <549577+cchaos@users.noreply.github.com> Date: Thu, 25 Jul 2019 10:11:28 -0400 Subject: [PATCH 03/24] [Feature branch] Compressed EuiSuperSelect dropdown (#2155) - Added truncation example - Added max-height --- src-docs/src/views/super_select/super_select.js | 7 +++++-- .../views/super_select/super_select_complex.js | 5 +---- .../context_menu/_context_menu_item.scss | 1 + .../form/super_select/_super_select.scss | 16 +++++++++++++++- src/components/form/super_select/super_select.js | 5 ++++- .../form/super_select/super_select.test.js | 13 +++++++++++++ 6 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src-docs/src/views/super_select/super_select.js b/src-docs/src/views/super_select/super_select.js index d6414d6d76f..b356b870072 100644 --- a/src-docs/src/views/super_select/super_select.js +++ b/src-docs/src/views/super_select/super_select.js @@ -19,8 +19,11 @@ export default class extends Component { }, { value: 'option_three', - inputDisplay: - 'Option three has a super long text to see if it will truncate or what', + inputDisplay: ( + + Option three has a super long text and added truncation + + ), }, ]; diff --git a/src-docs/src/views/super_select/super_select_complex.js b/src-docs/src/views/super_select/super_select_complex.js index 881d42842a5..fc44e4bef25 100644 --- a/src-docs/src/views/super_select/super_select_complex.js +++ b/src-docs/src/views/super_select/super_select_complex.js @@ -1,6 +1,6 @@ import React, { Component, Fragment } from 'react'; -import { EuiSuperSelect, EuiSpacer, EuiText } from '../../../../src/components'; +import { EuiSuperSelect, EuiText } from '../../../../src/components'; export default class extends Component { constructor(props) { @@ -13,7 +13,6 @@ export default class extends Component { dropdownDisplay: ( Option one -

Has a short description giving more detail to the option. @@ -28,7 +27,6 @@ export default class extends Component { dropdownDisplay: ( Option two -

Has a short description giving more detail to the option. @@ -43,7 +41,6 @@ export default class extends Component { dropdownDisplay: ( Option three -

Has a short description giving more detail to the option. diff --git a/src/components/context_menu/_context_menu_item.scss b/src/components/context_menu/_context_menu_item.scss index c3c2dfc9f04..8675f1429cb 100644 --- a/src/components/context_menu/_context_menu_item.scss +++ b/src/components/context_menu/_context_menu_item.scss @@ -31,6 +31,7 @@ .euiContextMenuItem__text { flex-grow: 1; + overflow: hidden; // allows for text truncation } .euiContextMenuItem__arrow { diff --git a/src/components/form/super_select/_super_select.scss b/src/components/form/super_select/_super_select.scss index cfae17820d0..19e9f4212fb 100644 --- a/src/components/form/super_select/_super_select.scss +++ b/src/components/form/super_select/_super_select.scss @@ -11,6 +11,13 @@ } } +.euiSuperSelect__listbox { + @include euiScrollBar; + max-height: 300px; + overflow: hidden; + overflow-y: auto; +} + .euiSuperSelect__popoverPanel[class*='bottom'] { /* 3 */ border-top-color: transparentize($euiBorderColor, .2); border-top-right-radius: 0; /* 2 */ @@ -26,11 +33,18 @@ } .euiSuperSelect__item { - &:hover, + @include euiFontSizeS; + padding: $euiSizeS; + + &:hover:not(:disabled), &:focus { text-decoration: none; background-color: $euiFocusBackgroundColor; } + + &:disabled { + cursor: not-allowed; + } } .euiSuperSelect__item--hasDividers:not(:last-of-type) { diff --git a/src/components/form/super_select/super_select.js b/src/components/form/super_select/super_select.js index 67c4b386cac..19ebab80986 100644 --- a/src/components/form/super_select/super_select.js +++ b/src/components/form/super_select/super_select.js @@ -165,6 +165,7 @@ export class EuiSuperSelect extends Component { itemLayoutAlign, fullWidth, popoverClassName, + compressed, ...rest } = this.props; @@ -206,6 +207,7 @@ export class EuiSuperSelect extends Component { className={buttonClasses} fullWidth={fullWidth} isInvalid={isInvalid} + compressed={compressed} {...rest} /> ); @@ -222,7 +224,6 @@ export class EuiSuperSelect extends Component { onKeyDown={this.onItemKeyDown} layoutAlign={itemLayoutAlign} buttonRef={node => this.setItemNode(node, index)} - style={{ width: this.state.menuWidth }} role="option" id={value} aria-selected={valueOfSelected === value} @@ -256,8 +257,10 @@ export class EuiSuperSelect extends Component {

{items}
diff --git a/src/components/form/super_select/super_select.test.js b/src/components/form/super_select/super_select.test.js index 7023fa6c7f6..20702df0380 100644 --- a/src/components/form/super_select/super_select.test.js +++ b/src/components/form/super_select/super_select.test.js @@ -42,6 +42,19 @@ describe('EuiSuperSelect', () => { expect(component).toMatchSnapshot(); }); + test('compressed is rendered', () => { + const component = render( + {}} + compressed + /> + ); + + expect(component).toMatchSnapshot(); + }); + test('select component is rendered', () => { const component = render( Date: Tue, 30 Jul 2019 13:38:11 -0400 Subject: [PATCH 04/24] [Feature Branch] Update compressed form control styles (#2174) * Updated compressed visual style in mixin * Compressed updates to from control groups * Fix compressed state overrides * Reduce horizontal padding for compressed * Icons and button icons in input groups * Added a compressed option for from` euiFormControlLayoutPadding` * Added compressed padding for inputs with icons * Fix readonly & compressed input groups * Fix group heights * Update file picker with new compressed styles * Fix delimited compressed and fullwidth styles * Fixed EuiComboBox * Added reduced padding for EuiColorPicker * Fixed date pickers * Variables for border-radius --- .../__snapshots__/color_picker.test.js.snap | 16 ++-- .../color_picker/_color_picker.scss | 15 ++++ src/components/color_picker/color_picker.js | 1 + src/components/combo_box/_combo_box.scss | 9 ++- .../combo_box_input/_combo_box_pill.scss | 18 ++++- src/components/date_picker/_date_picker.scss | 4 + .../quick_select_popover.test.js.snap | 2 + .../_quick_select_popover.scss | 4 + .../quick_select_popover.js | 1 + src/components/form/_mixins.scss | 50 +++++++++---- src/components/form/_variables.scss | 5 +- .../form/field_number/_field_number.scss | 4 + .../form/field_password/_field_password.scss | 4 + .../form/field_search/_field_search.scss | 4 + .../form/field_text/_field_text.scss | 4 + .../form/file_picker/_file_picker.scss | 33 ++++---- .../form/file_picker/file_picker.js | 10 +-- ...orm_control_layout_delimited.test.tsx.snap | 12 +-- .../_form_control_layout.scss | 75 +++++++++++++++---- ...ss => _form_control_layout_delimited.scss} | 48 +++++++++--- .../_form_control_layout_icons.scss | 9 +++ .../form/form_control_layout/_index.scss | 2 +- .../form/form_control_layout/_mixins.scss | 18 +++-- .../form/form_control_layout/_variables.scss | 1 + .../form_control_layout_delimited.tsx | 3 +- src/components/form/select/_select.scss | 1 + .../super_select/_super_select_control.scss | 1 + 27 files changed, 261 insertions(+), 93 deletions(-) rename src/components/form/form_control_layout/{_form_control_layout_range.scss => _form_control_layout_delimited.scss} (50%) diff --git a/src/components/color_picker/__snapshots__/color_picker.test.js.snap b/src/components/color_picker/__snapshots__/color_picker.test.js.snap index 9156adca9ac..2c1ee677c44 100644 --- a/src/components/color_picker/__snapshots__/color_picker.test.js.snap +++ b/src/components/color_picker/__snapshots__/color_picker.test.js.snap @@ -25,7 +25,7 @@ exports[`renders EuiColorPicker 1`] = ` {([openLabel, closeLabel]) => ( input { @@ -73,6 +73,10 @@ &.euiComboBox-isOpen { .euiComboBox__inputWrap { @include euiFormControlFocusStyle; + + &--compressed { + @include euiFormControlFocusStyle($borderOnly: true); + } } } @@ -90,6 +94,7 @@ &.euiComboBox--compressed { .euiComboBox__inputWrap { + // height: $euiFormControlCompressedHeight; /* 2 */ line-height: $euiFormControlCompressedHeight; /* 2 */ padding-top: 0; padding-bottom: 0; diff --git a/src/components/combo_box/combo_box_input/_combo_box_pill.scss b/src/components/combo_box/combo_box_input/_combo_box_pill.scss index b45de89e028..76885f306de 100644 --- a/src/components/combo_box/combo_box_input/_combo_box_pill.scss +++ b/src/components/combo_box/combo_box_input/_combo_box_pill.scss @@ -1,10 +1,22 @@ -// Overwrites the base styling of EuiBadge, to give it a larger size and margins -// that make sense in the input wrap. +/* + * 1. Overwrites the base styling of EuiBadge, to give it a larger size and margins + * that make sense in the input wrap. + */ .euiComboBoxPill { - margin: $euiSizeXS !important; // sass-lint:disable-line no-important + height: $euiSizeL - 2px; line-height: $euiSizeL - 2px; vertical-align: baseline; + &, + & + & /* 1 */ { + margin: $euiSizeXS; + } + + .euiComboBox--compressed &, + .euiComboBox--compressed & + & /* 1 */ { + margin: $euiSizeXS $euiSizeXS 0 0; + } + &--plainText { @include euiFont; @include euiTextTruncate; diff --git a/src/components/date_picker/_date_picker.scss b/src/components/date_picker/_date_picker.scss index e5e693ff171..b4ef09779af 100644 --- a/src/components/date_picker/_date_picker.scss +++ b/src/components/date_picker/_date_picker.scss @@ -28,6 +28,10 @@ // This is mostly here so that we can provide an inline version that doesn't have the // shadows and depth. .euiDatePicker { + .euiFormControlLayout { + height: auto; + } + &.euiDatePicker--shadow { .react-datepicker-popper { @include euiBottomShadowMedium; diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select_popover.test.js.snap b/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select_popover.test.js.snap index a9a9fd442a9..aa037a3d983 100644 --- a/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select_popover.test.js.snap +++ b/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select_popover.test.js.snap @@ -2,6 +2,7 @@ exports[`EuiQuickSelectPopover is rendered 1`] = `
start @@ -24,7 +24,7 @@ exports[`EuiFormControlLayoutDelimited is rendered 1`] = `
end @@ -40,7 +40,7 @@ exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a node 1`] class="euiFormControlLayout__childrenWrapper" > start @@ -61,7 +61,7 @@ exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a node 1`]
end @@ -77,7 +77,7 @@ exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a string 1 class="euiFormControlLayout__childrenWrapper" > start @@ -91,7 +91,7 @@ exports[`EuiFormControlLayoutDelimited props delimiter is rendered as a string 1 end 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 12cfbafe776..db4b0a93d0f 100644 --- a/src/components/form/form_control_layout/_form_control_layout.scss +++ b/src/components/form/form_control_layout/_form_control_layout.scss @@ -3,7 +3,7 @@ .euiFormControlLayout { // Let the height expand as needed - @include euiFormControlSize(auto, $includeAlternates: true); + @include euiFormControlSize($includeAlternates: true); } .euiFormControlLayout__childrenWrapper { @@ -18,7 +18,7 @@ // Match just the regular drop shadow of inputs @include euiFormControlDefaultShadow; display: flex; - align-items: center; + align-items: stretch; padding: 1px; /* 1 */ .euiFormControlLayout__childrenWrapper { @@ -28,25 +28,61 @@ .euiFormControlLayout__prepend, .euiFormControlLayout__append { flex-shrink: 0; - height: $euiFormControlLayoutGroupInputHeight; - line-height: $euiFontSize; + height: 100%; + line-height: $euiFontSize - 1px; // The 1px less aligns the icons better border: none; // remove any border in case it exists + border-radius: 0; + + &:first-child { + border-top-left-radius: $euiFormControlLayoutGroupInputCompressedBorderRadius; + border-bottom-left-radius: $euiFormControlLayoutGroupInputCompressedBorderRadius; + } + + &:last-child { + border-top-right-radius: $euiFormControlLayoutGroupInputCompressedBorderRadius; + border-bottom-right-radius: $euiFormControlLayoutGroupInputCompressedBorderRadius; + } &:disabled { background-color: $euiFormBackgroundDisabledColor; color: $euiFormControlDisabledColor; // ensures established contrast } + // sass-lint:disable-block no-important // This is the only way to target specific components to override styling + &.euiFormLabel, + &.euiText, + &.euiButtonIcon, + &.euiIcon { + background-color: $euiFormInputGroupLabelBackground; + + & + .euiFormControlLayout__prepend, + & + .euiFormControlLayout__append { + padding-left: 0 !important; + + &.euiButtonIcon, + &.euiIcon { + width: $euiSizeL; + } + } + } + &.euiFormLabel, &.euiText { white-space: nowrap; margin-bottom: 0; padding: $euiFormControlPadding; border: none; - background-color: $euiFormInputGroupLabelBackground; line-height: $euiFontSize; } + + &.euiButtonIcon, + &.euiIcon { + padding: 0 $euiSizeS; + width: $euiSizeXL; + border: none; + transform: none !important; + } } // @@ -64,22 +100,28 @@ // Compressed alterations &.euiFormControlLayout--compressed { + @include euiFormControlDefaultShadow($borderOnly: true); + border-radius: $euiBorderRadius / 2; + .euiFormControlLayout__prepend, .euiFormControlLayout__append { - height: $euiFormControlLayoutGroupInputCompressedHeight; + &:first-child { + border-top-left-radius: $euiFormControlLayoutGroupInputCompressedBorderRadius; + border-bottom-left-radius: $euiFormControlLayoutGroupInputCompressedBorderRadius; + } + + &:last-child { + border-top-right-radius: $euiFormControlLayoutGroupInputCompressedBorderRadius; + border-bottom-right-radius: $euiFormControlLayoutGroupInputCompressedBorderRadius; + } &.euiFormLabel, &.euiText { - padding-top: $euiFormControlCompressedPadding; - padding-bottom: $euiFormControlCompressedPadding; + padding: $euiFormControlCompressedPadding; } } } - > .euiFormControlLayout--compressed { - height: $euiFormControlLayoutGroupInputCompressedHeight; - } - // // ReadOnly alterations &.euiFormControlLayout--readOnly { @@ -89,10 +131,17 @@ input { background-color: transparent; // Ensures the input and layout don't double up on background color } + } + + // + // ReadOnly-Compressed alterations + &.euiFormControlLayout--compressed.euiFormControlLayout--readOnly { .euiFormControlLayout__prepend, .euiFormControlLayout__append { - height: $euiFormControlHeight; // Matching input height, as euiFormControlSize() does not apply to the smaller height to readOnly states + height: $euiFormControlCompressedHeight; + border-top-left-radius: $euiFormControlCompressedBorderRadius; + border-bottom-left-radius: $euiFormControlCompressedBorderRadius; } } } diff --git a/src/components/form/form_control_layout/_form_control_layout_range.scss b/src/components/form/form_control_layout/_form_control_layout_delimited.scss similarity index 50% rename from src/components/form/form_control_layout/_form_control_layout_range.scss rename to src/components/form/form_control_layout/_form_control_layout_delimited.scss index 81c7af082c3..824785c0d1d 100644 --- a/src/components/form/form_control_layout/_form_control_layout_range.scss +++ b/src/components/form/form_control_layout/_form_control_layout_delimited.scss @@ -1,6 +1,11 @@ +@import '../variables'; +@import '../mixins'; + .euiFormControlLayoutDelimited { // Match just the regular drop shadow of inputs @include euiFormControlDefaultShadow; + display: flex; + align-items: stretch; padding: 1px; /* 1 */ > .euiFormControlLayout__childrenWrapper { @@ -8,18 +13,34 @@ align-items: center; } - input { - height: $euiFormControlLayoutGroupInputHeight; + &[class*='--compressed'] { + @include euiFormControlDefaultShadow($borderOnly: true); + border-radius: $euiBorderRadius / 2; + + .euiFormControlLayoutDelimited__input { + height: 100%; + padding-top: 0; // Fixes IE + padding-bottom: 0; // Fixes IE + padding-left: $euiFormControlCompressedPadding; + padding-right: $euiFormControlCompressedPadding; + } + + .euiFormControlLayoutIcons { + padding-left: $euiFormControlCompressedPadding; + padding-right: $euiFormControlCompressedPadding; + } } - &[class*='--compressed'] input { - height: $euiFormControlLayoutGroupInputCompressedHeight; - padding-top: 0; // Fixes IE - padding-bottom: 0; // Fixes IE + &[class*='--fullWidth'] .euiFormControlLayout__childrenWrapper { + width: 100%; } - &[class*='--fullWidth'] input { - max-width: none; + &[class*='--readOnly'] { + @include euiFormControlReadOnlyStyle; + + input { + background-color: transparent; // Ensures the input and layout don't double up on background color + } } .euiFormControlLayoutIcons { @@ -36,14 +57,17 @@ } } -.euiFormControlLayoutDelimited__child--noStyle { +.euiFormControlLayoutDelimited__input { // sass-lint:disable-block no-important box-shadow: none !important; border-radius: 0 !important; -} - -.euiFormControlLayoutDelimited__child--centered { text-align: center; + height: 100%; + min-width: 0; // Fixes FF + + .euiFormControlLayoutDelimited[class*='--compressed'] & { + max-width: none; + } } .euiFormControlLayoutDelimited__delimeter { diff --git a/src/components/form/form_control_layout/_form_control_layout_icons.scss b/src/components/form/form_control_layout/_form_control_layout_icons.scss index 5d2b4e12eb4..732b12d1dcb 100644 --- a/src/components/form/form_control_layout/_form_control_layout_icons.scss +++ b/src/components/form/form_control_layout/_form_control_layout_icons.scss @@ -10,11 +10,20 @@ > * + * { margin-left: $euiFormControlPadding / 2; } + + .euiFormControlLayout--compressed & { + left: $euiFormControlCompressedPadding; + } } .euiFormControlLayoutIcons--right { left: auto; right: $euiFormControlPadding; + + .euiFormControlLayout--compressed & { + left: auto; + right: $euiFormControlCompressedPadding; + } } // If the control is disabled, change the color of the icons diff --git a/src/components/form/form_control_layout/_index.scss b/src/components/form/form_control_layout/_index.scss index d14b350f0ef..a3a22b9f3a7 100644 --- a/src/components/form/form_control_layout/_index.scss +++ b/src/components/form/form_control_layout/_index.scss @@ -1,7 +1,7 @@ @import 'variables'; @import 'mixins'; @import 'form_control_layout'; -@import 'form_control_layout_range'; +@import 'form_control_layout_delimited'; @import 'form_control_layout_icons'; @import 'form_control_layout_clear_button'; @import 'form_control_layout_custom_icon'; diff --git a/src/components/form/form_control_layout/_mixins.scss b/src/components/form/form_control_layout/_mixins.scss index 8a174285f9a..bd4ab8c56e5 100644 --- a/src/components/form/form_control_layout/_mixins.scss +++ b/src/components/form/form_control_layout/_mixins.scss @@ -1,14 +1,22 @@ -@mixin euiFormControlLayoutPadding($numOfIcons, $side: 'right') { - $iconPaddingStart: $euiSizeXXL; +@import '../variables'; + +@mixin euiFormControlLayoutPadding($numOfIcons, $side: 'right', $compressed: false) { + $firstIconSize: $euiFormControlPadding + $euiSize + $euiFormControlPadding; + $secondIconSize: $euiFormControlPadding + $euiSize; + + @if ($compressed) { + $firstIconSize: $euiFormControlCompressedPadding + $euiSize + $euiFormControlCompressedPadding; + $secondIconSize: $euiFormControlCompressedPadding + $euiSize; + } @if variable-exists(numOfIcons) == false { @error '$numOfIcons:integer (1-3) must be provided to @mixin euiFormControlLayoutPadding().'; } @else if $numOfIcons == 1 { - padding-#{$side}: $iconPaddingStart; + padding-#{$side}: $firstIconSize; } @else if $numOfIcons == 2 { - padding-#{$side}: $iconPaddingStart + $euiSize; + padding-#{$side}: $firstIconSize + $secondIconSize; } @else if $numOfIcons == 3 { - padding-#{$side}: $iconPaddingStart + ($euiSize * 2) + $euiSizeS; + padding-#{$side}: $firstIconSize + ($secondIconSize * 2); } } diff --git a/src/components/form/form_control_layout/_variables.scss b/src/components/form/form_control_layout/_variables.scss index 8e04c7aeba1..75232099a40 100644 --- a/src/components/form/form_control_layout/_variables.scss +++ b/src/components/form/form_control_layout/_variables.scss @@ -6,3 +6,4 @@ $euiFormControlLayoutGroupInputHeight: $euiFormControlHeight - 2px; /* 1 */ $euiFormControlLayoutGroupInputCompressedHeight: $euiFormControlCompressedHeight - 2px; /* 1 */ +$euiFormControlLayoutGroupInputCompressedBorderRadius: $euiFormControlCompressedBorderRadius / 2; diff --git a/src/components/form/form_control_layout/form_control_layout_delimited.tsx b/src/components/form/form_control_layout/form_control_layout_delimited.tsx index 56f3b34481a..57a6a426dc4 100644 --- a/src/components/form/form_control_layout/form_control_layout_delimited.tsx +++ b/src/components/form/form_control_layout/form_control_layout_delimited.tsx @@ -49,8 +49,7 @@ function addClassesToControl(control: ReactElement) { return cloneElement(control, { className: classNames( control.props.className, - 'euiFormControlLayoutDelimited__child--noStyle', - 'euiFormControlLayoutDelimited__child--centered' + 'euiFormControlLayoutDelimited__input' ), }); } diff --git a/src/components/form/select/_select.scss b/src/components/form/select/_select.scss index 93e2f795623..26db7bbcebb 100644 --- a/src/components/form/select/_select.scss +++ b/src/components/form/select/_select.scss @@ -14,6 +14,7 @@ padding-bottom: 0; /* 2 */ &--compressed { + @include euiFormControlWithIcon($side: 'right', $compressed: true); /* 1 */ line-height: $euiFormControlCompressedHeight; /* 2 */ padding-top: 0; /* 2 */ padding-bottom: 0; /* 2 */ diff --git a/src/components/form/super_select/_super_select_control.scss b/src/components/form/super_select/_super_select_control.scss index 07460eba20b..2d96c6a81b0 100644 --- a/src/components/form/super_select/_super_select_control.scss +++ b/src/components/form/super_select/_super_select_control.scss @@ -24,6 +24,7 @@ } &--compressed { + @include euiFormControlWithIcon($side: 'right', $compressed: true); /* 1 */ line-height: $euiFormControlCompressedHeight; /* 2 */ padding-top: 0; /* 2 */ padding-bottom: 0; /* 2 */ From f917029280079b9059d0757b34f0cc1c1cc2646c Mon Sep 17 00:00:00 2001 From: Caroline Horn <549577+cchaos@users.noreply.github.com> Date: Tue, 13 Aug 2019 09:29:24 -0400 Subject: [PATCH 05/24] [Feature branch] Compressed form rows (#2181) * Removed padding from compressed form row * Create mixin for `euiTextBreakWord` * Added option for horizontal compressed style Breaking: `compressed` is no longer passed to children * [Docs] Final compressed doc example changes * Fix combobox height * Fixed usages where spacers were needed * Deprecated `displayOnly` for `display: center` --- .../guide_locale_selector.js | 1 - .../guide_page/guide_page_chrome.js | 10 +- .../src/views/color_picker/custom_button.js | 2 + src-docs/src/views/combo_box/containers.js | 2 + src-docs/src/views/context/context.js | 2 + .../src/views/context_menu/context_menu.js | 2 + .../src/views/flyout/flyout_complicated.js | 1 + .../src/views/form_layouts/form_compressed.js | 44 +- .../form_layouts/form_layouts_example.js | 34 +- src-docs/src/views/form_layouts/form_rows.js | 3 + .../src/views/form_layouts/inline_popover.js | 3 + .../src/views/form_layouts/inline_sizing.js | 6 +- .../src/views/form_validation/validation.js | 3 + src-docs/src/views/popover/trap_focus.js | 3 + src/components/combo_box/_combo_box.scss | 6 +- .../date_popover/relative_tab.js | 2 +- .../__snapshots__/quick_select.test.js.snap | 20 +- .../quick_select_popover/quick_select.js | 3 + .../quick_select_popover/refresh_interval.js | 2 + src/components/expression/_expression.scss | 2 +- .../described_form_group.test.js.snap | 89 ++-- .../form/file_picker/_file_picker.scss | 3 +- .../form/form_help_text/_form_help_text.scss | 2 +- .../form/form_label/_form_label.scss | 1 - .../__snapshots__/form_row.test.js.snap | 425 ++++++++++++------ src/components/form/form_row/_form_row.scss | 53 ++- src/components/form/form_row/form_row.js | 86 ++-- src/components/form/form_row/form_row.test.js | 28 +- src/components/form/form_row/index.d.ts | 1 + src/components/table/_table.scss | 2 +- src/global_styling/mixins/_typography.scss | 13 +- src/global_styling/utility/_utility.scss | 5 +- 32 files changed, 602 insertions(+), 257 deletions(-) diff --git a/src-docs/src/components/guide_locale_selector/guide_locale_selector.js b/src-docs/src/components/guide_locale_selector/guide_locale_selector.js index e6f8c1065b6..52f545c5478 100644 --- a/src-docs/src/components/guide_locale_selector/guide_locale_selector.js +++ b/src-docs/src/components/guide_locale_selector/guide_locale_selector.js @@ -12,7 +12,6 @@ export const GuideLocaleSelector = ({ selectedLocale, onToggleLocale }) => { onChange={() => onToggleLocale(selectedLocale === 'en' ? 'en-xa' : 'en') } - compressed={true} /> ); diff --git a/src-docs/src/components/guide_page/guide_page_chrome.js b/src-docs/src/components/guide_page/guide_page_chrome.js index 9971aefb689..352ac98ab62 100644 --- a/src-docs/src/components/guide_page/guide_page_chrome.js +++ b/src-docs/src/components/guide_page/guide_page_chrome.js @@ -166,12 +166,10 @@ export class GuidePageChrome extends Component { selectedTheme={this.props.selectedTheme} /> {location.host === 'localhost:8030' ? ( // eslint-disable-line no-restricted-globals - - - + ) : null} diff --git a/src-docs/src/views/color_picker/custom_button.js b/src-docs/src/views/color_picker/custom_button.js index 31d715b6a91..57625d7af47 100644 --- a/src-docs/src/views/color_picker/custom_button.js +++ b/src-docs/src/views/color_picker/custom_button.js @@ -5,6 +5,7 @@ import { EuiFormRow, EuiColorPickerSwatch, EuiBadge, + EuiSpacer, } from '../../../../src/components'; import { isValidHex } from '../../../../src/services'; @@ -43,6 +44,7 @@ export class CustomButton extends Component { } /> + + + + + {action} )} diff --git a/src-docs/src/views/context_menu/context_menu.js b/src-docs/src/views/context_menu/context_menu.js index 6b7aa521605..1b724641ca3 100644 --- a/src-docs/src/views/context_menu/context_menu.js +++ b/src-docs/src/views/context_menu/context_menu.js @@ -7,6 +7,7 @@ import { EuiIcon, EuiPopover, EuiSwitch, + EuiSpacer, } from '../../../../src/components'; function flattenPanelTree(tree, array = []) { @@ -87,6 +88,7 @@ export default class extends Component { label="Current time range" /> + Copy iFrame code ), diff --git a/src-docs/src/views/flyout/flyout_complicated.js b/src-docs/src/views/flyout/flyout_complicated.js index 6901f5e3014..343d5412e63 100644 --- a/src-docs/src/views/flyout/flyout_complicated.js +++ b/src-docs/src/views/flyout/flyout_complicated.js @@ -195,6 +195,7 @@ export class FlyoutComplicated extends Component { + {flyoutContent} {htmlCode} diff --git a/src-docs/src/views/form_layouts/form_compressed.js b/src-docs/src/views/form_layouts/form_compressed.js index 7151cd19c48..8ab9ba27cb8 100644 --- a/src-docs/src/views/form_layouts/form_compressed.js +++ b/src-docs/src/views/form_layouts/form_compressed.js @@ -10,6 +10,7 @@ import { EuiFilePicker, EuiRange, EuiSelect, + EuiSpacer, EuiSwitch, EuiPanel, } from '../../../../src/components'; @@ -57,9 +58,16 @@ export default class extends Component { ], radioIdSelected: `${idPrefix}5`, comboBoxSelectionOptions: [], + value: '20', }; } + onRangeChange = e => { + this.setState({ + value: e.target.value, + }); + }; + onSwitchChange = () => { this.setState({ isSwitchChecked: !this.state.isSwitchChecked, @@ -92,31 +100,35 @@ export default class extends Component { - + display="columnCompressed"> + - + - - + + - + this.setState({ comboBoxSelectionOptions }) @@ -124,13 +136,22 @@ export default class extends Component { /> - - + + + display="rowCompressed"> - + + + 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 dd71d1199b8..47bb218318a 100644 --- a/src-docs/src/views/form_layouts/form_layouts_example.js +++ b/src-docs/src/views/form_layouts/form_layouts_example.js @@ -108,7 +108,7 @@ export const FormLayoutsExample = { `, }, { - title: 'Compressed', + title: 'Compressed and horizontal', source: [ { type: GuideSectionTypes.JS, @@ -122,21 +122,33 @@ export const FormLayoutsExample = { text: (

If the particular form is in an area with a small amount of real - estate, you can add the prop compressed to the{' '} - EuiFormRows and it will pass down to the form - controls. + 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', @@ -224,12 +236,16 @@ export const FormLayoutsExample = {

When supplying children to an EuiFormRow that is{' '} not a form control, and you need to the content to - vertically center with the other form controls, add the prop{' '} - displayOnly. + vertically center with the other form controls, change the{' '} + display prop to center or{' '} + centerCompressed.

), demo: , + snippet: ` + +`, }, { title: 'In a popover', diff --git a/src-docs/src/views/form_layouts/form_rows.js b/src-docs/src/views/form_layouts/form_rows.js index 00ea340f377..42b14c9ab53 100644 --- a/src-docs/src/views/form_layouts/form_rows.js +++ b/src-docs/src/views/form_layouts/form_rows.js @@ -10,6 +10,7 @@ import { EuiLink, EuiRange, EuiSelect, + EuiSpacer, EuiSwitch, EuiText, } from '../../../../src/components'; @@ -135,6 +136,8 @@ export default class extends Component { />
+ + Save form diff --git a/src-docs/src/views/form_layouts/inline_popover.js b/src-docs/src/views/form_layouts/inline_popover.js index 23a9fa41e66..c9af9fa01d7 100644 --- a/src-docs/src/views/form_layouts/inline_popover.js +++ b/src-docs/src/views/form_layouts/inline_popover.js @@ -10,6 +10,7 @@ import { EuiFlexItem, EuiFieldNumber, EuiRange, + EuiSpacer, EuiSwitch, } from '../../../../src/components'; @@ -125,6 +126,8 @@ export default class extends Component { + + Save ); diff --git a/src-docs/src/views/form_layouts/inline_sizing.js b/src-docs/src/views/form_layouts/inline_sizing.js index d8602cae275..d66e8da3c98 100644 --- a/src-docs/src/views/form_layouts/inline_sizing.js +++ b/src-docs/src/views/form_layouts/inline_sizing.js @@ -23,13 +23,13 @@ export default () => (
- + - - Save + + Save diff --git a/src-docs/src/views/form_validation/validation.js b/src-docs/src/views/form_validation/validation.js index ae1c6834413..b1667d0ccfc 100644 --- a/src-docs/src/views/form_validation/validation.js +++ b/src-docs/src/views/form_validation/validation.js @@ -7,6 +7,7 @@ import { EuiFormRow, EuiTextArea, EuiFieldText, + EuiSpacer, } from '../../../../src/components'; export default class extends Component { @@ -70,6 +71,8 @@ export default class extends Component { />
+ + {button} diff --git a/src-docs/src/views/popover/trap_focus.js b/src-docs/src/views/popover/trap_focus.js index 6b62246e343..7d69f04ceb5 100644 --- a/src-docs/src/views/popover/trap_focus.js +++ b/src-docs/src/views/popover/trap_focus.js @@ -4,6 +4,7 @@ import { EuiButton, EuiFormRow, EuiPopover, + EuiSpacer, EuiSwitch, } from '../../../../src/components'; @@ -54,6 +55,8 @@ export default class extends Component {
+ + Copy IFRAME code
); diff --git a/src/components/combo_box/_combo_box.scss b/src/components/combo_box/_combo_box.scss index e962ee457ff..4f3e2be4976 100644 --- a/src/components/combo_box/_combo_box.scss +++ b/src/components/combo_box/_combo_box.scss @@ -11,7 +11,7 @@ */ &--compressed, - .euiFormControlLayout--compressed { + .euiFormControlLayout { height: auto; } @@ -98,6 +98,10 @@ line-height: $euiFormControlCompressedHeight; /* 2 */ padding-top: 0; padding-bottom: 0; + + &.euiComboBox__inputWrap-isClearable { + @include euiFormControlLayoutPadding(2, $compressed: true); /* 2 */ + } } } } diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_tab.js b/src/components/date_picker/super_date_picker/date_popover/relative_tab.js index 008913739e1..1399f260242 100644 --- a/src/components/date_picker/super_date_picker/date_popover/relative_tab.js +++ b/src/components/date_picker/super_date_picker/date_popover/relative_tab.js @@ -104,7 +104,7 @@ export class EuiRelativeTab extends Component { - + @@ -160,6 +161,7 @@ export class EuiQuickSelect extends Component { aria-label="Quick time value" value={this.state.timeValue} onChange={this.onTimeValueChange} + compressed /> @@ -170,6 +172,7 @@ export class EuiQuickSelect extends Component { value={this.state.timeUnits} options={timeUnitsOptions} onChange={this.onTimeUnitsChange} + compressed /> 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 fc618ef33f5..e7f5e52b1cb 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 @@ -128,6 +128,7 @@ export class EuiRefreshInterval extends Component { onChange={this.onValueChange} aria-label="Refresh interval value" data-test-subj="superDatePickerRefreshIntervalInput" + compressed /> @@ -139,6 +140,7 @@ export class EuiRefreshInterval extends Component { options={refreshUnitsOptions} onChange={this.onUnitsChange} data-test-subj="superDatePickerRefreshIntervalUnitsSelect" + compressed /> diff --git a/src/components/expression/_expression.scss b/src/components/expression/_expression.scss index 3ee436b8af4..3797018cc0b 100644 --- a/src/components/expression/_expression.scss +++ b/src/components/expression/_expression.scss @@ -3,7 +3,7 @@ * but then wrap long words */ .euiExpression { - @include euiTextOverflowWrap; /* 1 */ + @include euiTextBreakWord; /* 1 */ @include euiFontSizeS; @include euiCodeFont; diff --git a/src/components/form/described_form_group/__snapshots__/described_form_group.test.js.snap b/src/components/form/described_form_group/__snapshots__/described_form_group.test.js.snap index 7009392b9b5..7c5dbeffbc1 100644 --- a/src/components/form/described_form_group/__snapshots__/described_form_group.test.js.snap +++ b/src/components/form/described_form_group/__snapshots__/described_form_group.test.js.snap @@ -36,6 +36,7 @@ exports[`EuiDescribedFormGroup is rendered 1`] = ` > -
+
- - -
+ - Error one -
-
- -
+ Error one +
+
+ - Error two -
- - -
+ Error two +
+ + - Help text - - +
+ Help text +
+
+
diff --git a/src/components/form/file_picker/_file_picker.scss b/src/components/form/file_picker/_file_picker.scss index bb8aca6035a..f22ba6b295e 100644 --- a/src/components/form/file_picker/_file_picker.scss +++ b/src/components/form/file_picker/_file_picker.scss @@ -44,6 +44,7 @@ .euiFilePicker--compressed & { top: $euiSizeS; + left: $euiSizeS; } .euiFilePicker--large & { @@ -76,7 +77,7 @@ .euiFilePicker--compressed & { @include euiFormControlStyleCompressed($includeStates: false); - @include euiFormControlWithIcon; /* 2 */ + @include euiFormControlWithIcon($compressed: true); /* 2 */ height: $euiFormControlCompressedHeight; } diff --git a/src/components/form/form_help_text/_form_help_text.scss b/src/components/form/form_help_text/_form_help_text.scss index 2bce1e4caad..d449b0e2c6a 100644 --- a/src/components/form/form_help_text/_form_help_text.scss +++ b/src/components/form/form_help_text/_form_help_text.scss @@ -1,5 +1,5 @@ .euiFormHelpText { @include euiFontSizeXS; - padding-top: $euiSizeS; + padding-top: $euiSizeXS; color: $euiColorDarkShade; } diff --git a/src/components/form/form_label/_form_label.scss b/src/components/form/form_label/_form_label.scss index e321f960221..887d7de476c 100644 --- a/src/components/form/form_label/_form_label.scss +++ b/src/components/form/form_label/_form_label.scss @@ -4,7 +4,6 @@ .euiFormLabel { @include euiFontSizeXS; display: inline-block; - margin-bottom: $euiSizeXS; transition: all $euiAnimSpeedFast $euiAnimSlightResistance; color: $euiTitleColor; font-weight: $euiFontWeightSemiBold; diff --git a/src/components/form/form_row/__snapshots__/form_row.test.js.snap b/src/components/form/form_row/__snapshots__/form_row.test.js.snap index 0ef700dad94..c239a1bc3ac 100644 --- a/src/components/form/form_row/__snapshots__/form_row.test.js.snap +++ b/src/components/form/form_row/__snapshots__/form_row.test.js.snap @@ -3,6 +3,7 @@ exports[`EuiFormRow behavior onBlur is called in child 1`] = ` -
+
- +
+ +
`; @@ -44,6 +52,7 @@ exports[`EuiFormRow behavior onBlur is called in child 1`] = ` exports[`EuiFormRow behavior onBlur works in parent even if not in child 1`] = ` -
+
- +
+ +
`; @@ -85,6 +101,7 @@ exports[`EuiFormRow behavior onBlur works in parent even if not in child 1`] = ` exports[`EuiFormRow behavior onFocus is called in child 1`] = ` -
+
- +
+ +
`; @@ -126,6 +150,7 @@ exports[`EuiFormRow behavior onFocus is called in child 1`] = ` exports[`EuiFormRow behavior onFocus works in parent even if not in child 1`] = ` -
+
- +
+ +
`; @@ -171,9 +203,28 @@ exports[`EuiFormRow is rendered 1`] = ` data-test-subj="test subject string" id="generated-id-row" > - +
+ +
+ +`; + +exports[`EuiFormRow props compressed is rendered 1`] = ` +
+
+ +
`; @@ -182,12 +233,91 @@ exports[`EuiFormRow props describedByIds is rendered 1`] = ` className="euiFormRow" id="generated-id-row" > - +
+ +
+ +`; + +exports[`EuiFormRow props display type center is rendered 1`] = ` +
+
+ +
+
+`; + +exports[`EuiFormRow props display type centerCompressed is rendered 1`] = ` +
+
+ +
+
+`; + +exports[`EuiFormRow props display type columnCompressed is rendered 1`] = ` +
+
+ +
+
+`; + +exports[`EuiFormRow props display type row is rendered 1`] = ` +
+
+ +
+
+`; + +exports[`EuiFormRow props display type rowCompressed is rendered 1`] = ` +
+
+ +
`; @@ -197,7 +327,7 @@ exports[`EuiFormRow props displayOnly is rendered 1`] = ` id="generated-id-row" >
-
- Error -
-
- Error2 + +
+ Error +
+
+ Error2 +
`; @@ -239,16 +373,20 @@ exports[`EuiFormRow props error as string is rendered 1`] = ` class="euiFormRow" id="generated-id-row" > -
- Error + +
+ Error +
`; @@ -258,9 +396,13 @@ exports[`EuiFormRow props error is not rendered if isInvalid is false 1`] = ` class="euiFormRow" id="generated-id-row" > - +
+ +
`; @@ -269,9 +411,13 @@ exports[`EuiFormRow props fullWidth is rendered 1`] = ` class="euiFormRow euiFormRow--fullWidth" id="generated-id-row" > - +
+ +
`; @@ -280,9 +426,13 @@ exports[`EuiFormRow props hasEmptyLabelSpace is rendered 1`] = ` class="euiFormRow euiFormRow--hasEmptyLabelSpace" id="generated-id-row" > - +
+ +
`; @@ -291,17 +441,21 @@ exports[`EuiFormRow props helpText is rendered 1`] = ` class="euiFormRow" id="generated-id-row" > -
- - This is help text. - + +
+ + This is help text. + +
`; @@ -311,9 +465,13 @@ exports[`EuiFormRow props id is rendered 1`] = ` class="euiFormRow" id="id-row" > - +
+ +
`; @@ -322,18 +480,24 @@ exports[`EuiFormRow props isInvalid is rendered 1`] = ` class="euiFormRow" id="generated-id-row" > -
+
- +
+ +
`; @@ -342,36 +506,29 @@ exports[`EuiFormRow props label append is rendered 1`] = ` className="euiFormRow" id="generated-id-row" > - - -
- - label - -
-
- - append - -
- + label + + + append + +
+ +
`; @@ -380,8 +537,11 @@ exports[`EuiFormRow props label is rendered 1`] = ` className="euiFormRow" id="generated-id-row" > -
+
- +
+ +
`; @@ -403,8 +567,11 @@ exports[`EuiFormRow props label renders as a legend and subsquently a fieldset w className="euiFormRow" id="generated-id-row" > -
+
- +
+ +
`; diff --git a/src/components/form/form_row/_form_row.scss b/src/components/form/form_row/_form_row.scss index b4220f576ab..f0c6ff0e701 100644 --- a/src/components/form/form_row/_form_row.scss +++ b/src/components/form/form_row/_form_row.scss @@ -6,9 +6,8 @@ display: flex; /* 1 */ flex-direction: column; /* 1 */ max-width: $euiFormMaxWidth; - padding-bottom: $euiSizeS; - + * { + + .euiFormRow { margin-top: $euiSize; } } @@ -18,26 +17,60 @@ } .euiFormRow--hasEmptyLabelSpace { - margin-top: $euiFontSizeXS + $euiSizeS; /* 2 */ + margin-top: ($euiFontSizeXS * $euiLineHeight) + $euiSizeXS; /* 2 */ // the following ensure that contents that aren't inheritly the same height // as inputs will align to the vertical center - min-height: $euiSizeXXL; + min-height: $euiFormControlHeight; padding-bottom: 0; justify-content: center; } -.euiFormRow--compressed { - + * { - margin-top: $euiSizeS; +.euiFormRow__labelWrapper { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + margin-bottom: $euiSizeXS; +} + +.euiFormRow--horizontal { + flex-direction: row; + align-items: stretch; + + .euiFormRow__label { + @include euiTextBreakWord; + hyphens: auto; + max-width: 100%; // Fixes IE + } + + .euiFormRow__labelWrapper { + display: block; + line-height: $euiFormControlCompressedHeight - 1px; // The 1px less helps the alignment of the text baseline + width: calc(33% - #{$euiSizeS}); + margin-right: $euiSizeS; + margin-bottom: 0; } - .euiFormRow__text { - padding-top: $euiSizeM / 2; + .euiFormRow__fieldWrapper { + width: 67%; + } + + + .euiFormRow--horizontal { + margin-top: $euiSizeS; } } -.euiFormRow__displayOnlyWrapper { +.euiFormRow__fieldWrapperDisplayOnly { min-height: $euiFormControlHeight; display: flex; align-items: center; } + +.euiFormRow--compressed { + &.euiFormRow--hasEmptyLabelSpace { + min-height: $euiFormControlCompressedHeight; + } + + .euiFormRow__fieldWrapperDisplayOnly { + min-height: $euiFormControlCompressedHeight; + } +} diff --git a/src/components/form/form_row/form_row.js b/src/components/form/form_row/form_row.js index 79835cb54df..2eed0fdca96 100644 --- a/src/components/form/form_row/form_row.js +++ b/src/components/form/form_row/form_row.js @@ -8,10 +8,19 @@ import { withRequiredProp } from '../../../utils/prop_types/with_required_prop'; import { EuiFormHelpText } from '../form_help_text'; import { EuiFormErrorText } from '../form_error_text'; import { EuiFormLabel } from '../form_label'; -import { EuiFlexGroup, EuiFlexItem } from '../../flex'; import makeId from './make_id'; +const displayToClassNameMap = { + row: null, + rowCompressed: 'euiFormRow--compressed', + columnCompressed: 'euiFormRow--compressed euiFormRow--horizontal', + center: null, + centerCompressed: 'euiFormRow--compressed', +}; + +export const DISPLAYS = Object.keys(displayToClassNameMap); + export class EuiFormRow extends Component { constructor(props) { super(props); @@ -63,19 +72,39 @@ export class EuiFormRow extends Component { className, describedByIds, compressed, + display, displayOnly, ...rest } = this.props; const { id } = this.state; + /** + * Remove when `compressed` is deprecated + */ + let shimDisplay; + if (compressed && display === 'row') { + shimDisplay = 'rowCompressed'; + } else { + shimDisplay = display; + } + + /** + * Remove when `displayOnly` is deprecated + */ + if (compressed && displayOnly) { + shimDisplay = 'centerCompressed'; + } else if (displayOnly && display === 'row') { + shimDisplay = 'center'; + } + const classes = classNames( 'euiFormRow', { 'euiFormRow--hasEmptyLabelSpace': hasEmptyLabelSpace, 'euiFormRow--fullWidth': fullWidth, - 'euiFormRow--compressed': compressed, }, + displayToClassNameMap[shimDisplay], className ); @@ -110,11 +139,11 @@ export class EuiFormRow extends Component { const isLegend = label && labelType === 'legend' ? true : false; const labelID = isLegend ? `${id}-${labelType}` : undefined; - if (label) { + if (label || labelAppend) { optionalLabel = ( - // Outer div ensures the label is inline-block (only takes up as much room as it needs) -
+
{label} + {labelAppend && ' '} + {labelAppend}
); } - if (labelAppend) { - optionalLabel = ( - - {optionalLabel} - {labelAppend} - - ); - } - const optionalProps = {}; const describingIds = [...describedByIds]; @@ -155,17 +173,17 @@ export class EuiFormRow extends Component { optionalProps['aria-describedby'] = describingIds.join(' '); } - let field = cloneElement(Children.only(children), { + const field = cloneElement(Children.only(children), { id, onFocus: this.onFocus, onBlur: this.onBlur, - compressed: compressed, ...optionalProps, }); - if (displayOnly) { - field =
{field}
; - } + const fieldWrapperClasses = classNames('euiFormRow__fieldWrapper', { + euiFormRow__fieldWrapperDisplayOnly: + displayOnly || display.startsWith('center'), + }); const Element = labelType === 'legend' ? 'fieldset' : 'div'; @@ -177,9 +195,11 @@ export class EuiFormRow extends Component { aria-labelledby={labelID} // Only renders a string if label type is 'legend' > {optionalLabel} - {field} - {optionalErrors} - {optionalHelpText} +
+ {field} + {optionalErrors} + {optionalHelpText} +
); } @@ -219,11 +239,20 @@ EuiFormRow.propTypes = { */ describedByIds: PropTypes.array, /** - * Tightens up the spacing and sends down the - * compressed prop to the input + * **DEPRECATED: use `display: rowCompressed` instead.** + * When `true`, tightens up the spacing. */ compressed: PropTypes.bool, /** + * When `rowCompressed`, just tightens up the spacing; + * Set to `columnCompressed` if compressed + * and horizontal layout is needed. + * Set to `center` or `centerCompressed` to align non-input + * content better with inline rows. + */ + display: PropTypes.oneOf(DISPLAYS), + /** + * **DEPRECATED: use `display: center` instead.** * Vertically centers non-input style content so it aligns * better with input style content. */ @@ -231,6 +260,7 @@ EuiFormRow.propTypes = { }; EuiFormRow.defaultProps = { + display: 'row', hasEmptyLabelSpace: false, fullWidth: false, describedByIds: [], diff --git a/src/components/form/form_row/form_row.test.js b/src/components/form/form_row/form_row.test.js index c32f7d24ac2..69d7e270667 100644 --- a/src/components/form/form_row/form_row.test.js +++ b/src/components/form/form_row/form_row.test.js @@ -3,7 +3,7 @@ import { shallow, render, mount } from 'enzyme'; import { requiredProps } from '../../../test'; import sinon from 'sinon'; -import { EuiFormRow } from './form_row'; +import { EuiFormRow, DISPLAYS } from './form_row'; jest.mock('./make_id', () => () => 'generated-id'); @@ -200,6 +200,32 @@ describe('EuiFormRow', () => { expect(component).toMatchSnapshot(); }); + + describe('compressed', () => { + test('is rendered', () => { + const component = render( + + + + ); + + expect(component).toMatchSnapshot(); + }); + }); + + describe('display type', () => { + DISPLAYS.forEach(display => { + test(`${display} is rendered`, () => { + const component = render( + + + + ); + + expect(component).toMatchSnapshot(); + }); + }); + }); }); describe('behavior', () => { diff --git a/src/components/form/form_row/index.d.ts b/src/components/form/form_row/index.d.ts index 93aadba7221..76c08290f4c 100644 --- a/src/components/form/form_row/index.d.ts +++ b/src/components/form/form_row/index.d.ts @@ -21,6 +21,7 @@ declare module '@elastic/eui' { labelAppend?: ReactNode; describedByIds?: string[]; compressed?: boolean; + display?: 'row' | 'rowCompressed' | 'columnCompressed'; displayOnly?: boolean; }; diff --git a/src/components/table/_table.scss b/src/components/table/_table.scss index 468c0c96ec3..d4d1aa61d13 100644 --- a/src/components/table/_table.scss +++ b/src/components/table/_table.scss @@ -138,7 +138,7 @@ } .euiTableCellContent__text { - @include euiTextOverflowWrap; /* 4 */ + @include euiTextBreakWord; /* 4 */ min-width: 0; text-overflow: ellipsis; } diff --git a/src/global_styling/mixins/_typography.scss b/src/global_styling/mixins/_typography.scss index a677a7aa711..18d86ffb6b6 100644 --- a/src/global_styling/mixins/_typography.scss +++ b/src/global_styling/mixins/_typography.scss @@ -1,4 +1,5 @@ // sass-lint:disable no-vendor-prefixes +// sass-lint:disable no-important // Our base fonts @@ -96,13 +97,11 @@ letter-spacing: -.03em; } -// Overflow-wrap for breaking on word -// Does not work on `display: flex` items -@mixin euiTextOverflowWrap { - @include internetExplorerOnly { - word-break: break-all; - } - overflow-wrap: break-word; +@mixin euiTextBreakWord { + // https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/ + overflow-wrap: break-word !important; // makes sure the long string will wrap and not bust out of the container + word-wrap: break-word !important; // spec says, they are literally just alternate names for each other but some browsers support one and not the other + word-break: break-word; // IE doesn't understand but that's ok } // Text truncation diff --git a/src/global_styling/utility/_utility.scss b/src/global_styling/utility/_utility.scss index d5cc5c41d6f..55765690c41 100644 --- a/src/global_styling/utility/_utility.scss +++ b/src/global_styling/utility/_utility.scss @@ -25,10 +25,7 @@ .eui-textInheritColor {color: inherit !important;} .eui-textBreakWord { - // https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/ - overflow-wrap: break-word !important; // makes sure the long string will wrap and not bust out of the container - word-wrap: break-word !important; // spec says, they are literally just alternate names for each other but some browsers support one and not the other - word-break: break-word; // IE doesn't understand but that's ok + @include euiTextBreakWord; } .eui-textBreakAll { From 8d3ae7161505061c750e9e21935f3aec3e9ddc89 Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 29 Aug 2019 12:03:15 -0400 Subject: [PATCH 06/24] Fix snap --- .../__snapshots__/super_select.test.js.snap | 87 ++++++++++++++----- 1 file changed, 67 insertions(+), 20 deletions(-) diff --git a/src/components/form/super_select/__snapshots__/super_select.test.js.snap b/src/components/form/super_select/__snapshots__/super_select.test.js.snap index 8d1d83433eb..174b7a51fad 100644 --- a/src/components/form/super_select/__snapshots__/super_select.test.js.snap +++ b/src/components/form/super_select/__snapshots__/super_select.test.js.snap @@ -56,6 +56,62 @@ exports[`EuiSuperSelect is rendered 1`] = `
`; +exports[`EuiSuperSelect props compressed is rendered 1`] = ` +
+
+ +
+
+ + Select an option: , is selected + +
+
+
+
+`; + exports[`EuiSuperSelect props custom display is propagated to dropdown 1`] = `
@@ -345,6 +402,7 @@ exports[`EuiSuperSelect props more props are propogated to each option 1`] = `

@@ -711,6 +769,7 @@ exports[`EuiSuperSelect props more props are propogated to each option 2`] = `

@@ -799,6 +858,7 @@ exports[`EuiSuperSelect props more props are propogated to each option 2`] = `

@@ -923,7 +983,13 @@ exports[`EuiSuperSelect props more props are propogated to each option 2`] = `
+
+
+
+
`; @@ -168,6 +168,14 @@ exports[`EuiDualRange props disabled should render 1`] = `
+
+
+
-
-
-
`; @@ -197,6 +197,14 @@ exports[`EuiDualRange props fullWidth should render 1`] = `
+
+
+
-
-
-
`; @@ -244,6 +244,14 @@ exports[`EuiDualRange props inputs should render 1`] = `
+
+
+
-
-
-
+
+
+
-
-
-
`; @@ -248,13 +248,6 @@ exports[`EuiRange props levels should render 1`] = `
-
@@ -267,6 +260,13 @@ exports[`EuiRange props levels should render 1`] = ` style="width:80%" />
+
`; @@ -278,14 +278,6 @@ exports[`EuiRange props range should render 1`] = `
-
@@ -294,6 +286,14 @@ exports[`EuiRange props range should render 1`] = ` style="margin-left:0%;width:8%" />
+
`; @@ -306,13 +306,6 @@ exports[`EuiRange props ticks should render 1`] = ` class="euiRangeTrack" style="margin-right:0.6em" > -
+
`; diff --git a/src/components/form/range/_range_highlight.scss b/src/components/form/range/_range_highlight.scss index 507377a4ade..447e32e3a0f 100644 --- a/src/components/form/range/_range_highlight.scss +++ b/src/components/form/range/_range_highlight.scss @@ -3,7 +3,6 @@ left: 0; width: 100%; top: calc(50% - 2px); - z-index: $euiZLevel0; overflow: hidden; &__progress { diff --git a/src/components/form/range/_range_input.scss b/src/components/form/range/_range_input.scss index a67a257fa38..e4954a325c8 100644 --- a/src/components/form/range/_range_input.scss +++ b/src/components/form/range/_range_input.scss @@ -9,4 +9,10 @@ &--max { margin-left: $euiSize; } + + .euiRange__popover & { + // sass-lint:disable no-important + margin: 0 !important; + width: 100%; + } } diff --git a/src/components/form/range/_range_levels.scss b/src/components/form/range/_range_levels.scss index 24d13c083e0..fc178cb9b67 100644 --- a/src/components/form/range/_range_levels.scss +++ b/src/components/form/range/_range_levels.scss @@ -1,8 +1,6 @@ .euiRangeLevels { display: flex; justify-content: stretch; - z-index: $euiZLevel0; - position: absolute; left: 0; right: 0; diff --git a/src/components/form/range/_range_slider.scss b/src/components/form/range/_range_slider.scss index 0712650a289..60a72ddb20c 100644 --- a/src/components/form/range/_range_slider.scss +++ b/src/components/form/range/_range_slider.scss @@ -18,7 +18,6 @@ background: transparent; // Otherwise white in Chrome width: 100%; // ensures the slider expands to fill flex display position: relative; - z-index: $euiZLevel2; // stay above tick marks cursor: pointer; // Keep cursor to full range bounds &:disabled { diff --git a/src/components/form/range/_range_thumb.scss b/src/components/form/range/_range_thumb.scss index 49e2e6bbbda..e2a709c46ae 100644 --- a/src/components/form/range/_range_thumb.scss +++ b/src/components/form/range/_range_thumb.scss @@ -6,7 +6,6 @@ left: 0; top: 50%; margin-top: -($euiRangeThumbHeight / 2); - z-index: $euiZLevel2; pointer-events: none; &:focus { diff --git a/src/components/form/range/_range_ticks.scss b/src/components/form/range/_range_ticks.scss index 85906a52b89..c3412de52e0 100644 --- a/src/components/form/range/_range_ticks.scss +++ b/src/components/form/range/_range_ticks.scss @@ -4,7 +4,6 @@ right: ($euiRangeThumbWidth / 2); top: $euiSizeS; display: flex; - z-index: $euiZLevel1; } .euiRangeTick { diff --git a/src/components/form/range/_range_tooltip.scss b/src/components/form/range/_range_tooltip.scss index d04642f2345..406acc8c092 100644 --- a/src/components/form/range/_range_tooltip.scss +++ b/src/components/form/range/_range_tooltip.scss @@ -7,9 +7,11 @@ bottom: 0; width: calc(100% - #{$euiRangeThumbWidth}); margin-left: $euiRangeThumbWidth / 2; + pointer-events: none; } .euiRangeTooltip__value { + // TODO: Use the new tooltip mixin // Indentation for legibility in transition // sass-lint:disable-block indentation @include euiFontSizeS; @@ -20,7 +22,6 @@ background-color: tintOrShade($euiColorFullShade, 25%, 90%); color: $euiColorGhost; max-width: 256px; - z-index: $euiZLevel4; top: 50%; transition: box-shadow $euiAnimSpeedNormal $euiAnimSlightResistance, diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index 0f7d68e2714..6098629e9bc 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -287,6 +287,18 @@ export class EuiDualRange extends Component { levels={levels} onChange={this.handleSliderChange} value={value}> + {showRange && this.isValid && ( + + )} + )} - - {showRange && this.isValid && ( - - )} {showLabels && {max}} {showInput && ( diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js index 59dede19188..97ef2dcc9e6 100644 --- a/src/components/form/range/range.js +++ b/src/components/form/range/range.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { isWithinRange } from '../../../services/number'; +import { EuiPopover } from '../../popover'; import { EuiRangeHighlight } from './range_highlight'; import { EuiRangeInput } from './range_input'; @@ -13,6 +14,13 @@ import { EuiRangeTrack, LEVEL_COLORS } from './range_track'; import { EuiRangeWrapper } from './range_wrapper'; export class EuiRange extends Component { + constructor(props) { + super(props); + this.state = { + isPopoverOpen: false, + }; + } + handleOnChange = e => { const isValid = isWithinRange( this.props.min, @@ -26,6 +34,18 @@ export class EuiRange extends Component { return isWithinRange(this.props.min, this.props.max, this.props.value); } + onInputClick = () => { + this.setState({ + isPopoverOpen: true, + }); + }; + + closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + }; + render() { const { className, @@ -54,10 +74,34 @@ export class EuiRange extends Component { ...rest } = this.props; - const classes = classNames('euiRange', className); const digitTolerance = Math.max(String(min).length, String(max).length); + const showInputOnly = showInput === 'only'; + const classes = classNames( + 'euiRange', + { 'euiRange--inputOnly': showInputOnly }, + className + ); + + const theInput = !!showInput ? ( + + ) : ( + undefined + ); - return ( + const theRange = ( + {showRange && this.isValid && ( + + )} + )} - - {showRange && this.isValid && ( - - )} {showLabels && ( {max} )} - {showInput && ( - - )} + {!showInputOnly && showInput && theInput} ); + + const thePopover = showInputOnly ? ( + + {theRange} + + ) : ( + undefined + ); + + return thePopover ? thePopover : theRange; } } @@ -159,9 +212,10 @@ EuiRange.propTypes = { */ showLabels: PropTypes.bool, /** - * Displays an extra input control for direct manipulation + * Pass `true` to displays an extra input control for direct manipulation. + * Pass `'only'` to only show the input but show the range in a dropdown. */ - showInput: PropTypes.bool, + showInput: PropTypes.oneOf([true, false, 'only']), /** * Shows clickable tick marks and labels at the given interval (`step`/`tickInterval`) */ diff --git a/src/components/form/range/range_input.js b/src/components/form/range/range_input.js index 732a28b5541..dcb62c78c78 100644 --- a/src/components/form/range/range_input.js +++ b/src/components/form/range/range_input.js @@ -19,7 +19,9 @@ export const EuiRangeInput = ({ // Chrome will properly size the input based on the max value, but FF & IE do not. // Calculate the width of the input based on highest number of characters. // Add 2 to accomodate for input stepper - const widthStyle = { width: `${digitTolerance / 1.25 + 2}em` }; + const widthStyle = compressed + ? undefined + : { width: `${digitTolerance / 1.25 + 2}em` }; return ( { return (
- {children} {levels && !!levels.length && ( { interval={tickInterval || step} /> )} + {children}
); } From d1dc24b42afc5cd01963167a2f47c78f46877f7d Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 11 Jul 2019 13:12:18 -0400 Subject: [PATCH 09/24] Compressed EuiRange step 2 (cont) - Fix up widths --- src/components/form/range/_index.scss | 2 ++ src/components/form/range/_range.scss | 6 ++++++ src/components/form/range/range.js | 10 ++++------ 3 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 src/components/form/range/_range.scss diff --git a/src/components/form/range/_index.scss b/src/components/form/range/_index.scss index 9f0f884dec0..b8d4204e060 100644 --- a/src/components/form/range/_index.scss +++ b/src/components/form/range/_index.scss @@ -1,5 +1,7 @@ @import 'variables'; @import 'mixins'; + +@import 'range'; @import 'range_highlight'; @import 'range_input'; @import 'range_label'; diff --git a/src/components/form/range/_range.scss b/src/components/form/range/_range.scss new file mode 100644 index 00000000000..a36ea335235 --- /dev/null +++ b/src/components/form/range/_range.scss @@ -0,0 +1,6 @@ +@import '../mixins'; + +// Specificity needed to override .euiPopover max-width +.euiPopover.euiRange__popover { + @include euiFormControlSize(auto, $includeAlternates: true); +} diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js index 97ef2dcc9e6..b5ffd0d14d9 100644 --- a/src/components/form/range/range.js +++ b/src/components/form/range/range.js @@ -76,11 +76,7 @@ export class EuiRange extends Component { const digitTolerance = Math.max(String(min).length, String(max).length); const showInputOnly = showInput === 'only'; - const classes = classNames( - 'euiRange', - { 'euiRange--inputOnly': showInputOnly }, - className - ); + const classes = classNames('euiRange', className); const theInput = !!showInput ? ( Date: Thu, 11 Jul 2019 18:24:27 -0400 Subject: [PATCH 10/24] Compressed EuiRange step 3 Dual range now supports dropdown style --- src-docs/src/views/range/compressed.js | 27 +---- src/components/form/range/dual_range.js | 140 ++++++++++++++++------- src/components/form/range/range.js | 6 +- src/components/form/range/range_input.js | 12 +- 4 files changed, 119 insertions(+), 66 deletions(-) diff --git a/src-docs/src/views/range/compressed.js b/src-docs/src/views/range/compressed.js index 86ae0a0a3c5..d8ff861d354 100644 --- a/src-docs/src/views/range/compressed.js +++ b/src-docs/src/views/range/compressed.js @@ -51,20 +51,10 @@ export default class extends Component { id={makeId()} value={this.state.value} onChange={this.onChange} - compressed - fullWidth - // showTicks + // compressed showInput="only" showLabels - // showValue - // showRange - // tickInterval={20} - // levels={this.levels} - // aria-describedby="levelsHelp4" /> - {/* - Recommended levels are {this.levels[1].min} and above. - */} @@ -72,18 +62,11 @@ export default class extends Component { id={makeId()} value={this.state.dualValue} onChange={this.onDualChange} - compressed - // fullWidth - // showLabels - showInput - // showTicks - // ticks={[{ label: '20kb', value: 20 }, { label: '100kb', value: 100 }]} - // levels={this.levels} - // aria-describedby="levelsHelp5" + // compressed + showInput="only" + showLabels + levels={this.levels} /> - {/* - Recommended size is {this.levels[1].min}kb and above. - */} ); } diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index 6098629e9bc..307a6f2e745 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -4,6 +4,8 @@ import classNames from 'classnames'; import { keyCodes } from '../../../services'; import { isWithinRange } from '../../../services/number'; +import { EuiPopover } from '../../popover'; +import { EuiFormControlLayoutRange } from '../form_control_layout'; import { EuiRangeHighlight } from './range_highlight'; import { EuiRangeInput } from './range_input'; @@ -17,6 +19,7 @@ export class EuiDualRange extends Component { state = { hasFocus: false, rangeSliderRefAvailable: false, + isPopoverOpen: false, }; rangeSliderRef = null; @@ -221,6 +224,18 @@ export class EuiDualRange extends Component { }); }; + onInputClick = () => { + this.setState({ + isPopoverOpen: true, + }); + }; + + closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + }; + render() { const { className, @@ -245,31 +260,62 @@ export class EuiDualRange extends Component { ...rest } = this.props; - const classes = classNames('euiDualRange', className); const digitTolerance = Math.max(String(min).length, String(max).length); + const showInputOnly = showInput === 'only'; - return ( + const minInput = !!showInput ? ( + + ) : ( + undefined + ); + + const maxInput = !!showInput ? ( + + ) : ( + undefined + ); + + const classes = classNames('euiDualRange', className); + const theRange = ( - {showInput && ( - - )} + {!showInputOnly && minInput} {showLabels && ( {min} @@ -327,7 +373,7 @@ export class EuiDualRange extends Component { value={this.lowerValue} disabled={disabled} showTicks={showTicks} - showInput={showInput} + showInput={!!showInput} onKeyDown={this.handleLowerKeyDown} onFocus={() => this.toggleHasFocus(true)} onBlur={() => this.toggleHasFocus(false)} @@ -341,7 +387,7 @@ export class EuiDualRange extends Component { value={this.upperValue} disabled={disabled} showTicks={showTicks} - showInput={showInput} + showInput={!!showInput} onKeyDown={this.handleUpperKeyDown} onFocus={() => this.toggleHasFocus(true)} onBlur={() => this.toggleHasFocus(false)} @@ -353,25 +399,40 @@ export class EuiDualRange extends Component { )} {showLabels && {max}} - {showInput && ( - + ); + + const thePopover = showInputOnly ? ( + - )} - + } + isOpen={this.state.isPopoverOpen} + closePopover={this.closePopover} + // zIndex={popoverZIndex} + className={classNames('euiRange__popover', { + 'euiRange__popover--fullWidth': fullWidth, + })} + anchorClassName="euiRange__popoverAnchor" + display="block" + // panelClassName={panelClasses} + // attachToAnchor={button ? false : true} + anchorPosition="downLeft" + panelPaddingSize="s"> + {theRange} + + ) : ( + undefined ); + + return thePopover || theRange; } } @@ -395,9 +456,10 @@ EuiDualRange.propTypes = { */ showLabels: PropTypes.bool, /** - * Displays a input controls for direct manipulation + * Pass `true` to displays an extra input control for direct manipulation. + * Pass `'only'` to only show the input but show the range in a dropdown. */ - showInput: PropTypes.bool, + showInput: PropTypes.oneOf([true, false, 'only']), /** * Shows clickable tick marks and labels at the given interval (`step`/`tickInterval`) */ diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js index b5ffd0d14d9..fd58bcfdee3 100644 --- a/src/components/form/range/range.js +++ b/src/components/form/range/range.js @@ -76,7 +76,6 @@ export class EuiRange extends Component { const digitTolerance = Math.max(String(min).length, String(max).length); const showInputOnly = showInput === 'only'; - const classes = classNames('euiRange', className); const theInput = !!showInput ? ( ) : ( undefined ); + const classes = classNames('euiRange', className); + const theRange = ( )} - {!showInputOnly && showInput && theInput} + {!showInputOnly && theInput} ); diff --git a/src/components/form/range/range_input.js b/src/components/form/range/range_input.js index dcb62c78c78..5386d4aab68 100644 --- a/src/components/form/range/range_input.js +++ b/src/components/form/range/range_input.js @@ -14,14 +14,16 @@ export const EuiRangeInput = ({ name, side, digitTolerance, + fullWidth, + autoSize, ...rest }) => { // Chrome will properly size the input based on the max value, but FF & IE do not. // Calculate the width of the input based on highest number of characters. // Add 2 to accomodate for input stepper - const widthStyle = compressed - ? undefined - : { width: `${digitTolerance / 1.25 + 2}em` }; + const widthStyle = autoSize + ? { width: `${digitTolerance / 1.25 + 2}em` } + : undefined; return ( ); @@ -50,7 +53,10 @@ EuiRangeInput.propTypes = { name: PropTypes.string, digitTolerance: PropTypes.number.isRequired, side: PropTypes.oneOf(['min', 'max']), + fullWidth: PropTypes.bool, + autoSize: PropTypes.bool, }; EuiRangeInput.defaultProps = { side: 'max', + autoSize: true, }; From 732ffc65e0e90c15d6e778eac887a33cc953f176 Mon Sep 17 00:00:00 2001 From: cchaos Date: Mon, 29 Jul 2019 15:39:21 -0400 Subject: [PATCH 11/24] Fix for delimited --- src-docs/src/views/range/compressed.js | 25 +++++++++++++++++-- .../__snapshots__/dual_range.test.js.snap | 2 +- .../range/__snapshots__/range.test.js.snap | 2 +- src/components/form/range/dual_range.js | 4 +-- src/components/form/range/range_wrapper.tsx | 3 +++ 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src-docs/src/views/range/compressed.js b/src-docs/src/views/range/compressed.js index d8ff861d354..eb34dfb062d 100644 --- a/src-docs/src/views/range/compressed.js +++ b/src-docs/src/views/range/compressed.js @@ -51,7 +51,6 @@ export default class extends Component { id={makeId()} value={this.state.value} onChange={this.onChange} - // compressed showInput="only" showLabels /> @@ -62,7 +61,29 @@ export default class extends Component { id={makeId()} value={this.state.dualValue} onChange={this.onDualChange} - // compressed + showInput="only" + showLabels + levels={this.levels} + /> + + + + + + + +
= ({ children, className, fullWidth, + compressed, }) => { const classes = classNames( 'euiRangeWrapper', { 'euiRangeWrapper--fullWidth': fullWidth, + 'euiRangeWrapper--compressed': compressed, }, className ); From db0e01645c20d4a9c789dc5523b268ab9b314e3f Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 14 Aug 2019 15:57:11 -0400 Subject: [PATCH 12/24] Fix full-width delimited --- .../form_control_layout/_form_control_layout_delimited.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/src/components/form/form_control_layout/_form_control_layout_delimited.scss index 824785c0d1d..2537b7df614 100644 --- a/src/components/form/form_control_layout/_form_control_layout_delimited.scss +++ b/src/components/form/form_control_layout/_form_control_layout_delimited.scss @@ -31,8 +31,10 @@ } } - &[class*='--fullWidth'] .euiFormControlLayout__childrenWrapper { + &[class*='--fullWidth'] .euiFormControlLayout__childrenWrapper, + &[class*='--fullWidth'] input { width: 100%; + max-width: none; } &[class*='--readOnly'] { From b29fe1d1212a7f699ef6e23666eb788f8be45d33 Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 14 Aug 2019 16:36:23 -0400 Subject: [PATCH 13/24] Added `controlOnly` prop to EuiFieldNumber --- .../__snapshots__/field_number.test.js.snap | 9 ++++ .../form/field_number/field_number.js | 44 ++++++++++++------- .../form/field_number/field_number.test.js | 6 +++ 3 files changed, 44 insertions(+), 15 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..70fd3227055 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 @@ -24,6 +24,15 @@ exports[`EuiFieldNumber is rendered 1`] = ` `; +exports[`EuiFieldNumber props controlOnly is rendered 1`] = ` + + + +`; + exports[`EuiFieldNumber props fullWidth is rendered 1`] = ` { const classes = classNames('euiFieldNumber', className, { @@ -33,6 +34,28 @@ export const EuiFieldNumber = ({ 'euiFieldNumber-isLoading': isLoading, }); + const control = ( + + + + ); + + if (controlOnly) { + return control; + } + return ( - - - + {control} ); }; @@ -113,6 +122,11 @@ EuiFieldNumber.propTypes = { PropTypes.node, PropTypes.arrayOf(PropTypes.node), ]), + /** + * Completely removes form control layout wrapper and ignores + * icon, prepend, and append. Best used inside EuiFormControlLayoutDelimited. + */ + controlOnly: PropTypes.bool, }; EuiFieldNumber.defaultProps = { diff --git a/src/components/form/field_number/field_number.test.js b/src/components/form/field_number/field_number.test.js index a1082c3c986..939f1b317a3 100644 --- a/src/components/form/field_number/field_number.test.js +++ b/src/components/form/field_number/field_number.test.js @@ -59,6 +59,12 @@ describe('EuiFieldNumber', () => { expect(component).toMatchSnapshot(); }); + test('controlOnly is rendered', () => { + const component = render(); + + expect(component).toMatchSnapshot(); + }); + describe('value', () => { test('value is number', () => { const component = render( From e8a6d82007ee9e1ba6e86fc8d49b7f33a3628722 Mon Sep 17 00:00:00 2001 From: cchaos Date: Wed, 14 Aug 2019 16:37:22 -0400 Subject: [PATCH 14/24] Finalize styles of input only ranges - Needed some fixes to EuiFormControlLayoutDelimited --- .../range/{compressed.js => input_only.js} | 1 + src-docs/src/views/range/range_example.js | 80 +++++++------------ .../_form_control_layout_delimited.scss | 5 ++ .../__snapshots__/dual_range.test.js.snap | 48 +++++++++++ .../range/__snapshots__/range.test.js.snap | 30 +++++++ src/components/form/range/dual_range.js | 35 ++++---- src/components/form/range/dual_range.test.js | 17 ++++ src/components/form/range/range.js | 23 ++---- src/components/form/range/range.test.js | 17 ++++ 9 files changed, 173 insertions(+), 83 deletions(-) rename src-docs/src/views/range/{compressed.js => input_only.js} (98%) diff --git a/src-docs/src/views/range/compressed.js b/src-docs/src/views/range/input_only.js similarity index 98% rename from src-docs/src/views/range/compressed.js rename to src-docs/src/views/range/input_only.js index eb34dfb062d..bca1e3410bf 100644 --- a/src-docs/src/views/range/compressed.js +++ b/src-docs/src/views/range/input_only.js @@ -87,6 +87,7 @@ export default class extends Component { showInput="only" showLabels levels={this.levels} + readOnly /> ); diff --git a/src-docs/src/views/range/range_example.js b/src-docs/src/views/range/range_example.js index 36aeb889d99..71792e6eb76 100644 --- a/src-docs/src/views/range/range_example.js +++ b/src-docs/src/views/range/range_example.js @@ -45,9 +45,9 @@ import StatesExample from './states'; const statesSource = require('!!raw-loader!./states'); const statesHtml = renderToHtml(StatesExample); -import CompressedExample from './compressed'; -const compressedSource = require('!!raw-loader!./compressed'); -const compressedHtml = renderToHtml(CompressedExample); +import InputOnlyExample from './input_only'; +const inputOnlySource = require('!!raw-loader!./input_only'); +const inputOnlyHtml = renderToHtml(InputOnlyExample); export const RangeControlExample = { title: 'Range sliders', @@ -116,16 +116,16 @@ export const RangeControlExample = { EuiRange, }, demo: , - snippet: ` - -// Show tooltip +/>`, + `// Show tooltip - -// Show thickened range and prepend a string to the tooltip +/>`, + `// Show thickened range and prepend a string to the tooltip `, + ], }, { title: 'Dual range', @@ -228,9 +228,7 @@ export const RangeControlExample = { ], demo: , props: { EuiRangeInput }, - snippet: ` - -`, + snippet: ['', ''], }, { title: 'Tick marks', @@ -269,17 +267,17 @@ export const RangeControlExample = { ], demo: , props: { EuiRangeTicks }, - snippet: ` - - - -', + '', + ``, + ], }, { title: 'Levels', @@ -340,45 +338,28 @@ export const RangeControlExample = { source: [ { type: GuideSectionTypes.JS, - code: compressedSource, + code: inputOnlySource, }, { type: GuideSectionTypes.HTML, - code: compressedHtml, + code: inputOnlyHtml, }, ], - demo: , - snippet: `, + snippet: [ + ` {}} - compressed - fullWidth - disabled - showTicks - showInput - showLabels - showValue - showRange - tickInterval={} - levels={[]} - aria-describedBy={replaceWithID} -/> - -`, + ` {}} - compressed - fullWidth - disabled - showLabels - showInput - showTicks - ticks={[]} - levels={[]} - aria-describedBy={replaceWithID} + showInput="only" />`, + ], }, { title: 'Kitchen sink', @@ -401,7 +382,8 @@ export const RangeControlExample = { }, ], demo: , - snippet: ` {}} @@ -415,9 +397,8 @@ export const RangeControlExample = { tickInterval={} levels={[]} aria-describedBy={replaceWithID} -/> - -`, + ` {}} @@ -430,6 +411,7 @@ export const RangeControlExample = { levels={[]} aria-describedBy={replaceWithID} />`, + ], }, ], }; diff --git a/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/src/components/form/form_control_layout/_form_control_layout_delimited.scss index 2537b7df614..61a9f2c03e4 100644 --- a/src/components/form/form_control_layout/_form_control_layout_delimited.scss +++ b/src/components/form/form_control_layout/_form_control_layout_delimited.scss @@ -11,6 +11,7 @@ > .euiFormControlLayout__childrenWrapper { display: flex; align-items: center; + width: 100%; } &[class*='--compressed'] { @@ -37,6 +38,10 @@ max-width: none; } + &[class*='-isDisabled'] { + @include euiFormControlDisabledStyle; + } + &[class*='--readOnly'] { @include euiFormControlReadOnlyStyle; diff --git a/src/components/form/range/__snapshots__/dual_range.test.js.snap b/src/components/form/range/__snapshots__/dual_range.test.js.snap index 63f9b377f05..4128662c12e 100644 --- a/src/components/form/range/__snapshots__/dual_range.test.js.snap +++ b/src/components/form/range/__snapshots__/dual_range.test.js.snap @@ -366,6 +366,54 @@ exports[`EuiDualRange props levels should render 1`] = `
`; +exports[`EuiDualRange props only input should render 1`] = ` +
+
+
+
+ +
+
+ → +
+
+ +
+
+
+
+`; + exports[`EuiDualRange props range should render 1`] = `
`; +exports[`EuiRange props input only should render 1`] = ` +
+
+
+
+ +
+
+
+
+`; + exports[`EuiRange props input should render 1`] = `
) : ( undefined @@ -302,8 +305,10 @@ export class EuiDualRange extends Component { aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} onClick={this.onInputClick} + readOnly={readOnly} autoSize={!showInputOnly} fullWidth={!!showInputOnly && fullWidth} + controlOnly={showInputOnly} /> ) : ( undefined @@ -404,30 +409,23 @@ export class EuiDualRange extends Component { ); const thePopover = showInputOnly ? ( - } + fullWidth={fullWidth} isOpen={this.state.isPopoverOpen} - closePopover={this.closePopover} - // zIndex={popoverZIndex} - className={classNames('euiRange__popover', { - 'euiRange__popover--fullWidth': fullWidth, - })} - anchorClassName="euiRange__popoverAnchor" - display="block" - // panelClassName={panelClasses} - // attachToAnchor={button ? false : true} - anchorPosition="downLeft" - panelPaddingSize="s"> + closePopover={this.closePopover}> {theRange} - + ) : ( undefined ); @@ -451,6 +449,7 @@ EuiDualRange.propTypes = { fullWidth: PropTypes.bool, compressed: PropTypes.bool, disabled: PropTypes.bool, + readOnly: PropTypes.bool, /** * Shows static min/max labels on the sides of the range slider */ diff --git a/src/components/form/range/dual_range.test.js b/src/components/form/range/dual_range.test.js index cc010c8b06d..4b96afebd01 100644 --- a/src/components/form/range/dual_range.test.js +++ b/src/components/form/range/dual_range.test.js @@ -86,6 +86,23 @@ describe('EuiDualRange', () => { expect(component).toMatchSnapshot(); }); + test('only input should render', () => { + const component = render( + {}} + showInput="only" + {...requiredProps} + /> + ); + + expect(component).toMatchSnapshot(); + }); + test('levels should render', () => { const component = render( + closePopover={this.closePopover}> {theRange} - + ) : ( undefined ); diff --git a/src/components/form/range/range.test.js b/src/components/form/range/range.test.js index 652a6c104be..b645f82bcbf 100644 --- a/src/components/form/range/range.test.js +++ b/src/components/form/range/range.test.js @@ -99,6 +99,23 @@ describe('EuiRange', () => { expect(component).toMatchSnapshot(); }); + test('input only should render', () => { + const component = render( + {}} + showInput="only" + {...requiredProps} + /> + ); + + expect(component).toMatchSnapshot(); + }); + test('levels should render', () => { const component = render( Date: Mon, 19 Aug 2019 17:42:57 -0400 Subject: [PATCH 15/24] Some cleanup --- src-docs/src/views/range/input_only.js | 7 +------ src-docs/src/views/range/range_example.js | 9 +++++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src-docs/src/views/range/input_only.js b/src-docs/src/views/range/input_only.js index bca1e3410bf..43a33d7c124 100644 --- a/src-docs/src/views/range/input_only.js +++ b/src-docs/src/views/range/input_only.js @@ -1,11 +1,6 @@ import React, { Component, Fragment } from 'react'; -import { - EuiRange, - EuiSpacer, - // EuiFormHelpText, - EuiDualRange, -} from '../../../../src/components'; +import { EuiRange, EuiSpacer, EuiDualRange } from '../../../../src/components'; import makeId from '../../../../src/components/form/form_row/make_id'; diff --git a/src-docs/src/views/range/range_example.js b/src-docs/src/views/range/range_example.js index 71792e6eb76..7bdbde3d1f0 100644 --- a/src-docs/src/views/range/range_example.js +++ b/src-docs/src/views/range/range_example.js @@ -307,21 +307,22 @@ export const RangeControlExample = { ], demo: , props: { EuiRangeLevels }, - snippet: ` - -`, + ``, + ], }, { title: 'Inputs with range in a dropdown', From 8ded06a8aca62ff4b2d624e2c0d6ce5a767fdd0a Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 29 Aug 2019 12:00:00 -0400 Subject: [PATCH 16/24] Use tooltip background variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Can’t use mixin, too many overrides/differences --- src/components/form/range/_range_tooltip.scss | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/form/range/_range_tooltip.scss b/src/components/form/range/_range_tooltip.scss index 406acc8c092..77cab4b0ea3 100644 --- a/src/components/form/range/_range_tooltip.scss +++ b/src/components/form/range/_range_tooltip.scss @@ -1,3 +1,5 @@ +@import '../../tool_tip/variables'; + .euiRangeTooltip { // Keeps tooltip (value) aligned to percentage of actual slider display: block; @@ -11,15 +13,14 @@ } .euiRangeTooltip__value { - // TODO: Use the new tooltip mixin // Indentation for legibility in transition // sass-lint:disable-block indentation @include euiFontSizeS; - border: 1px solid transparentize($euiColorDarkestShade, .8); + border: 1px solid $euiTooltipBackgroundColor; position: absolute; border-radius: $euiBorderRadius; padding: ($euiSizeXS / 2) $euiSizeS; - background-color: tintOrShade($euiColorFullShade, 25%, 90%); + background-color: $euiTooltipBackgroundColor; color: $euiColorGhost; max-width: 256px; top: 50%; @@ -38,14 +39,14 @@ bottom: -$arrowSize / 2; left: 50%; transform-origin: center; - background-color: tintOrShade($euiColorFullShade, 25%, 90%); + background-color: $euiTooltipBackgroundColor; width: $arrowSize; height: $arrowSize; border-radius: 2px; } &::before { - background-color: transparentize($euiColorDarkestShade, .8); + background-color: $euiTooltipBackgroundColor; } // Positions the arrow From b9937a53cf2afb10a2898b016b4684077bdc4f69 Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 29 Aug 2019 12:20:33 -0400 Subject: [PATCH 17/24] Open popover on focus --- .../__snapshots__/dual_range.test.js.snap | 56 ++++++++++--------- .../range/__snapshots__/range.test.js.snap | 32 ++++++----- src/components/form/range/_range.scss | 6 -- src/components/form/range/dual_range.js | 7 ++- src/components/form/range/range.js | 7 ++- 5 files changed, 55 insertions(+), 53 deletions(-) diff --git a/src/components/form/range/__snapshots__/dual_range.test.js.snap b/src/components/form/range/__snapshots__/dual_range.test.js.snap index 4128662c12e..d6cc79d08b0 100644 --- a/src/components/form/range/__snapshots__/dual_range.test.js.snap +++ b/src/components/form/range/__snapshots__/dual_range.test.js.snap @@ -373,41 +373,43 @@ exports[`EuiDualRange props only input should render 1`] = `
-
+
-
+
- → +
+ → +
+
-
diff --git a/src/components/form/range/__snapshots__/range.test.js.snap b/src/components/form/range/__snapshots__/range.test.js.snap index f7db9774fc4..a4369a479ca 100644 --- a/src/components/form/range/__snapshots__/range.test.js.snap +++ b/src/components/form/range/__snapshots__/range.test.js.snap @@ -176,23 +176,25 @@ exports[`EuiRange props input only should render 1`] = `
-
+
- +
+ +
diff --git a/src/components/form/range/_range.scss b/src/components/form/range/_range.scss index a36ea335235..e69de29bb2d 100644 --- a/src/components/form/range/_range.scss +++ b/src/components/form/range/_range.scss @@ -1,6 +0,0 @@ -@import '../mixins'; - -// Specificity needed to override .euiPopover max-width -.euiPopover.euiRange__popover { - @include euiFormControlSize(auto, $includeAlternates: true); -} diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index a3b8b014574..927da0d2332 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -224,7 +224,7 @@ export class EuiDualRange extends Component { }); }; - onInputClick = () => { + onInputFocus = () => { this.setState({ isPopoverOpen: true, }); @@ -263,6 +263,7 @@ export class EuiDualRange extends Component { const digitTolerance = Math.max(String(min).length, String(max).length); const showInputOnly = showInput === 'only'; + const canShowDropdown = showInputOnly && !readOnly && !disabled; const minInput = !!showInput ? ( { + onInputFocus = () => { this.setState({ isPopoverOpen: true, }); @@ -52,6 +52,7 @@ export class EuiRange extends Component { compressed, disabled, fullWidth, + readOnly, id, max, min, @@ -76,6 +77,7 @@ export class EuiRange extends Component { const digitTolerance = Math.max(String(min).length, String(max).length); const showInputOnly = showInput === 'only'; + const canShowDropdown = showInputOnly && !readOnly && !disabled; const theInput = !!showInput ? ( Date: Wed, 4 Sep 2019 14:11:52 -0500 Subject: [PATCH 18/24] focus direction --- .../__snapshots__/dual_range.test.js.snap | 10 ++++++++++ .../range/__snapshots__/range.test.js.snap | 11 +++++++++++ src/components/form/range/dual_range.js | 19 +++++++++++++++++-- src/components/form/range/dual_range.test.js | 2 ++ src/components/form/range/range.js | 18 ++++++++++++++++-- src/components/form/range/range.test.js | 2 ++ src/components/popover/input_popover.tsx | 9 ++++++--- 7 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/components/form/range/__snapshots__/dual_range.test.js.snap b/src/components/form/range/__snapshots__/dual_range.test.js.snap index d6cc79d08b0..d9bdf8df45b 100644 --- a/src/components/form/range/__snapshots__/dual_range.test.js.snap +++ b/src/components/form/range/__snapshots__/dual_range.test.js.snap @@ -10,6 +10,7 @@ exports[`EuiDualRange allows value prop to accept empty strings 1`] = ` { + // Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget` + const relatedTarget = e.relatedTarget || e.explicitOriginalTarget; + if (!relatedTarget || relatedTarget.id !== this.state.id) { + this.closePopover(); + } + }; + closePopover = () => { this.setState({ isPopoverOpen: false, @@ -243,7 +253,7 @@ export class EuiDualRange extends Component { disabled, fullWidth, readOnly, - id, + id: propsId, max, min, name, @@ -261,6 +271,8 @@ export class EuiDualRange extends Component { ...rest } = this.props; + const { id } = this.state; + const digitTolerance = Math.max(String(min).length, String(max).length); const showInputOnly = showInput === 'only'; const canShowDropdown = showInputOnly && !readOnly && !disabled; @@ -281,6 +293,7 @@ export class EuiDualRange extends Component { aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} onFocus={canShowDropdown ? this.onInputFocus : undefined} + onBlur={canShowDropdown ? this.onInputBlur : undefined} readOnly={readOnly} autoSize={!showInputOnly} fullWidth={!!showInputOnly && fullWidth} @@ -306,6 +319,7 @@ export class EuiDualRange extends Component { aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} onFocus={canShowDropdown ? this.onInputFocus : undefined} + onBlur={canShowDropdown ? this.onInputBlur : undefined} readOnly={readOnly} autoSize={!showInputOnly} fullWidth={!!showInputOnly && fullWidth} @@ -424,7 +438,8 @@ export class EuiDualRange extends Component { } fullWidth={fullWidth} isOpen={this.state.isPopoverOpen} - closePopover={this.closePopover}> + closePopover={this.closePopover} + disableFocusTrap={true}> {theRange} ) : ( diff --git a/src/components/form/range/dual_range.test.js b/src/components/form/range/dual_range.test.js index 4b96afebd01..39c9a2cb947 100644 --- a/src/components/form/range/dual_range.test.js +++ b/src/components/form/range/dual_range.test.js @@ -4,6 +4,8 @@ import { requiredProps } from '../../../test/required_props'; import { EuiDualRange } from './dual_range'; +jest.mock('../form_row/make_id', () => () => 'generated-id'); + describe('EuiDualRange', () => { test('is rendered', () => { const component = render( diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js index b760ecefec1..7be1b7dcc57 100644 --- a/src/components/form/range/range.js +++ b/src/components/form/range/range.js @@ -4,6 +4,7 @@ import classNames from 'classnames'; import { isWithinRange } from '../../../services/number'; import { EuiInputPopover } from '../../popover'; +import makeId from '../form_row/make_id'; import { EuiRangeHighlight } from './range_highlight'; import { EuiRangeInput } from './range_input'; @@ -17,6 +18,7 @@ export class EuiRange extends Component { constructor(props) { super(props); this.state = { + id: props.id || makeId(), isPopoverOpen: false, }; } @@ -40,6 +42,14 @@ export class EuiRange extends Component { }); }; + onInputBlur = e => { + // Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget` + const relatedTarget = e.relatedTarget || e.explicitOriginalTarget; + if (!relatedTarget || relatedTarget.id !== this.state.id) { + this.closePopover(); + } + }; + closePopover = () => { this.setState({ isPopoverOpen: false, @@ -53,7 +63,7 @@ export class EuiRange extends Component { disabled, fullWidth, readOnly, - id, + id: propsId, max, min, name, @@ -75,6 +85,8 @@ export class EuiRange extends Component { ...rest } = this.props; + const { id } = this.state; + const digitTolerance = Math.max(String(min).length, String(max).length); const showInputOnly = showInput === 'only'; const canShowDropdown = showInputOnly && !readOnly && !disabled; @@ -92,6 +104,7 @@ export class EuiRange extends Component { onChange={this.handleOnChange} name={name} onFocus={canShowDropdown ? this.onInputFocus : undefined} + onBlur={canShowDropdown ? this.onInputBlur : undefined} fullWidth={showInputOnly && fullWidth} autoSize={!showInputOnly} {...rest} @@ -180,7 +193,8 @@ export class EuiRange extends Component { input={theInput} fullWidth={fullWidth} isOpen={this.state.isPopoverOpen} - closePopover={this.closePopover}> + closePopover={this.closePopover} + disableFocusTrap={true}> {theRange} ) : ( diff --git a/src/components/form/range/range.test.js b/src/components/form/range/range.test.js index b645f82bcbf..33495ea665d 100644 --- a/src/components/form/range/range.test.js +++ b/src/components/form/range/range.test.js @@ -4,6 +4,8 @@ import { requiredProps } from '../../../test/required_props'; import { EuiRange } from './range'; +jest.mock('../form_row/make_id', () => () => 'generated-id'); + describe('EuiRange', () => { test('is rendered', () => { const component = render( diff --git a/src/components/popover/input_popover.tsx b/src/components/popover/input_popover.tsx index 6659708b0aa..8145f91dfb4 100644 --- a/src/components/popover/input_popover.tsx +++ b/src/components/popover/input_popover.tsx @@ -15,6 +15,7 @@ import { cascadingMenuKeyCodes } from '../../services'; interface EuiInputPopoverProps extends Omit { + disableFocusTrap?: boolean; fullWidth?: boolean; input: EuiPopoverProps['button']; inputRef?: EuiPopoverProps['buttonRef']; @@ -27,6 +28,7 @@ type Props = CommonProps & export const EuiInputPopover: FunctionComponent = ({ children, className, + disableFocusTrap = false, input, fullWidth = false, ...props @@ -68,8 +70,9 @@ export const EuiInputPopover: FunctionComponent = ({ ); }); if ( - tabbableItems.length && - tabbableItems[tabbableItems.length - 1] === document.activeElement + disableFocusTrap || + (tabbableItems.length && + tabbableItems[tabbableItems.length - 1] === document.activeElement) ) { props.closePopover(); } @@ -96,7 +99,7 @@ export const EuiInputPopover: FunctionComponent = ({ panelRef={panelRef} className={classes} {...props}> - +
{children}
From ac953175239966e7ec6526c98eaaa9982512ed18 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 5 Sep 2019 11:56:06 -0500 Subject: [PATCH 19/24] dual range respond to resize events when in showInputOnly mode --- src/components/form/range/dual_range.js | 28 ++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index 984991a176a..60e5a14c0d7 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -6,6 +6,7 @@ import { keyCodes } from '../../../services'; import { isWithinRange } from '../../../services/number'; import { EuiInputPopover } from '../../popover'; import { EuiFormControlLayoutDelimited } from '../form_control_layout'; +import { EuiResizeObserver } from '../../observer/resize_observer'; import makeId from '../form_row/make_id'; import { EuiRangeHighlight } from './range_highlight'; @@ -22,6 +23,7 @@ export class EuiDualRange extends Component { hasFocus: false, rangeSliderRefAvailable: false, isPopoverOpen: false, + rangeWidth: null, }; rangeSliderRef = null; @@ -29,6 +31,7 @@ export class EuiDualRange extends Component { this.rangeSliderRef = ref; this.setState({ rangeSliderRefAvailable: !!ref, + rangeWidth: !!ref ? ref.clientWidth : null, }); }; @@ -206,7 +209,7 @@ export class EuiDualRange extends Component { this._handleOnChange(this.lowerValue, upper, e); }; - calculateThumbPositionStyle = value => { + calculateThumbPositionStyle = (value, width) => { // Calculate the left position based on value const decimal = (value - this.props.min) / (this.props.max - this.props.min); @@ -215,7 +218,8 @@ export class EuiDualRange extends Component { valuePosition = valuePosition >= 0 ? valuePosition : 0; const EUI_THUMB_SIZE = 16; - const thumbToTrackRatio = EUI_THUMB_SIZE / this.rangeSliderRef.clientWidth; + const trackWidth = width || this.rangeSliderRef.clientWidth; + const thumbToTrackRatio = EUI_THUMB_SIZE / trackWidth; const trackPositionScale = (1 - thumbToTrackRatio) * 100; return { left: `${valuePosition * trackPositionScale}%` }; }; @@ -246,6 +250,12 @@ export class EuiDualRange extends Component { }); }; + onResize = ({ width }) => { + this.setState({ + rangeWidth: width, + }); + }; + render() { const { className, @@ -397,7 +407,10 @@ export class EuiDualRange extends Component { onKeyDown={this.handleLowerKeyDown} onFocus={() => this.toggleHasFocus(true)} onBlur={() => this.toggleHasFocus(false)} - style={this.calculateThumbPositionStyle(this.lowerValue || min)} + style={this.calculateThumbPositionStyle( + this.lowerValue || min, + showInputOnly ? this.state.rangeWidth : null + )} aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} /> @@ -411,7 +424,10 @@ export class EuiDualRange extends Component { onKeyDown={this.handleUpperKeyDown} onFocus={() => this.toggleHasFocus(true)} onBlur={() => this.toggleHasFocus(false)} - style={this.calculateThumbPositionStyle(this.upperValue || max)} + style={this.calculateThumbPositionStyle( + this.upperValue || max, + showInputOnly ? this.state.rangeWidth : null + )} aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} /> @@ -440,7 +456,9 @@ export class EuiDualRange extends Component { isOpen={this.state.isPopoverOpen} closePopover={this.closePopover} disableFocusTrap={true}> - {theRange} + + {resizeRef =>
{theRange}
} +
) : ( undefined From 1b58cdf736d83e224a8488e00857b0f4d67dab35 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 5 Sep 2019 12:02:06 -0500 Subject: [PATCH 20/24] clean up --- src/components/form/range/dual_range.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index 60e5a14c0d7..1aa5658369d 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -218,7 +218,10 @@ export class EuiDualRange extends Component { valuePosition = valuePosition >= 0 ? valuePosition : 0; const EUI_THUMB_SIZE = 16; - const trackWidth = width || this.rangeSliderRef.clientWidth; + const trackWidth = + this.props.showInput === 'only' && !!width + ? width + : this.rangeSliderRef.clientWidth; const thumbToTrackRatio = EUI_THUMB_SIZE / trackWidth; const trackPositionScale = (1 - thumbToTrackRatio) * 100; return { left: `${valuePosition * trackPositionScale}%` }; @@ -409,7 +412,7 @@ export class EuiDualRange extends Component { onBlur={() => this.toggleHasFocus(false)} style={this.calculateThumbPositionStyle( this.lowerValue || min, - showInputOnly ? this.state.rangeWidth : null + this.state.rangeWidth )} aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} @@ -426,7 +429,7 @@ export class EuiDualRange extends Component { onBlur={() => this.toggleHasFocus(false)} style={this.calculateThumbPositionStyle( this.upperValue || max, - showInputOnly ? this.state.rangeWidth : null + this.state.rangeWidth )} aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} From e132f7e75eb8e5b9c50e2aa8a2ac318919cd93d3 Mon Sep 17 00:00:00 2001 From: cchaos Date: Fri, 6 Sep 2019 16:02:06 -0400 Subject: [PATCH 21/24] PR Feedback --- src-docs/src/views/range/input_only.js | 8 ++++---- src-docs/src/views/range/range_example.js | 12 ++++++------ .../_form_control_layout_delimited.scss | 4 ++++ src/components/form/range/_index.scss | 1 - src/components/form/range/_range.scss | 0 src/components/form/range/_range_highlight.scss | 11 ++++++----- src/components/form/range/_variables.scss | 2 ++ src/components/form/range/dual_range.js | 6 +++--- src/components/form/range/dual_range.test.js | 2 +- src/components/form/range/range.js | 6 +++--- src/components/form/range/range.test.js | 2 +- 11 files changed, 30 insertions(+), 24 deletions(-) delete mode 100644 src/components/form/range/_range.scss diff --git a/src-docs/src/views/range/input_only.js b/src-docs/src/views/range/input_only.js index 43a33d7c124..f6e1cd08463 100644 --- a/src-docs/src/views/range/input_only.js +++ b/src-docs/src/views/range/input_only.js @@ -46,7 +46,7 @@ export default class extends Component { id={makeId()} value={this.state.value} onChange={this.onChange} - showInput="only" + showInput="inputWithPopover" showLabels /> @@ -56,7 +56,7 @@ export default class extends Component { id={makeId()} value={this.state.dualValue} onChange={this.onDualChange} - showInput="only" + showInput="inputWithPopover" showLabels levels={this.levels} /> @@ -68,7 +68,7 @@ export default class extends Component { value={this.state.value} onChange={this.onChange} compressed - showInput="only" + showInput="inputWithPopover" showLabels /> @@ -79,7 +79,7 @@ export default class extends Component { value={this.state.dualValue} onChange={this.onDualChange} compressed - showInput="only" + showInput="inputWithPopover" showLabels levels={this.levels} readOnly diff --git a/src-docs/src/views/range/range_example.js b/src-docs/src/views/range/range_example.js index 7bdbde3d1f0..f2d0d37c740 100644 --- a/src-docs/src/views/range/range_example.js +++ b/src-docs/src/views/range/range_example.js @@ -329,10 +329,10 @@ export const RangeControlExample = { text: (

- Passing showInput="only" instead of a - boolean will only display the inputs until the input is interacted - with in which case a dropdown will appear displaying the actual - slider. + Passing showInput="inputWithPopover"{' '} + instead of a boolean will only display the inputs until the input is + interacted with in which case a dropdown will appear displaying the + actual slider.

), @@ -352,13 +352,13 @@ export const RangeControlExample = { id="" value={} onChange={() => {}} - showInput="only" + showInput="inputWithPopover" />`, ` {}} - showInput="only" + showInput="inputWithPopover" />`, ], }, diff --git a/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/src/components/form/form_control_layout/_form_control_layout_delimited.scss index 61a9f2c03e4..17a1c7dbafa 100644 --- a/src/components/form/form_control_layout/_form_control_layout_delimited.scss +++ b/src/components/form/form_control_layout/_form_control_layout_delimited.scss @@ -14,6 +14,7 @@ width: 100%; } + // Target when the euiFormControlLayout is compressed without specifying the full class name in case it ever changes &[class*='--compressed'] { @include euiFormControlDefaultShadow($borderOnly: true); border-radius: $euiBorderRadius / 2; @@ -32,16 +33,19 @@ } } + // Target when the euiFormControlLayout is fullWidth without specifying the full class name in case it ever changes &[class*='--fullWidth'] .euiFormControlLayout__childrenWrapper, &[class*='--fullWidth'] input { width: 100%; max-width: none; } + // Target when the euiFormControlLayout is disabled without specifying the full class name in case it ever changes &[class*='-isDisabled'] { @include euiFormControlDisabledStyle; } + // Target when the euiFormControlLayout is readOnly without specifying the full class name in case it ever changes &[class*='--readOnly'] { @include euiFormControlReadOnlyStyle; diff --git a/src/components/form/range/_index.scss b/src/components/form/range/_index.scss index b8d4204e060..b118aebe3d7 100644 --- a/src/components/form/range/_index.scss +++ b/src/components/form/range/_index.scss @@ -1,7 +1,6 @@ @import 'variables'; @import 'mixins'; -@import 'range'; @import 'range_highlight'; @import 'range_input'; @import 'range_label'; diff --git a/src/components/form/range/_range.scss b/src/components/form/range/_range.scss deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/components/form/range/_range_highlight.scss b/src/components/form/range/_range_highlight.scss index 447e32e3a0f..289478342b5 100644 --- a/src/components/form/range/_range_highlight.scss +++ b/src/components/form/range/_range_highlight.scss @@ -1,13 +1,14 @@ +// Calcs account for .euiRangeHighlight { position: absolute; left: 0; width: 100%; - top: calc(50% - 2px); + top: calc(50% - #{($euiRangeHighlightHeight / 2)}); overflow: hidden; &__progress { - height: 4px; - border-radius: 4px; + height: $euiRangeHighlightHeight; + border-radius: $euiRangeHighlightHeight; background-color: $euiRangeTrackColor; &--hasFocus { @@ -16,10 +17,10 @@ } &--hasTicks { - top: ($euiFormControlHeight / 4) - 2px; + top: ($euiFormControlHeight / 4) - ($euiRangeHighlightHeight / 2); } &--hasTicks.euiRangeHighlight--compressed { - top: ($euiFormControlCompressedHeight / 4) - 2px; + top: ($euiFormControlCompressedHeight / 4) - ($euiRangeHighlightHeight / 2); } } diff --git a/src/components/form/range/_variables.scss b/src/components/form/range/_variables.scss index ce6a5cfd8e6..623e58acce8 100644 --- a/src/components/form/range/_variables.scss +++ b/src/components/form/range/_variables.scss @@ -12,3 +12,5 @@ $euiRangeTrackBorderColor: $euiRangeTrackColor !default; $euiRangeTrackRadius: $euiBorderRadius !default; $euiRangeDisabledOpacity: .25; + +$euiRangeHighlightHeight: $euiSizeXS; diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index 927da0d2332..7500d59c6d3 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -262,7 +262,7 @@ export class EuiDualRange extends Component { } = this.props; const digitTolerance = Math.max(String(min).length, String(max).length); - const showInputOnly = showInput === 'only'; + const showInputOnly = showInput === 'inputWithPopover'; const canShowDropdown = showInputOnly && !readOnly && !disabled; const minInput = !!showInput ? ( @@ -457,9 +457,9 @@ EuiDualRange.propTypes = { showLabels: PropTypes.bool, /** * Pass `true` to displays an extra input control for direct manipulation. - * Pass `'only'` to only show the input but show the range in a dropdown. + * Pass `'inputWithPopover'` to only show the input but show the range in a dropdown. */ - showInput: PropTypes.oneOf([true, false, 'only']), + showInput: PropTypes.oneOf([true, false, 'inputWithPopover']), /** * Shows clickable tick marks and labels at the given interval (`step`/`tickInterval`) */ diff --git a/src/components/form/range/dual_range.test.js b/src/components/form/range/dual_range.test.js index 4b96afebd01..697a337f75a 100644 --- a/src/components/form/range/dual_range.test.js +++ b/src/components/form/range/dual_range.test.js @@ -95,7 +95,7 @@ describe('EuiDualRange', () => { max={10} value={['1', '8']} onChange={() => {}} - showInput="only" + showInput="inputWithPopover" {...requiredProps} /> ); diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js index b760ecefec1..981581035f9 100644 --- a/src/components/form/range/range.js +++ b/src/components/form/range/range.js @@ -76,7 +76,7 @@ export class EuiRange extends Component { } = this.props; const digitTolerance = Math.max(String(min).length, String(max).length); - const showInputOnly = showInput === 'only'; + const showInputOnly = showInput === 'inputWithPopover'; const canShowDropdown = showInputOnly && !readOnly && !disabled; const theInput = !!showInput ? ( @@ -207,9 +207,9 @@ EuiRange.propTypes = { showLabels: PropTypes.bool, /** * Pass `true` to displays an extra input control for direct manipulation. - * Pass `'only'` to only show the input but show the range in a dropdown. + * Pass `'inputWithPopover'` to only show the input but show the range in a dropdown. */ - showInput: PropTypes.oneOf([true, false, 'only']), + showInput: PropTypes.oneOf([true, false, 'inputWithPopover']), /** * Shows clickable tick marks and labels at the given interval (`step`/`tickInterval`) */ diff --git a/src/components/form/range/range.test.js b/src/components/form/range/range.test.js index b645f82bcbf..46362048558 100644 --- a/src/components/form/range/range.test.js +++ b/src/components/form/range/range.test.js @@ -108,7 +108,7 @@ describe('EuiRange', () => { max={10} value="8" onChange={() => {}} - showInput="only" + showInput="inputWithPopover" {...requiredProps} /> ); From 2fd14f42e7182441a1ed0f4b4f3a5fca8176ef04 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 5 Sep 2019 13:19:13 -0500 Subject: [PATCH 22/24] use callback instead of resizeObserver --- src/components/form/range/dual_range.js | 10 ++++------ src/components/popover/input_popover.tsx | 5 +++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index 5c660a78093..8d922a1c634 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -6,7 +6,6 @@ import { keyCodes } from '../../../services'; import { isWithinRange } from '../../../services/number'; import { EuiInputPopover } from '../../popover'; import { EuiFormControlLayoutDelimited } from '../form_control_layout'; -import { EuiResizeObserver } from '../../observer/resize_observer'; import makeId from '../form_row/make_id'; import { EuiRangeHighlight } from './range_highlight'; @@ -253,7 +252,7 @@ export class EuiDualRange extends Component { }); }; - onResize = ({ width }) => { + onResize = width => { this.setState({ rangeWidth: width, }); @@ -458,10 +457,9 @@ export class EuiDualRange extends Component { fullWidth={fullWidth} isOpen={this.state.isPopoverOpen} closePopover={this.closePopover} - disableFocusTrap={true}> - - {resizeRef =>
{theRange}
} -
+ disableFocusTrap={true} + onPanelResize={this.onResize}> + {theRange} ) : ( undefined diff --git a/src/components/popover/input_popover.tsx b/src/components/popover/input_popover.tsx index 8145f91dfb4..a9f4f2df543 100644 --- a/src/components/popover/input_popover.tsx +++ b/src/components/popover/input_popover.tsx @@ -19,6 +19,7 @@ interface EuiInputPopoverProps fullWidth?: boolean; input: EuiPopoverProps['button']; inputRef?: EuiPopoverProps['buttonRef']; + onPanelResize?: (width?: number) => void; } type Props = CommonProps & @@ -31,6 +32,7 @@ export const EuiInputPopover: FunctionComponent = ({ disableFocusTrap = false, input, fullWidth = false, + onPanelResize, ...props }) => { const [inputEl, setInputEl] = useState(); @@ -44,6 +46,9 @@ export const EuiInputPopover: FunctionComponent = ({ if (panelEl && (!!inputElWidth || !!width)) { const newWidth = !!width ? width : inputElWidth; panelEl.style.width = `${newWidth}px`; + if (onPanelResize) { + onPanelResize(newWidth); + } } }; const onResize = () => { From 657e3d8ca07faad96bec92b5f8aabb1a0679c5d3 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Mon, 9 Sep 2019 12:27:43 -0500 Subject: [PATCH 23/24] ie11 focus fix --- src/components/form/range/dual_range.js | 3 ++- src/components/form/range/range.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index 8d922a1c634..ea8cef8872b 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -240,7 +240,8 @@ export class EuiDualRange extends Component { onInputBlur = e => { // Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget` - const relatedTarget = e.relatedTarget || e.explicitOriginalTarget; + const relatedTarget = + e.relatedTarget || e.explicitOriginalTarget || document.activeElement; if (!relatedTarget || relatedTarget.id !== this.state.id) { this.closePopover(); } diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js index 2cf63aba3b2..df450fb8672 100644 --- a/src/components/form/range/range.js +++ b/src/components/form/range/range.js @@ -44,7 +44,8 @@ export class EuiRange extends Component { onInputBlur = e => { // Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget` - const relatedTarget = e.relatedTarget || e.explicitOriginalTarget; + const relatedTarget = + e.relatedTarget || e.explicitOriginalTarget || document.activeElement; if (!relatedTarget || relatedTarget.id !== this.state.id) { this.closePopover(); } From 418e4e156e7fbfd8078a003f8d3448e06b73b587 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Mon, 9 Sep 2019 14:03:03 -0500 Subject: [PATCH 24/24] use focusout instead of blur --- src/components/form/range/dual_range.js | 25 ++++++++++++++++++++---- src/components/form/range/range.js | 25 ++++++++++++++++++++---- src/components/form/range/range_input.js | 1 + 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js index ea8cef8872b..8e0b3131bbb 100644 --- a/src/components/form/range/dual_range.js +++ b/src/components/form/range/dual_range.js @@ -25,6 +25,8 @@ export class EuiDualRange extends Component { rangeWidth: null, }; + maxNode = null; + minNode = null; rangeSliderRef = null; handleRangeSliderRefUpdate = ref => { this.rangeSliderRef = ref; @@ -240,8 +242,7 @@ export class EuiDualRange extends Component { onInputBlur = e => { // Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget` - const relatedTarget = - e.relatedTarget || e.explicitOriginalTarget || document.activeElement; + const relatedTarget = e.relatedTarget || e.explicitOriginalTarget; if (!relatedTarget || relatedTarget.id !== this.state.id) { this.closePopover(); } @@ -259,6 +260,22 @@ export class EuiDualRange extends Component { }); }; + inputRef = (node, ref) => { + if (!this.props.showInput !== 'inputWithPopover') return; + + // IE11 doesn't support the `relatedTarget` event property for blur events + // but does add it for focusout. React doesn't support `onFocusOut` so here we are. + if (this[ref] != null) { + this[ref].removeEventListener('focusout', this.onInputBlur); + } + + this[ref] = node; + + if (this[ref]) { + this[ref].addEventListener('focusout', this.onInputBlur); + } + }; + render() { const { className, @@ -306,11 +323,11 @@ export class EuiDualRange extends Component { aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} onFocus={canShowDropdown ? this.onInputFocus : undefined} - onBlur={canShowDropdown ? this.onInputBlur : undefined} readOnly={readOnly} autoSize={!showInputOnly} fullWidth={!!showInputOnly && fullWidth} controlOnly={showInputOnly} + inputRef={node => this.inputRef(node, 'minNode')} /> ) : ( undefined @@ -332,11 +349,11 @@ export class EuiDualRange extends Component { aria-describedby={this.props['aria-describedby']} aria-label={this.props['aria-label']} onFocus={canShowDropdown ? this.onInputFocus : undefined} - onBlur={canShowDropdown ? this.onInputBlur : undefined} readOnly={readOnly} autoSize={!showInputOnly} fullWidth={!!showInputOnly && fullWidth} controlOnly={showInputOnly} + inputRef={node => this.inputRef(node, 'maxNode')} /> ) : ( undefined diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js index df450fb8672..2de1b30db00 100644 --- a/src/components/form/range/range.js +++ b/src/components/form/range/range.js @@ -21,6 +21,8 @@ export class EuiRange extends Component { id: props.id || makeId(), isPopoverOpen: false, }; + + this.inputNode = null; } handleOnChange = e => { @@ -44,8 +46,7 @@ export class EuiRange extends Component { onInputBlur = e => { // Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget` - const relatedTarget = - e.relatedTarget || e.explicitOriginalTarget || document.activeElement; + const relatedTarget = e.relatedTarget || e.explicitOriginalTarget; if (!relatedTarget || relatedTarget.id !== this.state.id) { this.closePopover(); } @@ -57,6 +58,22 @@ export class EuiRange extends Component { }); }; + inputRef = node => { + if (!this.props.showInput !== 'inputWithPopover') return; + + // IE11 and Safar don't support the `relatedTarget` event property for blur events + // but do add it for focusout. React doesn't support `onFocusOut` so here we are. + if (this.inputNode != null) { + this.inputNode.removeEventListener('focusout', this.onInputBlur); + } + + this.inputNode = node; + + if (this.inputNode) { + this.inputNode.addEventListener('focusout', this.onInputBlur); + } + }; + render() { const { className, @@ -105,9 +122,9 @@ export class EuiRange extends Component { onChange={this.handleOnChange} name={name} onFocus={canShowDropdown ? this.onInputFocus : undefined} - onBlur={canShowDropdown ? this.onInputBlur : undefined} fullWidth={showInputOnly && fullWidth} autoSize={!showInputOnly} + inputRef={this.inputRef} {...rest} /> ) : ( @@ -162,7 +179,7 @@ export class EuiRange extends Component { style={style} showTicks={showTicks} showRange={showRange} - tabIndex={showInput === true ? -1 : tabIndex || null} + tabIndex={showInput ? -1 : tabIndex || null} {...rest} /> diff --git a/src/components/form/range/range_input.js b/src/components/form/range/range_input.js index 5386d4aab68..d7e240f9411 100644 --- a/src/components/form/range/range_input.js +++ b/src/components/form/range/range_input.js @@ -55,6 +55,7 @@ EuiRangeInput.propTypes = { side: PropTypes.oneOf(['min', 'max']), fullWidth: PropTypes.bool, autoSize: PropTypes.bool, + inputRef: PropTypes.func, }; EuiRangeInput.defaultProps = { side: 'max',