ui icon indicating copy to clipboard operation
ui copied to clipboard

feat(components): calendar/datepicker with month and year select

Open jhavej opened this issue 1 year ago • 10 comments

This PR implements the missing month/year select in the calendar/datepicker component.

Related PRs: https://github.com/shadcn-ui/ui/pull/1680 https://github.com/shadcn-ui/ui/pull/320 https://github.com/shadcn-ui/ui/issues/546 https://github.com/shadcn-ui/ui/issues/509 https://github.com/shadcn-ui/ui/issues/880

My approach relies exclusively on the native captionLayout prop offered by React DayPicker, along with additional Tailwind CSS styling for the Calendar component. This approach maximizes the capabilities of React DayPicker, simplifying the solution and reducing the risk of bugs.

Other calendar/datepicker use cases remain unchanged.

Screenshot 2023-10-13 at 16 40 38

Here's the demo:

https://github.com/shadcn-ui/ui/assets/9072750/fe0a164c-1bdf-4f9b-837a-01a5f328a6d4

Cheers, Jakub 👋

jhavej avatar Oct 13 '23 14:10 jhavej

@jhavej is attempting to deploy a commit to the shadcn-pro Team on Vercel.

A member of the Team first needs to authorize it.

vercel[bot] avatar Oct 13 '23 14:10 vercel[bot]

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
ui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 12, 2023 7:57am

vercel[bot] avatar Oct 15 '23 12:10 vercel[bot]

Whilst testing this change, it seems fromDate & toDate no longer work.

With the changes made in this PR:

image

With the previous calendar component:

image

In the 1st screenshot, the calendar defaults to October 2023. In the 2nd screenshot the calendar defaults to October 2005. The expected behaviour is the latter.

The following is my implementation of this component (which is static between the test scenarios):

<Calendar captionLayout="dropdown-buttons" fromDate={new Date("1900-01-01")} toDate={eighteenYearsAgo} mode="single" selected={field.value} onSelect={field.onChange} disabled={(date) => date > eighteenYearsAgo || date < new Date("1900-01-01") } initialFocus />

eighteenYearsAgo is a const defined to calculate 18 years from todays date:

const eighteenYearsAgo = moment().subtract(18, "years").toDate();

Maybe the implementation should change, but from the original comment I don't think so.

Happy to make changes to my implementation as per instruction.

Thanks

iaingymware avatar Oct 15 '23 19:10 iaingymware

@jhavej Could this be a duplicate of https://github.com/shadcn-ui/ui/pull/1680? What are your thoughts on #1680?

shadcn avatar Oct 18 '23 17:10 shadcn

Whilst testing this change, it seems fromDate & toDate no longer work.

With the changes made in this PR:

image

With the previous calendar component:

image

In the 1st screenshot, the calendar defaults to October 2023. In the 2nd screenshot the calendar defaults to October 2005. The expected behaviour is the latter.

The following is my implementation of this component (which is static between the test scenarios):

<Calendar captionLayout="dropdown-buttons" fromDate={new Date("1900-01-01")} toDate={eighteenYearsAgo} mode="single" selected={field.value} onSelect={field.onChange} disabled={(date) => date > eighteenYearsAgo || date < new Date("1900-01-01") } initialFocus />

eighteenYearsAgo is a const defined to calculate 18 years from todays date:

const eighteenYearsAgo = moment().subtract(18, "years").toDate();

Maybe the implementation should change, but from the original comment I don't think so.

Happy to make changes to my implementation as per instruction.

Thanks

Thanks for the catch @iaingymware 👍

It was caused because of the default values for fromYear/toYear (these are mandatory for captionLayout to work - see the official docs for React DayPicker) - these props always overrode fromDate/toDate or fromMonth/toMonth.

I removed the default values and passed fromYear/toYear props to Calendar directly from the DatePickerWithMonthYear - this way it's more explicit and aligns with the React DayPicker official docs.

Tested also with fromDate/toDate & fromMonth/toMonth 🆗

jhavej avatar Oct 24 '23 17:10 jhavej

@jhavej Could this be a duplicate of #1680? What are your thoughts on #1680?

Hi @shadcn 👋 Yeah, I noticed this PR, see it in my first comment. It brings unnecessary complexity as it adds a custom dropdown and event handlers - you can see it here.

My solution is purely based on the capabilities of React DayPicker by enabling its captionLayout prop + some needed Tailwind CSS styling.

Just fixed the minor issue above & built the registry so we can finish this soon.

Cheers, Jakub

jhavej avatar Oct 24 '23 17:10 jhavej

Hi @shadcn 👋 Yeah, I noticed this PR, see it in my first comment. It brings unnecessary complexity as it adds a custom dropdown and event handlers - you can see it here.

I tested both and imo @jhavej implementation is less bloated, and works better. Thank you @jhavej for making my life ez! it's already in prod ❤️ image

MendyLanda avatar Oct 31 '23 14:10 MendyLanda

I made slightly different versions of the dropdown buttons, lmk what you think

  • month is taking all available space with flex-1 to reduce ui shifting
  • added button behaviour (using buttonVariants)

with the outline variant: image

or with the ghost variant (cursor is hovering over month): image

MendyLanda avatar Oct 31 '23 15:10 MendyLanda

Thanks for the approval @pyloverm 👍

Should I merge main to resolve the conflicts? I think it'd discard your approval so maybe it'd speed up the PR merge if you do it from your end.

Let me know and thanks again.

jhavej avatar Nov 17 '23 17:11 jhavej

@pyloverm @shadcn is it scheduled for release?

MrLightful avatar Jan 29 '24 23:01 MrLightful

@jhavej Could this be a duplicate of #1680? What are your thoughts on #1680?

Hi @shadcn 👋 Yeah, I noticed this PR, see it in my first comment. It brings unnecessary complexity as it adds a custom dropdown and event handlers - you can see it here.

My solution is purely based on the capabilities of React DayPicker by enabling its captionLayout prop + some needed Tailwind CSS styling.

Just fixed the minor issue above & built the registry so we can finish this soon.

Cheers, Jakub

Hi @jhavej I have tried your approach [not gonna lie it is a clean one], however since it uses the default browser dropdown it's not working correctly while in dark mode

image image

Extra: I have also tried #1680 and yours works better, but is there a way to combine both the clean look of shadcn/ui select component and your approach? (Your approach works much better for range selection since I can change the month from both sides)

image

AssadAnabosi avatar Mar 04 '24 17:03 AssadAnabosi

would it be somehow add month and year picker but not only day picker in the future?

cblberlin avatar Mar 05 '24 15:03 cblberlin