[Feature Request] Date/Time Picker #1537
Replies: 13 comments
-
I agree: would be nice to have the Date Picker like the one from Shadcn |
Beta Was this translation helpful? Give feedback.
-
I totally agree too. I just miss a date picker and a combo box from Next-ui. It would be perfect |
Beta Was this translation helpful? Give feedback.
-
Any news about this? I was going to implement this library but It didn't have a date picker |
Beta Was this translation helpful? Give feedback.
-
Yes, would be nice to have like https://react-spectrum.adobe.com/react-aria/useDatePicker.html |
Beta Was this translation helpful? Give feedback.
-
like this it's rough code Calendarimport {
AriaCalendarGridProps,
DateValue,
useCalendar,
useCalendarCell,
useLocale,
} from 'react-aria'
import {
CalendarState,
CalendarStateOptions,
useCalendarState,
} from 'react-stately'
import { CalendarDate, createCalendar } from '@internationalized/date'
import { useCalendarGrid } from 'react-aria'
import { getWeeksInMonth } from '@internationalized/date'
import { RefObject, useRef } from 'react'
import { Button } from '@nextui-org/button'
import { forwardRef, HTMLNextUIProps } from '@nextui-org/system'
import { useDOMRef } from '@nextui-org/react-utils'
import clsx from 'clsx'
import { UseButtonProps, useButton } from '@nextui-org/button/dist/use-button'
import { Spinner } from '@nextui-org/spinner'
import { dataFocusVisibleClasses } from '@nextui-org/theme'
// interface Props {
// divProps: HTMLNextUIProps<'div'>
// calendarProps: CalendarStateOptions<CalendarDate>
// }
const Calendar = forwardRef<'div', CalendarStateOptions<CalendarDate>>(
(props, ref) => {
const { as, className, children, ...otherProps } = props
const Component = as || 'div'
const domRef = useDOMRef(ref)
let state = useCalendarState({
...props,
})
let { calendarProps, prevButtonProps, nextButtonProps, title } =
useCalendar(props, state)
return (
<Component
ref={domRef}
className={clsx(
className,
'block p-6 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700',
)}
{...calendarProps}
>
<div className="header 'inline-block text-gray-800'">
<h2>{title}</h2>
<Button {...prevButtonProps}>prev <</Button>
<Button {...nextButtonProps}>go ></Button>
</div>
<CalendarGrid state={state} />
</Component>
)
},
)
Calendar.displayName = 'NextUI.Calendar'
export default Calendar
function CalendarGrid({
state,
...props
}: { state: CalendarState } & AriaCalendarGridProps) {
let { locale } = useLocale()
let { gridProps, headerProps, weekDays } = useCalendarGrid(props, state)
// Get the number of weeks in the month so we can render the proper number of rows.
let weeksInMonth = getWeeksInMonth(state.visibleRange.start, locale)
return (
<table {...gridProps}>
<thead {...headerProps}>
<tr>
{weekDays.map((day, index) => (
<th key={index}>{day}</th>
))}
</tr>
</thead>
<tbody>
{Array.from(new Array(weeksInMonth).keys()).map((weekIndex) => (
<tr key={weekIndex}>
{state
.getDatesInWeek(weekIndex)
.map((date, i) =>
date ? (
<CalendarCell key={i} state={state} date={date} />
) : (
<td key={i} />
),
)}
</tr>
))}
</tbody>
</table>
)
}
function CalendarCell({
state,
date,
}: {
state: CalendarState
date: CalendarDate
}) {
let ref = useRef(null)
let {
cellProps,
buttonProps,
isSelected,
isOutsideVisibleRange,
isDisabled,
isUnavailable,
formattedDate,
} = useCalendarCell({ date }, state, ref)
return (
<td
{...cellProps}
className={clsx(
'py-2.5 px-5 me-2 mb-2 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700',
cellProps.className,
)}
>
<div
{...buttonProps}
ref={ref}
hidden={isOutsideVisibleRange}
className={clsx(
`cell ${isSelected ? 'selected' : ''} ${
isDisabled ? 'disabled' : ''
} ${isUnavailable ? 'unavailable' : ''}`,
[
'z-0',
'group',
'relative',
'inline-flex',
'items-center',
'justify-center',
'box-border',
'appearance-none',
'outline-none',
'select-none',
'whitespace-nowrap',
'min-w-max',
'font-normal',
'subpixel-antialiased',
'overflow-hidden',
'tap-highlight-transparent',
// focus ring
...dataFocusVisibleClasses,
],
buttonProps.className,
)}
>
{formattedDate}
</div>
</td>
)
} Date Field'use client'
import { DateValue, useDateField, useDateSegment, useLocale } from 'react-aria'
import {
CalendarStateOptions,
DateFieldStateOptions,
useDateFieldState,
} from 'react-stately'
import { RefObject, forwardRef, useRef, useState } from 'react'
import { Popover, PopoverContent, PopoverTrigger } from '@nextui-org/popover'
import { Button } from '@nextui-org/button'
import Calendar from '../calendar'
import {
today,
getLocalTimeZone,
createCalendar,
CalendarDate,
parseDate,
} from '@internationalized/date'
import dayjs from 'dayjs'
type DateFieldProps = Omit<
DateFieldStateOptions<DateValue>,
'locale' | 'createCalendar'
>
export default function DateField(props: DateFieldProps) {
let { locale } = useLocale()
const [date, setDate] = useState(parseDate(dayjs().format('YYYY-MM-DD')))
let state = useDateFieldState({
...props,
locale,
createCalendar,
})
let ref = useRef(null)
let { labelProps, fieldProps } = useDateField(props, state, ref)
return (
<div className=" flex flex-col items-center">
<span {...labelProps}>{props.label}</span>
<div
{...fieldProps}
ref={ref}
className="flex-nowrap px-2 py-3 inline-flex border-solid border-2 border-sky-500 "
>
{state.segments.map((segment, i) => (
<DateSegment key={i} segment={segment} state={state} />
))}
{state.isInvalid && <span aria-hidden="true">🚫</span>}
<PopoverCalendar
calendarProps={{
minValue: today(getLocalTimeZone()),
defaultValue: today(getLocalTimeZone()),
locale: locale,
createCalendar: createCalendar,
value: date,
onChange: (newDate) => {
console.log('newDate', newDate)
state.setValue(newDate)
setDate(newDate)
},
}}
/>
</div>
</div>
)
}
function DateSegment({ segment, state }: any) {
let ref = useRef(null)
let { segmentProps } = useDateSegment(segment, state, ref)
return (
<div
{...segmentProps}
ref={ref}
className={`segment ${segment.isPlaceholder ? 'placeholder' : ''}`}
>
{segment.text}
</div>
)
}
export function PopoverCalendar(props: {
calendarProps: CalendarStateOptions<CalendarDate>
}) {
return (
<Popover>
<PopoverTrigger>
<Button>Open Popover</Button>
</PopoverTrigger>
<PopoverContent>
<Calendar {...props.calendarProps} />
</PopoverContent>
</Popover>
)
} |
Beta Was this translation helpful? Give feedback.
-
Yes i definitely agree with the agenda date picker should be added in the upcoming update it would be a massive contribution |
Beta Was this translation helpful? Give feedback.
-
duplicate - #311 |
Beta Was this translation helpful? Give feedback.
-
Is your feature request related to a problem? Please describe.
The library does not offer a built-in Date/Time picker, which is often needed in forms or scheduling apps. Without this, users may have to manually enter date and time information, increasing the likelihood of errors.
Describe the solution you'd like
A Date/Time Picker component that supports both date and time selection would solve this problem effectively. Key features could include:
Range selection for date periods
Time zone support
Custom date/time format options
Describe alternatives you've considered
While there are third-party Date/Time Picker libraries that can be used, a native component would be advantageous in maintaining a cohesive UI/UX design throughout the application.
Screenshots or Videos
No response
Beta Was this translation helpful? Give feedback.
All reactions