Skip to content

Instantly share code, notes, and snippets.

@tanishqsh
Created July 3, 2023 03:54
Show Gist options
  • Save tanishqsh/6e5284b36c29c0e2effc6e187c8f911a to your computer and use it in GitHub Desktop.
Save tanishqsh/6e5284b36c29c0e2effc6e187c8f911a to your computer and use it in GitHub Desktop.
DOB Calendar
/**
/DOBPicker.tsx
**/
'use client';
import * as React from 'react';
import { format, subYears } from 'date-fns';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Calendar } from '@/components/ui/calendar';
import { buttonVariants } from '@/components/ui/button';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
export function DOBPicker({ dob, setDOB }: { dob: Date | undefined; setDOB: React.Dispatch<React.SetStateAction<Date | undefined>> }) {
/**
* The maximum date that can be selected is 18 years ago
*/
const maxDate = subYears(new Date(), 18);
return (
<div className="w-full">
<Popover>
<PopoverTrigger asChild>
<Button
variant={'default'}
className={cn('w-full justify-start font-mono text-left font-normal bg-white/5', !dob && 'text-muted-foreground')}
>
<svg className="w-4 h-4 mr-2" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
d="M4.75 8.75C4.75 7.64543 5.64543 6.75 6.75 6.75H17.25C18.3546 6.75 19.25 7.64543 19.25 8.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H6.75C5.64543 19.25 4.75 18.3546 4.75 17.25V8.75Z"
></path>
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8 4.75V8.25"></path>
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M16 4.75V8.25"></path>
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7.75 10.75H16.25"></path>
</svg>
{dob ? format(dob, 'PPP') : <span>Date of Birth</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-full p-0 font-mono text-white bg-black border border-white/10">
<Calendar
classNames={{
cell: 'text-center text-sm p-0 relative [&:has([aria-selected])]:bg-white/5 first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20',
day: cn(
buttonVariants({ variant: 'ghost' }),
'h-9 w-9 p-0 font-normal aria-selected:opacity-100 hover:bg-languid-lavendar/10 hover:text-white/40'
),
day_selected: 'rounded-full bg-languid-lavendar hover:bg-white/10 text-primary-foreground',
caption_label: 'hidden',
caption_dropdowns: 'flex w-full items-center justify-center space-x-2',
}}
mode="single"
selected={dob}
fromDate={subYears(new Date(), 100)}
toDate={maxDate}
captionLayout="dropdown"
onSelect={setDOB}
defaultMonth={new Date(dob?.getFullYear() ?? maxDate.getFullYear(), dob?.getMonth() ?? maxDate.getMonth(), 1)}
required
initialFocus
className="border rounded-md border-white/10"
/>
</PopoverContent>
</Popover>
</div>
);
}
export default DOBPicker;
/**
/ui/calendar.tsx
**/
'use client';
import * as React from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { DayPicker } from 'react-day-picker';
import { cn } from '@/lib/utils';
import { buttonVariants } from '@/components/ui/button';
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn('p-3', className)}
classNames={{
months: 'flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0',
month: 'space-y-4',
caption: 'flex justify-center pt-1 relative items-center',
caption_label: 'text-sm font-medium hidden',
nav: 'space-x-1 flex items-center',
nav_button: cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'),
nav_button_previous: 'absolute left-1 border border-white/20',
nav_button_next: 'absolute right-1 border border-white/20',
table: 'w-full border-collapse space-y-1',
head_row: 'flex',
head_cell: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',
row: 'flex w-full mt-2',
cell: 'text-center text-sm p-0 relative [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20',
day: cn(buttonVariants({ variant: 'ghost' }), 'h-9 w-9 p-0 font-normal aria-selected:opacity-100'),
day_selected:
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
day_today: 'bg-accent text-accent-foreground',
day_outside: 'text-muted-foreground opacity-50',
day_disabled: 'text-muted-foreground opacity-50',
day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',
day_hidden: 'invisible',
...classNames,
}}
components={{
Dropdown: ({ ...props }) => (
<div className="w-full">
<select
autoFocus
{...props}
className="w-full px-1 py-2 space-x-4 text-sm text-white transition-all duration-300 rounded-md outline-none bg-white/5 hover:bg-white/10 focus-outline:none"
/>
</div>
),
IconLeft: ({ ...props }) => <ChevronLeft className="w-4 h-4" />,
IconRight: ({ ...props }) => <ChevronRight className="w-4 h-4" />,
}}
{...props}
/>
);
}
Calendar.displayName = 'Calendar';
export { Calendar };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment