Skip to content

Commit

Permalink
[Feature Branch] Add support for EuiRange in a dropdown with input (#…
Browse files Browse the repository at this point in the history
…2179)

* Compressed EuiRange step 1: Decrease overall height of the range when compressed
* Compressed EuiRange step 2:
- Attempt at single range compressed input with popover
- Fixes z-indexes being too high
- Fix up widths
* Compressed EuiRange step 3: Dual range now supports dropdown style
* Fix for delimited
* Fix full-width delimited
* Added `controlOnly` prop to EuiFieldNumber
* Finalize styles of input only ranges
- Needed some fixes to EuiFormControlLayoutDelimited
* Open popover on focus
* dual range respond to resize events when in showInputOnly mode
* use callback instead of resizeObserver
* ie11 focus fix
* use focusout instead of blur
  • Loading branch information
cchaos authored Sep 9, 2019
1 parent 1dfd030 commit 7f88db7
Show file tree
Hide file tree
Showing 31 changed files with 903 additions and 309 deletions.
90 changes: 90 additions & 0 deletions src-docs/src/views/range/input_only.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React, { Component, Fragment } from 'react';

import { EuiRange, EuiSpacer, EuiDualRange } from '../../../../src/components';

import makeId from '../../../../src/components/form/form_row/make_id';

export default class extends Component {
constructor(props) {
super(props);

this.levels = [
{
min: 0,
max: 20,
color: 'danger',
},
{
min: 20,
max: 100,
color: 'success',
},
];

this.state = {
value: '20',
dualValue: [20, 100],
};
}

onChange = e => {
this.setState({
value: e.target.value,
});
};

onDualChange = value => {
this.setState({
dualValue: value,
});
};

render() {
return (
<Fragment>
<EuiRange
id={makeId()}
value={this.state.value}
onChange={this.onChange}
showInput="inputWithPopover"
showLabels
/>

<EuiSpacer size="xl" />

<EuiDualRange
id={makeId()}
value={this.state.dualValue}
onChange={this.onDualChange}
showInput="inputWithPopover"
showLabels
levels={this.levels}
/>

<EuiSpacer size="xl" />

<EuiRange
id={makeId()}
value={this.state.value}
onChange={this.onChange}
compressed
showInput="inputWithPopover"
showLabels
/>

<EuiSpacer size="xl" />

<EuiDualRange
id={makeId()}
value={this.state.dualValue}
onChange={this.onDualChange}
compressed
showInput="inputWithPopover"
showLabels
levels={this.levels}
readOnly
/>
</Fragment>
);
}
}
93 changes: 66 additions & 27 deletions src-docs/src/views/range/range_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ import StatesExample from './states';
const statesSource = require('!!raw-loader!./states');
const statesHtml = renderToHtml(StatesExample);

import InputOnlyExample from './input_only';
const inputOnlySource = require('!!raw-loader!./input_only');
const inputOnlyHtml = renderToHtml(InputOnlyExample);

