Merge pull request #761 from lethemanh/760-fix-date-picker-on-iphone

#760 fix date picker does not display on iphone
This commit is contained in:
lethemanh
2026-04-10 14:36:11 +07:00
committed by GitHub
2 changed files with 72 additions and 6 deletions
@@ -3,12 +3,15 @@ import { useTheme } from '@linagora/twake-mui'
import { StaticDatePicker } from '@mui/x-date-pickers/StaticDatePicker' import { StaticDatePicker } from '@mui/x-date-pickers/StaticDatePicker'
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider' import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs' import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
import React from 'react' import React, { useMemo } from 'react'
import { useI18n } from 'twake-i18n' import { useI18n } from 'twake-i18n'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import localeData from 'dayjs/plugin/localeData'
import { PickerValue } from '@mui/x-date-pickers/internals' import { PickerValue } from '@mui/x-date-pickers/internals'
import { MonthSelector } from './MonthSelector' import { MonthSelector } from './MonthSelector'
dayjs.extend(localeData)
export type DatePickerMobileProps = { export type DatePickerMobileProps = {
calendarRef: React.RefObject<CalendarApi | null> calendarRef: React.RefObject<CalendarApi | null>
currentDate: Date currentDate: Date
@@ -16,6 +19,59 @@ export type DatePickerMobileProps = {
onCloseDatePicker: () => void onCloseDatePicker: () => void
} }
// Calculate dynamic height based on month's week count
const calculateCalendarHeightByMonth = (
currentDate: Date,
lang: string
): {
rootMinHeight: number
calendarHeight: number
slideTransitionMinHeight: number
} => {
const date = dayjs(currentDate).locale(lang)
const firstDay = date.startOf('month')
const localeWeekStart = date.localeData().firstDayOfWeek()
const firstDayOfWeek = firstDay.day()
// Calculate days from start of month to first Sunday
// This determines how many days from previous month are shown
const daysFromPrevMonth = (firstDayOfWeek - localeWeekStart + 7) % 7
const daysInCurrentMonth = firstDay.daysInMonth()
// Total days displayed in calendar grid
const totalDaysDisplayed = daysFromPrevMonth + daysInCurrentMonth
// Calculate number of weeks needed (always round up to fill complete weeks)
const weekCount = Math.ceil(totalDaysDisplayed / 7)
// For showDaysOutsideCurrentMonth, most months will show 5-6 weeks
const adjustedWeekCount = Math.max(4, weekCount) // Minimum 4 weeks for consistency
// Base height per week + some padding
const baseHeightPerWeek = 50
const padding = 80
const minHeight = 200 // Minimum height for 4 weeks
const maxHeight = 400 // Maximum height for 6 weeks
const rootMinHeightOffset = 120
const slideTransitionOffset = 100
const calculatedHeight = Math.max(
minHeight,
Math.min(maxHeight, adjustedWeekCount * baseHeightPerWeek + padding)
)
return {
rootMinHeight: Math.max(minHeight, calculatedHeight - rootMinHeightOffset),
calendarHeight: calculatedHeight,
slideTransitionMinHeight: Math.max(
minHeight,
calculatedHeight - slideTransitionOffset
)
}
}
export const DatePickerMobile: React.FC<DatePickerMobileProps> = ({ export const DatePickerMobile: React.FC<DatePickerMobileProps> = ({
calendarRef, calendarRef,
currentDate, currentDate,
@@ -25,6 +81,11 @@ export const DatePickerMobile: React.FC<DatePickerMobileProps> = ({
const { t, lang } = useI18n() const { t, lang } = useI18n()
const theme = useTheme() const theme = useTheme()
const { rootMinHeight, calendarHeight, slideTransitionMinHeight } = useMemo(
() => calculateCalendarHeightByMonth(currentDate, lang ?? 'en'),
[currentDate, lang]
)
const onChangeDate = (newDate: PickerValue): void => { const onChangeDate = (newDate: PickerValue): void => {
if (newDate && calendarRef.current) { if (newDate && calendarRef.current) {
const d = newDate.toDate() const d = newDate.toDate()
@@ -66,7 +127,8 @@ export const DatePickerMobile: React.FC<DatePickerMobileProps> = ({
slots={{ calendarHeader: () => null, actionBar: () => null }} slots={{ calendarHeader: () => null, actionBar: () => null }}
sx={{ sx={{
width: '100%', width: '100%',
marginTop: '10px' marginTop: '10px',
minHeight: `${rootMinHeight}px`
}} }}
slotProps={{ slotProps={{
toolbar: { hidden: true }, toolbar: { hidden: true },
@@ -75,9 +137,9 @@ export const DatePickerMobile: React.FC<DatePickerMobileProps> = ({
'.MuiDateCalendar-root': { '.MuiDateCalendar-root': {
width: '100%', width: '100%',
margin: 0, margin: 0,
maxWidth: 'unset', maxWidth: 'none',
maxHeight: 'unset', maxHeight: 'none',
height: '400px' height: `${calendarHeight}px`
}, },
'.MuiDayCalendar-header': { '.MuiDayCalendar-header': {
width: '100%', width: '100%',
@@ -86,6 +148,9 @@ export const DatePickerMobile: React.FC<DatePickerMobileProps> = ({
'.MuiDayCalendar-weekContainer': { '.MuiDayCalendar-weekContainer': {
width: '100%', width: '100%',
justifyContent: 'space-around' justifyContent: 'space-around'
},
'.MuiDateCalendar-root .MuiDayCalendar-slideTransition': {
minHeight: `${slideTransitionMinHeight}px`
} }
} }
}, },
@@ -39,7 +39,8 @@ export const MonthSelector: React.FC<MonthSelectorProps> = ({
py: 1, py: 1,
scrollbarWidth: 'none', scrollbarWidth: 'none',
'&::-webkit-scrollbar': { display: 'none' }, '&::-webkit-scrollbar': { display: 'none' },
backgroundColor: '#FFF' backgroundColor: '#FFF',
minHeight: '48px'
}} }}
> >
{Array.from({ length: 12 }).map((_, i) => { {Array.from({ length: 12 }).map((_, i) => {