Skip to content

Commit

Permalink
SuperDatePicker tweaks to make it selection more obvious (#2049)
Browse files Browse the repository at this point in the history
- Fixed Absolute tab selection
- Using bottom border to indicate which time period is selected
- Added title to tab aria-labels
- Added prepend labels to inputs for start/end
- Also added `toSentenceCase` string service
  • Loading branch information
cchaos authored Jun 20, 2019
1 parent bb41f02 commit 0ce3e6b
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- Added a fully black (no matter the theme) color SASS variable `$euiColorInk` ([2060](https://github.com/elastic/eui/pull/2060))
- Added `autoFocus` prop to `EuiTabbedContent` ([2062](https://github.com/elastic/eui/pull/2062))
- Changed `popout` glyph in `EuiIcon` to look more like external link ([2064](https://github.com/elastic/eui/pull/2064))
- Tweaked `SuperDatePicker` to make the start/end date selection more obvious ([#2049](https://github.com/elastic/eui/pull/2049))
- Added `toSentenceCase` string service ([#2049](https://github.com/elastic/eui/pull/2049))

**Bug fixes**

Expand Down
2 changes: 1 addition & 1 deletion src/components/date_picker/super_date_picker/date_modes.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function getDateMode(value) {
return DATE_MODES.RELATIVE;
}

return DATE_MODES.absolute;
return DATE_MODES.ABSOLUTE;
}

export function toAbsoluteString(value, roundUp) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,37 @@

.euiDatePopoverButton {
@include euiSuperDatePickerText;
background-size: 100%; // For the bottom "border" via background-image

$backgroundColor: tintOrShade($euiColorSuccess, 90%, 70%);
$textColor: makeHighContrastColor($euiColorSuccess, $backgroundColor);

&-isSelected,
&-needsUpdating,
&:hover,
&:focus {
background-color: $backgroundColor;
&:focus,
&-isSelected {
background-image: euiFormControlGradient();
}

&-needsUpdating {
$backgroundColor: tintOrShade($euiColorSuccess, 90%, 70%);
$textColor: makeHighContrastColor($euiColorSuccess, $backgroundColor);

background-color: $backgroundColor;
color: $textColor;

&:focus,
&.euiDatePopoverButton-isSelected {
background-image: euiFormControlGradient($euiColorSuccess);
}
}

&-isInvalid {
$backgroundColor: tintOrShade($euiColorDanger, 90%, 70%);
$textColor: makeHighContrastColor($euiColorDanger, $backgroundColor);

background-color: $backgroundColor;
color: $textColor;

&:focus,
&.euiDatePopoverButton-isSelected {
background-image: euiFormControlGradient($euiColorDanger);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import moment from 'moment';
import dateMath from '@elastic/datemath';

import { EuiDatePicker } from '../../date_picker';
import { EuiFormRow, EuiFieldText } from '../../../form';
import { EuiFormRow, EuiFieldText, EuiFormLabel } from '../../../form';
import { toSentenceCase } from '../../../../services/string/to_case';

const INPUT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';

Expand All @@ -17,10 +18,13 @@ export class EuiAbsoluteTab extends Component {
const parsedValue = dateMath.parse(props.value, { roundUp: props.roundUp });
const valueAsMoment =
parsedValue && parsedValue.isValid() ? parsedValue : moment();
const sentenceCasedPosition = toSentenceCase(props.position);

this.state = {
valueAsMoment,
textInputValue: valueAsMoment.format(INPUT_DATE_FORMAT),
isTextInvalid: false,
sentenceCasedPosition,
};
}

Expand Down Expand Up @@ -70,6 +74,11 @@ export class EuiAbsoluteTab extends Component {
value={this.state.textInputValue}
onChange={this.handleTextChange}
data-test-subj={'superDatePickerAbsoluteDateInput'}
prepend={
<EuiFormLabel>
{this.state.sentenceCasedPosition} date
</EuiFormLabel>
}
/>
</EuiFormRow>
</div>
Expand All @@ -82,4 +91,5 @@ EuiAbsoluteTab.propTypes = {
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
roundUp: PropTypes.bool.isRequired,
position: PropTypes.oneOf(['start', 'end']),
};
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export function EuiDatePopoverButton(props) {
roundUp={roundUp}
onChange={onChange}
dateFormat={dateFormat}
position={position}
/>
</EuiPopover>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function EuiDatePopoverContent({
roundUp,
onChange,
dateFormat,
position,
}) {
const onTabClick = selectedTab => {
switch (selectedTab.id) {
Expand All @@ -32,6 +33,8 @@ export function EuiDatePopoverContent({
}
};

const ariaLabel = `${position === 'start' ? 'Start' : 'End'} date:`;

const renderTabs = () => {
return [
{
Expand All @@ -43,9 +46,11 @@ export function EuiDatePopoverContent({
value={value}
onChange={onChange}
roundUp={roundUp}
position={position}
/>
),
'data-test-subj': 'superDatePickerAbsoluteTab',
'aria-label': `${ariaLabel} Absolute`,
},
{
id: DATE_MODES.RELATIVE,
Expand All @@ -56,9 +61,11 @@ export function EuiDatePopoverContent({
value={value}
onChange={onChange}
roundUp={roundUp}
position={position}
/>
),
'data-test-subj': 'superDatePickerRelativeTab',
'aria-label': `${ariaLabel} Relative`,
},
{
id: DATE_MODES.NOW,
Expand All @@ -78,11 +85,12 @@ export function EuiDatePopoverContent({
fullWidth
size="s"
fill>
Set date and time to now
Set {position} date and time to now
</EuiButton>
</EuiText>
),
'data-test-subj': 'superDatePickerNowTab',
'aria-label': `${ariaLabel} Now`,
},
];
};
Expand All @@ -105,6 +113,7 @@ EuiDatePopoverContent.propTypes = {
onChange: PropTypes.func.isRequired,
roundUp: PropTypes.bool,
dateFormat: PropTypes.string.isRequired,
position: PropTypes.oneOf(['start', 'end']),
};

EuiDatePopoverContent.defaultProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import dateMath from '@elastic/datemath';
import { toSentenceCase } from '../../../../services/string/to_case';

import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
import {
Expand All @@ -10,6 +11,7 @@ import {
EuiFieldNumber,
EuiFieldText,
EuiSwitch,
EuiFormLabel,
} from '../../../form';
import { EuiSpacer } from '../../../spacer';

Expand All @@ -23,9 +25,11 @@ import {
export class EuiRelativeTab extends Component {
constructor(props) {
super(props);
const sentenceCasedPosition = toSentenceCase(props.position);

this.state = {
...parseRelativeParts(this.props.value),
sentenceCasedPosition,
};
}

Expand Down Expand Up @@ -108,7 +112,13 @@ export class EuiRelativeTab extends Component {
onChange={this.onRoundChange}
/>
<EuiSpacer size="m" />
<EuiFieldText value={formatedValue} readOnly />
<EuiFieldText
value={formatedValue}
readOnly
prepend={
<EuiFormLabel>{this.state.sentenceCasedPosition} date</EuiFormLabel>
}
/>
</EuiForm>
);
}
Expand All @@ -119,4 +129,5 @@ EuiRelativeTab.propTypes = {
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
roundUp: PropTypes.bool,
position: PropTypes.oneOf(['start', 'end']),
};
1 change: 1 addition & 0 deletions src/services/string/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { toInitials } from './to_initials';
export { toSentenceCase } from './to_case';
17 changes: 17 additions & 0 deletions src/services/string/to_case.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { toSentenceCase } from './to_case';

describe('toSentenceCase', () => {
it("should return the same single word with the first letter capitalized for 'single'", () => {
expect(toSentenceCase('single')).toBe('Single');
});

it("should return all the words with ony the first letter of the first word capitalized for 'two words'", () => {
expect(toSentenceCase('two words')).toBe('Two words');
});

it("should return all the words with ony the first letter of the first word capitalized for 'opposite Of Sentence Case'", () => {
expect(toSentenceCase('opposite Of Sentence Case')).toBe(
'Opposite of sentence case'
);
});
});
13 changes: 13 additions & 0 deletions src/services/string/to_case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* This function returns the same string with the first letter of the first word capitalized.
*
* @param {string} strint The input string
*/

export function toSentenceCase(string: string): string {
// First lowercase all letters
const lowercase = string.toLowerCase();

// Then just uppercase the first letter;
return string.charAt(0).toUpperCase() + lowercase.slice(1);
}

0 comments on commit 0ce3e6b

Please sign in to comment.