export const RangeControlExample = {
title: 'Range sliders',
intro: (
Expand Down Expand Up @@ -112,26 +116,25 @@ export const RangeControlExample = {
EuiRange,
},
demo: <RangeExample />,
snippet: `<EuiRange
snippet: [
`<EuiRange
min={100}
max={200}
step={0.05}
value={this.state.value}
onChange={this.onChange}
showLabels
/>
// Show tooltip
/>`,
`// Show tooltip
<EuiRange
min={100}
max={200}
value={this.state.value}
onChange={this.onChange}
showLabels
showValue
/>
// Show thickened range and prepend a string to the tooltip
/>`,
`// Show thickened range and prepend a string to the tooltip
<EuiRange
min={100}
max={200}
Expand All @@ -142,6 +145,7 @@ export const RangeControlExample = {
showValue
valuePrepend="100 - "
/>`,
],
},
{
title: 'Dual range',
Expand Down Expand Up @@ -224,9 +228,7 @@ export const RangeControlExample = {
],
demo: <InputExample />,
props: { EuiRangeInput },
snippet: `<EuiRange showInput />
<EuiDualRange showInput />`,
snippet: ['<EuiRange showInput />', '<EuiDualRange showInput />'],
},
{
title: 'Tick marks',
Expand Down Expand Up @@ -265,17 +267,17 @@ export const RangeControlExample = {
],
demo: <TicksExample />,
props: { EuiRangeTicks },
snippet: `<EuiRange step={10} showTicks />
<EuiRange showTicks tickInterval={20} />
<EuiDualRange
snippet: [
'<EuiRange step={10} showTicks />',
'<EuiRange showTicks tickInterval={20} />',
`<EuiDualRange
showTicks
ticks={[
{ label: '20kb', value: 20 },
{ label: '100kb', value: 100 }
]}
/>`,
],
},
{
title: 'Levels',
Expand Down Expand Up @@ -305,30 +307,68 @@ export const RangeControlExample = {
],
demo: <LevelsExample />,
props: { EuiRangeLevels },
snippet: `<EuiRange
snippet: [
`<EuiRange
levels={[
{min: 0, max: 20, color: 'danger'},
{min: 20, max: 100, color: 'success'}
]}
aria-describedBy={replaceWithID}
/>
<EuiDualRange
/>`,
`<EuiDualRange
levels={[
{min: 0, max: 20, color: 'danger'},
{min: 20, max: 100, color: 'success'}
]}
aria-describedBy={replaceWithID}
/>`,
],
},
{
title: 'Inputs with range in a dropdown',
text: (
<Fragment>
<p>
Passing <EuiCode>showInput=&quot;inputWithPopover&quot;</EuiCode>{' '}
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.
</p>
</Fragment>
),
source: [
{
type: GuideSectionTypes.JS,
code: inputOnlySource,
},
{
type: GuideSectionTypes.HTML,
code: inputOnlyHtml,
},
],
demo: <InputOnlyExample />,
snippet: [
`<EuiRange
id=""
value={}
onChange={() => {}}
showInput="inputWithPopover"
/>`,
`<EuiDualRange
id=""
value={}
onChange={() => {}}
showInput="inputWithPopover"
/>`,
],
},
{
title: 'Kitchen sink',
text: (
<Fragment>
<p>
Other alterations you can add to the range are{' '}
<EuiCode>compressed</EuiCode>, <EuiCode>fullWidth</EuiCode>, and{' '}
<EuiCode>disabled</EuiCode>.
<EuiCode>fullWidth</EuiCode>, and <EuiCode>disabled</EuiCode>.
</p>
</Fragment>
),
Expand All @@ -343,11 +383,11 @@ export const RangeControlExample = {
},
],
demo: <StatesExample />,
snippet: `<EuiRange
snippet: [
`<EuiRange
id=""
value={}
onChange={() => {}}
compressed
fullWidth
disabled
showTicks
Expand All @@ -358,13 +398,11 @@ export const RangeControlExample = {
tickInterval={}
levels={[]}
aria-describedBy={replaceWithID}
/>
<EuiDualRange
/>`,
`<EuiDualRange
id=""
value={}
onChange={() => {}}
compressed
fullWidth
disabled
showLabels
Expand All @@ -374,6 +412,7 @@ export const RangeControlExample = {
levels={[]}
aria-describedBy={replaceWithID}
/>`,
],
},
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ exports[`EuiFieldNumber is rendered 1`] = `
</eui-form-control-layout>
`;

exports[`EuiFieldNumber props controlOnly is rendered 1`] = `
<eui-validatable-control>
<input
class="euiFieldNumber"
type="number"
/>
</eui-validatable-control>
`;

exports[`EuiFieldNumber props fullWidth is rendered 1`] = `
<eui-form-control-layout
compressed="false"
Expand Down
44 changes: 29 additions & 15 deletions src/components/form/field_number/field_number.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const EuiFieldNumber = ({
append,
inputRef,
readOnly,
controlOnly,
...rest
}) => {
const classes = classNames('euiFieldNumber', className, {
Expand All @@ -33,6 +34,28 @@ export const EuiFieldNumber = ({
'euiFieldNumber-isLoading': isLoading,
});

const control = (
<EuiValidatableControl isInvalid={isInvalid}>
<input
type="number"
id={id}
min={min}
max={max}
name={name}
value={value}
placeholder={placeholder}
readOnly={readOnly}
className={classes}
ref={inputRef}
{...rest}
/>
</EuiValidatableControl>
);

if (controlOnly) {
return control;
}

return (
<EuiFormControlLayout
icon={icon}
Expand All @@ -43,21 +66,7 @@ export const EuiFieldNumber = ({
prepend={prepend}
append={append}
inputId={id}>
<EuiValidatableControl isInvalid={isInvalid}>
<input
type="number"
id={id}
min={min}
max={max}
name={name}
value={value}
placeholder={placeholder}
readOnly={readOnly}
className={classes}
ref={inputRef}
{...rest}
/>
</EuiValidatableControl>
{control}
</EuiFormControlLayout>
);
};
Expand Down Expand Up @@ -114,6 +123,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 = {
Expand Down
6 changes: 6 additions & 0 deletions src/components/form/field_number/field_number.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ describe('EuiFieldNumber', () => {
expect(component).toMatchSnapshot();
});

test('controlOnly is rendered', () => {
const component = render(<EuiFieldNumber controlOnly />);

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

describe('value', () => {
test('value is number', () => {
const component = render(
Expand Down
Loading

0 comments on commit 7f88db7

Please sign in to comment.