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

Component Date + Date Range #58

Closed
paulcpederson opened this issue Jun 14, 2019 · 42 comments
Closed

Component Date + Date Range #58

paulcpederson opened this issue Jun 14, 2019 · 42 comments
Assignees
Labels
enhancement Issues tied to a new feature or request. new component Issues tied to a new component.

Comments

@paulcpederson
Copy link
Member

paulcpederson commented Jun 14, 2019

Draft spec for a date picker component. This is a very common need for almost every team, so would be good to start working on this one. Below is a rough draft:

Date

Browser-consistent date selection can be accomplished with the calcite-date component. Set value, min, and max properties. Value will default to today if no value is provided:

<calcite-date value="2017-06-01" max="2019-06-01"></calcite-date>

We suggest you wrap the component and add a visible label for clarity:

<label>
  Due date
  <calcite-date value="2017-06-01" max="2019-06-01"></calcite-date>
</label>

When using with React, an input can be passed in which will act as the source of truth:

<label>
  Due date
  <calcite-date>
    <input type="date" min="2016-06-01" max="2019-06-01" value="2017-06-01">
  </calcite-date>
</label>

Events:

  • calciteDateChange emitted with standard event properties plus details: {date: "2018-03-05"}

Date Range

Frequently a UI will need to ask the user for a start and end date. Wrapping two calcite-date components inside a calcite-date-range will do the legwork of ensuring dates don't overlap:

<calcite-date-range>
  <calcite-date slot="start" value="2017-06-01" min="2016-06-01"></calcite-date>
  <calcite-date slot="end" value="2017-06-01" max="2019-06-01"></calcite-date>
</calcite-date-range>

Events:

  • calciteDateRangeChange emitted with standard event properties plus details: {startDate: "2018-03-05", endDate: "2018-03-05"}

Questions include:

  • how to integrate moment into the build without bloating people's apps
  • how to do locale-specific date formatting

Assigning to @julio8a to add his designs he's working on into this issue. We can work through API questions here prior to implementation.

@paulcpederson paulcpederson added the enhancement Issues tied to a new feature or request. label Jun 14, 2019
@julio8a
Copy link

julio8a commented Jun 14, 2019

Mockups:

date-picker-mockup

cc'ing @kumarGayu

@paulcpederson
Copy link
Member Author

@kumarGayu Feel free to take a crack at these if you have the time 👍

@julio8a
Copy link

julio8a commented Jun 17, 2019

image

@kumarGayu, here's a start. (FYI, $shadow-2 is still in the process of being added to calcite-base by Adam and it might be called something different).

@kumarGayu
Copy link
Contributor

@julio8a Thank you, I started on tsx part will be in touch with you sooner.

@kumarGayu
Copy link
Contributor

kumarGayu commented Jun 17, 2019

@julio8a, @paulcpederson @macandcheese @patrickarlt are we thinking of localization. rest all the tool we needed that to be fed from consuming app. but for this we at least need these things to be localized (or for now I can make it as fed from outside).

  1. Month Name
  2. Numbers
  3. date format
  4. Day name.
    ...

For now, I assume this is coming from the consuming apps. but, we can always turn on locale when we have the decision.

@macandcheese
Copy link
Contributor

I would assume we can either... allow folks to explicitly pass the Moment format/s they desire as prop/s, or base the Moment formatting off of a "lang" prop either on the component, the global calcite-config (WIP), or interpreted from the page?

@kumarGayu
Copy link
Contributor

I am kind of leaning towards using moment for formatting and locale support. does anyone see any problem using moment? because otherwise we might end up having many translation of same thing across the projects. Moment.locales already have the information which I needed.

@paulcpederson
Copy link
Member Author

Ideally, we would accept an optional locale. If no locale was provided we would go up into the document and find the lang attribute and use that as the locale. We would have a listed set of locales that the component supports.

Everything would be based on the locale:

  1. order of day/month/year inside the input
  2. Month translations
  3. Day abbreviations
  4. Mon vs. Sun start date for calendar itsself
  5. aria labels for "next month" and "previous month"

We could let the user pass in the translations but it would represent a rather huge config object. The localized moment build includes all of these strings, so we can lean on their translations. The only thing I think is missing is the "next month" text. This will be important for screen readers to infer what the caret icons mean. I think we could just have devs pass these in (or just label them with the month it would be if they clicked the caret)

@patrickarlt
Copy link
Contributor

patrickarlt commented Jun 18, 2019

I would be pretty strongly against Moment since it is really large and we would have to be REALLY careful about how we include the locales to not bloat bundles and we would have to document how to include the locales in the final apps all of which is complicated and could reduce adoption.

The input date format should always be an ISO 8601 date. The output format and all internal state should be that as well. Since all our internal references are just date objects the rendered UI could possibly be built on top of Intl.DateTimeFormat. Particularly the formatToParts method.

The Intl APIs can be polyfilled with https://github.com/andyearnshaw/Intl.js which could be loaded on the fly for IE 11.

So with the Intl APIs in mind lets looks at @paulcpederson's 5 items:

Order of day/month/year inside the input

var formatter = new Intl.DateTimeFormat('en-us', {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
});

var formattedDate = formatter.format(new Date());
console.log(formattedDate); // "6/18/2019"

Month translations

var formatter = new Intl.DateTimeFormat('en-us', {
  month: 'long'
});

var month = formatter.formatToParts(new Date())[0].value;
console.log(month); // "June"

You could execute this in a loop to get the month translations.

Day abbreviations

var formatter = new Intl.DateTimeFormat('en-us', {
  weekday: 'short'
});

var day = formatter.formatToParts(new Date())[0].value;
console.log(day); // "Tue"

You could execute this in a loop to get the day of week translations.

Mon vs. Sun start date for calendar itself

The Intl API doesn't support this yet but there is some old discussion in standards groups about it in tc39/ecma402#6 and tc39/ecma402#46.

However this information is REALLY easily accessible via the CLDR data in https://github.com/unicode-cldr/cldr-core/blob/master/supplemental/weekData.json. We could simply request the data and package it in. For the 40 locales Online supports a object of:

const WEEK_START_DAYS = {
  en: "mon",
  //...
}

Wouldn't be to big, especially if we assume everything starts on Monday except for the few locales where it doesn't.

We could use cldr-data and cldr-js to build a script to extract this for us. We could reuse that same script later if we needed additional things out of CLDR.

aria labels for "next month" and "previous month"

These can be provided by the user via @Prop().

@patrickarlt
Copy link
Contributor

It is also worth noting here that the JS API team is moving away from things like Moment and toward the Intl APIs wherever possible.

@paulcpederson
Copy link
Member Author

Using Intl matches the underlying concepts of this repo better, for sure: lightweight, use newer browser standards where possible, etc. I am very into this idea. I have never liked how ginormous moment is, so this seems like a good replacement.

@patrickarlt if we use intl.js polyfill does stencil take care of loading that for IE11?

@ycabon
Copy link
Member

ycabon commented Jun 18, 2019

Like @patrickarlt JS API 4.12 uses native Intl for date formatting. I don't think you will need formatToParts. You can use format to format months directly:

var formatter = new Intl.DateTimeFormat('en-us', {
  month: 'long'
});

formatter.format(new Date()); // June

We only need cldr info to parse dates from strings but if you choose ISO 8601 then you won't need.

And for moment we are removing in all places possible, this convenience brings 50kb of JS which we usually don't need.

@kumarGayu
Copy link
Contributor

@patrickarlt and @ycabon Thank you I will use native intl now. I haven't made use of moment until now.

@patrickarlt
Copy link
Contributor

if we use intl.js polyfill does stencil take care of loading that for IE11?
@paulcpederson - #58 (comment)

No my preference would personally be to document that if you want fill i18n in IE 11 for <calcite-date-picker> you should load the polyfill and the locale data yourself. Eventually IE 11 will go away and then we don't have to make any code changes here.

We COULD potentially make a loader for the polyfill but it feels really outside the domain of calcite-components since it would load the Intl polyfill for the whole app.

@paulcpederson
Copy link
Member Author

@patrickarlt that seems reasonable. We will have to make sure to doc that decision. It may be a good idea to have a browser support table in the readme with some notes on this stuff.

@julio8a
Copy link

julio8a commented Jul 24, 2019

added time:

image

image

@rmstinson
Copy link

rmstinson commented Jul 24, 2019

I'm working on a Date/Time format picker for AGOL charts - it might be a good idea to solidify MM/DD/YYYY and H:MM TT (01/24/2009 and 3:45 PM) to be the default format (as shown above)

@paulcpederson
Copy link
Member Author

@rmstinson yeah for comps and mockups def that is the correct format.

In the implementation, though, the order of day, month, year should probably be determined by the user's locale. Ie. in Korea the natural format is "YEAR. MONTH. DAY." with periods, it's crazy. Pretty much every country does something different, it's actually kind of insane. Here are some examples: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat#Using_locales

@julio8a
Copy link

julio8a commented Jul 25, 2019

Dark theme, I can help with styling:

image

@paulcpederson
Copy link
Member Author

😻

@bstifle
Copy link

