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

Focus/Selectable state on DayPicker? #82

Closed
JimmyMultani opened this issue Sep 13, 2016 · 7 comments
Closed

Focus/Selectable state on DayPicker? #82

JimmyMultani opened this issue Sep 13, 2016 · 7 comments

Comments

@JimmyMultani
Copy link

JimmyMultani commented Sep 13, 2016

Hello,

I was wondering if there was a way to have a selectable/focusable state when the user clicks on a date in the <DayPicker /> component?

For example, the <DateRangePicker /> component has a focus prop, but it doesn't seem like it's possible with the <DayPicker />.

Thanks.

@majapw
Copy link
Collaborator

majapw commented Sep 13, 2016

Hi @JimmyMultani, I don't think I fully understand the question (I think it may have gotten cut off). Can you clarify?

@JimmyMultani
Copy link
Author

Hey @majapw,

Sorry about that. I've fixed my initial post.

@majapw
Copy link
Collaborator

majapw commented Sep 16, 2016

Ah I see. So what it seems like you are looking for from this issue and from #81 is that you are looking for something like a SingleDatePicker but without the input and with the calendar always visible. So we don't provide any components right now that do this for you so you'd have to implement it yourself using the modifiers and the day event handlers.

You could build something as follows:

import React, { PropTypes } from 'react';
import { DayPicker, isSameDay } from 'react-dates';
import includes from 'array-includes';

export default class DayPickerWrapper extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      hoverDate: null,
      selectedDate: null,
    };

    this.handleDayMouseEnter = this.handleDayMouseEnter.bind(this);
    this.handleDayMouseLeave = this.handleDayMouseLeave.bind(this);
    this.handleDayClick = this.handleDayClick.bind(this);
  }

  handleDayMouseEnter(day) {
    this.setState({
      hoverDate: day,
    });
  }

  handleDayMouseLeave() {
    this.setState({
      hoverDate: null,
    });
  }

  handleDayClick(day, modifiers, e) {
    if (includes(modifiers, 'blocked')) return;

    this.setState({
      selectedDate: day,
    });
  }

  isBlocked(day) {
    const { isDayBlocked, isOutsideRange } = this.props;
    return isDayBlocked(day) || isOutsideRange(day);
  }

  isSelectedDate(day) {
    return isSameDay(day, this.state.selectedDate);
  }

  isHovered(day) {
    return isSameDay(day, this.state.hoverDate);
  }

  render() {
    const {
      isDayBlocked,
      isOutsideRange,
    } = this.props;

    const modifiers = {
      blocked: day => this.isBlocked(day),
      'blocked-calendar': day => isDayBlocked(day),
      'blocked-out-of-range': day => isOutsideRange(day),
      valid: day => !this.isBlocked(day),
      hovered: day => this.isHovered(day),
      selected: day => this.isSelected(day),
    };

    return (
      <DayPicker
        ref="DayPicker"
        modifiers={modifiers}
        numberOfMonths={1}
        onDayMouseEnter={this.handleMouseEnter}
        onDayMouseLeave={this.handleMouseLeave}
        onDayClick={this.handleDayClick}
      />
    );
  }
}

It might make sense to include this kind of component in the repo... but we pretty much always need the input. Right now, we don't yet have keyboard navigation on the calendar itself so for us this implementation won't even be technically usable until we make that a reality. Let me know if this helps!

@JimmyMultani
Copy link
Author

JimmyMultani commented Sep 16, 2016

Hey @majapw,

Yes, your code example explains it really well!

Thank you so much!

@chellberg
Copy link

In case it helps anyone, I found a slightly simpler (possibly inferior) workaround for disabling days on the DayPicker:

<DayPicker
  modifiers={{
    past: day => day.isBefore(moment()),
  }}
/>
td.CalendarMonth__day--past {
  pointer-events: none;
}

source

@DarrylD
Copy link

DarrylD commented Feb 18, 2017

A quick modification to @chellberg to make the non-selectable days apparent and allow the current day to be selected

past: day => day.isBefore( moment().subtract(1, 'day') )
td.CalendarMonth__day--past {
  pointer-events: none;
  opacity: .2;
}

@webdevfrancisco
Copy link

A quick modification to @chellberg to make the non-selectable days apparent and allow the current day to be selected

past: day => day.isBefore( moment().subtract(1, 'day') )
td.CalendarMonth__day--past {
  pointer-events: none;
  opacity: .2;
}

this no longer works, I'm on version ^21.8.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants