adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
12.6k stars 1.09k forks source link

useRangeCalendarState should allow controlling selectionAlignment #4721

Open longzheng opened 1 year ago

longzheng commented 1 year ago

๐Ÿ™‹ Feature Request

The useRangeCalendarState should allow controlling the selectionAlignment prop of useCalendarState https://github.com/adobe/react-spectrum/blob/dad2cefcbda8e0e73ce55a9c5054bcc1e74b3eb3/packages/%40react-stately/calendar/src/useCalendarState.ts#L50-L51

๐Ÿค” Expected Behavior

Allow setting selectionAlignment

๐Ÿ˜ฏ Current Behavior

Does not allow setting selectionAlignment, it is automatically calculated from value

https://github.com/adobe/react-spectrum/blob/dad2cefcbda8e0e73ce55a9c5054bcc1e74b3eb3/packages/%40react-stately/calendar/src/useRangeCalendarState.ts#L52-L60

๐Ÿ’ Possible Solution

There should be a selectionAlignment prop and use the prop value if it is set and fallback to the existing value logic if there is no prop value.

Maybe something like these changes to useRangeCalendarState.ts

export interface RangeCalendarStateOptions<T extends DateValue = DateValue> extends RangeCalendarProps<T> {
    /** The locale to display and edit the value according to. */
    locale: string;
    /**
     * A function that creates a [Calendar](../internationalized/date/Calendar.html)
     * object for a given calendar identifier. Such a function may be imported from the
     * `@internationalized/date` package, or manually implemented to include support for
     * only certain calendars.
     */
    createCalendar: (name: string) => Calendar;
    /**
     * The amount of days that will be displayed at once. This affects how pagination works.
     * @default {months: 1}
     */
    visibleDuration?: DateDuration;
+   /** Determines how to align the initial selection relative to the visible date range. */
+   selectionAlignment?: 'start' | 'center' | 'end';
}
  let calendar = useCalendarState({
    ...calendarProps,
    value: value && value.start,
    createCalendar,
    locale,
    visibleDuration,
    minValue: min,
    maxValue: max,
-   selectionAlignment: alignment
+   selectionAlignment: props.selectionAlignment ?? alignment
  });

๐Ÿ”ฆ Context

I want to show a range calendar with 2 months but the selection should always be aligned at the start, so it should always start on the left/first month.

๐Ÿ’ป Examples

Without this fix, sometimes my range selection start is shown on the right month.

image

I want it always be shown on the left month.

image

๐Ÿงข Your Company/Team

๐ŸŽ Tracking Ticket (optional)

LFDanLu commented 1 year ago

This seems reasonable, would need to test the behavior to make sure it doesn't have any unintended side effects.