Skip to content

Latest commit

 

History

History
215 lines (182 loc) · 11.6 KB

range-calendar.md

File metadata and controls

215 lines (182 loc) · 11.6 KB

RangeCalendar

RangeCalendar component provides a way to a range of dates while allowing you to style them however. All the date, month & year calculations are done internally using @internationalized/date to provide the ease of use. It follows the Grid Pattern for the keyboard navigaiton & focus management. Supports all the features as React Aria's useRangeCalendar.

Table of Contents

Usage

import * as React from "react";
import { VisuallyHidden } from "ariakit";
import { createCalendar, getWeeksInMonth } from "@internationalized/date";
import { useLocale } from "@react-aria/i18n";

import { ChevronLeft, ChevronRight } from "./Utils.component";
import {
  CalendarCell,
  CalendarCellButton,
  CalendarGrid,
  CalendarNextButton,
  CalendarPreviousButton,
  CalendarTitle,
  RangeCalendar,
  useCalendarCellState,
  useCalendarGridState,
  useRangeCalendarBaseState,
  useRangeCalendarState,
} from "@adaptui/react";

export const RangeCalendarBasic = props => {
  const { locale } = useLocale();

  const state = useRangeCalendarBaseState({ locale, createCalendar, ...props });
  const calendar = useRangeCalendarState({ ...props, state });

  return (
    <RangeCalendar state={calendar} className="calendar-range">
      <div className="header">
        <CalendarPreviousButton state={calendar} className="prev-month">
          <ChevronLeft />
        </CalendarPreviousButton>
        <CalendarTitle state={calendar} />
        <CalendarNextButton state={calendar} className="next-month">
          <ChevronRight />
        </CalendarNextButton>
      </div>
      <CalendarGridComp state={state} />
    </RangeCalendar>
  );
};

export default RangeCalendarBasic;

const CalendarGridComp = props => {
  const { state: baseState } = props;
  let { locale } = useLocale();
  let gridState = useCalendarGridState(props);

  let weeksInMonth = getWeeksInMonth(baseState.visibleRange.start, locale);

  return (
    <CalendarGrid state={gridState} className="dates">
      <thead>
        <tr>
          {gridState.weekDays.map((day, index) => {
            return (
              <th key={index}>
                {}
                <VisuallyHidden>{day}</VisuallyHidden>
                <span aria-hidden="true">{day}</span>
              </th>
            );
          })}
        </tr>
      </thead>
      <tbody>
        {[...new Array(weeksInMonth).keys()].map(weekIndex => (
          <tr key={weekIndex}>
            {baseState
              .getDatesInWeek(weekIndex)
              .map((date, i) =>
                date ? (
                  <CalendarCellComp key={i} state={baseState} date={date} />
                ) : (
                  <td key={i} />
                ),
              )}
          </tr>
        ))}
      </tbody>
    </CalendarGrid>
  );
};

const CalendarCellComp = props => {
  const cellState = useCalendarCellState(props);
  const {
    isOutsideVisibleRange,
    isDisabled,
    isSelected,
    isUnavailable,
    formattedDate,
  } = cellState;

  return (
    <CalendarCell state={cellState}>
      <CalendarCellButton
        state={cellState}
        hidden={isOutsideVisibleRange}
        className={`cell ${isSelected ? "selected" : ""} ${
          isDisabled ? "disabled" : ""
        } ${isUnavailable ? "unavailable" : ""}`}
      >
        {formattedDate}
      </CalendarCellButton>
    </CalendarCell>
  );
};

Edit CodeSandbox Edit CodeSandbox

You can customize and style the ranges with CSS attribute selectors

[data-is-range-selection] > span {
  /* styles for any cells between start-end (inclusive) */
}
[data-is-selection-start] > span {
  /* styles for first selected range cell */
}
[data-is-selection-end] > span {
  /* styles for end selected range cell */
}

/* only applied if cell date is first or last of the month*/
[data-is-range-start] > span {
  /**/
}
[data-is-range-end] > span {
  /**/
}

Other Examples

Edit CodeSandbox Edit CodeSandbox

Composition

  • RangeCalendar uses Role
  • useRangeCalendarBaseState uses useRangeCalendarState
  • useRangeCalendarState uses its own state

Props

RangeCalendarOptions

Name Type Description
state RangeCalendarState Object returned by the useRangeCalendarState hook.

RangeCalendarBaseStateProps

Name Type Description
locale string The locale to display and edit the value according to.
createCalendar (name: string) => Calendar A function that creates a Calendarobject for a given calendar identifier. Such a function may be imported from the@internationalized/date package, or manually implemented to include support foronly certain calendars.
RangeCalendarStateProps props > These props are returned by the other props You can also provide these props.
Name Type Description
visibleDuration DateDuration | undefined The amount of days that will be displayed at once. This affects how pagination works.
allowsNonContiguousRanges boolean | undefined When combined with isDateUnavailable, determines whether non-contiguous ranges,i.e. ranges containing unavailable dates, may be selected.
minValue DateValue | undefined The minimum allowed date that a user may select.
maxValue DateValue | undefined The maximum allowed date that a user may select.
isDateUnavailable ((date: DateValue) => boolean) | undefined Callback that is called for each date of the calendar. If it returns true, then the date is unavailable.
isDisabled boolean | undefined Whether the calendar is disabled.
isReadOnly boolean | undefined Whether the calendar value is immutable.
autoFocus boolean | undefined Whether to automatically focus the calendar when it mounts.
focusedValue DateValue | undefined Controls the currently focused date within the calendar.
defaultFocusedValue DateValue | undefined The date that is focused when the calendar first mounts (uncountrolled).
onFocusChange ((date: CalendarDate) => void) | undefined Handler that is called when the focused date changes.
validationState ValidationState | undefined Whether the current selection is valid or invalid according to application logic.
errorMessage ReactNode An error message to display when the selected value is invalid.
value T | undefined The current value (controlled).
defaultValue T | undefined The default value (uncontrolled).
onChange ((value: C) => void) | undefined Handler that is called when the value changes.

RangeCalendarStateProps

Name Type Description
state RangeCalendarState Object returned by the useRangeCalendarBaseState hook.