mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 09:13:11 +00:00
Render status dropdown via React portal to fix transparency
- Menu now renders on document.body via createPortal - Positioned using getBoundingClientRect from the badge button - Eliminates all parent stacking context / overflow issues
This commit is contained in:
parent
4c54d3499f
commit
24c83c6535
2 changed files with 35 additions and 23 deletions
|
|
@ -34,14 +34,10 @@
|
|||
.woStatusBadge.done, .woStatusBadge.completed { background: #28a745; }
|
||||
.woStatusBadge.cancelled { background: #dc3545; }
|
||||
|
||||
.woStatusDropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.woStatusClickable {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.woStatusClickable:hover {
|
||||
|
|
@ -54,17 +50,14 @@
|
|||
}
|
||||
|
||||
.woStatusMenu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
margin-top: 4px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #ddd;
|
||||
position: fixed;
|
||||
background: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
z-index: 1000;
|
||||
min-width: 160px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.2);
|
||||
z-index: 99999;
|
||||
min-width: 170px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.woStatusOption {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useState, useEffect, useRef } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { useParams, useNavigate } from "react-router";
|
||||
import { toast } from "react-toastify";
|
||||
import { getWorkOrderById, addComment, changeWorkOrderStatus } from "../api";
|
||||
|
|
@ -121,27 +122,44 @@ const STATUS_OPTIONS = ["Open", "In Progress", "On Hold", "Done", "Cancelled"];
|
|||
|
||||
function StatusDropdown({ status, onStatusChange }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const ref = useRef(null);
|
||||
const btnRef = useRef(null);
|
||||
const menuRef = useRef(null);
|
||||
const [menuPos, setMenuPos] = useState({ top: 0, left: 0 });
|
||||
const statusClass = (status || "").toLowerCase().replace(/\s+/g, "-");
|
||||
|
||||
useEffect(() => {
|
||||
const handleClick = (e) => {
|
||||
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
||||
if (btnRef.current?.contains(e.target)) return;
|
||||
if (menuRef.current?.contains(e.target)) return;
|
||||
setOpen(false);
|
||||
};
|
||||
document.addEventListener("mousedown", handleClick);
|
||||
return () => document.removeEventListener("mousedown", handleClick);
|
||||
}, []);
|
||||
|
||||
const handleOpen = () => {
|
||||
if (btnRef.current) {
|
||||
const rect = btnRef.current.getBoundingClientRect();
|
||||
setMenuPos({ top: rect.bottom + 4, left: rect.left });
|
||||
}
|
||||
setOpen(!open);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="woStatusDropdown" ref={ref}>
|
||||
<>
|
||||
<button
|
||||
ref={btnRef}
|
||||
className={`woStatusBadge ${statusClass} woStatusClickable`}
|
||||
onClick={() => setOpen(!open)}
|
||||
onClick={handleOpen}
|
||||
>
|
||||
{status} <span className="woStatusCaret">▾</span>
|
||||
</button>
|
||||
{open && (
|
||||
<div className="woStatusMenu">
|
||||
{open && ReactDOM.createPortal(
|
||||
<div
|
||||
ref={menuRef}
|
||||
className="woStatusMenu"
|
||||
style={{ top: menuPos.top, left: menuPos.left }}
|
||||
>
|
||||
{STATUS_OPTIONS.map((s) => (
|
||||
<button
|
||||
key={s}
|
||||
|
|
@ -152,9 +170,10 @@ function StatusDropdown({ status, onStatusChange }) {
|
|||
{s}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue