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

Allow dateFields to have different formats #6266

Open
yusijs opened this issue Apr 25, 2024 · 7 comments
Open

Allow dateFields to have different formats #6266

yusijs opened this issue Apr 25, 2024 · 7 comments
Labels
enhancement New feature or request rsp:DatePicker

Comments

@yusijs
Copy link

yusijs commented Apr 25, 2024

Provide a general summary of the feature here

Our users are from multiple countries around the world but when they are travelling and work on different locations, there are some "issues" with how the date-inputs are formatted due to the locale on their temporary machines (if not on laptops). A request was made that the input format should be possible to customize to have the literal months rather than numerical.

🤔 Expected Behavior?

I would expect something like this:

const formatter = useDateFormatter({ month: 'short', year: 'numeric', day: '2-digit' })
const state = useDateFieldState({...props, formatter})

which would result in an input looking something like this:
image

😯 Current Behavior

The format is always numerical based on the default locale:
image

💁 Possible Solution

No response

🔦 Context

Make it easier to have human-readable dates, without the users having to wonder if 03/05/2024 means the 3rd of May or the 5th of March, depending on which computer they are currently working from.

💻 Examples

No response

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

@binaryartifex
Copy link

this. for the love of god, this.

@binaryartifex
Copy link

@yusijs what I ultimately ended up doing was thinking a little outside the box and just adding a 'hidden' class on the entire DateInput inner component and adding my own span with a formatted date value. everything works exactly the same as before, screen reader behaves the exact same as well. Minus the types and styles, this is my entire date picker component. The styles.input() class only has a class of hidden on it.

export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(function DatePicker(
  { description, errorMessage, hideLabel = false, label, onChange, placeholder, ...props },
  ref,
) {
  const formatter = useDateFormatter({ dateStyle: "medium" });
  const timezone = getLocalTimeZone();
  const isInvalid = Boolean(errorMessage || props.isInvalid);
  const styles = datePickerStyles({ isInvalid });

  const formatDate = useCallback(
    (value: DateValue | null) => (value ? formatter.format(value.toDate(timezone)) : placeholder),
    [formatter, placeholder, timezone],
  );

  const handleChange = useCallback(
    (value: DateValue) => onChange && onChange(value.toString()),
    [onChange],
  );

  return (
    <AriaDatePicker
      {...props}
      className={styles.base()}
      isInvalid={isInvalid}
      onChange={handleChange}
      ref={ref}
    >
      {({ state }) => (
        <Fragment>
          <div>
            <FieldLabel hideLabel={hideLabel}>{label}</FieldLabel>
            {description && <FieldDescription>{description}</FieldDescription>}
          </div>
          <div className={styles.body()}>
            <Group className={styles.field()}>
              <span className={styles.value()}>{formatDate(state.value)}</span>
              <DateInput className={styles.input()}>
                {(segment) => <DateSegment className={styles.segment()} segment={segment} />}
              </DateInput>
              <Button className={styles.button()}>
                <Icon.Interface.Calendar />
              </Button>
            </Group>
            <FieldValidation>{errorMessage}</FieldValidation>
          </div>
          <Popover className={styles.popover()}>
            <Dialog>
              <Calendar />
            </Dialog>
          </Popover>
        </Fragment>
      )}
    </AriaDatePicker>
  );
});

image

@yusijs
Copy link
Author

yusijs commented May 1, 2024

@binaryartifex I'm looking into creating an overlay that shows the formatted value on blur, but the input as numeric. It will work, but I'd obviously prefer this being something that just works, and also has a forgiving input.

To be clear though, I'm not using react-aria-components, but the hooks from react-aria, so I have a bit more code than you 😅

@LFDanLu
Copy link
Member

LFDanLu commented May 2, 2024

Would the formatted value month value revert to a number when the user enters one of the number segments?

@yusijs
Copy link
Author

yusijs commented May 3, 2024

Would the formatted value month value revert to a number when the user enters one of the number segments?

Ideally it would be possible to write w/ literals as well, but not sure how feasible that is. I've actually implemented the solution you mention here on my end now, as I figured a neat way to solve it yesterday. Ideally I would like it out of the box, but this works as well tbh.. :)

When using a literal month, the format often turns a bit around:
Localized -> December 31, 2024
Numeric -> 31.12.2024
Replaced on blur -> 31. December. 2024

So it's not localized properly, but it works.

@LFDanLu
Copy link
Member

LFDanLu commented May 3, 2024

From a gut feeling writing the literals seems like it could be pretty hard, just thinking about languages that use a IME like Chinese/Japanese/etc. Would need to experiment with it, but supporting the text representations on blur like you've done might be something we could consider adding ourselves.

@LFDanLu LFDanLu added enhancement New feature or request rsp:DatePicker labels May 3, 2024
@yusijs
Copy link
Author

yusijs commented May 4, 2024

From a gut feeling writing the literals seems like it could be pretty hard, just thinking about languages that use a IME like Chinese/Japanese/etc. Would need to experiment with it, but supporting the text representations on blur like you've done might be something we could consider adding ourselves.

Yeah, I imagine it's quite a bit harder to handle in multiple locales. I've handled it previously, but that was only for en-US locale, so it was fairly straight forward to handle.

It would be a great QOL improvement for the display-value to change natively though; it's a bit tedious to handle it now imo:

    <Segment
      {...segmentProps}
      onFocus={(e) => {
        setFocus(true)
        segmentProps.onFocus(e)
      }}
      onBlur={(e) => {
        setFocus(false)
        segmentProps.onBlur(e)
      }}>
            {focus
        ? (segment.isPlaceholder || segment.type === 'literal'
          ? segment.text
          : segment.text.padStart(segment.type === 'year' ? 4 : 2, '0') )
        : value}

Being able to avoid the focus-check / custom focus-handling would be neat, and reduce the additional code I've had to add quite a bit :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request rsp:DatePicker
Projects
None yet
Development

No branches or pull requests

3 participants