Range picker with presets
Usage
theme="ios" You can turn auto theming on and let it decide based on the platform.
Usage
themeVariant="light" You can turn auto dark mode on based on system settings.
Usage
touchUi={true}
// touch interaction is enabled Use touch interaction on mobile or pointer interaction on desktop.
Usage
locale={localeEn} Selecting the locale loads the localized settings and the translated UI text.
Range picker with presets
Build complex pickers to show within popups to make things easy for your users. A great example is date-range selection with presets. If you've ever used Google Analytics, you have probably seen the date range selector for filtering the data, which is very similar to what you can see in this example. Select custom start and end dates along with presets is helpful for easy access to predefined ranges that people are usually interested in.
Demo
Code
View code on GitHub
import { Button, Datepicker, formatDate, Input, options, Page, Popup, Select, setOptions } from '@mobiscroll/react';
import { useCallback, useEffect, useState } from 'react';
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
});
const startDate = '2026-11-04T00:00';
const endDate = '2026-11-10T00:00';
const now = new Date();
const day = now.getDay();
const monday = now.getDate() - day + (day === 0 ? -6 : 1);
const respSelect = {
xsmall: {
touchUi: true,
},
small: {
touchUi: false,
},
};
const myData = [
{
value: 'custom',
text: 'Custom',
},
{
value: 'today',
text: 'Today',
},
{
value: 'yesterday',
text: 'Yesterday',
},
{
value: 'last-week',
text: 'Last week',
},
{
value: 'last-month',
text: 'Last month',
},
{
value: 'last-7-days',
text: 'Last 7 days',
},
{
value: 'last-30-days',
text: 'Last 30 days',
},
];
function App() {
const [isOpen, setOpen] = useState(false);
const [start, startRef] = useState(null);
const [end, endRef] = useState(null);
const [selected, setSelected] = useState('custom');
const [selectedDate, setSelectedDate] = useState([startDate, endDate]);
const [inputValue, setInputValue] = useState('');
const [disabledInput, setDisabledInput] = useState(false);
const respPopup = {
xsmall: {
display: 'bottom',
touchUi: true,
buttons: [
{
text: 'Apply',
handler: () => {
const date = selectedDate;
changeInputValue(date[0], date[1] || date[0]);
setOpen(false);
},
},
'cancel',
],
},
custom: {
breakpoint: 559,
buttons: [],
display: 'anchored',
anchor: document.querySelector('.date-filter-input'),
anchorAlign: 'start',
touchUi: false,
scrollLock: false,
showArrow: false,
maxWidth: 920,
},
};
const inputClick = useCallback(() => {
setOpen(true);
}, []);
const changeInputValue = useCallback((start, end) => {
const locale = options.locale || {};
const dateFormat = locale.dateFormat || 'DD/MM/YYYY';
setInputValue(formatDate(dateFormat, new Date(start)) + ' - ' + formatDate(dateFormat, new Date(end)));
}, []);
const applyClick = useCallback(() => {
changeInputValue(selectedDate[0], selectedDate[1] || selectedDate[0]);
setOpen(false);
}, [selectedDate, changeInputValue]);
const cancelClick = useCallback(() => {
setOpen(false);
}, []);
const onChange = useCallback((event) => {
const s = event.value;
if (s === 'custom') {
setDisabledInput(false);
} else {
setDisabledInput(true);
switch (s) {
case 'today':
setSelectedDate(['2026-11-04T00:00', '2026-11-04T00:00']);
break;
case 'yesterday':
setSelectedDate(['2026-11-03T00:00', '2026-11-03T00:00']);
break;
case 'last-week':
setSelectedDate([
new Date(now.getFullYear(), now.getMonth(), monday - 7),
new Date(now.getFullYear(), now.getMonth(), monday - 1),
]);
break;
case 'last-month':
setSelectedDate(['2026-10-01T00:00', '2026-10-31T00:00']);
break;
case 'last-7-days':
setSelectedDate(['2026-10-29T00:00', '2026-11-04T00:00']);
break;
case 'last-30-days':
setSelectedDate(['2026-10-06T00:00', '2026-11-04T00:00']);
break;
default:
break;
}
}
setSelected(s);
}, []);
const onDateChange = useCallback((ev) => {
const date = ev.value;
setDisabledInput(false);
setSelected('custom');
setSelectedDate(date);
}, []);
const onClose = useCallback(() => {
setOpen(false);
}, []);
useEffect(() => {
changeInputValue(startDate, endDate);
});
return (
<Page>
<div className="mbsc-form-group">
<Input inputStyle="box" onClick={inputClick} defaultValue={inputValue} className="date-filter-input"></Input>
</div>
<Popup isOpen={isOpen} onClose={onClose} responsive={respPopup} cssClass="demo-date-filtering-popup">
<div className="mbsc-grid mbsc-no-padding">
<div className="mbsc-row">
<div className="mbsc-col-sm-4 mbsc-push-sm-8 demo-date-filtering-dates">
<div className="demo-date-filtering-inputs">
<Select
data={myData}
label="Date range"
labelStyle="stacked"
inputStyle="box"
responsive={respSelect}
touchUi={true}
value={selected}
onChange={onChange}
/>
<Input
ref={startRef}
disabled={disabledInput}
label="Start"
labelStyle="stacked"
inputStyle="box"
className="demo-date-filtering-range-input"
placeholder="Please Select..."
/>
<Input
ref={endRef}
disabled={disabledInput}
label="End"
labelStyle="stacked"
inputStyle="box"
className="demo-date-filtering-range-input"
placeholder="Please Select..."
/>
</div>
<div className="demo-date-filtering-desktop-buttons mbsc-button-group-justified">
<Button className="apply-button" onClick={applyClick}>
Apply
</Button>
<Button className="cancel-button" onClick={cancelClick}>
Cancel
</Button>
</div>
</div>
<div className="mbsc-col-sm-8 mbsc-pull-sm-4">
<Datepicker
select="range"
display="inline"
showRangeLabels={false}
pages="auto"
startInput={start}
endInput={end}
returnFormat="iso8601"
showOnClick={false}
showOnFocus={false}
value={selectedDate}
onChange={onDateChange}
/>
</div>
</div>
</div>
</Popup>
</Page>
);
}
export default App;
import {
Button,
Datepicker,
formatDate,
Input,
MbscDatepickerChangeEvent,
MbscDateType,
MbscPopupOptions,
MbscResponsiveOptions,
MbscSelectChangeEvent,
options,
Page,
Popup,
Select,
setOptions ,
} from '@mobiscroll/react';
import { FC, useCallback, useEffect, useState } from 'react';
setOptions({
locale: ,
theme: ' ',
themeVariant: ' '
});
const startDate = '2026-11-04T00:00';
const endDate = '2026-11-10T00:00';
const now = new Date();
const day = now.getDay();
const monday = now.getDate() - day + (day === 0 ? -6 : 1);
const respSelect = {
xsmall: {
touchUi: true,
},
small: {
touchUi: false,
},
};
const myData = [
{
value: 'custom',
text: 'Custom',
},
{
value: 'today',
text: 'Today',
},
{
value: 'yesterday',
text: 'Yesterday',
},
{
value: 'last-week',
text: 'Last week',
},
{
value: 'last-month',
text: 'Last month',
},
{
value: 'last-7-days',
text: 'Last 7 days',
},
{
value: 'last-30-days',
text: 'Last 30 days',
},
];
const App: FC = () => {
const [isOpen, setOpen] = useState<boolean>(false);
const [start, startRef] = useState<Input | null>(null);
const [end, endRef] = useState<Input | null>(null);
const [selected, setSelected] = useState<string>('custom');
const [selectedDate, setSelectedDate] = useState<MbscDateType[]>([startDate, endDate]);
const [inputValue, setInputValue] = useState<string>('');
const [disabledInput, setDisabledInput] = useState<boolean>(false);
const respPopup: MbscResponsiveOptions<MbscPopupOptions> = {
xsmall: {
display: 'bottom',
touchUi: true,
buttons: [
{
text: 'Apply',
handler: () => {
const date = selectedDate;
changeInputValue(date[0] as string, (date[1] as string) || (date[0] as string));
setOpen(false);
},
},
'cancel',
],
},
custom: {
breakpoint: 559,
buttons: [],
display: 'anchored',
anchor: document.querySelector('.date-filter-input') as HTMLInputElement,
anchorAlign: 'start',
touchUi: false,
scrollLock: false,
showArrow: false,
maxWidth: 920,
},
};
const inputClick = useCallback(() => {
setOpen(true);
}, []);
const changeInputValue = useCallback((start: string, end: string) => {
const locale = options.locale || {};
const dateFormat = locale.dateFormat || 'DD/MM/YYYY';
setInputValue(formatDate(dateFormat, new Date(start)) + ' - ' + formatDate(dateFormat, new Date(end)));
}, []);
const applyClick = useCallback(() => {
changeInputValue(selectedDate[0] as string, (selectedDate[1] as string) || (selectedDate[0] as string));
setOpen(false);
}, [selectedDate, changeInputValue]);
const cancelClick = useCallback(() => {
setOpen(false);
}, []);
const onChange = useCallback((event: MbscSelectChangeEvent) => {
const s = event.value;
if (s === 'custom') {
setDisabledInput(false);
} else {
setDisabledInput(true);
switch (s) {
case 'today':
setSelectedDate(['2026-11-04T00:00', '2026-11-04T00:00']);
break;
case 'yesterday':
setSelectedDate(['2026-11-03T00:00', '2026-11-03T00:00']);
break;
case 'last-week':
setSelectedDate([
new Date(now.getFullYear(), now.getMonth(), monday - 7),
new Date(now.getFullYear(), now.getMonth(), monday - 1),
]);
break;
case 'last-month':
setSelectedDate(['2026-10-01T00:00', '2026-10-31T00:00']);
break;
case 'last-7-days':
setSelectedDate(['2026-10-29T00:00', '2026-11-04T00:00']);
break;
case 'last-30-days':
setSelectedDate(['2026-10-06T00:00', '2026-11-04T00:00']);
break;
default:
break;
}
}
setSelected(s);
}, []);
const onDateChange = useCallback((ev: MbscDatepickerChangeEvent) => {
const date = ev.value as MbscDateType[];
setDisabledInput(false);
setSelected('custom');
setSelectedDate(date);
}, []);
const onClose = useCallback(() => {
setOpen(false);
}, []);
useEffect(() => {
changeInputValue(startDate, endDate);
});
return (
<Page>
<div className="mbsc-form-group">
<Input inputStyle="box" onClick={inputClick} defaultValue={inputValue} className="date-filter-input"></Input>
</div>
<Popup isOpen={isOpen} onClose={onClose} responsive={respPopup} cssClass="demo-date-filtering-popup">
<div className="mbsc-grid mbsc-no-padding">
<div className="mbsc-row">
<div className="mbsc-col-sm-4 mbsc-push-sm-8 demo-date-filtering-dates">
<div className="demo-date-filtering-inputs">
<Select
data={myData}
label="Date range"
labelStyle="stacked"
inputStyle="box"
responsive={respSelect}
touchUi={true}
value={selected}
onChange={onChange}
/>
<Input
ref={startRef}
disabled={disabledInput}
label="Start"
labelStyle="stacked"
inputStyle="box"
className="demo-date-filtering-range-input"
placeholder="Please Select..."
/>
<Input
ref={endRef}
disabled={disabledInput}
label="End"
labelStyle="stacked"
inputStyle="box"
className="demo-date-filtering-range-input"
placeholder="Please Select..."
/>
</div>
<div className="demo-date-filtering-desktop-buttons mbsc-button-group-justified">
<Button className="apply-button" onClick={applyClick}>
Apply
</Button>
<Button className="cancel-button" onClick={cancelClick}>
Cancel
</Button>
</div>
</div>
<div className="mbsc-col-sm-8 mbsc-pull-sm-4">
<Datepicker
select="range"
display="inline"
showRangeLabels={false}
pages="auto"
startInput={start}
endInput={end}
returnFormat="iso8601"
showOnClick={false}
showOnFocus={false}
value={selectedDate}
onChange={onDateChange}
/>
</div>
</div>
</div>
</Popup>
</Page>
);
};
export default App;
.demo-date-filtering-popup .mbsc-ios.mbsc-datepicker-inline {
border: none;
border-radius: 4px;
overflow: hidden;
}
.demo-date-filtering-popup .mbsc-textfield-wrapper-box {
margin-top: 0;
margin-right: 0;
}
.demo-date-filtering-dates {
display: flex;
flex-direction: column;
}
.demo-date-filtering-inputs {
flex: 1;
}
.demo-date-filtering-desktop-buttons.mbsc-button-group-justified,
.demo-date-filtering-desktop-buttons.mbsc-button-group-justified button {
margin-bottom: 0;
}
@media (max-width: 575px) {
.demo-date-filtering-desktop-buttons {
display: none;
}
.demo-date-filtering-popup .mbsc-textfield-wrapper-box {
margin-left: 0;
}
}