Skip to content

Commit

Permalink
style: fix range highlight
Browse files Browse the repository at this point in the history
  • Loading branch information
wildergd committed May 19, 2020
1 parent fa21005 commit 6130642
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 79 deletions.
50 changes: 33 additions & 17 deletions src/components/Calendar/day.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { Consumer } from './context';
import StyledDay from './styled/day';
import StyledDayAdjacent from './styled/dayAdjacent';
import StyledDayButton from './styled/dayButton';
import { isSameDay, compareDates } from './helpers';
import StyledRangeHighlight from './styled/rangeHighlight';
import { isSameDay, compareDates, isEmptyRange } from './helpers';

function DayComponent(props) {
const {
Expand All @@ -16,23 +17,30 @@ function DayComponent(props) {
maxDate,
onChange,
isWithinRange,
// isFirstDayOfWeek,
// isLastDayOfWeek,
isFirstDayOfWeek,
isLastDayOfWeek,
} = props;
const {
useAutoFocus,
focusedDate,
currentRange,
privateKeyDown,
privateOnFocus,
privateOnBlur,
privateOnHover,
// privateOnHover,
} = props;
const day = date.getDate();
const isAdjacentDate = date.getMonth() !== firstDayMonth.getMonth();
const isDisabled = compareDates(date, maxDate) > 0 || compareDates(date, minDate) < 0;
const tabIndex = isSameDay(focusedDate, date) ? 0 : -1;
const buttonRef = useRef();

const isRangeStartDate = !isEmptyRange(currentRange) ? isSameDay(date, currentRange[0]) : false;
const isRangeEndDate =
!isEmptyRange(currentRange) && currentRange.length >= 2
? isSameDay(date, currentRange[1])
: false;

useEffect(() => {
if (!useAutoFocus || !buttonRef.current || tabIndex === -1) return;
buttonRef.current.focus();
Expand All @@ -48,20 +56,28 @@ function DayComponent(props) {

return (
<StyledDay role="gridcell">
<StyledDayButton
ref={buttonRef}
tabIndex={tabIndex}
onClick={() => onChange(new Date(date))}
onMouseOver={() => privateOnHover(new Date(date))}
isSelected={isSelected}
data-selected={isSelected}
onKeyDown={privateKeyDown}
onFocus={privateOnFocus}
onBlur={privateOnBlur}
isWithinRange={isWithinRange}
<StyledRangeHighlight
isVisible={isWithinRange}
isFirstInRange={isRangeStartDate}
isLastInRange={isRangeEndDate}
isFirstDayOfWeek={isFirstDayOfWeek}
isLastDayOfWeek={isLastDayOfWeek}
>
{day}
</StyledDayButton>
<StyledDayButton
ref={buttonRef}
tabIndex={tabIndex}
onClick={() => onChange(new Date(date))}
// onMouseOver={() => privateOnHover(new Date(date))}
isSelected={isSelected}
data-selected={isSelected}
onKeyDown={privateKeyDown}
onFocus={privateOnFocus}
onBlur={privateOnBlur}
isWithinRange={isWithinRange}
>
{day}
</StyledDayButton>
</StyledRangeHighlight>
</StyledDay>
);
}
Expand Down
16 changes: 16 additions & 0 deletions src/components/Calendar/helpers/__test__/isEmptyRange.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import isEmptyRange from '../isEmptyRange';

describe('isEmptyRange', () => {
it('should return true', () => {
const ranges = [null, undefined, [], {}, 0, [undefined], [undefined, undefined]];
ranges.forEach(range => {
expect(isEmptyRange(range)).toBe(true);
});
});
it('should return false', () => {
const ranges = [[1], [1, 2]];
ranges.forEach(range => {
expect(isEmptyRange(range)).toBe(false);
});
});
});
1 change: 1 addition & 0 deletions src/components/Calendar/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export { default as isDateWithinRange } from './isDateWithinRange';
export { default as buildNewRangeFromValue } from './buildNewRangeFromValue';
export { default as shouldDateBeSelected } from './shouldDateBeSelected';
export { default as isSameDatesRange } from './isSameDatesRange';
export { default as isEmptyRange } from './isEmptyRange';
6 changes: 6 additions & 0 deletions src/components/Calendar/helpers/isEmptyRange.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default function isEmptyRange(range) {
if ([null, undefined, [], {}].includes(range)) return true;
if (!Array.isArray(range) || range.length === 0) return true;
const nullFilteredRange = range.filter(item => !!item);
return nullFilteredRange.length === 0;
}
1 change: 1 addition & 0 deletions src/components/Calendar/hooks/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as useCurrentDateFromValue } from './useCurrentDateFromValue';
export { default as useRangeFromValue } from './useRangeFromValue';
export { default as useDaysBuilder } from './useDaysBuilder';
55 changes: 55 additions & 0 deletions src/components/Calendar/hooks/useDaysBuilder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useMemo } from 'react';
import { addDays, shouldDateBeSelected, isDateWithinRange, isSameDay } from '../helpers';

export default function useDaysBuilder(Component, props) {
const {
startDate,
endDate,
firstDayMonth,
lastDayMonth,
minDate,
maxDate,
selectionType,
value,
selectedRange,
currentRange,
onChange,
} = props;
return useMemo(() => {
let date = new Date(startDate);
const days = [];

let index = 0;
while (date <= endDate) {
days.push(
<Component
date={date}
firstDayMonth={firstDayMonth}
key={date.getTime()}
minDate={minDate}
maxDate={maxDate}
onChange={onChange}
isSelected={shouldDateBeSelected(date, value, selectionType, selectedRange)}
isWithinRange={isDateWithinRange(date, currentRange)}
isFirstDayOfWeek={index === 0 || isSameDay(date, firstDayMonth)}
isLastDayOfWeek={index === 6 || isSameDay(date, lastDayMonth)}
/>,
);
date = addDays(date, 1);
index += 1;
}
return days;
}, [
currentRange,
endDate,
firstDayMonth,
lastDayMonth,
maxDate,
minDate,
onChange,
selectedRange,
selectionType,
startDate,
value,
]);
}
1 change: 1 addition & 0 deletions src/components/Calendar/month.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default function Month(props) {
minDate={minDate}
maxDate={maxDate}
firstDayMonth={firstDayMonth}
lastDayMonth={lastDayMonth}
key={date.getTime()}
onChange={onChange}
/>,
Expand Down
9 changes: 6 additions & 3 deletions src/components/Calendar/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ const calendarContainerStyles = {
import React from 'react';
import { Card, Calendar, Avatar } from 'react-rainbow-components';

initialState = { date: undefined };
initialState = { range: [
new Date(2019, 0, 1),
new Date(2019, 0, 19)
] };
const calendarContainerStyles = {
width: '28rem',
height: '27rem',
Expand All @@ -87,8 +90,8 @@ const calendarContainerStyles = {
<Card style={calendarContainerStyles} className="rainbow-p-around_large">
<Calendar
selectionType="range"
value={state.date}
onChange={value => setState({ date: value })}
value={state.range}
onChange={value => setState({ range: value })}
/>
</Card>
</div>
Expand Down
22 changes: 14 additions & 8 deletions src/components/Calendar/singleCalendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
isDateBeyondLimit,
getNextFocusedDate,
isSameDatesRange,
// isEmptyRange,
} from './helpers';
import StyledControlsContainer from './styled/controlsContainer';
import StyledMonthContainer from './styled/monthContainer';
Expand Down Expand Up @@ -89,7 +90,7 @@ class SingleCalendar extends Component {

this.onDayFocus = this.onDayFocus.bind(this);
this.onDayBlur = this.onDayBlur.bind(this);
this.onDayHover = this.onDayHover.bind(this);
// this.onDayHover = this.onDayHover.bind(this);
}

componentDidUpdate(prevProps) {
Expand All @@ -113,12 +114,17 @@ class SingleCalendar extends Component {
this.enableNavKeys = false;
}

// eslint-disable-next-line class-methods-use-this, no-unused-vars
onDayHover(date) {
// console.log(date, this.props);
// const { selectedRange } = this.props;
// this.setState({});
}
// onDayHover(date) {
// const { selectionType, selectedRange } = this.props;
// if (selectionType === 'single' || isEmptyRange(selectedRange)) return;

// const [rangeStart, rangeEnd] = selectedRange;
// if (rangeEnd !== undefined) return;

// this.setState({
// currentRange: [rangeStart, date],
// });
// }

getContext() {
const { focusedDate, currentRange } = this.state;
Expand All @@ -132,7 +138,7 @@ class SingleCalendar extends Component {
privateKeyDown: this.handleKeyDown,
privateOnFocus: this.onDayFocus,
privateOnBlur: this.onDayBlur,
privateOnHover: this.onDayHover,
// privateOnHover: this.onDayHover,
};
}

Expand Down
18 changes: 0 additions & 18 deletions src/components/Calendar/styled/dayButton.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import styled from 'styled-components';
import { FONT_SIZE_TEXT_MEDIUM } from '../../../styles/fontSizes';
import attachThemeAttrs from '../../../styles/helpers/attachThemeAttrs';
import { replaceAlpha } from '../../../styles/helpers/color';

const StyledDayButton = attachThemeAttrs(styled.button)`
font: inherit;
Expand All @@ -13,7 +12,6 @@ const StyledDayButton = attachThemeAttrs(styled.button)`
line-height: 38px;
height: 38px;
width: 38px;
margin: 6px auto;
box-sizing: border-box;
cursor: pointer;
color: inherit;
Expand All @@ -38,10 +36,6 @@ const StyledDayButton = attachThemeAttrs(styled.button)`
line-height: 36px;
}
@media (max-width: 600px) {
margin: 3px auto;
}
${props =>
props.isSelected &&
`
Expand All @@ -54,7 +48,6 @@ const StyledDayButton = attachThemeAttrs(styled.button)`
line-height: 36px;
height: 38px;
width: 38px;
margin: 5px auto;
padding: 0;
border: none;
outline: none;
Expand All @@ -71,17 +64,6 @@ const StyledDayButton = attachThemeAttrs(styled.button)`
&:focus {
box-shadow: 0 0 8px ${props.palette.brand.main};
}
@media (max-width: 600px) {
margin: 3px auto;
}
`};
${props =>
props.isWithinRange &&
!props.isSelected &&
`
background-color: ${replaceAlpha(props.palette.brand.light, 1)};
`};
`;

Expand Down
71 changes: 71 additions & 0 deletions src/components/Calendar/styled/rangeHighlight.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import styled from 'styled-components';
import attachThemeAttrs from '../../../styles/helpers/attachThemeAttrs';

const StyledRangeHighlight = attachThemeAttrs(styled.div).attrs(props => {
const gradientStart = props.palette.brand.light;
const gradientEnd = props.palette.background.main;

return {
gradientStart,
gradientEnd,
};
})`
height: 38px;
line-height: 38px;
margin: 5px auto;
@media (max-width: 600px) {
margin: 3px auto;
}
${props =>
props.isVisible &&
`
background: ${props.gradientStart};
`};
${props =>
props.isVisible &&
props.isFirstDayOfWeek &&
`
background: linear-gradient(
to left,
${props.gradientStart},
${props.gradientEnd}
);
`};
${props =>
props.isVisible &&
props.isLastDayOfWeek &&
`
background: linear-gradient(
to right,
${props.gradientStart},
${props.gradientEnd}
);
`};
${props =>
props.isVisible &&
props.isFirstInRange &&
`
background: linear-gradient(
to left,
${props.gradientStart},
${props.gradientEnd} 60%,
${props.gradientEnd}
);
`};
${props =>
props.isVisible &&
props.isLastInRange &&
`
background: linear-gradient(
to right,
${props.gradientStart},
${props.gradientEnd} 60%,
${props.gradientEnd}
);
`};
`;

export default StyledRangeHighlight;
Loading

0 comments on commit 6130642

Please sign in to comment.