fix: nested scrolls on /bookings (#19284)
This commit is contained in:
@@ -7,7 +7,9 @@ import {
|
||||
getSortedRowModel,
|
||||
createColumnHelper,
|
||||
} from "@tanstack/react-table";
|
||||
import { useMemo, useState, useEffect } from "react";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { debounce } from "lodash";
|
||||
import { useMemo, useState, useRef, useEffect, useCallback } from "react";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { WipeMyCalActionButton } from "@calcom/app-store/wipemycalother/components";
|
||||
@@ -105,6 +107,8 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
const { t } = useLocale();
|
||||
const user = useMeQuery().data;
|
||||
const [isFiltersVisible, setIsFiltersVisible] = useState<boolean>(false);
|
||||
const tableContainerRef = useRef<HTMLDivElement>(null);
|
||||
useProperHeightForMobile(tableContainerRef);
|
||||
|
||||
useEffect(() => {
|
||||
if (user?.isTeamAdminOrOwner && !filterQuery.userIds?.length) {
|
||||
@@ -276,6 +280,7 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
|
||||
)}
|
||||
<DataTableWrapper
|
||||
tableContainerRef={tableContainerRef}
|
||||
table={table}
|
||||
testId={`${status}-bookings`}
|
||||
bodyTestId="bookings"
|
||||
@@ -305,3 +310,39 @@ function BookingsContent({ status }: BookingsProps) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Dynamically adjusts DataTable height on mobile to prevent nested scrolling
|
||||
// and ensure the table fits within the viewport without overflowing (hacky)
|
||||
function useProperHeightForMobile(ref: React.RefObject<HTMLDivElement>) {
|
||||
const lastOffsetY = useRef<number>();
|
||||
const lastWindowHeight = useRef<number>();
|
||||
const BOTTOM_NAV_HEIGHT = 64;
|
||||
const BUFFER = 32;
|
||||
|
||||
const updateHeight = useCallback(
|
||||
debounce(() => {
|
||||
if (!ref.current || window.innerWidth >= 640) return;
|
||||
const rect = ref.current.getBoundingClientRect();
|
||||
if (rect.top !== lastOffsetY.current || window.innerHeight !== lastWindowHeight.current) {
|
||||
lastOffsetY.current = rect.top;
|
||||
lastWindowHeight.current = window.innerHeight;
|
||||
const height = window.innerHeight - lastOffsetY.current - BOTTOM_NAV_HEIGHT - BUFFER;
|
||||
ref.current.style.height = `${height}px`;
|
||||
}
|
||||
}, 200),
|
||||
[ref.current]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
updateHeight();
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
}, [updateHeight]);
|
||||
|
||||
updateHeight();
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ export type DataTableWrapperProps<TData, TValue> = {
|
||||
className?: string;
|
||||
containerClassName?: string;
|
||||
children?: React.ReactNode;
|
||||
tableContainerRef?: React.RefObject<HTMLDivElement>;
|
||||
};
|
||||
|
||||
export function DataTableWrapper<TData, TValue>({
|
||||
@@ -46,8 +47,10 @@ export function DataTableWrapper<TData, TValue>({
|
||||
className,
|
||||
containerClassName,
|
||||
children,
|
||||
tableContainerRef: externalRef,
|
||||
}: DataTableWrapperProps<TData, TValue>) {
|
||||
const tableContainerRef = useRef<HTMLDivElement>(null);
|
||||
const internalRef = useRef<HTMLDivElement>(null);
|
||||
const tableContainerRef = externalRef || internalRef;
|
||||
const fetchMoreOnBottomReached = useFetchMoreOnBottomReached({
|
||||
tableContainerRef,
|
||||
hasNextPage,
|
||||
|
||||
Reference in New Issue
Block a user