Skip to content

Commit

Permalink
Add directionAnchor prop to allow right-aligned Components
Browse files Browse the repository at this point in the history
DateRangePicker and SingleDatePicker have a new prop, directionAnchor
that will align the components to the left/right side of the page.
This prop has two new constants, DIRECTION_ANCHOR_LEFT (default)
and DIRECTION_ANCHOR_RIGHT.
  • Loading branch information
Travis Bloom authored and travisbloom committed Oct 8, 2016
1 parent 8c03d77 commit fde2a41
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 25 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ The `orientation` prop indicates whether months are stacked on top of each other
orientation: PropTypes.oneOf([HORIZONTAL_ORIENTATION, VERTICAL_ORIENTATION])
```
The `anchorDirection` prop indicates whether the calendar is anchored to the right or left side of the input. You can import the `ANCHOR_LEFT` and `ANCHOR_RIGHT` constants from `react-dates/constants`. Defaults to `ANCHOR_LEFT`.
```
direction: PropTypes.oneOf([ANCHOR_LEFT, ANCHOR_RIGHT])
```
`withPortal` was designed for use on mobile devices. Namely, if this prop is set to true, the `DayPicker` will be rendered centrally on the screen, above the current plane, with a transparent black background behind it. Clicking on the background will hide the `DayPicker`. This option is currently only available for a `DateRangePicker` with a horizontal orientation.
```
withPortal: PropTypes.bool
Expand Down
5 changes: 4 additions & 1 deletion constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ module.exports = {
END_DATE: 'endDate',

HORIZONTAL_ORIENTATION: 'horizontal',
VERTICAL_ORIENTATION: 'vertical'
VERTICAL_ORIENTATION: 'vertical',

ANCHOR_LEFT: 'left',
ANCHOR_RIGHT: 'right',
};
43 changes: 31 additions & 12 deletions css/DateRangePicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
z-index: 1;
position: absolute;
top: 145%;
left: 0;

&::before,
&::after {
Expand All @@ -32,6 +31,14 @@
}
}

.DateRangePicker__picker--direction-left {
left: 0;
}

.DateRangePicker__picker--direction-right {
right: 0;
}

.DateRangePicker__picker--show {
visibility: visible;
}
Expand All @@ -55,34 +62,46 @@

.DateRangePicker__picker--start::before,
.DateRangePicker__picker--end::before {
top: -10px;
border: 10px solid transparent;
top: -$react-dates-width-tooltip-arrow / 2;
border: $react-dates-width-tooltip-arrow / 2 solid transparent;
border-top: 0;
border-bottom-color: rgba(0, 0, 0, 0.1);
}

