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

feat(DatePicker): DatePicker implementation #674

Merged
merged 133 commits into from
Mar 4, 2024

Conversation

epr3
Copy link
Collaborator

@epr3 epr3 commented Feb 8, 2024

Closes #379.

Hello,

First of all, I want to say thank you for this awesome library.

I implemented this feature taking inspiration from https://melt-ui.com/, https://www.bits-ui.com/docs/introduction and https://react-spectrum.adobe.com/react-stately, plus the examples provided on the issue.

The components that I've implemented are:

  • DateField
  • DateRangeField
  • Calendar
  • RangeCalendar
  • DatePicker
  • DateRangePicker

The last two are basically composing the field components, the calendar components and the popover component and are re-exporting them under the DatePicker/DateRangePicker naming.

The components are fully navigable by keyboard and should have all accessibility tags.

I open this as a draft PR because it still needs some stuff added to it.

The things that I did not manage to implement are: adding documentation, styling for the components in Histoire, usage examples, general cleanup and do some refactoring to clean the code and prevent unnecessary re-renders.

I appreciate any feedback and will implement any refactor, bugfix or feature required.

@epr3 epr3 marked this pull request as draft February 8, 2024 09:19
@epr3 epr3 changed the title Draft: Date Picker Feature feat(DatePicker): DatePicker implementation Feb 8, 2024
@zernonia
Copy link
Collaborator

zernonia commented Feb 8, 2024

WHOAAAAA @epr3 !! I was just started looking into this, and you already have the PR ready!!! I'll review it shortly ya! 💚

@sadeghbarati
Copy link
Contributor

sadeghbarati commented Feb 9, 2024

@epr3 Thanks for your time ❤️

Found a source that can guide you to add month or year selection, the project is also using @internationalized/date

I don't know which one is more convenient

  • Popover for selection
  • Overlay on calendar
  • v-if and v-else or <component :is=""> for selection (component replacement) which also need KeepAlive I think

or it should be done in shadcn-vue?

@zernonia wdyt?

@epr3
Copy link
Collaborator Author

epr3 commented Feb 10, 2024

@sadeghbarati Thank you for your guidance.

I'm leaning towards implementing the year and month selection by providing two new primitives: CalendarYearSelect and CalendarMonthSelect which on click would either replace the values provided through the months v-slot value (and probably rename it to something more intuitive) by keeping an internal state for the view and letting the end-user re-use all the Calendar building blocks or providing separate values for dates, months and years and the current view through v-slot and letting the user the ability to make the decision on how he wants to display these values.

The only thing that I don't know how I should approach for this feature is what should the values be if number-of-months is set to something greater than 1 and paged-navigation is set to false.
image

Shadcn Svelte seems to have used a couple of selects for the month and year.

What do you think?

@sadeghbarati
Copy link
Contributor

sadeghbarati commented Feb 10, 2024

@epr3 It's nice that you create new Primitives for it ❤️

And also use Vue features like slotProps 💚

The only thing that I don't know how I should approach for this feature is what should the values be if number-of-months is set to something greater than 1 and paged-navigation is set to false

Can you make a demo of this problem? You can push it in this PR so we could checkout to your branch and see what we can do about it


MuiX DatePicker demos might be helpful

https://mui.com/x/react-date-pickers/date-picker/

@zernonia
Copy link
Collaborator

zernonia commented Mar 1, 2024

@epr3 why remove the defaultValue props? I would like to keep that the same as other Primitives

@epr3
Copy link
Collaborator Author

epr3 commented Mar 1, 2024

@epr3 why remove the defaultValue props?

They seem redundant, since the modelValue would get populated through the v-model. I can add those back if needed.
EDIT: seen the updated comment, will add those back in a bit

@epr3
Copy link
Collaborator Author

epr3 commented Mar 1, 2024

@zernonia - I've added back the defaultValue props

I also would need some guidance on this issue if possible: Do you have any idea on how we could properly handle the DateValue values inside ref?

A lot of errors pop up due to the fact that Vue seems to drop nested values of DateValue (always returning a new DateValue doesn't always work), namely the calendar field which contains a lot of functions needed by @internationalized/date for various comparisons/operations and the package itself is built with ES6 classes which I believe builds Objects and populates their prototypes with class methods.

@zernonia
Copy link
Collaborator

zernonia commented Mar 4, 2024

@epr3 unfortunately I dont think we can have a solution for now, as it seems like a problem with Vue.

https://www.reddit.com/r/vuejs/comments/xbfa3x/prop_as_a_typescript_class_object/
https://stackoverflow.com/questions/75557531/vue3-unwrap-properties-in-typescript-class

(relevant playground too see the types broken down by ref)

However we can get this PR merged. Absolutely banger job @epr3 !!!! 🤩

@zernonia zernonia merged commit 3f0254b into radix-vue:1.5 Mar 4, 2024
2 of 3 checks passed
@maelp
Copy link

maelp commented Mar 4, 2024

Nice! Looking forward to seeing this in Shadcn! @zernonia will you do a custom styling of the component to replace the old one, or as an entirely new one?

@epr3 epr3 deleted the 379-feature-datepicker branch March 4, 2024 09:55
@epr3 epr3 restored the 379-feature-datepicker branch March 4, 2024 09:55
@sadeghbarati
Copy link
Contributor

@zernonia

This issue might help vuejs/core#8149

I had the same issue but I went with shallowRef

consider using Composition API and using Composables.

@epr3
Copy link
Collaborator Author

epr3 commented Mar 4, 2024

@zernonia Thank you very much! Glad I could help.

I'll still have a look around and see if I can work around Vue with toRaw/markRaw or decompose the DateValue somehow and get the calendar field to not be made reactive by Vue, since DateValue looks like it needs methods from the calendar field to work (which might cause other issues with instanceof for determining CalendarDate/CalendarDateTime/ZonedDateTime if decomposed).

I'll make a PR if I get any better results.

@ico85
Copy link

ico85 commented Mar 8, 2024

I would like to express my gratitude and emphasize the importance of component libraries that are consistently developed with accessibility in mind. I work for a service provider that creates websites for public entities (e.g., websites for municipalities and cities, which are legally required to be accessible!). We are legally obligated to implement guidelines that ensure accessibility. In Germany, these guidelines are known as BITV 2.0 ("Barrierefreie Informationstechnik-Verordnung 2.0"). Your framework and your work are incredibly important. Thank you!

@epr3 epr3 deleted the 379-feature-datepicker branch March 25, 2024 17:18
@valh1996
Copy link

Hello @epr3, how do you pass a DateTime instead of a Date? I need to control the time too.

I see that radix-vue exports a DateRange type but no DateTimeRange.

Could you please give me a hint on how to do this (with an example) ?

import type { DateRange } from 'radix-vue'

Congratulations on your work! It's fantastic!

@epr3
Copy link
Collaborator Author

epr3 commented Apr 21, 2024

Hello @valh1996,

You would need to use CalendarDateTime or ZonedDateTime from the @internationalized/date package to be able to manipulate the time.

The DateRange type is meant to be used with the date range components: DateRangeField/DateRangePicker/RangeCalendar.

@valh1996
Copy link

Hello @valh1996,

You would need to use CalendarDateTime or ZonedDateTime from the @internationalized/date package to be able to manipulate the time.

The DateRange type is meant to be used with the date range components: DateRangeField/DateRangePicker/RangeCalendar.

Ok, thanks, so if I understand correctly, the calendar doesn't support the time, so I have to manage it myself?

@epr3
Copy link
Collaborator Author

epr3 commented Apr 21, 2024

Yes, you would need to build the time picker yourself.

@sadeghbarati
Copy link
Contributor

sadeghbarati commented Apr 21, 2024

I will send a Stackblitz demo with a description, but with a single calendar date

If you are in Discord, feel free to DM me or send us your Discord ID

https://stackblitz.com/edit/rmqdng-4zeuhv

lul

Stackblitz demo is the Composition of Calendar and DateField which is these components connected to the value ref


With toCalendarDateTime or CalendarDateTime or ZonedDateTime or others DateTime APIs

let time = new Time(8, 30);
const value = ref(toCalendarDateTime(today(getLocalTimeZone()), time)) as Ref<DateValue>;

// or

const value = ref(toCalendarDateTime(today(getLocalTimeZone()))) as Ref<DateValue>;

DateFieldRoot will render Dates and Times segments


With toCalendar or CalendarDate or other related Date APIs which I'm not yet aware of

DateFieldRoot will only render Date segments

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

Successfully merging this pull request may close these issues.

[Feature]: DatePicker
7 participants