mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
refactor(calendar): cell tab index fixed, width property added (#2744)
* refactor(calendar): cell tab index fixed, width property added * chore(date-picker): remove needless omit
This commit is contained in:
parent
ccd8f730e1
commit
158c2aa004
7
.changeset/tall-buttons-jam.md
Normal file
7
.changeset/tall-buttons-jam.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
"@nextui-org/calendar": patch
|
||||
"@nextui-org/date-picker": patch
|
||||
"@nextui-org/theme": patch
|
||||
---
|
||||
|
||||
Refactor calendar cell tab index, add calendar default width
|
||||
@ -23,11 +23,10 @@ A calendar consists of a grouping element containing one or more date grids (e.g
|
||||
npm: "npm install @nextui-org/calendar",
|
||||
yarn: "yarn add @nextui-org/calendar",
|
||||
pnpm: "pnpm add @nextui-org/calendar",
|
||||
bun: "bun add @nextui-org/calendar"
|
||||
bun: "bun add @nextui-org/calendar",
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
## Import
|
||||
|
||||
<ImportTabs
|
||||
@ -209,6 +208,7 @@ Here's the example to customize `topContent` and `bottomContent` to have some pr
|
||||
| visibleMonths | `number` | The number of months to display at once. Up to 3 months are supported. Passing a number greater than 1 will disable the `showMonthAndYearPickers` prop | `1` |
|
||||
| focusedValue | `DateValue` | Controls the currently focused date within the calendar. | - |
|
||||
| defaultFocusedValue | `DateValue` | The date that is focused when the calendar first mounts (uncountrolled). | - |
|
||||
| calendarWidth | `number` \| `string` | The width to be applied to the calendar component. This value is multiplied by the `visibleMonths` number to determine the total width of the calendar. | `256` |
|
||||
| pageBehavior | `single` \| `visible` | Controls the behavior of paging. Pagination either works by advancing the visible page by visibleDuration (default) or one unit of visibleDuration. | `visible` |
|
||||
| weekdayStyle | `narrow` \|`short` \| `long` \| `undefined` | The style of weekday names to display in the calendar grid header, e.g. single letter, abbreviation, or full day name. | `narrow` |
|
||||
| showMonthAndYearPickers | `boolean` | Whether the label should be crossed out. | `false` |
|
||||
|
||||
@ -23,7 +23,7 @@ A range calendar consists of a grouping element containing one or more date grid
|
||||
npm: "npm install @nextui-org/calendar",
|
||||
yarn: "yarn add @nextui-org/calendar",
|
||||
pnpm: "pnpm add @nextui-org/calendar",
|
||||
bun: "bun add @nextui-org/calendar"
|
||||
bun: "bun add @nextui-org/calendar",
|
||||
}}
|
||||
/>
|
||||
|
||||
@ -210,6 +210,7 @@ Here's the example to customize `topContent` and `bottomContent` to have some pr
|
||||
| visibleMonths | `number` | The number of months to display at once. Up to 3 months are supported. Passing a number greater than 1 will disable the `showMonthAndYearPickers` prop | `1` | |
|
||||
| focusedValue | `DateValue` | Controls the currently focused date within the calendar. | - | |
|
||||
| defaultFocusedValue | `DateValue` | The date that is focused when the calendar first mounts (uncountrolled). | - | |
|
||||
| calendarWidth | `number` \| `string` | The width to be applied to the calendar component. This value is multiplied by the `visibleMonths` number to determine the total width of the calendar. | `256` |
|
||||
| pageBehavior | `PageBehavior` | Controls the behavior of paging. Pagination either works by advancing the visible page by visibleDuration (default) or one unit of visibleDuration. | `visible` | |
|
||||
| weekdayStyle | `"narrow" \|"short" \| "long" \| undefined` | The style of weekday names to display in the calendar grid header, e.g. single letter, abbreviation, or full day name. | `narrow` | |
|
||||
| allowsNonContiguousRanges | `boolean` | When combined with `isDateUnavailable`, determines whether non-contiguous ranges, i.e. ranges containing unavailable dates, may be selected. | `false` | |
|
||||
|
||||
@ -69,7 +69,7 @@ export function CalendarCell(originalProps: CalendarCellProps) {
|
||||
|
||||
return (
|
||||
<td className={slots?.cell({class: classNames?.cell})} data-slot="cell" {...cellProps}>
|
||||
<button
|
||||
<span
|
||||
{...mergeProps(buttonProps, hoverProps, focusProps)}
|
||||
ref={ref}
|
||||
className={slots?.cellButton({class: classNames?.cellButton})}
|
||||
@ -88,10 +88,9 @@ export function CalendarCell(originalProps: CalendarCellProps) {
|
||||
data-selection-start={dataAttr(isSelectionStart)}
|
||||
data-today={dataAttr(isToday(props.date, state.timeZone))}
|
||||
data-unavailable={dataAttr(isUnavailable)}
|
||||
tabIndex={isDisabled ? -1 : 0}
|
||||
>
|
||||
<span>{formattedDate}</span>
|
||||
</button>
|
||||
</span>
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
@ -63,6 +63,9 @@ export function CalendarMonth(props: CalendarMonthProps) {
|
||||
key={weekIndex}
|
||||
className={slots?.gridBodyRow({class: classNames?.gridBodyRow})}
|
||||
data-slot="grid-body-row"
|
||||
// makes the browser ignore the element and its children when tabbing
|
||||
// @ts-ignore
|
||||
inert={isHeaderExpanded ? true : undefined}
|
||||
>
|
||||
{state
|
||||
.getDatesInWeek(weekIndex, startDate)
|
||||
|
||||
@ -65,6 +65,9 @@ export function CalendarPicker(props: CalendarPickerProps) {
|
||||
class: classNames?.pickerWrapper,
|
||||
})}
|
||||
data-slot="picker-wrapper"
|
||||
// makes the browser ignore the element and its children when tabbing
|
||||
// @ts-ignore
|
||||
inert={isHeaderExpanded ? true : undefined}
|
||||
>
|
||||
<div
|
||||
ref={highlightRef}
|
||||
|
||||
@ -16,7 +16,7 @@ import {calendar} from "@nextui-org/theme";
|
||||
import {useControlledState} from "@react-stately/utils";
|
||||
import {ReactRef, useDOMRef} from "@nextui-org/react-utils";
|
||||
import {useLocale} from "@react-aria/i18n";
|
||||
import {clamp, objectToDeps} from "@nextui-org/shared-utils";
|
||||
import {clamp, dataAttr, objectToDeps} from "@nextui-org/shared-utils";
|
||||
import {mergeProps} from "@react-aria/utils";
|
||||
import {useProviderContext} from "@nextui-org/system";
|
||||
|
||||
@ -42,6 +42,13 @@ interface Props extends NextUIBaseProps {
|
||||
* @default 1
|
||||
*/
|
||||
visibleMonths?: number;
|
||||
/**
|
||||
* The width to be applied to the calendar component. This value is multiplied by the number
|
||||
* of visible months to determine the total width of the calendar.
|
||||
*
|
||||
* @default 256
|
||||
*/
|
||||
calendarWidth?: number | string;
|
||||
/**
|
||||
* Props for the navigation button, prev button and next button.
|
||||
*/
|
||||
@ -185,6 +192,7 @@ export function useCalendarBase(originalProps: UseCalendarBasePropsComplete) {
|
||||
topContent,
|
||||
bottomContent,
|
||||
showHelper = true,
|
||||
calendarWidth = 256,
|
||||
visibleMonths: visibleMonthsProp = 1,
|
||||
weekdayStyle = "narrow",
|
||||
navButtonProps = {},
|
||||
@ -229,6 +237,7 @@ export function useCalendarBase(originalProps: UseCalendarBasePropsComplete) {
|
||||
);
|
||||
|
||||
const visibleDuration = useMemo(() => ({months: visibleMonths}), [visibleMonths]);
|
||||
const hasMultipleMonths = visibleMonths > 1;
|
||||
const shouldFilterDOMProps = typeof Component === "string";
|
||||
|
||||
const {locale} = useLocale();
|
||||
@ -256,6 +265,16 @@ export function useCalendarBase(originalProps: UseCalendarBasePropsComplete) {
|
||||
...navButtonProps,
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
"data-slot": "base",
|
||||
"data-has-multiple-months": dataAttr(hasMultipleMonths),
|
||||
style: {
|
||||
// @ts-ignore
|
||||
"--visible-months": visibleMonths,
|
||||
"--calendar-width": calendarWidth,
|
||||
} as React.CSSProperties,
|
||||
};
|
||||
|
||||
const getPrevButtonProps = (props = {}) => {
|
||||
return {
|
||||
"data-slot": "prev-button",
|
||||
@ -290,6 +309,7 @@ export function useCalendarBase(originalProps: UseCalendarBasePropsComplete) {
|
||||
locale,
|
||||
minValue,
|
||||
maxValue,
|
||||
baseProps,
|
||||
showHelper,
|
||||
weekdayStyle,
|
||||
visibleMonths,
|
||||
|
||||
@ -38,6 +38,7 @@ export function useCalendar<T extends DateValue>({
|
||||
showHelper,
|
||||
weekdayStyle,
|
||||
visibleDuration,
|
||||
baseProps,
|
||||
shouldFilterDOMProps,
|
||||
isHeaderExpanded,
|
||||
visibleMonths,
|
||||
@ -81,6 +82,7 @@ export function useCalendar<T extends DateValue>({
|
||||
|
||||
const getBaseCalendarProps = (props = {}): CalendarBaseProps => {
|
||||
return {
|
||||
...baseProps,
|
||||
Component,
|
||||
showHelper,
|
||||
topContent,
|
||||
|
||||
@ -40,6 +40,7 @@ export function useRangeCalendar<T extends DateValue>({
|
||||
isHeaderExpanded,
|
||||
visibleMonths,
|
||||
createCalendar: createCalendarProp,
|
||||
baseProps,
|
||||
getPrevButtonProps,
|
||||
getNextButtonProps,
|
||||
getErrorMessageProps,
|
||||
@ -73,6 +74,7 @@ export function useRangeCalendar<T extends DateValue>({
|
||||
|
||||
const getBaseCalendarProps = (props = {}): CalendarBaseProps => {
|
||||
return {
|
||||
...baseProps,
|
||||
Component,
|
||||
showHelper,
|
||||
topContent,
|
||||
|
||||
@ -12,8 +12,7 @@ import {CalendarBoldIcon} from "@nextui-org/shared-icons";
|
||||
|
||||
import {UseDatePickerProps, useDatePicker} from "./use-date-picker";
|
||||
|
||||
export interface Props<T extends DateValue>
|
||||
extends Omit<UseDatePickerProps<T>, "hasMultipleMonths"> {}
|
||||
export interface Props<T extends DateValue> extends UseDatePickerProps<T> {}
|
||||
|
||||
function DatePicker<T extends DateValue>(props: Props<T>, ref: ForwardedRef<HTMLDivElement>) {
|
||||
const {
|
||||
|
||||
@ -13,8 +13,7 @@ import {CalendarBoldIcon} from "@nextui-org/shared-icons";
|
||||
import DateRangePickerField from "./date-range-picker-field";
|
||||
import {UseDateRangePickerProps, useDateRangePicker} from "./use-date-range-picker";
|
||||
|
||||
export interface Props<T extends DateValue>
|
||||
extends Omit<UseDateRangePickerProps<T>, "hasMultipleMonths"> {}
|
||||
export interface Props<T extends DateValue> extends UseDateRangePickerProps<T> {}
|
||||
|
||||
function DateRangePicker<T extends DateValue>(props: Props<T>, ref: ForwardedRef<HTMLDivElement>) {
|
||||
const {
|
||||
|
||||
@ -236,18 +236,8 @@ export function useDatePickerBase<T extends DateValue>(originalProps: UseDatePic
|
||||
|
||||
const calendarProps = {
|
||||
...slotsProps.calendarProps,
|
||||
calendarWidth,
|
||||
"data-slot": "calendar",
|
||||
"data-has-multiple-months": dataAttr(hasMultipleMonths),
|
||||
style: mergeProps(
|
||||
hasMultipleMonths
|
||||
? {
|
||||
// @ts-ignore
|
||||
"--visible-months": visibleMonths,
|
||||
}
|
||||
: {},
|
||||
{"--calendar-width": `${calendarWidth}px`},
|
||||
slotsProps.calendarProps.style,
|
||||
),
|
||||
} as CalendarProps;
|
||||
|
||||
const selectorButtonProps = {
|
||||
|
||||
@ -59,7 +59,6 @@ export function useDatePicker<T extends DateValue>({
|
||||
endContent,
|
||||
selectorIcon,
|
||||
createCalendar,
|
||||
hasMultipleMonths,
|
||||
isCalendarHeaderExpanded,
|
||||
disableAnimation,
|
||||
CalendarTopContent,
|
||||
@ -88,10 +87,9 @@ export function useDatePicker<T extends DateValue>({
|
||||
() =>
|
||||
datePicker({
|
||||
...variantProps,
|
||||
hasMultipleMonths,
|
||||
className,
|
||||
}),
|
||||
[objectToDeps(variantProps), hasMultipleMonths, className],
|
||||
[objectToDeps(variantProps), className],
|
||||
);
|
||||
|
||||
let {
|
||||
|
||||
@ -116,10 +116,9 @@ export function useDateRangePicker<T extends DateValue>({
|
||||
() =>
|
||||
dateRangePicker({
|
||||
...variantProps,
|
||||
hasMultipleMonths,
|
||||
className,
|
||||
}),
|
||||
[objectToDeps(variantProps), hasMultipleMonths, className],
|
||||
[objectToDeps(variantProps), className],
|
||||
);
|
||||
|
||||
// Time field values
|
||||
@ -258,7 +257,7 @@ export function useDateRangePicker<T extends DateValue>({
|
||||
labelPlacement,
|
||||
className,
|
||||
}),
|
||||
[objectToDeps(variantProps), hasMultipleMonths, className],
|
||||
[objectToDeps(variantProps), className],
|
||||
);
|
||||
|
||||
const getStartDateInputProps = (props: DOMAttributes = {}) => {
|
||||
|
||||
@ -8,6 +8,7 @@ const calendar = tv({
|
||||
base: [
|
||||
"relative w-fit max-w-full shadow-small inline-block overflow-y-hidden",
|
||||
"rounded-large overflow-x-auto bg-default-50 dark:bg-background",
|
||||
"w-[calc(var(--visible-months)_*_var(--calendar-width))]",
|
||||
],
|
||||
prevButton: [],
|
||||
nextButton: [],
|
||||
@ -22,7 +23,7 @@ const calendar = tv({
|
||||
],
|
||||
header: "flex w-full items-center justify-center gap-2 z-10",
|
||||
title: "text-default-500 text-small font-medium",
|
||||
content: "w-fit",
|
||||
content: "w-[calc(var(--visible-months)_*_var(--calendar-width))]",
|
||||
gridWrapper: "flex max-w-full overflow-hidden pb-2 h-auto relative",
|
||||
grid: "w-full border-collapse z-0",
|
||||
gridHeader: "bg-content1 shadow-[0px_20px_20px_0px_rgb(0_0_0/0.05)]",
|
||||
|
||||
@ -18,19 +18,6 @@ const datePicker = tv({
|
||||
timeInputLabel: "font-medium",
|
||||
timeInput: "px-5 pb-4 flex-wrap gap-x-6",
|
||||
},
|
||||
variants: {
|
||||
// @internal
|
||||
hasMultipleMonths: {
|
||||
true: {
|
||||
calendar: "w-[calc(var(--visible-months)_*_var(--calendar-width))]",
|
||||
calendarContent: "w-[calc(var(--visible-months)_*_var(--calendar-width))]",
|
||||
},
|
||||
false: {},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
hasMultipleMonths: false,
|
||||
},
|
||||
});
|
||||
|
||||
const dateRangePicker = tv({
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user