Skip to content

Instantly share code, notes, and snippets.

@igoro00
Forked from baumandm/Chakra-UI x React-datepicker.md
Last active September 20, 2024 18:56
Show Gist options
  • Save igoro00/99e9d244677ccafbf39667c24b5b35ed to your computer and use it in GitHub Desktop.
Save igoro00/99e9d244677ccafbf39667c24b5b35ed to your computer and use it in GitHub Desktop.
Chakra-UI x React-datepicker

Tiny wrapper component for React-Datepicker to stylistically fit with Chakra-UI 1.x.

<DatePicker selectedDate={myDate} onChange={(d) => console.log(d)} />

Clearable version:

<DatePicker selectedDate={myDate} onChange={(d) => console.log(d)} isClearable={true} />

The HTMLAttributes interface is included to support passing additional properties like id, className, aria-*, etc., for example:

<FormControl>
  <FormLabel htmlFor="published-date">Published Date</FormLabel>
  <DatePicker
    id="published-date"
    selectedDate={publishedDate}
    onChange={onChange}
    showPopperArrow={true}
  />
  <FormHelperText>Date this widget was published</FormHelperText>
</FormControl>

Adapted from this comment

.light-theme{
--light-gray: var(--chakra-colors-gray-200);
--gray: var(--chakra-colors-gray-300);
--blue700:var(--chakra-colors-blue-600);
--blue600: var(--chakra-colors-blue-500);
--blue500: var(--chakra-colors-gray-400);
--blue400: var(--chakra-colors-gray-300);
--blue300: var(--chakra-colors-gray-200);
--blue200: var(--chakra-colors-gray-200);
--blue100: var(--chakra-colors-gray-100);
--monthBackground: var(--chakra-colors-white);
--text:var(--chakra-colors-black);
--negative-text:var(--chakra-colors-white);
}
.dark-theme{
--light-gray: var(--chakra-colors-gray-600);
--gray: var(--chakra-colors-gray-500);
--blue700: var(--chakra-colors-blue-600);
--blue600: var(--chakra-colors-blue-300);
--blue500: var(--chakra-colors-gray-500);
--blue400: var(--chakra-colors-gray-600);
--blue300: var(--chakra-colors-gray-700);
--blue200: var(--chakra-colors-gray-600);
--blue100: var(--chakra-colors-gray-800);
--monthBackground: var(--chakra-colors-gray-700);
--text:var(--chakra-colors-gray-200);
--negative-text:var(--chakra-colors-black);
}
/* if you dont want to use chakra's theme use this class in the wrapping div. These are the exact original values */
.light-theme-original{
--light-gray: #cccccc;
--gray: #b3b3b3;
--blue700:#2a69ac;
--blue600: #3182ce;
--blue500: #a0aec0;
--blue400: #cbd5e0;
--blue300: #e2e8f0;
--blue200: #edf2f7;
--blue100: #f7fafc;
}
.react-datepicker {
font-family: unset;
font-size: 0.9rem;
border-color: var(--light-gray);
}
.react-datepicker-wrapper,
.react-datepicker__input-container {
display: block;
}
.react-datepicker__input-container {
font-size: 1rem;
padding-left: 1rem;
padding-right: 1rem;
height: 2.5rem;
border-radius: 0.25rem;
border: 1px solid;
border-color: var(--light-gray);
}
.react-datapicker__input-text {
background-color: transparent;
}
.react-datepicker__input-container:hover {
border-color: var(--gray)
}
.react-datepicker__input-container:focus-within {
z-index: 1;
border-color: var(--blue600);
box-shadow: 0 0 0 1px var(--blue600);
}
.react-datepicker__input-container > input {
width: 100%;
height: 100%;
outline: 0;
}
.react-datepicker__navigation--next--with-time:not(.react-datepicker__navigation--next--with-today-button) {
right: 90px;
}
.react-datepicker__navigation--previous,
.react-datepicker__navigation--next {
height: 8px;
}
.react-datepicker__navigation--previous {
border-right-color: var(--blue400);
}
.react-datepicker__navigation--previous:hover {
border-right-color: var(--blue500);
}
.react-datepicker__navigation--next {
border-left-color: var(--blue400);
}
.react-datepicker__navigation--next:hover {
border-left-color: var(--blue500);
}
.react-datepicker__header {
background-color: var(--blue100);
}
.react-datepicker__header,
.react-datepicker__time-container {
border-color: var(--blue300);
}
.react-datepicker__current-month,
.react-datepicker-time__header,
.react-datepicker-year-header {
font-size: inherit;
font-weight: 600;
color: var(--text)
}
.react-datepicker__month{
background-color: var(--monthBackground);
margin:0;
padding:0.4rem;
}
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item {
margin: 0 1px 0 0;
height: auto;
padding: 7px 10px;
}
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item:hover {
background: var(--blue200);
}
.react-datepicker__day {
color: var(--text)
}
.react-datepicker__day:hover {
background: var(--blue200);
}
.react-datepicker__day-name {
color:var(--text)
}
.react-datepicker__day--selected,
.react-datepicker__day--in-selecting-range,
.react-datepicker__day--in-range,
.react-datepicker__month-text--selected,
.react-datepicker__month-text--in-selecting-range,
.react-datepicker__month-text--in-range,
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected {
background: var(--blue600);
font-weight: normal;
color:var(--negative-text);
}
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected:hover {
background: var(--blue700);
}
.react-datepicker__close-icon::after {
background-color: unset;
border-radius: unset;
font-size: 1.5rem;
font-weight: bold;
color: var(--light-gray);
height: 20px;
width: 20px;
}
.react-datepicker__close-icon::after:hover {
color: var(--gray)
}
import React, { HTMLAttributes } from 'react';
import ReactDatePicker from 'react-datepicker';
import { useColorMode } from '@chakra-ui/react';
import 'react-datepicker/dist/react-datepicker.css';
import './date-picker.css';
interface Props {
isClearable?: boolean;
onChange: (date: Date) => any;
selectedDate: Date | undefined;
showPopperArrow?: boolean;
}
const DatePicker = ({
selectedDate,
onChange,
isClearable = false,
showPopperArrow = false,
...props
}: Props & HTMLAttributes<HTMLElement>) => {
const isLight = useColorMode().colorMode==='light';//you can check what theme you are using right now however you want
return (
// if you don't want to use chakra's colors or you just wwant to use the original ones,
// set className to "light-theme-original" ↓↓↓↓
<div className={isLight?"light-theme":"dark-theme"}>
<ReactDatePicker
selected={selectedDate}
onChange={onChange}
isClearable={isClearable}
showPopperArrow={showPopperArrow}
className="react-datapicker__input-text"//input is white by default and there is no already defined class for it so I created a new one
{...props}
/>
</div>
);
};
export default DatePicker;
@cosletmihai
Copy link

