Created
October 13, 2025 11:39
-
-
Save baharalidurrani/a38eec9de4e3b474b2f5dabdcd5aad5c to your computer and use it in GitHub Desktop.
Mui Free Date Range Picker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; | |
| import Button from '@mui/material/Button'; | |
| import Grid from '@mui/material/Grid'; | |
| import Popover from '@mui/material/Popover'; | |
| import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; | |
| import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; | |
| import { StaticDatePicker } from '@mui/x-date-pickers/StaticDatePicker'; | |
| import dayjs, { type Dayjs } from 'dayjs'; | |
| import { useState } from 'react'; | |
| function displayDate(date: Date | Dayjs | string, template = 'MMM DD, YYYY'): string { | |
| return dayjs(date).format(template); | |
| } | |
| type Props = { | |
| fromDate?: Dayjs; | |
| toDate?: Dayjs; | |
| onAccept: (dateRange: { fromDate: Dayjs | null; toDate: Dayjs | null }) => void; | |
| }; | |
| export default function DateRangePicker({ fromDate, toDate, onAccept }: Props) { | |
| console.debug('π DateRangePicker Rendered'); | |
| const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null); | |
| const [value, setValue] = useState<{ fromDate: Dayjs | null; toDate: Dayjs | null }>({ | |
| fromDate: fromDate || dayjs().startOf('month'), | |
| toDate: toDate || dayjs(), | |
| }); | |
| function clearHandler() { | |
| onAccept({ fromDate: null, toDate: null }); | |
| setValue({ fromDate: null, toDate: null }); | |
| setAnchorEl(null); | |
| } | |
| function submitHandler() { | |
| onAccept(value); | |
| setAnchorEl(null); | |
| } | |
| return ( | |
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |
| <Button | |
| variant="outlined" | |
| color="inherit" | |
| startIcon={<CalendarMonthIcon />} | |
| onClick={(e) => setAnchorEl(e.currentTarget)} | |
| > | |
| {fromDate && toDate ? `${displayDate(fromDate)} β ${displayDate(toDate)}` : 'Select Dates'} | |
| </Button> | |
| <Popover | |
| open={Boolean(anchorEl)} | |
| anchorEl={anchorEl} | |
| onClose={() => setAnchorEl(null)} | |
| anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }} | |
| > | |
| <Grid container> | |
| <Grid size={{ xs: 12, md: 6 }}> | |
| <StaticDatePicker | |
| localeText={{ toolbarTitle: 'Start Date' }} | |
| slotProps={{ actionBar: { actions: [] } }} | |
| sx={{ backgroundColor: 'unset' }} | |
| value={value.fromDate} | |
| maxDate={value.toDate || undefined} | |
| onChange={(newValue) => setValue((p) => ({ ...p, fromDate: newValue }))} | |
| /> | |
| </Grid> | |
| <Grid size={{ xs: 12, md: 6 }}> | |
| <StaticDatePicker | |
| localeText={{ toolbarTitle: 'End Date' }} | |
| slotProps={{ actionBar: { actions: [] } }} | |
| sx={{ backgroundColor: 'unset' }} | |
| value={value.toDate} | |
| minDate={value.fromDate || undefined} | |
| onChange={(newValue) => setValue((p) => ({ ...p, toDate: newValue }))} | |
| /> | |
| </Grid> | |
| </Grid> | |
| <Grid container sx={{ justifyContent: 'flex-end', alignItems: 'center', pb: 2, pr: 2 }}> | |
| {fromDate && toDate ? ( | |
| <Button onClick={clearHandler} color="error"> | |
| Clear | |
| </Button> | |
| ) : ( | |
| <Button onClick={() => setAnchorEl(null)}>Cancel</Button> | |
| )} | |
| <Button onClick={submitHandler}>Apply</Button> | |
| </Grid> | |
| </Popover> | |
| </LocalizationProvider> | |
| ); | |
| } |
Author
Author
Toolbar texts can be styled using classes like MuiPickersToolbar-title:
import { datePickerToolbarClasses } from '@mui/x-date-pickers/DatePicker';
import { pickersToolbarClasses } from '@mui/x-date-pickers/internals';
<StaticDatePicker
localeText={{ toolbarTitle: 'Start Date' }}
slotProps={{
actionBar: { actions: [] },
toolbar: {
sx: {
[`& .${datePickerToolbarClasses.title}`]: { fontSize: '1.75rem' },
[`& .${pickersToolbarClasses.title}`]: { fontSize: '1rem' },
// '& .MuiPickersToolbar-title': { bgcolor: 'aqua' },
},
},
}}
sx={{ backgroundColor: 'unset' }}
value={value.fromDate}
maxDate={value.toDate || undefined}
onChange={(newValue) => setValue((p) => ({ ...p, fromDate: newValue }))}
/>
Author
Selected days can be highlighted using custom Day slot:
import { PickersDay, type PickersDayProps } from '@mui/x-date-pickers/PickersDay';
function Day(props: PickersDayProps) {
return (
<PickersDay
{...props}
sx={{
...(props.day.diff(value.fromDate) >= 0 &&
props.day.diff(value.toDate) <= 0 && {
bgcolor: (t) => t.palette.primary.main,
color: (t) => t.palette.primary.contrastText,
}),
}}
/>
);
}
<StaticDatePicker
localeText={{ toolbarTitle: 'Start Date' }}
slotProps={{ actionBar: { actions: [] } }}
slots={{ day: Day }}
sx={{ backgroundColor: 'unset' }}
value={value.fromDate}
maxDate={value.toDate || undefined}
onChange={(newValue) => setValue((p) => ({ ...p, fromDate: newValue }))}
/>Looks good but a bit confusion for the users.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Free Date Range Picker using StaticDatePicker
Features:
Demo CodeSandbox: https://codesandbox.io/p/sandbox/mui-freedaterange-picker-vs9xsn