.DateRangePicker__picker--start::before {
.DateRangePicker__picker--direction-left.DateRangePicker__picker--start::before {
left: 22px;
}
.DateRangePicker__picker--direction-right.DateRangePicker__picker--start::before {
right: $react-dates-width-input + $react-dates-width-arrow + 22px;
}

.DateRangePicker__picker--end::before {
left: 162px;
.DateRangePicker__picker--direction-left.DateRangePicker__picker--end::before {
left: $react-dates-width-arrow + $react-dates-width-input + 22px;
}
.DateRangePicker__picker--direction-right.DateRangePicker__picker--end::before {
right: 22px;
}

.DateRangePicker__picker--start::after,
.DateRangePicker__picker--end::after {
top: -9px;
border: 9px solid transparent;
top: -$react-dates-width-tooltip-arrow / 2;
border: $react-dates-width-tooltip-arrow / 2 solid transparent;
border-top: 0;
border-bottom-color: $react-dates-color-white;
}

.DateRangePicker__picker--start::after {
.DateRangePicker__picker--direction-left.DateRangePicker__picker--start::after {
left: 23px;
}
.DateRangePicker__picker--direction-right.DateRangePicker__picker--start::after {
right: $react-dates-width-input + $react-dates-width-arrow + 23px;
}

.DateRangePicker__picker--end::after {
left: 163px;
.DateRangePicker__picker--direction-left.DateRangePicker__picker--end::after {
left: $react-dates-width-arrow + $react-dates-width-input + 23px;
}
.DateRangePicker__picker--direction-right.DateRangePicker__picker--end::after {
right: 23px;
}

.DateRangePicker__close {
Expand Down Expand Up @@ -112,4 +131,4 @@
color: darken(#cacccd, 10%);
text-decoration: none;
}
}
}
4 changes: 2 additions & 2 deletions css/DateRangePickerInput.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
.DateRangePickerInput__arrow svg {
vertical-align: middle;
fill: $react-dates-color-text;
height: 24px;
width: 24px;
height: $react-dates-width-arrow;
width: $react-dates-width-arrow;
}

.DateRangePickerInput__clear-dates {
Expand Down
23 changes: 20 additions & 3 deletions css/SingleDatePicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
z-index: 1;
position: absolute;
top: 145%;
left: 0;

&::before,
&::after {
Expand All @@ -25,18 +24,36 @@
border: 10px solid transparent;
border-top: 0;
border-bottom-color: rgba(0, 0, 0, 0.1);
left: 22px;
}

&::after {
top: -9px;
border: 9px solid transparent;
border-top: 0;
border-bottom-color: #fff;
left: 23px;
}
}

.SingleDatePicker__picker--direction-left {
left: 0;
&::before {
left: 22px;
}
&::after {
left: 23px;
}
}

.SingleDatePicker__picker--direction-right {
right: 0;
&::before {
right: 22px;
}
&::after {
right: 23px;
}
}

.SingleDatePicker__picker--show {
visibility: visible;
}
Expand Down
2 changes: 2 additions & 0 deletions css/variables.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
$react-dates-width-input: 130px !default;
$react-dates-width-arrow: 24px !default;
$react-dates-width-tooltip-arrow: 20px !default;
$react-dates-width-day-picker: 300px !default;

$react-dates-color-primary: #00a699 !default;
Expand Down
13 changes: 12 additions & 1 deletion src/components/DateRangePicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
END_DATE,
HORIZONTAL_ORIENTATION,
VERTICAL_ORIENTATION,
ANCHOR_LEFT,
ANCHOR_RIGHT,
} from '../../constants';

const propTypes = DateRangePickerShape;
Expand All @@ -46,6 +48,7 @@ const defaultProps = {
reopenPickerOnClearDates: false,

orientation: HORIZONTAL_ORIENTATION,
anchorDirection: ANCHOR_LEFT,
withPortal: false,
withFullScreenPortal: false,

Expand Down Expand Up @@ -210,11 +213,19 @@ export default class DateRangePicker extends React.Component {
}

getDayPickerContainerClasses() {
const { focusedInput, orientation, withPortal, withFullScreenPortal } = this.props;
const {
focusedInput,
orientation,
withPortal,
withFullScreenPortal,
anchorDirection,
} = this.props;
const { hoverDate } = this.state;
const showDatepicker = focusedInput === START_DATE || focusedInput === END_DATE;

const dayPickerClassName = cx('DateRangePicker__picker', {
'DateRangePicker__picker--direction-left': anchorDirection === ANCHOR_LEFT,
'DateRangePicker__picker--direction-right': anchorDirection === ANCHOR_RIGHT,
'DateRangePicker__picker--show': showDatepicker,
'DateRangePicker__picker--invisible': !showDatepicker,
'DateRangePicker__picker--start': focusedInput === START_DATE,
Expand Down
12 changes: 10 additions & 2 deletions src/components/SingleDatePicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ import isSameDay from '../utils/isSameDay';

import SingleDatePickerShape from '../shapes/SingleDatePickerShape';

import { HORIZONTAL_ORIENTATION, VERTICAL_ORIENTATION } from '../../constants';
import {
HORIZONTAL_ORIENTATION,
VERTICAL_ORIENTATION,
ANCHOR_LEFT,
ANCHOR_RIGHT,
} from '../../constants';

const propTypes = SingleDatePickerShape;

Expand All @@ -36,6 +41,7 @@ const defaultProps = {
enableOutsideDays: false,
numberOfMonths: 2,
orientation: HORIZONTAL_ORIENTATION,
anchorDirection: ANCHOR_LEFT,
withPortal: false,
withFullScreenPortal: false,

Expand Down Expand Up @@ -121,12 +127,14 @@ export default class SingleDatePicker extends React.Component {
}

getDayPickerContainerClasses() {
const { focused, orientation, withPortal, withFullScreenPortal } = this.props;
const { focused, orientation, withPortal, withFullScreenPortal, anchorDirection } = this.props;
const { hoverDate } = this.state;

const dayPickerClassName = cx('SingleDatePicker__picker', {
'SingleDatePicker__picker--show': focused,
'SingleDatePicker__picker--invisible': !focused,
'SingleDatePicker__picker--direction-left': anchorDirection === ANCHOR_LEFT,
'SingleDatePicker__picker--direction-right': anchorDirection === ANCHOR_RIGHT,
'SingleDatePicker__picker--horizontal': orientation === HORIZONTAL_ORIENTATION,
'SingleDatePicker__picker--vertical': orientation === VERTICAL_ORIENTATION,
'SingleDatePicker__picker--portal': withPortal || withFullScreenPortal,
Expand Down
8 changes: 8 additions & 0 deletions src/shapes/AnchorDirectionShape.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { PropTypes } from 'react';

import {
ANCHOR_LEFT,
ANCHOR_RIGHT,
} from '../../constants';

export default PropTypes.oneOf([ANCHOR_LEFT, ANCHOR_RIGHT]);
3 changes: 2 additions & 1 deletion src/shapes/DateRangePickerShape.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import momentPropTypes from 'react-moment-proptypes';

import FocusedInputShape from '../shapes/FocusedInputShape';
import OrientationShape from '../shapes/OrientationShape';
import anchorDirectionShape from '../shapes/AnchorDirectionShape';

export default {
startDate: momentPropTypes.momentObj,
Expand All @@ -18,7 +19,7 @@ export default {
disabled: PropTypes.bool,

orientation: OrientationShape,

anchorDirection: anchorDirectionShape,
// portal options
withPortal: PropTypes.bool,
withFullScreenPortal: PropTypes.bool,
Expand Down
2 changes: 2 additions & 0 deletions src/shapes/SingleDatePickerShape.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { PropTypes } from 'react';
import momentPropTypes from 'react-moment-proptypes';

import OrientationShape from '../shapes/OrientationShape';
import anchorDirectionShape from '../shapes/AnchorDirectionShape';

export default {
id: PropTypes.string.isRequired,
Expand All @@ -18,6 +19,7 @@ export default {
enableOutsideDays: PropTypes.bool,
numberOfMonths: PropTypes.number,
orientation: OrientationShape,
anchorDirection: anchorDirectionShape,

// portal options
withPortal: PropTypes.bool,
Expand Down
17 changes: 16 additions & 1 deletion stories/DateRangePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import moment from 'moment';
import { storiesOf } from '@kadira/storybook';

import { VERTICAL_ORIENTATION } from '../constants';
import { VERTICAL_ORIENTATION, ANCHOR_RIGHT } from '../constants';

import isSameDay from '../src/utils/isSameDay';
import isInclusivelyAfterDay from '../src/utils/isInclusivelyAfterDay';
Expand All @@ -29,11 +29,26 @@ storiesOf('DateRangePicker', module)
numberOfMonths={1}
/>
))
.add('anchored right', () => (
<div style={{ float: 'right' }}>
<DateRangePickerWrapper
anchorDirection={ANCHOR_RIGHT}
/>
</div>
))
.add('vertical', () => (
<DateRangePickerWrapper
orientation={VERTICAL_ORIENTATION}
/>
))
.add('vertical anchored right', () => (
<div style={{ float: 'right' }}>
<DateRangePickerWrapper
orientation={VERTICAL_ORIENTATION}
anchorDirection={ANCHOR_RIGHT}
/>
</div>
))
.add('horizontal with portal', () => (
<DateRangePickerWrapper
withPortal
Expand Down
9 changes: 8 additions & 1 deletion stories/SingleDatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { storiesOf } from '@kadira/storybook';

import SingleDatePickerWrapper from '../examples/SingleDatePickerWrapper';

import { VERTICAL_ORIENTATION } from '../constants';
import { VERTICAL_ORIENTATION, ANCHOR_RIGHT } from '../constants';

storiesOf('SingleDatePicker', module)
.add('default', () => (
Expand All @@ -15,6 +15,13 @@ storiesOf('SingleDatePicker', module)
numberOfMonths={1}
/>
))
.add('anchored right', () => (
<div style={{ float: 'right' }}>
<SingleDatePickerWrapper
anchorDirection={ANCHOR_RIGHT}
/>
</div>
))
.add('vertical', () => (
<SingleDatePickerWrapper
orientation={VERTICAL_ORIENTATION}
Expand Down
16 changes: 16 additions & 0 deletions test/components/DateRangePicker_spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
VERTICAL_ORIENTATION,
START_DATE,
END_DATE,
ANCHOR_LEFT,
ANCHOR_RIGHT,
} from '../../constants';

const today = moment().startOf('day');
Expand Down Expand Up @@ -69,6 +71,20 @@ describe('DateRangePicker', () => {
});
});

describe('props.anchorDirection === ANCHOR_LEFT', () => {
it('renders .DateRangePicker__picker--direction-left class', () => {
const wrapper = shallow(<DateRangePicker anchorDirection={ANCHOR_LEFT} />);
expect(wrapper.find('.DateRangePicker__picker--direction-left')).to.have.length(1);
});
});

describe('props.orientation === ANCHOR_RIGHT', () => {
it('renders .DateRangePicker__picker--direction-right class', () => {
const wrapper = shallow(<DateRangePicker anchorDirection={ANCHOR_RIGHT} />);
expect(wrapper.find('.DateRangePicker__picker--direction-right')).to.have.length(1);
});
});

describe('props.withPortal is truthy', () => {
it('renders .DateRangePicker__picker--portal class', () => {
const wrapper = shallow(<DateRangePicker withPortal />);
Expand Down
Loading

0 comments on commit fde2a41

Please sign in to comment.