Esri / calcite-design-system

A monorepo containing the packages for Esri's Calcite Design System
https://developers.arcgis.com/calcite-design-system/
Other
285 stars 76 forks source link

[Time Picker / Input Time Picker / Input type="time"] Handle 24 hour format #4756

Open macandcheese opened 2 years ago

macandcheese commented 2 years ago

Description

Currently, the time-picker, input-time-picker, and input type="time" do not allow for the use of 24 hour time format from an end-user use case.

Acceptance Criteria

Allow the ability to control the format - 12/24hr, in these components / component configurations.

Relevant Info

A native (non-calcite) input of type="time" automatically changes from 12 -> 24 hour format when I changed my Time Format in OS preferences to 24-hour time (Mac / Chrome). I could not replicate this behavior with calcite-input of type time.

Which Component

[Time Picker / Input Time Picker / Input type="time"]

Example Use Case

No response

jcfranco commented 2 years ago

@annierm18 Can you confirm if this needs to be configurable? So far, the format has been automatically determined by the locale.

eriklharper commented 2 years ago

Sounds like the issue is just that the component doesn't respond to browser or OS locale changes properly. Is that correct?

eriklharper commented 2 years ago

From the looks of it, this doesn't seem possible to do with the existing browser APIs. I'm going to do some more research, but I don't think there's a way to access this system setting via javascript in the browser.

benelan commented 2 years ago

IIRC navigator.language should be the system's preferred language when provided.

Last time I looked into this I found it really depends on the browser and OS. For example, FireFox:

All major operating systems have a Settings UI for selecting those preferences, and since Firefox does not provide its own, Gecko looks into the OS for them. A special API mozilla::intl::OSPreferences handles communication with the host operating system, retrieving regional preferences and altering internationalization formatting with user preferences.

https://firefox-source-docs.mozilla.org/intl/locale.html#regional-preferences

@macandcheese said he is using Mac/Chrome: https://developer.chrome.com/docs/extensions/reference/i18n/#mac-os-x

Where as it looks like Chrome won't use Window's system settings and you have to make shortcuts: https://developer.chrome.com/docs/extensions/reference/i18n/#windows

I don't think input uses navigator.language atm

eriklharper commented 2 years ago

Yeah, and even if the specific browser provides a hook into the OS locale, which would imply a default hour cycle, it would still need to hook into the OS hour cycle checkbox to determine if a user has overridden the default.

annierm18 commented 2 years ago

Thank you for the info @eriklharper and @benelan! I will discuss this with Babak and will follow up soon.

annierm18 commented 2 years ago

Update on this - the i18n team would like for this to be implemented if it's possible.

eriklharper commented 2 years ago

Update on this - the i18n team would like for this to be implemented if it's possible.

What we can support is an hour-cycle property, but we won't be able to set the hour cycle based on the user's OS setting. I can look into doing this in browser-specific time format settings, but after the research I did I discovered the browsers don't have a hook into the OS-level system preferences like I assumed they would. Perhaps in the future this is something they will implement.

Would a property that overrides the existing locale's hour cycle suffice?

benelan commented 2 years ago

What we can support is an hour-cycle property, but we won't be able to set the hour cycle based on the user's OS setting.

I'm pretty sure it's possible using navigator.language like I mentioned above. What about something like this?

/*
 * Detects navigator locale 24h time preference
 * It works by checking whether hour output contains AM ('1 AM' or '01 h')
 * based on the user's preferred language
 */
const isBrowserLocale24h = () =>
  !new Intl.DateTimeFormat(navigator.language, { hour: "numeric" })
    .format(0)
    .match(/AM/);
benelan commented 2 years ago

Looking at the guys code you would probably have to check for "PM" too:

const isBrowserLocale24h = () =>
  !new Intl.DateTimeFormat(navigator.language, { hour: "numeric" })
    .format(0)
    .match(/[AM|PM]/);
benelan commented 2 years ago

Alright I tested the guys code and it doesn't work at all lol. The AM/PM string is dependant on the locale. https://codepen.io/benesri/pen/RwMpGeZ?editors=0011

This seems to work based on my limited testing

const isBrowserLocale24h = () =>
  !new Intl.DateTimeFormat(navigator.language, { hour: "numeric" })
    .format(new Date(1, 1, 1, 14))
    .match(new RegExp(Number(2).toLocaleString(navigator.language)));

I think using the code above by default would be good, but there is still the case of the OS/browser combos that don't use the locale system settings. So I could see Erik's prop recommendation as well. Thoughts @jcfranco ?

eriklharper commented 2 years ago

Correct, I wouldn't expect this to work anyway because Intl.DateTimeFormat is just a formatting api. It knows nothing about user preferences.

eriklharper commented 2 years ago

That code snippet won't work consistently enough to rely on it. Didn't work for me when I changed my OS time preference to 24 hour with an en-US locale.

benelan commented 2 years ago

Yeah I'm starting to think Chrome's documentation lied to me. Here it says:

On Mac or Linux? Chrome will automatically display in the default system language for your computer.

I have Windows, but I asked Franco to change his system language to Spanish and Chrome did not automatically display in Spanish. My understanding is that navigator.language is the browsers preferred locale. So if changing the locale in the system actually affected Chrome then that code should work, but maybe the doc is outdated.

eriklharper commented 2 years ago

The kicker there is "default system language". The trick is getting it to recognize the non-default hour setting, which it doesn't appear to support.

annierm18 commented 2 years ago

Implementing support an for hour-cycle property that @eriklharper mentioned sounds like a good option

driskull commented 1 year ago

Can we use this? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle

eriklharper commented 1 year ago

Can we use this? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle

Yes, we would use this to set the default value of the hour-cycle prop based on the locale. Being a prop, hour-cycle would also be overridable from the locale's default hour cycle.

geospatialem commented 1 year ago

Reallocated to October to accommodate a different higher impacted moderate issue for the Maps SDK for JS team.

geospatialem commented 1 year ago

Updated the milestone to December, and upgraded the priority to medium (previously low) to ensure this enhancement lands prior to the 24R1 release. cc @hgonzago and @JonUihlein

eriklharper commented 1 month ago

Update: Almost done writing tests for all the supported locales, and looking at a handful of some locale-specific issues with typing in localized meridiem characters and one with the arab numbering-system, and then refactoring from hour-cycle to hour-format before this is ready. Getting close :)