fix(frontend): Fix date picker ux (#9715)

- fix #9315

What have I changed?

- Allowed the user to select the month and year using a dropdown.
- Removed the "Prev" and "Next" buttons for month navigation.
- Fixed the "Today" date design.

<img width="847" alt="Screenshot 2025-03-28 at 6 28 20 PM"
src="https://github.com/user-attachments/assets/740bddfd-e0a2-4799-8325-d52dec31a512"
/>

---------

Co-authored-by: Bently <tomnoon9@gmail.com>
This commit is contained in:
Abhimanyu Yadav
2025-04-01 14:12:04 +05:30
committed by GitHub
parent 7440f71527
commit dbb85baf4c
2 changed files with 66 additions and 12 deletions

View File

@@ -209,9 +209,9 @@ const NodeDateTimeInput: FC<{
hideDate = false,
hideTime = false,
}) => {
const date = value ? new Date(value) : new Date();
const date = value ? new Date(value) : undefined;
const [timeInput, setTimeInput] = useState(
value ? format(date, "HH:mm") : "00:00",
value && date ? format(date, "HH:mm") : "00:00",
);
const handleDateSelect = (newDate: Date | undefined) => {
@@ -259,7 +259,7 @@ const NodeDateTimeInput: FC<{
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{value ? format(date, "PPP") : <span>Pick a date</span>}
{value && date ? format(date, "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
@@ -267,7 +267,7 @@ const NodeDateTimeInput: FC<{
mode="single"
selected={date}
onSelect={handleDateSelect}
initialFocus
autoFocus
/>
</PopoverContent>
</Popover>

View File

@@ -7,10 +7,17 @@ import {
ChevronRightIcon,
ChevronUpIcon,
} from "@radix-ui/react-icons";
import { DayPicker } from "react-day-picker";
import { DayPicker, DropdownProps } from "react-day-picker";
import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "./select";
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
@@ -23,17 +30,20 @@ function Calendar({
return (
<DayPicker
showOutsideDays={showOutsideDays}
captionLayout={"dropdown"}
endMonth={new Date(2100, 0)}
startMonth={new Date(1900, 0)}
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",
month_caption: "flex justify-center pt-1 relative items-center",
caption_label: "text-sm font-medium",
nav: "space-x-1 flex items-center",
month_caption: "flex items-center justify-center text-sm font-medium",
dropdowns: "flex gap-2 ",
caption_label: "hidden",
nav: "hidden",
button_previous:
"absolute left-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
button_next:
"absolute right-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 ",
button_next: " h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
month_grid: "w-full border-collapse space-y-1",
weekdays: "flex",
weekday:
@@ -52,7 +62,7 @@ function Calendar({
range_start: "range-start",
range_end: "range-end",
selected:
"bg-neutral-900 text-neutral-50 hover:bg-neutral-900 hover:text-neutral-50 focus:bg-neutral-700 focus:text-neutral-50 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-50 dark:hover:text-neutral-900 dark:focus:bg-neutral-50 dark:focus:text-neutral-900",
"bg-neutral-900 text-neutral-100 hover:bg-neutral-900 hover:text-neutral-50 focus:bg-neutral-700 focus:text-neutral-50 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-50 dark:hover:text-neutral-900 dark:focus:bg-neutral-50 dark:focus:text-neutral-900",
today:
"bg-neutral-100 text-neutral-900 dark:bg-neutral-800 dark:text-neutral-50",
outside:
@@ -75,6 +85,7 @@ function Calendar({
return <ChevronUpIcon className="h-4 w-4" />;
}
},
Dropdown: (props) => <CustomDropdown {...props} />,
}}
{...props}
/>
@@ -82,4 +93,47 @@ function Calendar({
}
Calendar.displayName = "Calendar";
const CustomDropdown = ({
options,
value,
onChange,
name,
disabled,
}: DropdownProps) => {
const handleValueChange = (newValue: string) => {
if (onChange) {
const syntheticEvent = {
target: {
name,
value: newValue,
},
} as React.ChangeEvent<HTMLSelectElement>;
onChange(syntheticEvent);
}
};
return (
<Select
value={value?.toString()}
onValueChange={handleValueChange}
disabled={disabled}
>
<SelectTrigger className="w-[120px] space-x-2 bg-white text-sm">
<SelectValue placeholder="Select" />
</SelectTrigger>
<SelectContent className="bg-white">
{options?.map((option) => (
<SelectItem
key={option.value}
value={option.value.toString()}
disabled={option.disabled}
>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
);
};
export { Calendar };