Date Picker
Installation
npx shadcn@latest add https://uibrik.com/r/date-picker.jsonInstall the packages
npm install motionSet up squircle corners
Needs
@squircle/core,@squircle/tailwindcssand a few lines of CSS. See squircle setup.Copy the source into your project
components/uibrik/date-picker/date-picker.tsx"use client" import { useMemo, useState } from "react" import { WheelColumn } from "./wheel-column" const MONTHS = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ] const CURRENT_YEAR = new Date().getFullYear() function daysInMonth(year: number, month: number) { return new Date(year, month + 1, 0).getDate() } export type DatePickerProps = { /** Starting day of the month (1-31). */ defaultDay?: number /** Starting month, 0 = January. */ defaultMonth?: number /** Years listed before the current year. */ yearsBefore?: number /** Years listed after the current year. */ yearsAfter?: number /** Day and month wheels wrap around. */ infinite?: boolean onChange?: (date: Date) => void } export function DatePicker({ defaultDay = 15, defaultMonth = 8, yearsBefore = 40, yearsAfter = 19, infinite = true, onChange, }: DatePickerProps) { const YEARS = useMemo( () => Array.from({ length: yearsBefore + yearsAfter + 1 }, (_, i) => String(CURRENT_YEAR - yearsBefore + i)), [yearsBefore, yearsAfter] ) const [day, setDayIndex] = useState(defaultDay - 1) const [month, setMonthIndex] = useState(defaultMonth) const [yearIndex, setYearIndexState] = useState(YEARS.indexOf(String(CURRENT_YEAR))) // report the picked date whenever a wheel settles const report = (d: number, m: number, y: number) => { if (!onChange) return const year = Number(YEARS[y]) onChange(new Date(year, m, Math.min(d + 1, daysInMonth(year, m)))) } const setDay = (d: number) => { setDayIndex(d) report(d, month, yearIndex) } const setMonth = (m: number) => { setMonthIndex(m) report(day, m, yearIndex) } const setYearIndex = (y: number) => { setYearIndexState(y) report(day, month, y) } const year = Number(YEARS[yearIndex]) const dayCount = daysInMonth(year, month) const days = useMemo( () => Array.from({ length: dayCount }, (_, i) => String(i + 1)), [dayCount] ) const clampedDay = Math.min(day, dayCount - 1) return ( <div className="flex text-xl font-medium select-none"> <WheelColumn values={days} index={clampedDay} onChange={setDay} className="size-14 bg-neutral-100 dark:bg-neutral-900 squircle-mask squircle-l-2xl" infinite={infinite} /> <WheelColumn values={MONTHS} index={month} onChange={setMonth} className="h-14 w-16 bg-neutral-100 dark:bg-neutral-900" infinite={infinite} /> <WheelColumn values={YEARS} index={yearIndex} onChange={setYearIndex} className="h-14 w-20 bg-neutral-100 dark:bg-neutral-900 squircle-mask squircle-r-2xl" /> </div> ) }
Adds the files to
components/uibrik/date-picker and installs motion. With the @uibrik namespace set up: npx shadcn@latest add @uibrik/date-picker.Props
DatePicker- defaultDay
- Type number
- 15
- Starting day of the month.
- defaultMonth
- Type number
- 8
- Starting month, 0 = January.
- yearsBefore
- Type number
- 40
- Years listed before the current year.
- yearsAfter
- Type number
- 19
- Years listed after the current year.
- infinite
- Type boolean
- true
- Day and month wheels loop.
- onChange
- Type (date: Date) => void
- –
- Called with the picked date when a wheel settles.