diff --git a/app/client/src/components/autoHeight/AutoHeightContainer.test.tsx b/app/client/src/components/autoHeight/AutoHeightContainer.test.tsx
new file mode 100644
index 0000000000..33098fed23
--- /dev/null
+++ b/app/client/src/components/autoHeight/AutoHeightContainer.test.tsx
@@ -0,0 +1,72 @@
+import React from "react";
+import "@testing-library/jest-dom";
+import { render } from "@testing-library/react";
+import AutoHeightContainer from "./AutoHeightContainer";
+import "jest-styled-components";
+import renderer from "react-test-renderer";
+
+describe("", () => {
+ it("should wrap the children in a div whose height is auto.", async () => {
+ const tree = renderer
+ .create(
+ {}}
+ >
+
+ ,
+ )
+ .toJSON();
+ expect(tree).toHaveStyleRule("height", "auto");
+ });
+
+ describe("when isAutoHeightWithLimits is false", () => {
+ it("should wrap the children in a simple div with class auto-height-container", async () => {
+ const getTestComponent = () => (
+ {}}
+ >
+
+
+ );
+ const component = getTestComponent();
+ const renderResult = render(component);
+ const child = await renderResult.findByTestId("test");
+ expect(
+ child.parentElement?.classList.contains("auto-height-container"),
+ ).toBe(true);
+ });
+ });
+
+ describe("when isAutoHeightWithLimits is true", () => {
+ it("should wrap the children in a div of class auto-height-container and then a div with class auto-height-scroll-container", async () => {
+ const getTestComponent = () => (
+ {}}
+ >
+
+
+ );
+ const component = getTestComponent();
+ const renderResult = render(component);
+ const child = await renderResult.findByTestId("test");
+ expect(child.parentElement?.tagName).toBe("DIV");
+ expect(
+ child.parentElement?.classList.contains("auto-height-container"),
+ ).toBe(true);
+ expect(
+ child.parentElement?.parentElement?.classList.contains(
+ "auto-height-scroll-container",
+ ),
+ ).toBe(true);
+ });
+ });
+});
diff --git a/app/client/src/components/autoHeight/AutoHeightContainer.tsx b/app/client/src/components/autoHeight/AutoHeightContainer.tsx
new file mode 100644
index 0000000000..30b91d1af5
--- /dev/null
+++ b/app/client/src/components/autoHeight/AutoHeightContainer.tsx
@@ -0,0 +1,78 @@
+import React, { PropsWithChildren, useRef, useEffect, useState } from "react";
+import { GridDefaults } from "constants/WidgetConstants";
+import styled from "styled-components";
+
+const StyledAutoHeightContainer = styled.div<{ isOverflow?: boolean }>`
+ overflow-y: ${(props) => (props.isOverflow ? "auto" : "unset")};
+ overflow-x: ${(props) => (props.isOverflow ? "hidden" : "unset")};
+`;
+
+interface AutoHeightContainerProps {
+ maxDynamicHeight: number;
+ minDynamicHeight: number;
+ isAutoHeightWithLimits: boolean;
+ onHeightUpdate: (height: number) => void;
+}
+
+const SimpleContainer = styled.div`
+ height: auto;
+`;
+
+export default function AutoHeightContainer({
+ children,
+ isAutoHeightWithLimits,
+ maxDynamicHeight,
+ minDynamicHeight,
+ onHeightUpdate,
+}: PropsWithChildren) {
+ const [expectedHeight, setExpectedHeight] = useState(0);
+
+ const ref = useRef(null);
+
+ const observer = useRef(
+ new ResizeObserver((entries) => {
+ const height = entries[0].contentRect.height;
+ setExpectedHeight(height);
+ onHeightUpdate(height);
+ }),
+ );
+
+ useEffect(() => {
+ if (ref.current) {
+ observer.current.observe(ref.current);
+ }
+
+ return () => {
+ if (ref.current) {
+ observer.current.unobserve(ref.current);
+ }
+ };
+ }, []);
+
+ useEffect(() => {
+ onHeightUpdate(expectedHeight);
+ }, [minDynamicHeight, maxDynamicHeight]);
+
+ if (isAutoHeightWithLimits) {
+ const expectedHeightInRows = Math.ceil(
+ expectedHeight / GridDefaults.DEFAULT_GRID_ROW_HEIGHT,
+ );
+
+ return (
+
+
+ {children}
+
+
+ );
+ }
+
+ return (
+
+ {children}
+
+ );
+}