Skip to content

Commit 20d3044

Browse files
committed
Add openDirection prop
Addresses #648. * Add `openDirection` prop to `<DateRangePicker/>`, `<SingleDatePicker/>`, `<DateRangePickerInputController/>`, `<DateRangePickerInput/>`, `<SingleDatePickerInput/>`, `<DateInput/> * Add SCSS variables for input font size, padding, etc. (used in calculation for open-up absolute positioning) * Add stories and tests for new prop
1 parent 9685cc9 commit 20d3044

19 files changed

+206
-20
lines changed

constants.js

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ module.exports = {
1313
ANCHOR_LEFT: 'left',
1414
ANCHOR_RIGHT: 'right',
1515

16+
OPEN_DOWN: 'down',
17+
OPEN_UP: 'up',
18+
1619
DAY_SIZE: 39,
1720
BLOCKED_MODIFIER: 'blocked',
1821
WEEKDAYS: [0, 1, 2, 3, 4, 5, 6],

css/DateInput.scss

+31-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
$caret-top: $react-dates-spacing-vertical-picker - $react-dates-width-tooltip-arrow / 2;
1+
$input-height: $react-dates-input-line-height + $react-dates-input-padding * 2 + $react-dates-input-displaytext-padding-vertical * 2;
2+
$caret-top-down: $react-dates-spacing-vertical-picker - $react-dates-width-tooltip-arrow / 2;
3+
$caret-top-up: $input-height - $react-dates-spacing-vertical-picker;
24

35
.DateInput {
46
// font
57
font-weight: 200;
6-
font-size: 18px;
7-
line-height: 24px;
8+
font-size: $react-dates-input-font-size;
9+
line-height: $react-dates-input-line-height;
810
color: $react-dates-color-placeholder-text;
911
margin: 0;
10-
padding: 8px;
12+
padding: $react-dates-input-padding;
1113

1214
background: $react-dates-color-white;
1315
position: relative;
@@ -23,21 +25,40 @@ $caret-top: $react-dates-spacing-vertical-picker - $react-dates-width-tooltip-ar
2325
position: absolute;
2426
bottom: auto;
2527
border: $react-dates-width-tooltip-arrow / 2 solid transparent;
26-
border-top: 0;
2728
left: 22px;
2829
z-index: $react-dates-z-index + 2;
2930
}
3031

31-
.DateInput--with-caret::before {
32-
top: $caret-top;
32+
.DateInput--open-down.DateInput--with-caret::before,
33+
.DateInput--open-down.DateInput--with-caret::after {
34+
border-top: 0;
35+
}
36+
37+
.DateInput--open-down.DateInput--with-caret::before {
38+
top: $caret-top-down;
3339
border-bottom-color: rgba(0, 0, 0, 0.1);
3440
}
3541

36-
.DateInput--with-caret::after {
37-
top: $caret-top + 1;
42+
.DateInput--open-down.DateInput--with-caret::after {
43+
top: $caret-top-down + 1;
3844
border-bottom-color: $react-dates-color-white;
3945
}
4046

47+
.DateInput--open-up.DateInput--with-caret::before,
48+
.DateInput--open-up.DateInput--with-caret::after {
49+
border-bottom: 0;
50+
}
51+
52+
.DateInput--open-up.DateInput--with-caret::before {
53+
top: $caret-top-up;
54+
border-top-color: rgba(0, 0, 0, 0.1);
55+
}
56+
57+
.DateInput--open-up.DateInput--with-caret::after {
58+
top: $caret-top-up - 1;
59+
border-top-color: $react-dates-color-white;
60+
}
61+
4162
.DateInput--disabled {
4263
background: $react-dates-color-gray-lighter;
4364
}
@@ -60,7 +81,7 @@ $caret-top: $react-dates-spacing-vertical-picker - $react-dates-width-tooltip-ar
6081
}
6182

6283
.DateInput__display-text {
63-
padding: 4px 8px;
84+
padding: $react-dates-input-displaytext-padding-vertical $react-dates-input-displaytext-padding-horizontal;
6485
white-space: nowrap;
6586
overflow: hidden;
6687
}

css/DateRangePicker.scss

+9-2
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020
z-index: $react-dates-z-index + 1;
2121
background-color: $react-dates-color-white;
2222
position: absolute;
23-
top: $react-dates-spacing-vertical-picker;
2423
}
2524

26-
.DateRangePicker__picker--rtl {
25+
.DateRangePicker__picker--rtl {
2726
direction: rtl;
2827
}
2928

@@ -35,6 +34,14 @@
3534
right: 0;
3635
}
3736

37+
.DateRangePicker__picker--open-down {
38+
top: $react-dates-spacing-vertical-picker;
39+
}
40+
41+
.DateRangePicker__picker--open-up {
42+
bottom: $react-dates-spacing-vertical-picker;
43+
}
44+
3845
.DateRangePicker__picker--portal {
3946
background-color: rgba(0, 0, 0, 0.3);
4047
position: fixed;

css/SingleDatePicker.scss

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
z-index: $react-dates-z-index + 1;
1010
background-color: $react-dates-color-white;
1111
position: absolute;
12-
top: $react-dates-spacing-vertical-picker;
1312
}
1413

1514
.SingleDatePicker__picker--rtl {
@@ -24,6 +23,14 @@
2423
right: 0;
2524
}
2625

26+
.SingleDatePicker__picker--open-down {
27+
top: $react-dates-spacing-vertical-picker;
28+
}
29+
30+
.SingleDatePicker__picker--open-up {
31+
bottom: $react-dates-spacing-vertical-picker;
32+
}
33+
2734
.SingleDatePicker__picker--portal {
2835
background-color: rgba(0, 0, 0, 0.3);
2936
position: fixed;

css/variables.scss

+6
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,9 @@ $react-dates-color-text-focus: #007a87 !default;
2626
$react-dates-color-focus: #99ede6 !default;
2727

2828
$react-dates-z-index: 0 !default;
29+
30+
$react-dates-input-font-size: 18px !default;
31+
$react-dates-input-line-height: 24px !default;
32+
$react-dates-input-padding: 8px !default;
33+
$react-dates-input-displaytext-padding-horizontal: 8px !default;
34+
$react-dates-input-displaytext-padding-vertical: 4px !default;

src/components/DateInput.jsx

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import cx from 'classnames';
55
import throttle from 'lodash/throttle';
66
import isTouchDevice from 'is-touch-device';
77

8+
import openDirectionShape from '../shapes/OpenDirectionShape';
9+
import { OPEN_DOWN, OPEN_UP } from '../../constants';
10+
811
const propTypes = forbidExtraProps({
912
id: PropTypes.string.isRequired,
1013
placeholder: PropTypes.string, // also used as label
@@ -15,6 +18,7 @@ const propTypes = forbidExtraProps({
1518
disabled: PropTypes.bool,
1619
required: PropTypes.bool,
1720
readOnly: PropTypes.bool,
21+
openDirection: openDirectionShape,
1822
showCaret: PropTypes.bool,
1923

2024
onChange: PropTypes.func,
@@ -38,6 +42,7 @@ const defaultProps = {
3842
disabled: false,
3943
required: false,
4044
readOnly: null,
45+
openDirection: OPEN_DOWN,
4146
showCaret: false,
4247

4348
onChange() {},
@@ -145,6 +150,7 @@ export default class DateInput extends React.Component {
145150
disabled,
146151
required,
147152
readOnly,
153+
openDirection,
148154
} = this.props;
149155

150156
const displayText = displayValue || inputValue || dateString || placeholder || '';
@@ -156,6 +162,8 @@ export default class DateInput extends React.Component {
156162
className={cx('DateInput', {
157163
'DateInput--with-caret': showCaret && focused,
158164
'DateInput--disabled': disabled,
165+
'DateInput--open-down': openDirection === OPEN_DOWN,
166+
'DateInput--open-up': openDirection === OPEN_UP,
159167
})}
160168
>
161169
<input

src/components/DateRangePicker.jsx

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import {
2929
VERTICAL_ORIENTATION,
3030
ANCHOR_LEFT,
3131
ANCHOR_RIGHT,
32+
OPEN_DOWN,
33+
OPEN_UP,
3234
DAY_SIZE,
3335
} from '../../constants';
3436

@@ -59,6 +61,7 @@ const defaultProps = {
5961
renderMonth: null,
6062
orientation: HORIZONTAL_ORIENTATION,
6163
anchorDirection: ANCHOR_LEFT,
64+
openDirection: OPEN_DOWN,
6265
horizontalMargin: 0,
6366
withPortal: false,
6467
withFullScreenPortal: false,
@@ -203,12 +206,15 @@ export default class DateRangePicker extends React.Component {
203206
withPortal,
204207
withFullScreenPortal,
205208
anchorDirection,
209+
openDirection,
206210
isRTL,
207211
} = this.props;
208212

209213
const dayPickerClassName = cx('DateRangePicker__picker', {
210214
'DateRangePicker__picker--direction-left': anchorDirection === ANCHOR_LEFT,
211215
'DateRangePicker__picker--direction-right': anchorDirection === ANCHOR_RIGHT,
216+
'DateRangePicker__picker--open-down': openDirection === OPEN_DOWN,
217+
'DateRangePicker__picker--open-up': openDirection === OPEN_UP,
212218
'DateRangePicker__picker--horizontal': orientation === HORIZONTAL_ORIENTATION,
213219
'DateRangePicker__picker--vertical': orientation === VERTICAL_ORIENTATION,
214220
'DateRangePicker__picker--portal': withPortal || withFullScreenPortal,
@@ -401,6 +407,7 @@ export default class DateRangePicker extends React.Component {
401407
disabled,
402408
required,
403409
readOnly,
410+
openDirection,
404411
phrases,
405412
isOutsideRange,
406413
minimumNights,
@@ -440,6 +447,7 @@ export default class DateRangePicker extends React.Component {
440447
disabled={disabled}
441448
required={required}
442449
readOnly={readOnly}
450+
openDirection={openDirection}
443451
reopenPickerOnClearDates={reopenPickerOnClearDates}
444452
keepOpenOnDateSelect={keepOpenOnDateSelect}
445453
isOutsideRange={isOutsideRange}

src/components/DateRangePickerInput.jsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import cx from 'classnames';
55

66
import { DateRangePickerInputPhrases } from '../defaultPhrases';
77
import getPhrasePropTypes from '../utils/getPhrasePropTypes';
8+
import openDirectionShape from '../shapes/OpenDirectionShape';
89

910
import DateInput from './DateInput';
1011
import RightArrow from '../svg/arrow-right.svg';
1112
import LeftArrow from '../svg/arrow-left.svg';
1213
import CloseButton from '../svg/close.svg';
1314
import CalendarIcon from '../svg/calendar.svg';
1415

15-
import { START_DATE, END_DATE } from '../../constants';
16+
import { START_DATE, END_DATE, OPEN_DOWN } from '../../constants';
1617

1718
const propTypes = forbidExtraProps({
1819
startDateId: PropTypes.string,
@@ -43,6 +44,7 @@ const propTypes = forbidExtraProps({
4344
disabled: PropTypes.bool,
4445
required: PropTypes.bool,
4546
readOnly: PropTypes.bool,
47+
openDirection: openDirectionShape,
4648
showCaret: PropTypes.bool,
4749
showDefaultInputIcon: PropTypes.bool,
4850
customInputIcon: PropTypes.node,
@@ -85,6 +87,7 @@ const defaultProps = {
8587
disabled: false,
8688
required: false,
8789
readOnly: false,
90+
openDirection: OPEN_DOWN,
8891
showCaret: false,
8992
showDefaultInputIcon: false,
9093
customInputIcon: null,
@@ -150,6 +153,7 @@ export default class DateRangePickerInput extends React.Component {
150153
disabled,
151154
required,
152155
readOnly,
156+
openDirection,
153157
showCaret,
154158
showDefaultInputIcon,
155159
customInputIcon,
@@ -195,6 +199,7 @@ export default class DateRangePickerInput extends React.Component {
195199
disabled={disabled}
196200
required={required}
197201
readOnly={readOnly}
202+
openDirection={openDirection}
198203
showCaret={showCaret}
199204

200205
onChange={onStartDateChange}
@@ -223,6 +228,7 @@ export default class DateRangePickerInput extends React.Component {
223228
disabled={disabled}
224229
required={required}
225230
readOnly={readOnly}
231+
openDirection={openDirection}
226232
showCaret={showCaret}
227233

228234
onChange={onEndDateChange}

src/components/DateRangePickerInputController.jsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import moment from 'moment';
44

55
import momentPropTypes from 'react-moment-proptypes';
66
import { forbidExtraProps, nonNegativeInteger } from 'airbnb-prop-types';
7+
import openDirectionShape from '../shapes/OpenDirectionShape';
78

89
import { DateRangePickerInputPhrases } from '../defaultPhrases';
910
import getPhrasePropTypes from '../utils/getPhrasePropTypes';
@@ -17,7 +18,7 @@ import toISODateString from '../utils/toISODateString';
1718
import isInclusivelyAfterDay from '../utils/isInclusivelyAfterDay';
1819
import isBeforeDay from '../utils/isBeforeDay';
1920

20-
import { START_DATE, END_DATE } from '../../constants';
21+
import { START_DATE, END_DATE, OPEN_DOWN } from '../../constants';
2122

2223
const propTypes = forbidExtraProps({
2324
startDate: momentPropTypes.momentObj,
@@ -37,6 +38,7 @@ const propTypes = forbidExtraProps({
3738
disabled: PropTypes.bool,
3839
required: PropTypes.bool,
3940
readOnly: PropTypes.bool,
41+
openDirection: openDirectionShape,
4042

4143
keepOpenOnDateSelect: PropTypes.bool,
4244
reopenPickerOnClearDates: PropTypes.bool,
@@ -82,6 +84,7 @@ const defaultProps = {
8284
disabled: false,
8385
required: false,
8486
readOnly: false,
87+
openDirection: OPEN_DOWN,
8588

8689
keepOpenOnDateSelect: false,
8790
reopenPickerOnClearDates: false,
@@ -233,6 +236,7 @@ export default class DateRangePickerInputController extends React.Component {
233236
disabled,
234237
required,
235238
readOnly,
239+
openDirection,
236240
isFocused,
237241
phrases,
238242
onArrowDown,
@@ -261,6 +265,7 @@ export default class DateRangePickerInputController extends React.Component {
261265
disabled={disabled}
262266
required={required}
263267
readOnly={readOnly}
268+
openDirection={openDirection}
264269
showCaret={showCaret}
265270
showDefaultInputIcon={showDefaultInputIcon}
266271
customInputIcon={customInputIcon}

src/components/SingleDatePicker.jsx

+15-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import {
2828
VERTICAL_ORIENTATION,
2929
ANCHOR_LEFT,
3030
ANCHOR_RIGHT,
31+
OPEN_DOWN,
32+
OPEN_UP,
3133
DAY_SIZE,
3234
} from '../../constants';
3335

@@ -53,6 +55,7 @@ const defaultProps = {
5355
// calendar presentation and interaction related props
5456
orientation: HORIZONTAL_ORIENTATION,
5557
anchorDirection: ANCHOR_LEFT,
58+
openDirection: OPEN_DOWN,
5659
horizontalMargin: 0,
5760
withPortal: false,
5861
withFullScreenPortal: false,
@@ -216,11 +219,20 @@ export default class SingleDatePicker extends React.Component {
216219
}
217220

218221
getDayPickerContainerClasses() {
219-
const { orientation, withPortal, withFullScreenPortal, anchorDirection, isRTL } = this.props;
222+
const {
223+
orientation,
224+
withPortal,
225+
withFullScreenPortal,
226+
anchorDirection,
227+
openDirection,
228+
isRTL,
229+
} = this.props;
220230

221231
const dayPickerClassName = cx('SingleDatePicker__picker', {
222232
'SingleDatePicker__picker--direction-left': anchorDirection === ANCHOR_LEFT,
223233
'SingleDatePicker__picker--direction-right': anchorDirection === ANCHOR_RIGHT,
234+
'SingleDatePicker__picker--open-down': openDirection === OPEN_DOWN,
235+
'SingleDatePicker__picker--open-up': openDirection === OPEN_UP,
224236
'SingleDatePicker__picker--horizontal': orientation === HORIZONTAL_ORIENTATION,
225237
'SingleDatePicker__picker--vertical': orientation === VERTICAL_ORIENTATION,
226238
'SingleDatePicker__picker--portal': withPortal || withFullScreenPortal,
@@ -393,6 +405,7 @@ export default class SingleDatePicker extends React.Component {
393405
focused,
394406
required,
395407
readOnly,
408+
openDirection,
396409
showClearDate,
397410
showDefaultInputIcon,
398411
customInputIcon,
@@ -422,6 +435,7 @@ export default class SingleDatePicker extends React.Component {
422435
disabled={disabled}
423436
required={required}
424437
readOnly={readOnly}
438+
openDirection={openDirection}
425439
showCaret={!withPortal && !withFullScreenPortal}
426440
onClearDate={this.clearDate}
427441
showClearDate={showClearDate}

0 commit comments

Comments
 (0)