Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[datetime] feat(DatePicker): add option to highlight current day #3628

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions packages/datetime/src/_datepicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ $header-margin: ($header-height - $pt-input-height) / 2 !default;
}
}

.#{$ns}-datepicker-day-wrapper {
border-radius: $pt-border-radius;
padding: 7px;
}

.DayPicker-Month {
display: inline-table;
margin: 0 $datepicker-padding $datepicker-padding;
Expand Down Expand Up @@ -97,6 +102,12 @@ $header-margin: ($header-height - $pt-input-height) / 2 !default;
color: $pt-text-color-disabled;
}

&.DayPicker-Day--isToday {
.#{$ns}-datepicker-day-wrapper {
border: 1px solid $pt-divider-black;
}
}

&:hover,
&:focus {
background: $datepicker-day-background-color-hover;
Expand Down Expand Up @@ -196,6 +207,12 @@ $header-margin: ($header-height - $pt-input-height) / 2 !default;
color: $pt-dark-text-color-disabled;
}

&.DayPicker-Day--isToday {
.#{$ns}-datepicker-day-wrapper {
border: 1px solid $pt-dark-divider-white;
}
}

&:hover,
&:focus {
background: $dark-datepicker-day-background-color-hover;
Expand Down
2 changes: 2 additions & 0 deletions packages/datetime/src/common/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export const DATEPICKER_DAY = "DayPicker-Day";
export const DATEPICKER_DAY_DISABLED = `${DATEPICKER_DAY}--disabled`;
export const DATEPICKER_DAY_OUTSIDE = `${DATEPICKER_DAY}--outside`;
export const DATEPICKER_DAY_SELECTED = `${DATEPICKER_DAY}--selected`;
export const DATEPICKER_DAY_IS_TODAY = `${DATEPICKER_DAY}--isToday`;
export const DATEPICKER_DAY_WRAPPER = `${DATEPICKER}-day-wrapper`;
export const DATEPICKER_FOOTER = `${DATEPICKER}-footer`;
export const DATEPICKER_MONTH_SELECT = `${DATEPICKER}-month-select`;
export const DATEPICKER_YEAR_SELECT = `${DATEPICKER}-year-select`;
Expand Down
44 changes: 33 additions & 11 deletions packages/datetime/src/datePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ export interface IDatePickerProps extends IDatePickerBaseProps, IProps {
*/
defaultValue?: Date;

/**
* Whether the current day should be highlighted in the calendar.
* @default false
*/
highlightCurrentDay?: boolean;

/**
* Called when the user selects a day.
* If being used in an uncontrolled manner, `selectedDate` will be `null` if the user clicks the currently selected
Expand Down Expand Up @@ -95,6 +101,7 @@ export class DatePicker extends AbstractPureComponent<IDatePickerProps, IDatePic
canClearSelection: true,
clearButtonText: "Clear",
dayPickerProps: {},
highlightCurrentDay: false,
maxDate: getDefaultMaxDate(),
minDate: getDefaultMinDate(),
reverseMonthAndYearMenus: false,
Expand All @@ -120,16 +127,7 @@ export class DatePicker extends AbstractPureComponent<IDatePickerProps, IDatePic
}

public render() {
const {
className,
dayPickerProps,
locale,
localeUtils,
maxDate,
minDate,
modifiers,
showActionsBar,
} = this.props;
const { className, dayPickerProps, locale, localeUtils, maxDate, minDate, showActionsBar } = this.props;
const { displayMonth, displayYear } = this.state;

return (
Expand All @@ -138,7 +136,7 @@ export class DatePicker extends AbstractPureComponent<IDatePickerProps, IDatePic
showOutsideDays={true}
locale={locale}
localeUtils={localeUtils}
modifiers={modifiers}
modifiers={this.getDatePickerModifiers()}
{...dayPickerProps}
canChangeMonth={true}
captionElement={this.renderCaption}
Expand All @@ -150,6 +148,7 @@ export class DatePicker extends AbstractPureComponent<IDatePickerProps, IDatePic
onMonthChange={this.handleMonthChange}
selectedDays={this.state.value}
toMonth={maxDate}
renderDay={this.renderDay}
/>
{this.maybeRenderTimePicker()}
{showActionsBar && this.renderOptionsBar()}
Expand Down Expand Up @@ -195,6 +194,29 @@ export class DatePicker extends AbstractPureComponent<IDatePickerProps, IDatePic
}
}

private isToday = (date: Date) => DateUtils.areSameDay(date, new Date());

private shouldHighlightCurrentDay = (date: Date) => {
const { highlightCurrentDay } = this.props;

return highlightCurrentDay && this.isToday(date);
};

private getDatePickerModifiers = () => {
const { modifiers } = this.props;

return {
isToday: this.shouldHighlightCurrentDay,
...modifiers,
};
};

private renderDay = (day: Date) => {
const date = day.getDate();

return <div className={Classes.DATEPICKER_DAY_WRAPPER}>{date}</div>;
};

private disabledDays = (day: Date) => !DateUtils.isDayInRange(day, [this.props.minDate, this.props.maxDate]);

private getDisabledDaysModifier = () => {
Expand Down
10 changes: 10 additions & 0 deletions packages/datetime/test/datePickerTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ describe("<DatePicker>", () => {
assert.isNull(root.state("selectedDay"));
});

it("current day is not highlighted by default", () => {
const { root } = wrap(<DatePicker />);
assert.lengthOf(root.find(`.${Classes.DATEPICKER_DAY_IS_TODAY}`), 0);
});

it("current day should be highlighted when highlightCurrentDay={true}", () => {
const { root } = wrap(<DatePicker highlightCurrentDay={true} />);
assert.lengthOf(root.find(`.${Classes.DATEPICKER_DAY_IS_TODAY}`), 1);
});

describe("reconciliates dayPickerProps", () => {
it("week starts with firstDayOfWeek value", () => {
const selectedFirstDay = 3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { PrecisionSelect } from "./common/precisionSelect";

export interface IDatePickerExampleState {
date: Date | null;
highlightCurrentDay: boolean;
reverseMonthAndYearMenus: boolean;
showActionsBar: boolean;
timePrecision: TimePrecision | undefined;
Expand All @@ -32,11 +33,13 @@ export interface IDatePickerExampleState {
export class DatePickerExample extends React.PureComponent<IExampleProps, IDatePickerExampleState> {
public state: IDatePickerExampleState = {
date: null,
highlightCurrentDay: false,
reverseMonthAndYearMenus: false,
showActionsBar: false,
timePrecision: undefined,
};

private toggleHighlight = handleBooleanChange(highlightCurrentDay => this.setState({ highlightCurrentDay }));
private toggleActionsBar = handleBooleanChange(showActionsBar => this.setState({ showActionsBar }));
private toggleReverseMenus = handleBooleanChange(reverse => this.setState({ reverseMonthAndYearMenus: reverse }));
private handlePrecisionChange = handleStringChange((p: TimePrecision | "none") =>
Expand All @@ -50,6 +53,11 @@ export class DatePickerExample extends React.PureComponent<IExampleProps, IDateP
<>
<H5>Props</H5>
<Switch checked={props.showActionsBar} label="Show actions bar" onChange={this.toggleActionsBar} />
<Switch
checked={props.highlightCurrentDay}
label="Highlight current day"
onChange={this.toggleHighlight}
/>
<Switch
checked={props.reverseMonthAndYearMenus}
label="Reverse month and year menus"
Expand Down