Dropdown causing vertical overflow in table.
As from the image I shared you can see a table that holds few data, and one of them is status selection. I created dropdown for that. But on opening that it is not overlapping the table. Instead it creates a vertical scroll bar and empty space in the bottom.

3 Replies
Dropdown code
Table Code
https://codesandbox.io/p/sandbox/nifty-ishizaka-ym8fy6
const renderStatusDropdown = (record: AttendanceRecord) => {
const { id, status } = record;
const getStatusColor = (status: string) => {
switch (status) {
case "Present":
return "bg-green-100 text-green-800";
case "Absent":
return "bg-red-100 text-red-800";
case "Early Left":
return "bg-yellow-100 text-yellow-800";
default:
return "bg-gray-100 text-gray-800";
}
};
return (
<div className="relative inline-block w-full">
<div
className={`flex items-center justify-between px-3 py-1 rounded-md cursor-pointer ${getStatusColor(status)}`}
onClick={() => toggleDropdown(id)}
>
<span className="text-sm">{status}</span>
<GoTriangleDown className="ml-2" />
</div>
{/* Dropdown absolutely positioned over other rows */}
{openDropdownId === id && (
<div className="absolute left-0 mt-1 w-36 bg-white border border-gray-200 rounded-md shadow-lg z-50">
{["Present", "Absent", "Early Left"].map((statusOption) => (
<button
key={statusOption}
className={`block w-full text-left px-4 py-2 text-sm hover:bg-gray-100 rounded-none ${
status === statusOption ? getStatusColor(statusOption) : ""
}`}
onClick={() => updateStatus(id, statusOption as "Present" | "Absent" | "Early Left")}
>
{statusOption}
</button>
))}
</div>
)}
</div>
);
};
const renderStatusDropdown = (record: AttendanceRecord) => {
const { id, status } = record;
const getStatusColor = (status: string) => {
switch (status) {
case "Present":
return "bg-green-100 text-green-800";
case "Absent":
return "bg-red-100 text-red-800";
case "Early Left":
return "bg-yellow-100 text-yellow-800";
default:
return "bg-gray-100 text-gray-800";
}
};
return (
<div className="relative inline-block w-full">
<div
className={`flex items-center justify-between px-3 py-1 rounded-md cursor-pointer ${getStatusColor(status)}`}
onClick={() => toggleDropdown(id)}
>
<span className="text-sm">{status}</span>
<GoTriangleDown className="ml-2" />
</div>
{/* Dropdown absolutely positioned over other rows */}
{openDropdownId === id && (
<div className="absolute left-0 mt-1 w-36 bg-white border border-gray-200 rounded-md shadow-lg z-50">
{["Present", "Absent", "Early Left"].map((statusOption) => (
<button
key={statusOption}
className={`block w-full text-left px-4 py-2 text-sm hover:bg-gray-100 rounded-none ${
status === statusOption ? getStatusColor(statusOption) : ""
}`}
onClick={() => updateStatus(id, statusOption as "Present" | "Absent" | "Early Left")}
>
{statusOption}
</button>
))}
</div>
)}
</div>
);
};
{!isLoading && (
<div className="bg-white rounded-lg shadow-sm overflow-hidden mb-6">
{attendanceRecords.length === 0 ? (
<div className="text-center py-8 bg-gray-50">
<p className="text-gray-500">
{selectedBatch && syllabusTopic
? "No students found for the selected filters"
: "Please select batch and syllabus topic to load students"}
</p>
</div>
) : (
<div className="overflow-x-auto overflow-y-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50 sticky top-0 z-10">
<tr>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Student Name</th>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Class Name</th>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Status</th>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Hours Attended</th>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Completed Class</th>
</tr>
</thead>
{!isLoading && (
<div className="bg-white rounded-lg shadow-sm overflow-hidden mb-6">
{attendanceRecords.length === 0 ? (
<div className="text-center py-8 bg-gray-50">
<p className="text-gray-500">
{selectedBatch && syllabusTopic
? "No students found for the selected filters"
: "Please select batch and syllabus topic to load students"}
</p>
</div>
) : (
<div className="overflow-x-auto overflow-y-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50 sticky top-0 z-10">
<tr>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Student Name</th>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Class Name</th>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Status</th>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Hours Attended</th>
<th className="px-6 py-3 text-left text-sm font-medium text-gray-900">Completed Class</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{attendanceRecords.map((record) => (
<tr key={record.id}>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{record.studentName}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{record.courseName}</td>
<td className="align-top px-6 py-4 whitespace-nowrap text-sm">{renderStatusDropdown(record)}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm">
<input
type="number"
value={record.hoursAttended}
onChange={(e) => updateHours(record.id, parseInt(e.target.value) || 0)}
className="w-20 px-2 py-1 border border-gray-300 rounded text-center focus:outline-none focus:ring-2 focus:ring-blue-200"
min="0"
max="24"
/>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm">
<div className="flex items-center">
<input
type="checkbox"
checked={record.completedClass}
onChange={(e) => updateCompletedClass(record.id, e.target.checked)}
className="size-6 accent-[#e4fbb1] rounded focus:ring-2 focus:ring-[#e4fbb1]"
/>
<span className="ml-2 text-gray-600">
{record.completedClass ? "Yes" : "No"}
</span>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
)}
<tbody className="bg-white divide-y divide-gray-200">
{attendanceRecords.map((record) => (
<tr key={record.id}>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{record.studentName}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{record.courseName}</td>
<td className="align-top px-6 py-4 whitespace-nowrap text-sm">{renderStatusDropdown(record)}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm">
<input
type="number"
value={record.hoursAttended}
onChange={(e) => updateHours(record.id, parseInt(e.target.value) || 0)}
className="w-20 px-2 py-1 border border-gray-300 rounded text-center focus:outline-none focus:ring-2 focus:ring-blue-200"
min="0"
max="24"
/>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm">
<div className="flex items-center">
<input
type="checkbox"
checked={record.completedClass}
onChange={(e) => updateCompletedClass(record.id, e.target.checked)}
className="size-6 accent-[#e4fbb1] rounded focus:ring-2 focus:ring-[#e4fbb1]"
/>
<span className="ml-2 text-gray-600">
{record.completedClass ? "Yes" : "No"}
</span>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
)}
this must have position absolute
otherwise it stays in the flow of the document
oh, wait, you have it with position absolute
🤔
well, i tested it on my phone, and, before it crashed, it was working fine
the cause it the use of the overflow classes