文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar01() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
className="rounded-lg border shadow-sm"
/>
)
}
一个简单的日历。
calendar-01
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar01() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
className="rounded-lg border shadow-sm"
/>
)
}
文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar02() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
defaultMonth={date}
numberOfMonths={2}
selected={date}
onSelect={setDate}
className="rounded-lg border shadow-sm"
/>
)
}
多月单选。
calendar-02
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
2025 年 7 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar02() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
defaultMonth={date}
numberOfMonths={2}
selected={date}
onSelect={setDate}
className="rounded-lg border shadow-sm"
/>
)
}
文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar03() {
const [dates, setDates] = React.useState<Date[]>([
new Date(2025, 5, 12),
new Date(2025, 6, 24),
])
return (
<Calendar
mode="multiple"
numberOfMonths={2}
defaultMonth={dates[0]}
required
selected={dates}
onSelect={setDates}
max={5}
className="rounded-lg border shadow-sm"
/>
)
}
多月多选。
calendar-03
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
2025 年 7 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar03() {
const [dates, setDates] = React.useState<Date[]>([
new Date(2025, 5, 12),
new Date(2025, 6, 24),
])
return (
<Calendar
mode="multiple"
numberOfMonths={2}
defaultMonth={dates[0]}
required
selected={dates}
onSelect={setDates}
max={5}
className="rounded-lg border shadow-sm"
/>
)
}
文件
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar04() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 9),
to: new Date(2025, 5, 26),
})
return (
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
className="rounded-lg border shadow-sm"
/>
)
}
单月范围选择
calendar-04
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar04() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 9),
to: new Date(2025, 5, 26),
})
return (
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
className="rounded-lg border shadow-sm"
/>
)
}
文件
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar05() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 12),
to: new Date(2025, 6, 15),
})
return (
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={2}
className="rounded-lg border shadow-sm"
/>
)
}
多月范围选择
calendar-05
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
2025 年 7 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar05() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 12),
to: new Date(2025, 6, 15),
})
return (
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={2}
className="rounded-lg border shadow-sm"
/>
)
}
文件
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar06() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 12),
to: new Date(2025, 5, 26),
})
return (
<div className="flex min-w-0 flex-col gap-2">
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={1}
min={5}
className="rounded-lg border shadow-sm"
/>
<div className="text-muted-foreground text-center text-xs">
A minimum of 5 days is required
</div>
</div>
)
}
最少天数范围选择
calendar-06
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
至少需要选择 5 天
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar06() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 12),
to: new Date(2025, 5, 26),
})
return (
<div className="flex min-w-0 flex-col gap-2">
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={1}
min={5}
className="rounded-lg border shadow-sm"
/>
<div className="text-muted-foreground text-center text-xs">
A minimum of 5 days is required
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar07() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 18),
to: new Date(2025, 6, 7),
})
return (
<div className="flex min-w-0 flex-col gap-2">
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={2}
min={2}
max={20}
className="rounded-lg border shadow-sm"
/>
<div className="text-muted-foreground text-center text-xs">
Your stay must be between 2 and 20 nights
</div>
</div>
)
}
最少和最多天数范围选择
calendar-07
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
2025 年 7 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
您的住宿时长必须介于 2 到 20 晚之间
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar07() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 18),
to: new Date(2025, 6, 7),
})
return (
<div className="flex min-w-0 flex-col gap-2">
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={2}
min={2}
max={20}
className="rounded-lg border shadow-sm"
/>
<div className="text-muted-foreground text-center text-xs">
Your stay must be between 2 and 20 nights
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar08() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
disabled={{
before: new Date(2025, 5, 12),
}}
className="rounded-lg border shadow-sm"
/>
)
}
禁用日期的日历
calendar-08
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar08() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
disabled={{
before: new Date(2025, 5, 12),
}}
className="rounded-lg border shadow-sm"
/>
)
}
文件
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar09() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 17),
to: new Date(2025, 5, 20),
})
return (
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={2}
disabled={{ dayOfWeek: [0, 6] }}
className="rounded-lg border shadow-sm"
excludeDisabled
/>
)
}
禁用周末的日历
calendar-09
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
2025 年 7 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar09() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 17),
to: new Date(2025, 5, 20),
})
return (
<Calendar
mode="range"
defaultMonth={dateRange?.from}
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={2}
disabled={{ dayOfWeek: [0, 6] }}
className="rounded-lg border shadow-sm"
excludeDisabled
/>
)
}
文件
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
export function Calendar10() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
const [month, setMonth] = React.useState<Date | undefined>(new Date())
return (
<Card>
<CardHeader>
<CardTitle>Appointment</CardTitle>
<CardDescription>Find a date</CardDescription>
<CardAction>
<Button
size="sm"
variant="outline"
onClick={() => {
setMonth(new Date())
setDate(new Date())
}}
>
Today
</Button>
</CardAction>
</CardHeader>
<CardContent>
<Calendar
mode="single"
month={month}
onMonthChange={setMonth}
selected={date}
onSelect={setDate}
className="bg-transparent p-0"
/>
</CardContent>
</Card>
)
}
今日按钮
calendar-10
预约
选择日期
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
export function Calendar10() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
const [month, setMonth] = React.useState<Date | undefined>(new Date())
return (
<Card>
<CardHeader>
<CardTitle>Appointment</CardTitle>
<CardDescription>Find a date</CardDescription>
<CardAction>
<Button
size="sm"
variant="outline"
onClick={() => {
setMonth(new Date())
setDate(new Date())
}}
>
Today
</Button>
</CardAction>
</CardHeader>
<CardContent>
<Calendar
mode="single"
month={month}
onMonthChange={setMonth}
selected={date}
onSelect={setDate}
className="bg-transparent p-0"
/>
</CardContent>
</Card>
)
}
文件
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar11() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 17),
to: new Date(2025, 5, 20),
})
return (
<div className="flex min-w-0 flex-col gap-2">
<Calendar
mode="range"
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={2}
startMonth={new Date(2025, 5, 1)}
endMonth={new Date(2025, 6, 31)}
disableNavigation
className="rounded-lg border shadow-sm"
/>
<div className="text-muted-foreground text-center text-xs">
We are open in June and July only.
</div>
</div>
)
}
月份开始和结束
calendar-11
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
2025 年 7 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
我们仅在 6 月和 7 月开放。
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { Calendar } from "@/components/ui/calendar"
export function Calendar11() {
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 17),
to: new Date(2025, 5, 20),
})
return (
<div className="flex min-w-0 flex-col gap-2">
<Calendar
mode="range"
selected={dateRange}
onSelect={setDateRange}
numberOfMonths={2}
startMonth={new Date(2025, 5, 1)}
endMonth={new Date(2025, 6, 31)}
disableNavigation
className="rounded-lg border shadow-sm"
/>
<div className="text-muted-foreground text-center text-xs">
We are open in June and July only.
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { enUS, es } from "react-day-picker/locale"
import { Calendar } from "@/components/ui/calendar"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const localizedStrings = {
en: {
title: "Book an appointment",
description: "Select the dates for your appointment",
},
es: {
title: "Reserva una cita",
description: "Selecciona las fechas para tu cita",
},
} as const
export function Calendar12() {
const [locale, setLocale] =
React.useState<keyof typeof localizedStrings>("es")
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 8, 9),
to: new Date(2025, 8, 17),
})
return (
<Card>
<CardHeader className="border-b">
<CardTitle>{localizedStrings[locale].title}</CardTitle>
<CardDescription>
{localizedStrings[locale].description}
</CardDescription>
<CardAction>
<Select
value={locale}
onValueChange={(value) =>
setLocale(value as keyof typeof localizedStrings)
}
>
<SelectTrigger className="w-[100px]">
<SelectValue placeholder="Language" />
</SelectTrigger>
<SelectContent align="end">
<SelectItem value="es">Español</SelectItem>
<SelectItem value="en">English</SelectItem>
</SelectContent>
</Select>
</CardAction>
</CardHeader>
<CardContent>
<Calendar
mode="range"
selected={dateRange}
onSelect={setDateRange}
defaultMonth={dateRange?.from}
numberOfMonths={2}
locale={locale === "es" ? es : enUS}
className="bg-transparent p-0"
buttonVariant="outline"
/>
</CardContent>
</Card>
)
}
本地化日历
calendar-12
Reserva una cita
Selecciona las fechas para tu cita
septiembre 2025
lu | ma | mi | ju | vi | sá | do |
---|---|---|---|---|---|---|
octubre 2025
lu | ma | mi | ju | vi | sá | do |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { type DateRange } from "react-day-picker"
import { enUS, es } from "react-day-picker/locale"
import { Calendar } from "@/components/ui/calendar"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
const localizedStrings = {
en: {
title: "Book an appointment",
description: "Select the dates for your appointment",
},
es: {
title: "Reserva una cita",
description: "Selecciona las fechas para tu cita",
},
} as const
export function Calendar12() {
const [locale, setLocale] =
React.useState<keyof typeof localizedStrings>("es")
const [dateRange, setDateRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 8, 9),
to: new Date(2025, 8, 17),
})
return (
<Card>
<CardHeader className="border-b">
<CardTitle>{localizedStrings[locale].title}</CardTitle>
<CardDescription>
{localizedStrings[locale].description}
</CardDescription>
<CardAction>
<Select
value={locale}
onValueChange={(value) =>
setLocale(value as keyof typeof localizedStrings)
}
>
<SelectTrigger className="w-[100px]">
<SelectValue placeholder="Language" />
</SelectTrigger>
<SelectContent align="end">
<SelectItem value="es">Español</SelectItem>
<SelectItem value="en">English</SelectItem>
</SelectContent>
</Select>
</CardAction>
</CardHeader>
<CardContent>
<Calendar
mode="range"
selected={dateRange}
onSelect={setDateRange}
defaultMonth={dateRange?.from}
numberOfMonths={2}
locale={locale === "es" ? es : enUS}
className="bg-transparent p-0"
buttonVariant="outline"
/>
</CardContent>
</Card>
)
}
文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
import { Label } from "@/components/ui/label"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function Calendar13() {
const [dropdown, setDropdown] =
React.useState<React.ComponentProps<typeof Calendar>["captionLayout"]>(
"dropdown"
)
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<div className="flex flex-col gap-4">
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
captionLayout={dropdown}
className="rounded-lg border shadow-sm"
/>
<div className="flex flex-col gap-3">
<Label htmlFor="dropdown" className="px-1">
Dropdown
</Label>
<Select
value={dropdown}
onValueChange={(value) =>
setDropdown(
value as React.ComponentProps<typeof Calendar>["captionLayout"]
)
}
>
<SelectTrigger
id="dropdown"
size="sm"
className="bg-background w-full"
>
<SelectValue placeholder="Dropdown" />
</SelectTrigger>
<SelectContent align="center">
<SelectItem value="dropdown">Month and Year</SelectItem>
<SelectItem value="dropdown-months">Month Only</SelectItem>
<SelectItem value="dropdown-years">Year Only</SelectItem>
</SelectContent>
</Select>
</div>
</div>
)
}
带月份和年份下拉菜单
calendar-13
六月20252025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
import { Label } from "@/components/ui/label"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function Calendar13() {
const [dropdown, setDropdown] =
React.useState<React.ComponentProps<typeof Calendar>["captionLayout"]>(
"dropdown"
)
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<div className="flex flex-col gap-4">
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
captionLayout={dropdown}
className="rounded-lg border shadow-sm"
/>
<div className="flex flex-col gap-3">
<Label htmlFor="dropdown" className="px-1">
Dropdown
</Label>
<Select
value={dropdown}
onValueChange={(value) =>
setDropdown(
value as React.ComponentProps<typeof Calendar>["captionLayout"]
)
}
>
<SelectTrigger
id="dropdown"
size="sm"
className="bg-background w-full"
>
<SelectValue placeholder="Dropdown" />
</SelectTrigger>
<SelectContent align="center">
<SelectItem value="dropdown">Month and Year</SelectItem>
<SelectItem value="dropdown-months">Month Only</SelectItem>
<SelectItem value="dropdown-years">Year Only</SelectItem>
</SelectContent>
</Select>
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar14() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
const bookedDates = Array.from(
{ length: 12 },
(_, i) => new Date(2025, 5, 15 + i)
)
return (
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
disabled={bookedDates}
modifiers={{
booked: bookedDates,
}}
modifiersClassNames={{
booked: "[&>button]:line-through opacity-100",
}}
className="rounded-lg border shadow-sm"
/>
)
}
带已预订/不可用日期
calendar-14
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar14() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
const bookedDates = Array.from(
{ length: 12 },
(_, i) => new Date(2025, 5, 15 + i)
)
return (
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
disabled={bookedDates}
modifiers={{
booked: bookedDates,
}}
modifiersClassNames={{
booked: "[&>button]:line-through opacity-100",
}}
className="rounded-lg border shadow-sm"
/>
)
}
文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar15() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
className="rounded-lg border shadow-sm"
showWeekNumber
/>
)
}
带周数
calendar-15
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 | |
---|---|---|---|---|---|---|---|
23 | |||||||
24 | |||||||
25 | |||||||
26 | |||||||
27 |
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar15() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
defaultMonth={date}
selected={date}
onSelect={setDate}
className="rounded-lg border shadow-sm"
showWeekNumber
/>
)
}
文件
"use client"
import * as React from "react"
import { Clock2Icon } from "lucide-react"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export function Calendar16() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Card className="w-fit py-4">
<CardContent className="px-4">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="bg-transparent p-0"
/>
</CardContent>
<CardFooter className="flex flex-col gap-6 border-t px-4 !pt-4">
<div className="flex w-full flex-col gap-3">
<Label htmlFor="time-from">Start Time</Label>
<div className="relative flex w-full items-center gap-2">
<Clock2Icon className="text-muted-foreground pointer-events-none absolute left-2.5 size-4 select-none" />
<Input
id="time-from"
type="time"
step="1"
defaultValue="10:30:00"
className="appearance-none pl-8 [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
<div className="flex w-full flex-col gap-3">
<Label htmlFor="time-to">End Time</Label>
<div className="relative flex w-full items-center gap-2">
<Clock2Icon className="text-muted-foreground pointer-events-none absolute left-2.5 size-4 select-none" />
<Input
id="time-to"
type="time"
step="1"
defaultValue="12:30:00"
className="appearance-none pl-8 [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
</CardFooter>
</Card>
)
}
带时间选择器
calendar-16
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Clock2Icon } from "lucide-react"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export function Calendar16() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Card className="w-fit py-4">
<CardContent className="px-4">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="bg-transparent p-0"
/>
</CardContent>
<CardFooter className="flex flex-col gap-6 border-t px-4 !pt-4">
<div className="flex w-full flex-col gap-3">
<Label htmlFor="time-from">Start Time</Label>
<div className="relative flex w-full items-center gap-2">
<Clock2Icon className="text-muted-foreground pointer-events-none absolute left-2.5 size-4 select-none" />
<Input
id="time-from"
type="time"
step="1"
defaultValue="10:30:00"
className="appearance-none pl-8 [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
<div className="flex w-full flex-col gap-3">
<Label htmlFor="time-to">End Time</Label>
<div className="relative flex w-full items-center gap-2">
<Clock2Icon className="text-muted-foreground pointer-events-none absolute left-2.5 size-4 select-none" />
<Input
id="time-to"
type="time"
step="1"
defaultValue="12:30:00"
className="appearance-none pl-8 [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
</CardFooter>
</Card>
)
}
文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export function Calendar17() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Card className="w-fit py-4">
<CardContent className="px-4">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="bg-transparent p-0 [--cell-size:--spacing(10.5)]"
/>
</CardContent>
<CardFooter className="flex gap-2 border-t px-4 !pt-4 *:[div]:w-full">
<div>
<Label htmlFor="time-from" className="sr-only">
Start Time
</Label>
<Input
id="time-from"
type="time"
step="1"
defaultValue="10:30:00"
className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
<span>-</span>
<div>
<Label htmlFor="time-to" className="sr-only">
End Time
</Label>
<Input
id="time-to"
type="time"
step="1"
defaultValue="12:30:00"
className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</CardFooter>
</Card>
)
}
带内联时间选择器
calendar-17
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
-
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export function Calendar17() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Card className="w-fit py-4">
<CardContent className="px-4">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="bg-transparent p-0 [--cell-size:--spacing(10.5)]"
/>
</CardContent>
<CardFooter className="flex gap-2 border-t px-4 !pt-4 *:[div]:w-full">
<div>
<Label htmlFor="time-from" className="sr-only">
Start Time
</Label>
<Input
id="time-from"
type="time"
step="1"
defaultValue="10:30:00"
className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
<span>-</span>
<div>
<Label htmlFor="time-to" className="sr-only">
End Time
</Label>
<Input
id="time-to"
type="time"
step="1"
defaultValue="12:30:00"
className="appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</CardFooter>
</Card>
)
}
文件
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar18() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border [--cell-size:--spacing(11)] md:[--cell-size:--spacing(12)]"
buttonVariant="ghost"
/>
)
}
可变大小
calendar-18
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { Calendar } from "@/components/ui/calendar"
export function Calendar18() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="rounded-lg border [--cell-size:--spacing(11)] md:[--cell-size:--spacing(12)]"
buttonVariant="ghost"
/>
)
}
文件
"use client"
import * as React from "react"
import { addDays } from "date-fns"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
export function Calendar19() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Card className="max-w-[300px] py-4">
<CardContent className="px-4">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
defaultMonth={date}
className="bg-transparent p-0 [--cell-size:--spacing(9.5)]"
/>
</CardContent>
<CardFooter className="flex flex-wrap gap-2 border-t px-4 !pt-4">
{[
{ label: "Today", value: 0 },
{ label: "Tomorrow", value: 1 },
{ label: "In 3 days", value: 3 },
{ label: "In a week", value: 7 },
{ label: "In 2 weeks", value: 14 },
].map((preset) => (
<Button
key={preset.value}
variant="outline"
size="sm"
className="flex-1"
onClick={() => {
const newDate = addDays(new Date(), preset.value)
setDate(newDate)
}}
>
{preset.label}
</Button>
))}
</CardFooter>
</Card>
)
}
带预设
calendar-19
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { addDays } from "date-fns"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
export function Calendar19() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Card className="max-w-[300px] py-4">
<CardContent className="px-4">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
defaultMonth={date}
className="bg-transparent p-0 [--cell-size:--spacing(9.5)]"
/>
</CardContent>
<CardFooter className="flex flex-wrap gap-2 border-t px-4 !pt-4">
{[
{ label: "Today", value: 0 },
{ label: "Tomorrow", value: 1 },
{ label: "In 3 days", value: 3 },
{ label: "In a week", value: 7 },
{ label: "In 2 weeks", value: 14 },
].map((preset) => (
<Button
key={preset.value}
variant="outline"
size="sm"
className="flex-1"
onClick={() => {
const newDate = addDays(new Date(), preset.value)
setDate(newDate)
}}
>
{preset.label}
</Button>
))}
</CardFooter>
</Card>
)
}
文件
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
export function Calendar20() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
const [selectedTime, setSelectedTime] = React.useState<string | null>("10:00")
const timeSlots = Array.from({ length: 37 }, (_, i) => {
const totalMinutes = i * 15
const hour = Math.floor(totalMinutes / 60) + 9
const minute = totalMinutes % 60
return `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`
})
const bookedDates = Array.from(
{ length: 3 },
(_, i) => new Date(2025, 5, 17 + i)
)
return (
<Card className="gap-0 p-0">
<CardContent className="relative p-0 md:pr-48">
<div className="p-6">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
defaultMonth={date}
disabled={bookedDates}
showOutsideDays={false}
modifiers={{
booked: bookedDates,
}}
modifiersClassNames={{
booked: "[&>button]:line-through opacity-100",
}}
className="bg-transparent p-0 [--cell-size:--spacing(10)] md:[--cell-size:--spacing(12)]"
formatters={{
formatWeekdayName: (date) => {
return date.toLocaleString("en-US", { weekday: "short" })
},
}}
/>
</div>
<div className="no-scrollbar inset-y-0 right-0 flex max-h-72 w-full scroll-pb-6 flex-col gap-4 overflow-y-auto border-t p-6 md:absolute md:max-h-none md:w-48 md:border-t-0 md:border-l">
<div className="grid gap-2">
{timeSlots.map((time) => (
<Button
key={time}
variant={selectedTime === time ? "default" : "outline"}
onClick={() => setSelectedTime(time)}
className="w-full shadow-none"
>
{time}
</Button>
))}
</div>
</div>
</CardContent>
<CardFooter className="flex flex-col gap-4 border-t px-6 !py-5 md:flex-row">
<div className="text-sm">
{date && selectedTime ? (
<>
Your meeting is booked for{" "}
<span className="font-medium">
{" "}
{date?.toLocaleDateString("en-US", {
weekday: "long",
day: "numeric",
month: "long",
})}{" "}
</span>
at <span className="font-medium">{selectedTime}</span>.
</>
) : (
<>Select a date and time for your meeting.</>
)}
</div>
<Button
disabled={!date || !selectedTime}
className="w-full md:ml-auto md:w-auto"
variant="outline"
>
Continue
</Button>
</CardFooter>
</Card>
)
}
带时间预设
calendar-20
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
您的会议已预订在 6 月 12 日,星期四 于 10:00。
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
export function Calendar20() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
const [selectedTime, setSelectedTime] = React.useState<string | null>("10:00")
const timeSlots = Array.from({ length: 37 }, (_, i) => {
const totalMinutes = i * 15
const hour = Math.floor(totalMinutes / 60) + 9
const minute = totalMinutes % 60
return `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`
})
const bookedDates = Array.from(
{ length: 3 },
(_, i) => new Date(2025, 5, 17 + i)
)
return (
<Card className="gap-0 p-0">
<CardContent className="relative p-0 md:pr-48">
<div className="p-6">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
defaultMonth={date}
disabled={bookedDates}
showOutsideDays={false}
modifiers={{
booked: bookedDates,
}}
modifiersClassNames={{
booked: "[&>button]:line-through opacity-100",
}}
className="bg-transparent p-0 [--cell-size:--spacing(10)] md:[--cell-size:--spacing(12)]"
formatters={{
formatWeekdayName: (date) => {
return date.toLocaleString("en-US", { weekday: "short" })
},
}}
/>
</div>
<div className="no-scrollbar inset-y-0 right-0 flex max-h-72 w-full scroll-pb-6 flex-col gap-4 overflow-y-auto border-t p-6 md:absolute md:max-h-none md:w-48 md:border-t-0 md:border-l">
<div className="grid gap-2">
{timeSlots.map((time) => (
<Button
key={time}
variant={selectedTime === time ? "default" : "outline"}
onClick={() => setSelectedTime(time)}
className="w-full shadow-none"
>
{time}
</Button>
))}
</div>
</div>
</CardContent>
<CardFooter className="flex flex-col gap-4 border-t px-6 !py-5 md:flex-row">
<div className="text-sm">
{date && selectedTime ? (
<>
Your meeting is booked for{" "}
<span className="font-medium">
{" "}
{date?.toLocaleDateString("en-US", {
weekday: "long",
day: "numeric",
month: "long",
})}{" "}
</span>
at <span className="font-medium">{selectedTime}</span>.
</>
) : (
<>Select a date and time for your meeting.</>
)}
</div>
<Button
disabled={!date || !selectedTime}
className="w-full md:ml-auto md:w-auto"
variant="outline"
>
Continue
</Button>
</CardFooter>
</Card>
)
}
文件
"use client"
import * as React from "react"
import { DateRange } from "react-day-picker"
import { Calendar, CalendarDayButton } from "@/components/ui/calendar"
export function Calendar21() {
const [range, setRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 12),
to: new Date(2025, 5, 17),
})
return (
<Calendar
mode="range"
defaultMonth={range?.from}
selected={range}
onSelect={setRange}
numberOfMonths={1}
captionLayout="dropdown"
className="rounded-lg border shadow-sm [--cell-size:--spacing(11)] md:[--cell-size:--spacing(13)]"
formatters={{
formatMonthDropdown: (date) => {
return date.toLocaleString("default", { month: "long" })
},
}}
components={{
DayButton: ({ children, modifiers, day, ...props }) => {
const isWeekend = day.date.getDay() === 0 || day.date.getDay() === 6
return (
<CalendarDayButton day={day} modifiers={modifiers} {...props}>
{children}
{!modifiers.outside && <span>{isWeekend ? "$220" : "$100"}</span>}
</CalendarDayButton>
)
},
}}
/>
)
}
自定义日期和格式化器
calendar-21
六月20252025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
"use client"
import * as React from "react"
import { DateRange } from "react-day-picker"
import { Calendar, CalendarDayButton } from "@/components/ui/calendar"
export function Calendar21() {
const [range, setRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 12),
to: new Date(2025, 5, 17),
})
return (
<Calendar
mode="range"
defaultMonth={range?.from}
selected={range}
onSelect={setRange}
numberOfMonths={1}
captionLayout="dropdown"
className="rounded-lg border shadow-sm [--cell-size:--spacing(11)] md:[--cell-size:--spacing(13)]"
formatters={{
formatMonthDropdown: (date) => {
return date.toLocaleString("default", { month: "long" })
},
}}
components={{
DayButton: ({ children, modifiers, day, ...props }) => {
const isWeekend = day.date.getDay() === 0 || day.date.getDay() === 6
return (
<CalendarDayButton day={day} modifiers={modifiers} {...props}>
{children}
{!modifiers.outside && <span>{isWeekend ? "$220" : "$100"}</span>}
</CalendarDayButton>
)
},
}}
/>
)
}
文件
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar22() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Date of birth
</Label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date"
className="w-48 justify-between font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
)
}
日期选择器
calendar-22
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar22() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Date of birth
</Label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date"
className="w-48 justify-between font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
)
}
文件
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { type DateRange } from "react-day-picker"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar23() {
const [range, setRange] = React.useState<DateRange | undefined>(undefined)
return (
<div className="flex flex-col gap-3">
<Label htmlFor="dates" className="px-1">
Select your stay
</Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
id="dates"
className="w-56 justify-between font-normal"
>
{range?.from && range?.to
? `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()}`
: "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="range"
selected={range}
captionLayout="dropdown"
onSelect={(range) => {
setRange(range)
}}
/>
</PopoverContent>
</Popover>
</div>
)
}
日期范围选择器
calendar-23
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { type DateRange } from "react-day-picker"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar23() {
const [range, setRange] = React.useState<DateRange | undefined>(undefined)
return (
<div className="flex flex-col gap-3">
<Label htmlFor="dates" className="px-1">
Select your stay
</Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
id="dates"
className="w-56 justify-between font-normal"
>
{range?.from && range?.to
? `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()}`
: "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="range"
selected={range}
captionLayout="dropdown"
onSelect={(range) => {
setRange(range)
}}
/>
</PopoverContent>
</Popover>
</div>
)
}
文件
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar24() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex gap-4">
<div className="flex flex-col gap-3">
<Label htmlFor="date-picker" className="px-1">
Date
</Label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-picker"
className="w-32 justify-between font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col gap-3">
<Label htmlFor="time-picker" className="px-1">
Time
</Label>
<Input
type="time"
id="time-picker"
step="1"
defaultValue="10:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
)
}
日期和时间选择器
calendar-24
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar24() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex gap-4">
<div className="flex flex-col gap-3">
<Label htmlFor="date-picker" className="px-1">
Date
</Label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-picker"
className="w-32 justify-between font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col gap-3">
<Label htmlFor="time-picker" className="px-1">
Time
</Label>
<Input
type="time"
id="time-picker"
step="1"
defaultValue="10:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar25() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Date
</Label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date"
className="w-full justify-between font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
<div className="flex gap-4">
<div className="flex flex-col gap-3">
<Label htmlFor="time-from" className="px-1">
From
</Label>
<Input
type="time"
id="time-from"
step="1"
defaultValue="10:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
<div className="flex flex-col gap-3">
<Label htmlFor="time-to" className="px-1">
To
</Label>
<Input
type="time"
id="time-to"
step="1"
defaultValue="12:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
</div>
)
}
日期和时间范围选择器
calendar-25
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar25() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Date
</Label>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date"
className="w-full justify-between font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
<div className="flex gap-4">
<div className="flex flex-col gap-3">
<Label htmlFor="time-from" className="px-1">
From
</Label>
<Input
type="time"
id="time-from"
step="1"
defaultValue="10:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
<div className="flex flex-col gap-3">
<Label htmlFor="time-to" className="px-1">
To
</Label>
<Input
type="time"
id="time-to"
step="1"
defaultValue="12:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar26() {
const [openFrom, setOpenFrom] = React.useState(false)
const [openTo, setOpenTo] = React.useState(false)
const [dateFrom, setDateFrom] = React.useState<Date | undefined>(
new Date("2025-06-01")
)
const [dateTo, setDateTo] = React.useState<Date | undefined>(
new Date("2025-06-03")
)
return (
<div className="flex w-full max-w-64 min-w-0 flex-col gap-6">
<div className="flex gap-4">
<div className="flex flex-1 flex-col gap-3">
<Label htmlFor="date-from" className="px-1">
Check-in
</Label>
<Popover open={openFrom} onOpenChange={setOpenFrom}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-from"
className="w-full justify-between font-normal"
>
{dateFrom
? dateFrom.toLocaleDateString("en-US", {
day: "2-digit",
month: "short",
year: "numeric",
})
: "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent
className="w-auto overflow-hidden p-0"
align="start"
>
<Calendar
mode="single"
selected={dateFrom}
captionLayout="dropdown"
onSelect={(date) => {
setDateFrom(date)
setOpenFrom(false)
}}
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col gap-3">
<Label htmlFor="time-from" className="invisible px-1">
From
</Label>
<Input
type="time"
id="time-from"
step="1"
defaultValue="10:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
<div className="flex gap-4">
<div className="flex flex-1 flex-col gap-3">
<Label htmlFor="date-to" className="px-1">
Check-out
</Label>
<Popover open={openTo} onOpenChange={setOpenTo}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-to"
className="w-full justify-between font-normal"
>
{dateTo
? dateTo.toLocaleDateString("en-US", {
day: "2-digit",
month: "short",
year: "numeric",
})
: "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent
className="w-auto overflow-hidden p-0"
align="start"
>
<Calendar
mode="single"
selected={dateTo}
captionLayout="dropdown"
onSelect={(date) => {
setDateTo(date)
setOpenTo(false)
}}
disabled={dateFrom && { before: dateFrom }}
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col gap-3">
<Label htmlFor="time-to" className="invisible px-1">
To
</Label>
<Input
type="time"
id="time-to"
step="1"
defaultValue="12:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
</div>
)
}
带时间选择的日期范围选择器
calendar-26
"use client"
import * as React from "react"
import { ChevronDownIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar26() {
const [openFrom, setOpenFrom] = React.useState(false)
const [openTo, setOpenTo] = React.useState(false)
const [dateFrom, setDateFrom] = React.useState<Date | undefined>(
new Date("2025-06-01")
)
const [dateTo, setDateTo] = React.useState<Date | undefined>(
new Date("2025-06-03")
)
return (
<div className="flex w-full max-w-64 min-w-0 flex-col gap-6">
<div className="flex gap-4">
<div className="flex flex-1 flex-col gap-3">
<Label htmlFor="date-from" className="px-1">
Check-in
</Label>
<Popover open={openFrom} onOpenChange={setOpenFrom}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-from"
className="w-full justify-between font-normal"
>
{dateFrom
? dateFrom.toLocaleDateString("en-US", {
day: "2-digit",
month: "short",
year: "numeric",
})
: "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent
className="w-auto overflow-hidden p-0"
align="start"
>
<Calendar
mode="single"
selected={dateFrom}
captionLayout="dropdown"
onSelect={(date) => {
setDateFrom(date)
setOpenFrom(false)
}}
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col gap-3">
<Label htmlFor="time-from" className="invisible px-1">
From
</Label>
<Input
type="time"
id="time-from"
step="1"
defaultValue="10:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
<div className="flex gap-4">
<div className="flex flex-1 flex-col gap-3">
<Label htmlFor="date-to" className="px-1">
Check-out
</Label>
<Popover open={openTo} onOpenChange={setOpenTo}>
<PopoverTrigger asChild>
<Button
variant="outline"
id="date-to"
className="w-full justify-between font-normal"
>
{dateTo
? dateTo.toLocaleDateString("en-US", {
day: "2-digit",
month: "short",
year: "numeric",
})
: "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent
className="w-auto overflow-hidden p-0"
align="start"
>
<Calendar
mode="single"
selected={dateTo}
captionLayout="dropdown"
onSelect={(date) => {
setDateTo(date)
setOpenTo(false)
}}
disabled={dateFrom && { before: dateFrom }}
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col gap-3">
<Label htmlFor="time-to" className="invisible px-1">
To
</Label>
<Input
type="time"
id="time-to"
step="1"
defaultValue="12:30:00"
className="bg-background appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none"
/>
</div>
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { CalendarIcon } from "lucide-react"
import { DateRange } from "react-day-picker"
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import {
ChartConfig,
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from "@/components/ui/chart"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
const chartData = [
{ date: "2025-06-01", visitors: 178 },
{ date: "2025-06-02", visitors: 470 },
{ date: "2025-06-03", visitors: 103 },
{ date: "2025-06-04", visitors: 439 },
{ date: "2025-06-05", visitors: 88 },
{ date: "2025-06-06", visitors: 294 },
{ date: "2025-06-07", visitors: 323 },
{ date: "2025-06-08", visitors: 385 },
{ date: "2025-06-09", visitors: 438 },
{ date: "2025-06-10", visitors: 155 },
{ date: "2025-06-11", visitors: 92 },
{ date: "2025-06-12", visitors: 492 },
{ date: "2025-06-13", visitors: 81 },
{ date: "2025-06-14", visitors: 426 },
{ date: "2025-06-15", visitors: 307 },
{ date: "2025-06-16", visitors: 371 },
{ date: "2025-06-17", visitors: 475 },
{ date: "2025-06-18", visitors: 107 },
{ date: "2025-06-19", visitors: 341 },
{ date: "2025-06-20", visitors: 408 },
{ date: "2025-06-21", visitors: 169 },
{ date: "2025-06-22", visitors: 317 },
{ date: "2025-06-23", visitors: 480 },
{ date: "2025-06-24", visitors: 132 },
{ date: "2025-06-25", visitors: 141 },
{ date: "2025-06-26", visitors: 434 },
{ date: "2025-06-27", visitors: 448 },
{ date: "2025-06-28", visitors: 149 },
{ date: "2025-06-29", visitors: 103 },
{ date: "2025-06-30", visitors: 446 },
]
const total = chartData.reduce((acc, curr) => acc + curr.visitors, 0)
const chartConfig = {
visitors: {
label: "Visitors",
color: "var(--color-primary)",
},
} satisfies ChartConfig
export function Calendar27() {
const [range, setRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 5),
to: new Date(2025, 5, 20),
})
const filteredData = React.useMemo(() => {
if (!range?.from && !range?.to) {
return chartData
}
return chartData.filter((item) => {
const date = new Date(item.date)
return date >= range.from! && date <= range.to!
})
}, [range])
return (
<Card className="@container/card w-full max-w-xl">
<CardHeader className="flex flex-col border-b @md/card:grid">
<CardTitle>Web Analytics</CardTitle>
<CardDescription>
Showing total visitors for this month.
</CardDescription>
<CardAction className="mt-2 @md/card:mt-0">
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">
<CalendarIcon />
{range?.from && range?.to
? `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()}`
: "June 2025"}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="end">
<Calendar
className="w-full"
mode="range"
defaultMonth={range?.from}
selected={range}
onSelect={setRange}
disableNavigation
startMonth={range?.from}
fixedWeeks
showOutsideDays
disabled={{
after: new Date(2025, 5, 31),
}}
/>
</PopoverContent>
</Popover>
</CardAction>
</CardHeader>
<CardContent className="px-4">
<ChartContainer
config={chartConfig}
className="aspect-auto h-[250px] w-full"
>
<BarChart
accessibilityLayer
data={filteredData}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="date"
tickLine={false}
axisLine={false}
tickMargin={8}
minTickGap={20}
tickFormatter={(value) => {
const date = new Date(value)
return date.toLocaleDateString("en-US", {
day: "numeric",
})
}}
/>
<ChartTooltip
content={
<ChartTooltipContent
className="w-[150px]"
nameKey="visitors"
labelFormatter={(value) => {
return new Date(value).toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
})
}}
/>
}
/>
<Bar dataKey="visitors" fill={`var(--color-visitors)`} radius={4} />
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter className="border-t">
<div className="text-sm">
You had{" "}
<span className="font-semibold">{total.toLocaleString()}</span>{" "}
visitors for the month of June.
</div>
</CardFooter>
</Card>
)
}
图表筛选器
calendar-27
网站分析
显示本月总访问量。
您有 8,792 6 月份的访问量。
"use client"
import * as React from "react"
import { CalendarIcon } from "lucide-react"
import { DateRange } from "react-day-picker"
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import {
ChartConfig,
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from "@/components/ui/chart"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
const chartData = [
{ date: "2025-06-01", visitors: 178 },
{ date: "2025-06-02", visitors: 470 },
{ date: "2025-06-03", visitors: 103 },
{ date: "2025-06-04", visitors: 439 },
{ date: "2025-06-05", visitors: 88 },
{ date: "2025-06-06", visitors: 294 },
{ date: "2025-06-07", visitors: 323 },
{ date: "2025-06-08", visitors: 385 },
{ date: "2025-06-09", visitors: 438 },
{ date: "2025-06-10", visitors: 155 },
{ date: "2025-06-11", visitors: 92 },
{ date: "2025-06-12", visitors: 492 },
{ date: "2025-06-13", visitors: 81 },
{ date: "2025-06-14", visitors: 426 },
{ date: "2025-06-15", visitors: 307 },
{ date: "2025-06-16", visitors: 371 },
{ date: "2025-06-17", visitors: 475 },
{ date: "2025-06-18", visitors: 107 },
{ date: "2025-06-19", visitors: 341 },
{ date: "2025-06-20", visitors: 408 },
{ date: "2025-06-21", visitors: 169 },
{ date: "2025-06-22", visitors: 317 },
{ date: "2025-06-23", visitors: 480 },
{ date: "2025-06-24", visitors: 132 },
{ date: "2025-06-25", visitors: 141 },
{ date: "2025-06-26", visitors: 434 },
{ date: "2025-06-27", visitors: 448 },
{ date: "2025-06-28", visitors: 149 },
{ date: "2025-06-29", visitors: 103 },
{ date: "2025-06-30", visitors: 446 },
]
const total = chartData.reduce((acc, curr) => acc + curr.visitors, 0)
const chartConfig = {
visitors: {
label: "Visitors",
color: "var(--color-primary)",
},
} satisfies ChartConfig
export function Calendar27() {
const [range, setRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 5),
to: new Date(2025, 5, 20),
})
const filteredData = React.useMemo(() => {
if (!range?.from && !range?.to) {
return chartData
}
return chartData.filter((item) => {
const date = new Date(item.date)
return date >= range.from! && date <= range.to!
})
}, [range])
return (
<Card className="@container/card w-full max-w-xl">
<CardHeader className="flex flex-col border-b @md/card:grid">
<CardTitle>Web Analytics</CardTitle>
<CardDescription>
Showing total visitors for this month.
</CardDescription>
<CardAction className="mt-2 @md/card:mt-0">
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">
<CalendarIcon />
{range?.from && range?.to
? `${range.from.toLocaleDateString()} - ${range.to.toLocaleDateString()}`
: "June 2025"}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="end">
<Calendar
className="w-full"
mode="range"
defaultMonth={range?.from}
selected={range}
onSelect={setRange}
disableNavigation
startMonth={range?.from}
fixedWeeks
showOutsideDays
disabled={{
after: new Date(2025, 5, 31),
}}
/>
</PopoverContent>
</Popover>
</CardAction>
</CardHeader>
<CardContent className="px-4">
<ChartContainer
config={chartConfig}
className="aspect-auto h-[250px] w-full"
>
<BarChart
accessibilityLayer
data={filteredData}
margin={{
left: 12,
right: 12,
}}
>
<CartesianGrid vertical={false} />
<XAxis
dataKey="date"
tickLine={false}
axisLine={false}
tickMargin={8}
minTickGap={20}
tickFormatter={(value) => {
const date = new Date(value)
return date.toLocaleDateString("en-US", {
day: "numeric",
})
}}
/>
<ChartTooltip
content={
<ChartTooltipContent
className="w-[150px]"
nameKey="visitors"
labelFormatter={(value) => {
return new Date(value).toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
})
}}
/>
}
/>
<Bar dataKey="visitors" fill={`var(--color-visitors)`} radius={4} />
</BarChart>
</ChartContainer>
</CardContent>
<CardFooter className="border-t">
<div className="text-sm">
You had{" "}
<span className="font-semibold">{total.toLocaleString()}</span>{" "}
visitors for the month of June.
</div>
</CardFooter>
</Card>
)
}
文件
"use client"
import * as React from "react"
import { CalendarIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
function formatDate(date: Date | undefined) {
if (!date) {
return ""
}
return date.toLocaleDateString("en-US", {
day: "2-digit",
month: "long",
year: "numeric",
})
}
function isValidDate(date: Date | undefined) {
if (!date) {
return false
}
return !isNaN(date.getTime())
}
export function Calendar28() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(
new Date("2025-06-01")
)
const [month, setMonth] = React.useState<Date | undefined>(date)
const [value, setValue] = React.useState(formatDate(date))
return (
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Subscription Date
</Label>
<div className="relative flex gap-2">
<Input
id="date"
value={value}
placeholder="June 01, 2025"
className="bg-background pr-10"
onChange={(e) => {
const date = new Date(e.target.value)
setValue(e.target.value)
if (isValidDate(date)) {
setDate(date)
setMonth(date)
}
}}
onKeyDown={(e) => {
if (e.key === "ArrowDown") {
e.preventDefault()
setOpen(true)
}
}}
/>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
id="date-picker"
variant="ghost"
className="absolute top-1/2 right-2 size-6 -translate-y-1/2"
>
<CalendarIcon className="size-3.5" />
<span className="sr-only">Select date</span>
</Button>
</PopoverTrigger>
<PopoverContent
className="w-auto overflow-hidden p-0"
align="end"
alignOffset={-8}
sideOffset={10}
>
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
month={month}
onMonthChange={setMonth}
onSelect={(date) => {
setDate(date)
setValue(formatDate(date))
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
</div>
)
}
带日期选择器的输入框
calendar-28
"use client"
import * as React from "react"
import { CalendarIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
function formatDate(date: Date | undefined) {
if (!date) {
return ""
}
return date.toLocaleDateString("en-US", {
day: "2-digit",
month: "long",
year: "numeric",
})
}
function isValidDate(date: Date | undefined) {
if (!date) {
return false
}
return !isNaN(date.getTime())
}
export function Calendar28() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(
new Date("2025-06-01")
)
const [month, setMonth] = React.useState<Date | undefined>(date)
const [value, setValue] = React.useState(formatDate(date))
return (
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Subscription Date
</Label>
<div className="relative flex gap-2">
<Input
id="date"
value={value}
placeholder="June 01, 2025"
className="bg-background pr-10"
onChange={(e) => {
const date = new Date(e.target.value)
setValue(e.target.value)
if (isValidDate(date)) {
setDate(date)
setMonth(date)
}
}}
onKeyDown={(e) => {
if (e.key === "ArrowDown") {
e.preventDefault()
setOpen(true)
}
}}
/>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
id="date-picker"
variant="ghost"
className="absolute top-1/2 right-2 size-6 -translate-y-1/2"
>
<CalendarIcon className="size-3.5" />
<span className="sr-only">Select date</span>
</Button>
</PopoverTrigger>
<PopoverContent
className="w-auto overflow-hidden p-0"
align="end"
alignOffset={-8}
sideOffset={10}
>
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
month={month}
onMonthChange={setMonth}
onSelect={(date) => {
setDate(date)
setValue(formatDate(date))
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { parseDate } from "chrono-node"
import { CalendarIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
function formatDate(date: Date | undefined) {
if (!date) {
return ""
}
return date.toLocaleDateString("en-US", {
day: "2-digit",
month: "long",
year: "numeric",
})
}
export function Calendar29() {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState("In 2 days")
const [date, setDate] = React.useState<Date | undefined>(
parseDate(value) || undefined
)
const [month, setMonth] = React.useState<Date | undefined>(date)
return (
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Schedule Date
</Label>
<div className="relative flex gap-2">
<Input
id="date"
value={value}
placeholder="Tomorrow or next week"
className="bg-background pr-10"
onChange={(e) => {
setValue(e.target.value)
const date = parseDate(e.target.value)
if (date) {
setDate(date)
setMonth(date)
}
}}
onKeyDown={(e) => {
if (e.key === "ArrowDown") {
e.preventDefault()
setOpen(true)
}
}}
/>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
id="date-picker"
variant="ghost"
className="absolute top-1/2 right-2 size-6 -translate-y-1/2"
>
<CalendarIcon className="size-3.5" />
<span className="sr-only">Select date</span>
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="end">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
month={month}
onMonthChange={setMonth}
onSelect={(date) => {
setDate(date)
setValue(formatDate(date))
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
<div className="text-muted-foreground px-1 text-sm">
Your post will be published on{" "}
<span className="font-medium">{formatDate(date)}</span>.
</div>
</div>
)
}
自然语言日期选择器
calendar-29
您的帖子将于 2025 年 6 月 21 日.
"use client"
import * as React from "react"
import { parseDate } from "chrono-node"
import { CalendarIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
function formatDate(date: Date | undefined) {
if (!date) {
return ""
}
return date.toLocaleDateString("en-US", {
day: "2-digit",
month: "long",
year: "numeric",
})
}
export function Calendar29() {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState("In 2 days")
const [date, setDate] = React.useState<Date | undefined>(
parseDate(value) || undefined
)
const [month, setMonth] = React.useState<Date | undefined>(date)
return (
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Schedule Date
</Label>
<div className="relative flex gap-2">
<Input
id="date"
value={value}
placeholder="Tomorrow or next week"
className="bg-background pr-10"
onChange={(e) => {
setValue(e.target.value)
const date = parseDate(e.target.value)
if (date) {
setDate(date)
setMonth(date)
}
}}
onKeyDown={(e) => {
if (e.key === "ArrowDown") {
e.preventDefault()
setOpen(true)
}
}}
/>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
id="date-picker"
variant="ghost"
className="absolute top-1/2 right-2 size-6 -translate-y-1/2"
>
<CalendarIcon className="size-3.5" />
<span className="sr-only">Select date</span>
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="end">
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
month={month}
onMonthChange={setMonth}
onSelect={(date) => {
setDate(date)
setValue(formatDate(date))
setOpen(false)
}}
/>
</PopoverContent>
</Popover>
</div>
<div className="text-muted-foreground px-1 text-sm">
Your post will be published on{" "}
<span className="font-medium">{formatDate(date)}</span>.
</div>
</div>
)
}
文件
"use client"
import * as React from "react"
import { formatDateRange } from "little-date"
import { ChevronDownIcon } from "lucide-react"
import { type DateRange } from "react-day-picker"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar30() {
const [range, setRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 4),
to: new Date(2025, 5, 10),
})
return (
<div className="flex flex-col gap-3">
<Label htmlFor="dates" className="px-1">
Select your stay
</Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
id="dates"
className="w-56 justify-between font-normal"
>
{range?.from && range?.to
? formatDateRange(range.from, range.to, {
includeTime: false,
})
: "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="range"
selected={range}
captionLayout="dropdown"
onSelect={(range) => {
setRange(range)
}}
/>
</PopoverContent>
</Popover>
</div>
)
}
带精简日期
calendar-30
"use client"
import * as React from "react"
import { formatDateRange } from "little-date"
import { ChevronDownIcon } from "lucide-react"
import { type DateRange } from "react-day-picker"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Label } from "@/components/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function Calendar30() {
const [range, setRange] = React.useState<DateRange | undefined>({
from: new Date(2025, 5, 4),
to: new Date(2025, 5, 10),
})
return (
<div className="flex flex-col gap-3">
<Label htmlFor="dates" className="px-1">
Select your stay
</Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
id="dates"
className="w-56 justify-between font-normal"
>
{range?.from && range?.to
? formatDateRange(range.from, range.to, {
includeTime: false,
})
: "Select date"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto overflow-hidden p-0" align="start">
<Calendar
mode="range"
selected={range}
captionLayout="dropdown"
onSelect={(range) => {
setRange(range)
}}
/>
</PopoverContent>
</Popover>
</div>
)
}
文件
"use client"
import * as React from "react"
import { formatDateRange } from "little-date"
import { PlusIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
const events = [
{
title: "Team Sync Meeting",
from: "2025-06-12T09:00:00",
to: "2025-06-12T10:00:00",
},
{
title: "Design Review",
from: "2025-06-12T11:30:00",
to: "2025-06-12T12:30:00",
},
{
title: "Client Presentation",
from: "2025-06-12T14:00:00",
to: "2025-06-12T15:00:00",
},
]
export function Calendar31() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Card className="w-fit py-4">
<CardContent className="px-4">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="bg-transparent p-0"
required
/>
</CardContent>
<CardFooter className="flex flex-col items-start gap-3 border-t px-4 !pt-4">
<div className="flex w-full items-center justify-between px-1">
<div className="text-sm font-medium">
{date?.toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric",
})}
</div>
<Button
variant="ghost"
size="icon"
className="size-6"
title="Add Event"
>
<PlusIcon />
<span className="sr-only">Add Event</span>
</Button>
</div>
<div className="flex w-full flex-col gap-2">
{events.map((event) => (
<div
key={event.title}
className="bg-muted after:bg-primary/70 relative rounded-md p-2 pl-6 text-sm after:absolute after:inset-y-2 after:left-2 after:w-1 after:rounded-full"
>
<div className="font-medium">{event.title}</div>
<div className="text-muted-foreground text-xs">
{formatDateRange(new Date(event.from), new Date(event.to))}
</div>
</div>
))}
</div>
</CardFooter>
</Card>
)
}
带事件槽
calendar-31
2025 年 6 月
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
---|---|---|---|---|---|---|
2025 年 6 月 12 日
团队同步会议
6 月 12 日,9:00 - 10:00
设计评审
6 月 12 日,11:30 - 12:30
客户演示
6 月 12 日,14:00 - 15:00
"use client"
import * as React from "react"
import { formatDateRange } from "little-date"
import { PlusIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Card, CardContent, CardFooter } from "@/components/ui/card"
const events = [
{
title: "Team Sync Meeting",
from: "2025-06-12T09:00:00",
to: "2025-06-12T10:00:00",
},
{
title: "Design Review",
from: "2025-06-12T11:30:00",
to: "2025-06-12T12:30:00",
},
{
title: "Client Presentation",
from: "2025-06-12T14:00:00",
to: "2025-06-12T15:00:00",
},
]
export function Calendar31() {
const [date, setDate] = React.useState<Date | undefined>(
new Date(2025, 5, 12)
)
return (
<Card className="w-fit py-4">
<CardContent className="px-4">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
className="bg-transparent p-0"
required
/>
</CardContent>
<CardFooter className="flex flex-col items-start gap-3 border-t px-4 !pt-4">
<div className="flex w-full items-center justify-between px-1">
<div className="text-sm font-medium">
{date?.toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric",
})}
</div>
<Button
variant="ghost"
size="icon"
className="size-6"
title="Add Event"
>
<PlusIcon />
<span className="sr-only">Add Event</span>
</Button>
</div>
<div className="flex w-full flex-col gap-2">
{events.map((event) => (
<div
key={event.title}
className="bg-muted after:bg-primary/70 relative rounded-md p-2 pl-6 text-sm after:absolute after:inset-y-2 after:left-2 after:w-1 after:rounded-full"
>
<div className="font-medium">{event.title}</div>
<div className="text-muted-foreground text-xs">
{formatDateRange(new Date(event.from), new Date(event.to))}
</div>
</div>
))}
</div>
</CardFooter>
</Card>
)
}
文件
"use client"
import * as React from "react"
import { CalendarPlusIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Drawer,
DrawerContent,
DrawerDescription,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
import { Label } from "@/components/ui/label"
export function Calendar32() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Date of birth
</Label>
<Drawer open={open} onOpenChange={setOpen}>
<DrawerTrigger asChild>
<Button
variant="outline"
id="date"
className="w-48 justify-between font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
<CalendarPlusIcon />
</Button>
</DrawerTrigger>
<DrawerContent className="w-auto overflow-hidden p-0">
<DrawerHeader className="sr-only">
<DrawerTitle>Select date</DrawerTitle>
<DrawerDescription>Set your date of birth</DrawerDescription>
</DrawerHeader>
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
className="mx-auto [--cell-size:clamp(0px,calc(100vw/7.5),52px)]"
/>
</DrawerContent>
</Drawer>
<div className="text-muted-foreground px-1 text-sm">
This example works best on mobile.
</div>
</div>
)
}
抽屉式日期选择器
calendar-32
此示例在移动设备上效果最佳。
"use client"
import * as React from "react"
import { CalendarPlusIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Drawer,
DrawerContent,
DrawerDescription,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
import { Label } from "@/components/ui/label"
export function Calendar32() {
const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>(undefined)
return (
<div className="flex flex-col gap-3">
<Label htmlFor="date" className="px-1">
Date of birth
</Label>
<Drawer open={open} onOpenChange={setOpen}>
<DrawerTrigger asChild>
<Button
variant="outline"
id="date"
className="w-48 justify-between font-normal"
>
{date ? date.toLocaleDateString() : "Select date"}
<CalendarPlusIcon />
</Button>
</DrawerTrigger>
<DrawerContent className="w-auto overflow-hidden p-0">
<DrawerHeader className="sr-only">
<DrawerTitle>Select date</DrawerTitle>
<DrawerDescription>Set your date of birth</DrawerDescription>
</DrawerHeader>
<Calendar
mode="single"
selected={date}
captionLayout="dropdown"
onSelect={(date) => {
setDate(date)
setOpen(false)
}}
className="mx-auto [--cell-size:clamp(0px,calc(100vw/7.5),52px)]"
/>
</DrawerContent>
</Drawer>
<div className="text-muted-foreground px-1 text-sm">
This example works best on mobile.
</div>
</div>
)
}