bstifle commented Jul 25, 2019

beautyful!

@paulcpederson paulcpederson added the new component Issues tied to a new component. label Aug 3, 2019
@ekenes
Copy link

ekenes commented Aug 9, 2019

ccing myself @ekenes since I want to track progress on this for our Smart Mapping workflows in the JS API.

@ekenes
Copy link

ekenes commented Aug 20, 2019

@julio8a @kumarGayu What is the estimated milestone for this? There are several JS API widgets that would like to take advantage of this component.

@kumarGayu
Copy link
Contributor

@ekenes Right now i am in training for 2 weeks, but by then whenever i get free time i will make this available. However, now we have the date picker in place for light theme.

@ekenes
Copy link

ekenes commented Aug 20, 2019

Cool! So date + time picker is already available for light themes?

@kumarGayu
Copy link
Contributor

Time is not yet there. :(

@ekenes
Copy link

ekenes commented Aug 20, 2019

Ok. What's the approximate timeline for adding time?

@kumarGayu
Copy link
Contributor

a week or 2 max.

@macandcheese
Copy link
Contributor

Hey @kumarGayu - any update on the status of this or the related Edge issue? #137 - thanks in advance!

@ffaubry
Copy link
Member

ffaubry commented Nov 8, 2019

A bit of late feedback.

Feedback 1

A the case for a single calendar range selector. For Dashboard UI, the double calendar range selector is over killing. Too much space, etc. I would encourage a more compact range selector relying on a single calendar. You can look at:

Feedback 2

The case for date pattern. Currently if the calendar is set to French, the placeholder shows: DD/MM/YYYY.

DD, MM, YYYY have only a meaning for english language.
In German DD should TT, in French should be JJ.
My point is this pattern has no meaning outside of english speaking countries and it's inner guts exposed outside.

Feedback 3

I really hope that the calendar is a component by itself and can be decoupled from the click button behavior and hosted in other components such as Modal or just by itself.

Feedback 4

The current calendar is not using calcite colors.

Feedback 5

As I type in the input box a date, the calendar doesn't reflect the date.
image

@macandcheese
Copy link
Contributor

macandcheese commented Nov 10, 2019

@ffaubry agree on those points - @julio8a can we make some tweaks to support single input range? - would likely just need to update the input area a bit and place some divider or directional indicator between start / end dates.

@evanmosby
Copy link

evanmosby commented Jan 17, 2020

One additional consideration might be a slot for range shortcuts? For instance, select yesterday, last week, month etc. A simple example: Link
Monitor's got a bunch of date range selections - we're super interested in this. Looking epic!

@macandcheese
Copy link
Contributor

Agree @evanmosby I'd say that's almost expected behavior for many use cases.

@paulcpederson
Copy link
Member Author

@julio8a can you post the design for single input range selection?

@ffaubry
Copy link
Member

ffaubry commented Apr 6, 2020

@paulcpederson could add Ben to this repo?
He will provide our requirements for this.
He has been designing our date UX for dashboard.

@julio8a
Copy link

julio8a commented Apr 6, 2020

@paulcpederson design for single input range:
image

@ffaubry, I added Ben to the repo.

@evanmosby
Copy link

Hi guys, curious as to the timeline on this one. The Monitor product could sure use a date range picker :) We can implement two individual pickers today to get us by, but probably not something we'd wanna ship with. Thanks!

@paulcpederson
Copy link
Member Author

@julio8a what does the input look like for the range? Also what interaction model should it use? As in, if I click "8" does the range extend to 8 or am I selecting a new range beginning at 8.

As per the API for this, considering aligning this with calcite-slider props. Basically add two props for range:

  • minValue
  • maxValue

We would then need to change the event detail for the emit on date select to:

e.detail = { min: Date, max: Date }

@macandcheese thoughts on this API?

Because of the rework I did a while back, the range feature should be a lot easier to add now...

@paulcpederson
Copy link
Member Author

@julio8a also might be worth moving a full spec + designs for range to a new issue as this one is getting a little wacky.

@macandcheese
Copy link
Contributor

@paulcpederson API looks good, consistency is 👑 - Agree with a new issue.

@julio8a
Copy link

julio8a commented Apr 30, 2020

Will do new issue

@julio8a
Copy link

julio8a commented May 1, 2020

The date is in master. I split the range into another issue #541. Closing this one out.

@julio8a julio8a closed this as completed May 1, 2020
alisonailea added a commit that referenced this issue Aug 29, 2023
fix(tokens): bugfix revert token deletion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Issues tied to a new feature or request. new component Issues tied to a new component.
Projects
None yet
Development

No branches or pull requests