Hey, cool upgrade on this implementation.
I noticed and can't yet figure out why, when you select the date and the dropdown appears, the selected date is not "selected".
image
When I move to another month, the date gets "selected".
image
What do you think could be the issue?

@igoro00
Copy link
Author

igoro00 commented Mar 15, 2021

@cosletmihai thanks! It's my first open source contribution that someone actually uses.
I don't have an idea what could be the problem here. It works fine in my project(.tsx and .css files are the same as in this gist, I copied the original to my project, added the dark theme etc and uploaded everything to github as it is).
Also in your second screenshot the 18th April cell should have white text on blue background. Maybe some of your other css is causing this problem? Are you using the default chakra theme or a custom theme? Because it should look like this:
image

@demarchenac
Copy link

Hi! this can be implemented as a .jsx right?

@Bubblesphere
Copy link

If you're using Typescript, you can yarn add --dev @types/react-datepicker and use this component instead

import React from "react";
import ReactDatePicker, { ReactDatePickerProps } from "react-datepicker";
import { useColorMode } from "@chakra-ui/react";

const DatePicker = ({ ...props }: ReactDatePickerProps) => {
  const isLight = useColorMode().colorMode === "light"; //you can check what theme you are using right now however you want
  return (
    // if you don't want to use chakra's colors or you just wwant to use the original ones,
    // set className to "light-theme-original" ↓↓↓↓
    <div className={isLight ? "light-theme" : "dark-theme"}>
      <ReactDatePicker
        className="react-datapicker__input-text" //input is white by default and there is no already defined class for it so I created a new one
        {...props}
      />
    </div>
  );
};

export default DatePicker;

@wiredmatt
Copy link

wiredmatt commented May 3, 2021

I'm getting this in

<ReactDatePicker
        selected={selectedDate}
        onChange={onChange}
        isClearable={isClearable}
        showPopperArrow={showPopperArrow}
        className="react-datapicker__input-text" //input is white by default and there is no already defined class for it so I created a new one
        {...props}
      />

No overload matches this call.
Overload 1 of 2, '(props: ReactDatePickerProps | Readonly): ReactDatePicker', gave the following error.
Type '{ defaultChecked?: boolean | undefined; defaultValue?: string | number | readonly string[] | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; ... 252 more ...; showPopperArrow: boolean; }' is not assignable to type 'Readonly'.
Types of property 'onSelect' are incompatible.
Type 'ReactEventHandler | undefined' is not assignable to type '((date: Date, event: SyntheticEvent<any, Event> | undefined) => void) | undefined'.
Type 'ReactEventHandler' is not assignable to type '(date: Date, event: SyntheticEvent<any, Event> | undefined) => void'.
Types of parameters 'event' and 'date' are incompatible.
Type 'Date' is missing the following properties from type 'SyntheticEvent<HTMLElement, Event>': nativeEvent, currentTarget, target, bubbles, and 11 more.
Overload 2 of 2, '(props: ReactDatePickerProps, context: any): ReactDatePicker', gave the following error.
Type '{ defaultChecked?: boolean | undefined; defaultValue?: string | number | readonly string[] | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; ... 252 more ...; showPopperArrow: boolean; }' is not assignable to type 'Readonly'.
Types of property 'onSelect' are incompatible.
Type 'ReactEventHandler | undefined' is not assignable to type '((date: Date, event: SyntheticEvent<any, Event> | undefined) => void) | undefined'.ts(2769)

@Bubblesphere
Copy link

{...props} is destructuring a onSelect property which is incompatible with what ReactDatePicker expects

@madchester
Copy link

{...props} is destructuring a onSelect property which is incompatible with what ReactDatePicker expects

Is there solution to it?
i think @types/react-datepicker has some missing types

@abbasegbeyemi
Copy link

abbasegbeyemi commented Jun 23, 2021

Hey, cool upgrade on this implementation.
I noticed and can't yet figure out why, when you select the date and the dropdown appears, the selected date is not "selected".
image
When I move to another month, the date gets "selected".
image
What do you think could be the issue?

Hi I'm experiencing the same issue at the moment. Mine looks a bit worse than yours. Actually in my case, the selected date shows up, it's just that the same date is selected in future and past months as well.

Screenshot 2021-06-23 at 12 38 16 Screenshot 2021-06-23 at 12 38 41

Did you manage to solve it? And if you did, can you please share your solution? I am using a custom Chakra Theme, and I overrode the baseStyle and outline variant for the input component.

@eckertalex
Copy link

{...props} is destructuring a onSelect property which is incompatible with what ReactDatePicker expects

Is there solution to it?
i think @types/react-datepicker has some missing types

This is what I am using.

import React from 'react';
import ReactDatePicker, { ReactDatePickerProps } from 'react-datepicker';
import { useColorMode } from '@chakra-ui/react';

import 'react-datepicker/dist/react-datepicker.css';
import './date-picker.css';

function DatePicker(props: ReactDatePickerProps) {
  const {
  isClearable = false,
  showPopperArrow = false,
  ...rest
} = props
  const isLight = useColorMode().colorMode==='light';//you can check what theme you are using right now however you want

  return (
    // if you don't want to use chakra's colors or you just wwant to use the original ones,
    // set className to "light-theme-original" ↓↓↓↓
    <div className={isLight?"light-theme":"dark-theme"}>
      <ReactDatePicker
        isClearable={isClearable}
        showPopperArrow={showPopperArrow}
        className="react-datapicker__input-text"//input is white by default and there is no already defined class for it so I created a new one
        {...rest}
      />
    </div>
  );
};

export {DatePicker}

@SamuelDiazBidot
Copy link

I'm trying to add a fade animation since the date-picker renders immediately, How would i go about it? I know chakra UI has a nice transition api but it needs a toggle and i cant seem to find how to connect it with the date-picker.

@henriqgoncalvs
Copy link

Hey, cool upgrade on this implementation.
I noticed and can't yet figure out why, when you select the date and the dropdown appears, the selected date is not "selected".
image
When I move to another month, the date gets "selected".
image
What do you think could be the issue?

Hi I'm experiencing the same issue at the moment. Mine looks a bit worse than yours. Actually in my case, the selected date shows up, it's just that the same date is selected in future and past months as well.

Screenshot 2021-06-23 at 12 38 16 Screenshot 2021-06-23 at 12 38 41
Did you manage to solve it? And if you did, can you please share your solution? I am using a custom Chakra Theme, and I overrode the baseStyle and outline variant for the input component.

Hey, i did found a solution that works form me. I inspected the days that were wrongly selected to see their classes. So i took the class and change the style inside my date-picker.css file.

.react-datepicker__day--keyboard-selected,
.react-datepicker__month-text--keyboard-selected,
.react-datepicker__quarter-text--keyboard-selected,
.react-datepicker__year-text--keyboard-selected {
  background: transparent;
}

Didn't tested all cases, so i don't know if it will work for everyone.

@yovany-lg
Copy link

I was able to use a custom input component and it worked just fine, and the best thing is that you can customize the input using Chakra instead of custom CSS. Not sure if I'm missing something, I hope you find this helpful:

// customDateInput.tsx
const customDateInput = ({ value, onClick, onChange }, ref) => (
  <Input placeholder="Description" onClick={onClick} value={value} ref={ref} onChange={onChange} />
);
customDateInput.displayName = 'DateInput';

// MyForm.tsx
const CustomInput = forwardRef(customDateInput);

<DatePicker
  id="date"
  selected={startDate}
  onChange={(date) => setStartDate(date)}
  showTimeSelect
  dateFormat="MM/dd/yyyy h:mm aa"
  customInput={<CustomInput />}
/>

@ThaNico
Copy link

ThaNico commented Aug 18, 2022

@yovany-lg Thank you this was really helpful and easier to maintain probably
In my input I just passed all the props directly to make it shorter, I don't know if it's a good practice
const customDateInput = (props, ref) => <Input ref={ref} {...props} />;

@TaufiqSyed
Copy link

This is great work. Appreciate it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment