Skip to content

gr3enk/shadcn-ui-monthpicker

Repository files navigation

Monthpicker & Monthrangepicker for shadcn-ui

A fully customizable Monthpicker and Monthrangepicker component built for shadcn-ui. (Radix, Tailwind CSS).

header image

Try out the demo!

Installation

The components require the following shadcn-ui components.

CLI Installation:

npx shadcn-ui@latest add button popover

Link to components:

Also Lucide React is requiered for the Icons.

Monthpicker Component

Example

import React from "react";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Button } from "@/components/ui/button";
import { CalendarIcon } from "lucide-react";
import { format } from "date-fns/format";
import { cn } from "@/lib/utils";
import { MonthPicker } from "@/components/ui/monthpicker";

export default function Example() {
    const [date, setDate] = React.useState<Date>();

    return <MonthPicker onMonthSelect={setDate} selectedDate={date} />;
}

Use with shadcn-ui Popover component:

export default function Example() {
    const [date, setDate] = React.useState<Date>();

    return (
        <Popover>
            <PopoverTrigger asChild>
                <Button variant={"outline"} className={cn("w-[280px] justify-start text-left font-normal", !date && "text-muted-foreground")}>
                    <CalendarIcon className="mr-2 h-4 w-4" />
                    {date ? format(date, "MMM yyyy") : <span>Pick a month</span>}
                </Button>
            </PopoverTrigger>
            <PopoverContent className="w-auto p-0">
                <MonthPicker onMonthSelect={setDate} selectedMonth={date} />
            </PopoverContent>
        </Popover>
    );
}

Props

Prop Type Default Description
onMonthSelect (date: Date) => void - Called when a month has been selected
selectedMonth Date Today’s Month Month state for initialization
minDate Date no limit The minimum selectable date
maxDate Date no limit The maximum selectable date
disabledDates Date[] - Separate non-selectable months
callbacks object - See callbacks table
variant object - See variant table
onYearForward () => void - Called when calendar browsed forward
onYearBackward () => void - Called when calendar browsed backward
callbacks | Prop | Type | Description | | ------------ | ------------------------ | --------------------------------- | | `yearLabel` | (year: number) => string | Used for styling the Year Label | | `monthLabel` | (month: Month) | Used for styling the Month Labels |
type Month = { number: number; name: string };
variant
Prop Type Description
calendar {main: ButtonVariant, selected: ButtonVariant} Styling for the Month-buttons. main for non-selected & selected for selected Button
chevrons ButtonVariant Styling for the backward- & forward-chevron buttons
type ButtonVariant = "default" | "outline" | "ghost" | "link" | "destructive" | "secondary" | null | undefined;

Monthrangepicker Component

Example

import React from "react";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Button } from "@/components/ui/button";
import { CalendarIcon } from "lucide-react";
import { format } from "date-fns/format";
import { cn } from "@/lib/utils";
import { MonthRangePicker } from "@/components/ui/monthrangepicker";

export default function Example() {
    const [dates, setDates] = React.useState<{ start: Date; end: Date }>();

    return <MonthRangePicker onMonthRangeSelect={setDates} selectedMonthRange={dates} />;
}

Use with shadcn-ui Popover component:

export default function Example() {
    const [dates, setDates] = React.useState<{ start: Date; end: Date }>();

    return (
        <Popover>
            <PopoverTrigger asChild>
                <Button variant={"outline"} className={cn("w-[280px] justify-start text-left font-normal", !date && "text-muted-foreground")}>
                    <CalendarIcon className="mr-2 h-4 w-4" />
                    {dates ? `${format(dates.start, "MMM yyyy")} - ${format(dates.end, "MMM yyyy")}` : <span>Pick a month range</span>}
                </Button>
            </PopoverTrigger>
            <PopoverContent className="w-auto p-0">
                <MonthRangePicker onMonthRangeSelect={setDates} selectedMonthRange={dates} />
            </PopoverContent>
        </Popover>
    );
}

Props

Prop Type Default Description
onMonthRangeSelect (date: Date) => void - Called when a month range has been selected
onStartMonthSelect (date: Date) => void - Called when the range start month has been selected and the range end is still pending
selectedMonthRange Date Today’s Month Month state for initialization
minDate Date no limit The minimum selectable date
maxDate Date no limit The maximum selectable date
callbacks object - See callbacks table
variant object - See variant table
onYearForward () => void - Called when calendar browsed forward
onYearBackward () => void - Called when calendar browsed backward
quickSelectors Object[] - See quickselectors table
showQuickSelectors boolean true Show/Hide the quickselectors
quickselectors
Prop Type Description
label string Label for the button
startMonth Date Date for the range start month
endMonth Date Date for the range end month
variant ButtonVariant variant for the button
onClick (selector: QuickSelector) => void Called when quick selection has been clicked
callbacks
Prop Type Description
yearLabel (year: number) => string Used for styling the Year Label
monthLabel (month: Month) Used for styling the Month Labels
type Month = { number: number; name: string; yearOffset: number }; // yearOffset = 0 on the left calendar and 1 on the right side calendar
variant
Prop Type Description
calendar {main: ButtonVariant, selected: ButtonVariant} Styling for the Month-buttons. main for non-selected & selected for selected Button
chevrons ButtonVariant Styling for the backward- & forward-chevron buttons
type ButtonVariant = "default" | "outline" | "ghost" | "link" | "destructive" | "secondary" | null | undefined;

Example with shadcn form component

You can use Monthpicker and Monthrangepicker with shadcn forms. A Form schema could look like this:

const FormSchema = z.object({
    month: z.date(),
    monthrange: z.object({
        start: z.date(),
        end: z.date(),
    }),
});

You can check out a full form example here