feat(date-picker): support configurable week starts
This commit is contained in:
@@ -37,7 +37,7 @@ function DatePickerPlayground() {
|
|||||||
|
|
||||||
function DatePickerScenarios() {
|
function DatePickerScenarios() {
|
||||||
return (
|
return (
|
||||||
<div className="grid w-full max-w-4xl gap-4 md:grid-cols-2">
|
<div className="grid w-full max-w-6xl gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Empty state</CardTitle>
|
<CardTitle>Empty state</CardTitle>
|
||||||
@@ -48,6 +48,24 @@ function DatePickerScenarios() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Sunday-first calendar</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Opt into Sunday-through-Saturday when matching US-style calendar conventions.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<DatePicker
|
||||||
|
aria-label="Sunday-first launch date"
|
||||||
|
defaultMonth={new Date(2026, 2, 1)}
|
||||||
|
defaultValue={new Date(2026, 2, 18)}
|
||||||
|
locale="en-US"
|
||||||
|
weekStartsOn="sunday"
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Guardrailed window</CardTitle>
|
<CardTitle>Guardrailed window</CardTitle>
|
||||||
@@ -76,7 +94,7 @@ const meta = {
|
|||||||
docs: {
|
docs: {
|
||||||
description: {
|
description: {
|
||||||
component:
|
component:
|
||||||
"A single-date picker for launch windows, review deadlines, and operator scheduling surfaces. This first slice stays intentionally narrow: one date, one popover calendar, no range or timezone API."
|
"A single-date picker for launch windows, review deadlines, and operator scheduling surfaces. It defaults to a Monday-through-Sunday calendar, with an opt-in Sunday-first mode for teams that need that convention. This first slice stays intentionally narrow: one date, one popover calendar, no range or timezone API."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
layout: "centered"
|
layout: "centered"
|
||||||
|
|||||||
@@ -86,6 +86,39 @@ describe("DatePicker", () => {
|
|||||||
expect(screen.getByText("April 2028")).toBeInTheDocument();
|
expect(screen.getByText("April 2028")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("defaults to a monday-first calendar grid", () => {
|
||||||
|
render(
|
||||||
|
<DatePicker
|
||||||
|
aria-label="Monday-first date"
|
||||||
|
defaultMonth={new Date(2026, 2, 1)}
|
||||||
|
defaultOpen
|
||||||
|
locale="en-US"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const firstDay = within(screen.getByRole("grid")).getAllByRole("gridcell")[0];
|
||||||
|
|
||||||
|
expect(firstDay).toHaveAccessibleName("Feb 23, 2026");
|
||||||
|
expect(screen.getByText("Mon")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("supports sunday-first calendar grids when requested", () => {
|
||||||
|
render(
|
||||||
|
<DatePicker
|
||||||
|
aria-label="Sunday-first date"
|
||||||
|
defaultMonth={new Date(2026, 2, 1)}
|
||||||
|
defaultOpen
|
||||||
|
locale="en-US"
|
||||||
|
weekStartsOn="sunday"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const firstDay = within(screen.getByRole("grid")).getAllByRole("gridcell")[0];
|
||||||
|
|
||||||
|
expect(firstDay).toHaveAccessibleName("Mar 1, 2026");
|
||||||
|
expect(screen.getByText("Sun")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it("respects min and max dates", async () => {
|
it("respects min and max dates", async () => {
|
||||||
render(
|
render(
|
||||||
<DatePicker
|
<DatePicker
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import { createDataAttributes, createSlot } from "../lib/contracts";
|
|||||||
import { ChevronDownIcon, ChevronRightIcon } from "../lib/icons";
|
import { ChevronDownIcon, ChevronRightIcon } from "../lib/icons";
|
||||||
|
|
||||||
type DatePickerValue = Date | undefined;
|
type DatePickerValue = Date | undefined;
|
||||||
|
export type DatePickerWeekStartsOn = "monday" | "sunday";
|
||||||
|
|
||||||
function startOfMonth(value: Date) {
|
function startOfMonth(value: Date) {
|
||||||
return new Date(value.getFullYear(), value.getMonth(), 1);
|
return new Date(value.getFullYear(), value.getMonth(), 1);
|
||||||
@@ -102,9 +103,14 @@ function formatMonthLabel(value: Date, locale?: string) {
|
|||||||
}).format(value);
|
}).format(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMonthGrid(month: Date) {
|
function getWeekStartIndex(weekStartsOn: DatePickerWeekStartsOn) {
|
||||||
|
return weekStartsOn === "monday" ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMonthGrid(month: Date, weekStartsOn: DatePickerWeekStartsOn) {
|
||||||
const firstDay = startOfMonth(month);
|
const firstDay = startOfMonth(month);
|
||||||
const startOffset = firstDay.getDay();
|
const weekStartIndex = getWeekStartIndex(weekStartsOn);
|
||||||
|
const startOffset = (firstDay.getDay() - weekStartIndex + 7) % 7;
|
||||||
const gridStart = new Date(firstDay);
|
const gridStart = new Date(firstDay);
|
||||||
gridStart.setDate(firstDay.getDate() - startOffset);
|
gridStart.setDate(firstDay.getDate() - startOffset);
|
||||||
|
|
||||||
@@ -198,6 +204,7 @@ export type DatePickerProps = Omit<
|
|||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
todayLabel?: ReactNode;
|
todayLabel?: ReactNode;
|
||||||
value?: Date;
|
value?: Date;
|
||||||
|
weekStartsOn?: DatePickerWeekStartsOn;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(function DatePicker(
|
export const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(function DatePicker(
|
||||||
@@ -220,6 +227,7 @@ export const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(function
|
|||||||
placeholder = "Select date",
|
placeholder = "Select date",
|
||||||
todayLabel = "Today",
|
todayLabel = "Today",
|
||||||
value,
|
value,
|
||||||
|
weekStartsOn = "monday",
|
||||||
...props
|
...props
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
@@ -260,15 +268,18 @@ export const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(function
|
|||||||
const monthLabel = formatMonthLabel(visibleMonth, locale);
|
const monthLabel = formatMonthLabel(visibleMonth, locale);
|
||||||
const weekdays = useMemo(() => {
|
const weekdays = useMemo(() => {
|
||||||
const formatter = new Intl.DateTimeFormat(locale, { weekday: "short" });
|
const formatter = new Intl.DateTimeFormat(locale, { weekday: "short" });
|
||||||
const base = new Date(2025, 0, 5);
|
const base = new Date(2025, 0, 5 + getWeekStartIndex(weekStartsOn));
|
||||||
|
|
||||||
return Array.from({ length: 7 }, (_, index) => {
|
return Array.from({ length: 7 }, (_, index) => {
|
||||||
const day = new Date(base);
|
const day = new Date(base);
|
||||||
day.setDate(base.getDate() + index);
|
day.setDate(base.getDate() + index);
|
||||||
return formatter.format(day);
|
return formatter.format(day);
|
||||||
});
|
});
|
||||||
}, [locale]);
|
}, [locale, weekStartsOn]);
|
||||||
const days = useMemo(() => buildMonthGrid(visibleMonth), [visibleMonth]);
|
const days = useMemo(
|
||||||
|
() => buildMonthGrid(visibleMonth, weekStartsOn),
|
||||||
|
[visibleMonth, weekStartsOn]
|
||||||
|
);
|
||||||
const yearOptions = useMemo(
|
const yearOptions = useMemo(
|
||||||
() => getYearOptions(visibleMonth, selectedDate),
|
() => getYearOptions(visibleMonth, selectedDate),
|
||||||
[selectedDate, visibleMonth]
|
[selectedDate, visibleMonth]
|
||||||
@@ -420,161 +431,165 @@ export const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(function
|
|||||||
</PopoverAnchor>
|
</PopoverAnchor>
|
||||||
|
|
||||||
<PopoverContent className={datePickerContentVariants()} padding="sm" size="xl">
|
<PopoverContent className={datePickerContentVariants()} padding="sm" size="xl">
|
||||||
<div {...createSlot("header")} className={datePickerHeaderVariants()}>
|
<div className="grid gap-3">
|
||||||
<div className={datePickerNavigationVariants()}>
|
<div {...createSlot("header")} className={datePickerHeaderVariants()}>
|
||||||
<Button
|
<div className={datePickerNavigationVariants()}>
|
||||||
aria-label="Previous month"
|
<Button
|
||||||
size="icon"
|
aria-label="Previous month"
|
||||||
variant="ghost"
|
size="icon"
|
||||||
onClick={() => {
|
variant="ghost"
|
||||||
goToMonth(-1);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ChevronRightIcon className="size-3.5 rotate-180" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={datePickerSelectorsVariants()}>
|
|
||||||
<Select
|
|
||||||
value={String(visibleMonth.getMonth())}
|
|
||||||
onValueChange={(nextValue) => {
|
|
||||||
const nextMonth = new Date(visibleMonth.getFullYear(), Number(nextValue), 1);
|
|
||||||
setVisibleMonth(nextMonth);
|
|
||||||
onMonthChange?.(nextMonth);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectTrigger aria-label="Month" className="w-full">
|
|
||||||
<SelectValue placeholder={monthLabel} />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{Array.from({ length: 12 }, (_, monthIndex) => {
|
|
||||||
const monthName = new Intl.DateTimeFormat(locale, {
|
|
||||||
month: "long"
|
|
||||||
}).format(new Date(visibleMonth.getFullYear(), monthIndex, 1));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SelectItem key={monthIndex} value={String(monthIndex)}>
|
|
||||||
{monthName}
|
|
||||||
</SelectItem>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
value={String(visibleMonth.getFullYear())}
|
|
||||||
onValueChange={(nextValue) => {
|
|
||||||
const nextMonth = new Date(Number(nextValue), visibleMonth.getMonth(), 1);
|
|
||||||
setVisibleMonth(nextMonth);
|
|
||||||
onMonthChange?.(nextMonth);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectTrigger aria-label="Year" className="w-full">
|
|
||||||
<SelectValue placeholder={String(visibleMonth.getFullYear())} />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{yearOptions.map((year) => (
|
|
||||||
<SelectItem key={year} value={String(year)}>
|
|
||||||
{year}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={datePickerNavigationVariants()}>
|
|
||||||
<Button
|
|
||||||
aria-label="Next month"
|
|
||||||
size="icon"
|
|
||||||
variant="ghost"
|
|
||||||
onClick={() => {
|
|
||||||
goToMonth(1);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ChevronRightIcon className="size-3.5" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p className={datePickerCaptionVariants()}>{monthLabel}</p>
|
|
||||||
|
|
||||||
<div className={datePickerWeekdayVariants()}>
|
|
||||||
{weekdays.map((weekday) => (
|
|
||||||
<span key={weekday}>{weekday}</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={datePickerGridVariants()} role="grid">
|
|
||||||
{days.map((day, index) => {
|
|
||||||
const outside = day.getMonth() !== visibleMonth.getMonth();
|
|
||||||
const selected = sameDay(day, selectedDate);
|
|
||||||
const isToday = sameDay(day, today);
|
|
||||||
const dayDisabled = isDateDisabled(day, minDate, maxDate);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={day.toISOString()}
|
|
||||||
{...createSlot("day")}
|
|
||||||
{...createDataAttributes({
|
|
||||||
disabled: dayDisabled,
|
|
||||||
outside,
|
|
||||||
selected,
|
|
||||||
today: isToday
|
|
||||||
})}
|
|
||||||
aria-label={formatValue(day, locale)}
|
|
||||||
aria-pressed={selected}
|
|
||||||
className={datePickerDayVariants()}
|
|
||||||
disabled={dayDisabled}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedDate(normalizeDate(day));
|
goToMonth(-1);
|
||||||
setOpenState(false);
|
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => handleDayKeyDown(event, index)}
|
|
||||||
ref={(node) => {
|
|
||||||
dayRefs.current[index] = node;
|
|
||||||
}}
|
|
||||||
role="gridcell"
|
|
||||||
type="button"
|
|
||||||
>
|
>
|
||||||
{day.getDate()}
|
<ChevronRightIcon className="size-3.5 rotate-180" />
|
||||||
</button>
|
</Button>
|
||||||
);
|
</div>
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={datePickerFooterVariants()}>
|
<div className={datePickerSelectorsVariants()}>
|
||||||
<Button
|
<Select
|
||||||
size="sm"
|
value={String(visibleMonth.getMonth())}
|
||||||
variant="subtle"
|
onValueChange={(nextValue) => {
|
||||||
onClick={() => {
|
const nextMonth = new Date(visibleMonth.getFullYear(), Number(nextValue), 1);
|
||||||
setSelectedDate(today);
|
setVisibleMonth(nextMonth);
|
||||||
if (today) {
|
onMonthChange?.(nextMonth);
|
||||||
setVisibleMonth(startOfMonth(today));
|
}}
|
||||||
}
|
>
|
||||||
setOpenState(false);
|
<SelectTrigger aria-label="Month" className="w-full">
|
||||||
}}
|
<SelectValue placeholder={monthLabel} />
|
||||||
>
|
</SelectTrigger>
|
||||||
{todayLabel}
|
<SelectContent>
|
||||||
</Button>
|
{Array.from({ length: 12 }, (_, monthIndex) => {
|
||||||
<div className="flex items-center gap-2">
|
const monthName = new Intl.DateTimeFormat(locale, {
|
||||||
|
month: "long"
|
||||||
|
}).format(new Date(visibleMonth.getFullYear(), monthIndex, 1));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SelectItem key={monthIndex} value={String(monthIndex)}>
|
||||||
|
{monthName}
|
||||||
|
</SelectItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
value={String(visibleMonth.getFullYear())}
|
||||||
|
onValueChange={(nextValue) => {
|
||||||
|
const nextMonth = new Date(Number(nextValue), visibleMonth.getMonth(), 1);
|
||||||
|
setVisibleMonth(nextMonth);
|
||||||
|
onMonthChange?.(nextMonth);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger aria-label="Year" className="w-full">
|
||||||
|
<SelectValue placeholder={String(visibleMonth.getFullYear())} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{yearOptions.map((year) => (
|
||||||
|
<SelectItem key={year} value={String(year)}>
|
||||||
|
{year}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={datePickerNavigationVariants()}>
|
||||||
|
<Button
|
||||||
|
aria-label="Next month"
|
||||||
|
size="icon"
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
goToMonth(1);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ChevronRightIcon className="size-3.5" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<p className={datePickerCaptionVariants()}>{monthLabel}</p>
|
||||||
|
|
||||||
|
<div className={datePickerWeekdayVariants()}>
|
||||||
|
{weekdays.map((weekday) => (
|
||||||
|
<span key={weekday}>{weekday}</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={datePickerGridVariants()} role="grid">
|
||||||
|
{days.map((day, index) => {
|
||||||
|
const outside = day.getMonth() !== visibleMonth.getMonth();
|
||||||
|
const selected = sameDay(day, selectedDate);
|
||||||
|
const isToday = sameDay(day, today);
|
||||||
|
const dayDisabled = isDateDisabled(day, minDate, maxDate);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={day.toISOString()}
|
||||||
|
{...createSlot("day")}
|
||||||
|
{...createDataAttributes({
|
||||||
|
disabled: dayDisabled,
|
||||||
|
outside,
|
||||||
|
selected,
|
||||||
|
today: isToday
|
||||||
|
})}
|
||||||
|
aria-label={formatValue(day, locale)}
|
||||||
|
aria-pressed={selected}
|
||||||
|
className={datePickerDayVariants()}
|
||||||
|
disabled={dayDisabled}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedDate(normalizeDate(day));
|
||||||
|
setOpenState(false);
|
||||||
|
}}
|
||||||
|
onKeyDown={(event) => handleDayKeyDown(event, index)}
|
||||||
|
ref={(node) => {
|
||||||
|
dayRefs.current[index] = node;
|
||||||
|
}}
|
||||||
|
role="gridcell"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
{day.getDate()}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={datePickerFooterVariants()}>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="subtle"
|
||||||
onClick={() => {
|
|
||||||
setSelectedDate(undefined);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{clearLabel}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="secondary"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
setSelectedDate(today);
|
||||||
|
if (today) {
|
||||||
|
setVisibleMonth(startOfMonth(today));
|
||||||
|
}
|
||||||
setOpenState(false);
|
setOpenState(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Done
|
{todayLabel}
|
||||||
</Button>
|
</Button>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedDate(undefined);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{clearLabel}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
setOpenState(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Done
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ export const datePickerFieldVariants = cva("relative");
|
|||||||
export const datePickerTriggerVariants = cva("w-full");
|
export const datePickerTriggerVariants = cva("w-full");
|
||||||
|
|
||||||
export const datePickerContentVariants = cva([
|
export const datePickerContentVariants = cva([
|
||||||
"relative z-50 w-[21rem] overflow-hidden rounded-[var(--ui-panel-radius)] border border-[var(--ui-panel-border)] bg-[var(--ui-panel-bg)] p-0 text-[var(--color-card-foreground)] shadow-[var(--ui-panel-shadow)] outline-none",
|
"relative z-50 w-[22rem] overflow-hidden rounded-[var(--ui-panel-radius)] border border-[var(--ui-panel-border)] bg-[var(--ui-panel-bg)] text-[var(--color-card-foreground)] shadow-[var(--ui-panel-shadow)] outline-none",
|
||||||
"[border-width:var(--ui-panel-border-width)] backdrop-blur-[var(--ui-panel-backdrop-blur)]",
|
"[border-width:var(--ui-panel-border-width)] backdrop-blur-[var(--ui-panel-backdrop-blur)]",
|
||||||
"data-[state=open]:motion-enter-rise data-[state=closed]:motion-exit-drop"
|
"data-[state=open]:motion-enter-rise data-[state=closed]:motion-exit-drop"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const datePickerHeaderVariants = cva(
|
export const datePickerHeaderVariants = cva(
|
||||||
"grid gap-3 sm:grid-cols-[auto_minmax(0,1fr)_auto]"
|
"grid items-center gap-3 sm:grid-cols-[auto_minmax(0,1fr)_auto]"
|
||||||
);
|
);
|
||||||
|
|
||||||
export const datePickerNavigationVariants = cva("flex items-center gap-2");
|
export const datePickerNavigationVariants = cva("flex items-center gap-2");
|
||||||
@@ -26,7 +26,7 @@ export const datePickerMonthLabelVariants = cva(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const datePickerCaptionVariants = cva(
|
export const datePickerCaptionVariants = cva(
|
||||||
"px-1 text-sm leading-6 text-[var(--color-muted-foreground)]"
|
"text-sm leading-6 text-[var(--color-muted-foreground)]"
|
||||||
);
|
);
|
||||||
|
|
||||||
export const datePickerWeekdayVariants = cva(
|
export const datePickerWeekdayVariants = cva(
|
||||||
@@ -50,5 +50,5 @@ export const datePickerDayVariants = cva(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const datePickerFooterVariants = cva(
|
export const datePickerFooterVariants = cva(
|
||||||
"flex flex-wrap items-center justify-between gap-3 border-t border-[var(--ui-panel-border)] pt-3"
|
"mt-1 flex flex-wrap items-center justify-between gap-3 border-t border-[var(--ui-panel-border)] pt-3"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -148,7 +148,11 @@ export {
|
|||||||
dataTableTableVariants,
|
dataTableTableVariants,
|
||||||
dataTableToolbarVariants
|
dataTableToolbarVariants
|
||||||
} from "./components/data-table.variants";
|
} from "./components/data-table.variants";
|
||||||
export { DatePicker, type DatePickerProps } from "./components/date-picker";
|
export {
|
||||||
|
DatePicker,
|
||||||
|
type DatePickerProps,
|
||||||
|
type DatePickerWeekStartsOn
|
||||||
|
} from "./components/date-picker";
|
||||||
export {
|
export {
|
||||||
datePickerContentVariants,
|
datePickerContentVariants,
|
||||||
datePickerDayVariants,
|
datePickerDayVariants,
|
||||||
|
|||||||
Reference in New Issue
Block a user