fix: overlay & close on click outside to work in survey preview (#2436)

This commit is contained in:
Shubham Palriwala
2024-04-17 21:01:31 +05:30
committed by GitHub
parent 294b67a6cc
commit 2fca750931
5 changed files with 78 additions and 16 deletions

View File

@@ -31,6 +31,8 @@ export function EditPlacement({ product }: EditPlacementProps) {
const [overlay, setOverlay] = useState(product.darkOverlay ? "darkOverlay" : "lightOverlay");
const [clickOutside, setClickOutside] = useState(product.clickOutsideClose ? "allow" : "disallow");
const [updatingPlacement, setUpdatingPlacement] = useState(false);
const overlayStyle =
currentPlacement === "center" && overlay === "darkOverlay" ? "bg-gray-700/80" : "bg-slate-200";
const handleUpdatePlacement = async () => {
try {
@@ -58,18 +60,21 @@ export function EditPlacement({ product }: EditPlacementProps) {
{placements.map((placement) => (
<div key={placement.value} className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id={placement.value} value={placement.value} disabled={placement.disabled} />
<Label
htmlFor={placement.value}
className={cn(placement.disabled ? "cursor-not-allowed text-slate-500" : "text-slate-900")}>
<Label htmlFor={placement.value} className="text-slate-900">
{placement.name}
</Label>
</div>
))}
</RadioGroup>
<div className="relative ml-8 h-40 w-full rounded bg-slate-200">
<div
className={cn(
clickOutside === "disallow" ? "cursor-not-allowed" : "",
"relative ml-8 h-40 w-full rounded",
overlayStyle
)}>
<div
className={cn(
"absolute h-16 w-16 rounded bg-slate-700",
"absolute h-16 w-16 cursor-default rounded bg-slate-700",
getPlacementStyle(currentPlacement)
)}></div>
</div>

View File

@@ -99,8 +99,12 @@ export const ThemeStylingPreviewSurvey = ({
};
const { placement: surveyPlacement } = productOverwrites || {};
const { darkOverlay: surveyDarkOverlay } = productOverwrites || {};
const { clickOutsideClose: surveyClickOutsideClose } = productOverwrites || {};
const placement = surveyPlacement || product.placement;
const darkOverlay = surveyDarkOverlay ?? product.darkOverlay;
const clickOutsideClose = surveyClickOutsideClose ?? product.clickOutsideClose;
const highlightBorderColor = product.styling.highlightBorderColor?.light;
@@ -149,6 +153,8 @@ export const ThemeStylingPreviewSurvey = ({
isOpen
placement={placement}
highlightBorderColor={highlightBorderColor}
clickOutsideClose={clickOutsideClose}
darkOverlay={darkOverlay}
previewMode="desktop"
background={product.styling.cardBackgroundColor?.light}
borderRadius={product.styling.roundness ?? 8}>

View File

@@ -32,6 +32,8 @@ export default function Placement({
setClickOutsideClose,
clickOutsideClose,
}: TPlacementProps) {
const overlayStyle =
currentPlacement === "center" && overlay === "dark" ? "bg-gray-700/80" : "bg-slate-200";
return (
<>
<div className="flex">
@@ -39,18 +41,21 @@ export default function Placement({
{placements.map((placement) => (
<div key={placement.value} className="flex items-center space-x-2 whitespace-nowrap">
<RadioGroupItem id={placement.value} value={placement.value} disabled={placement.disabled} />
<Label
htmlFor={placement.value}
className={cn(placement.disabled ? "cursor-not-allowed text-slate-500" : "text-slate-900")}>
<Label htmlFor={placement.value} className="text-slate-900">
{placement.name}
</Label>
</div>
))}
</RadioGroup>
<div className="relative ml-8 h-40 w-full rounded bg-slate-200">
<div
className={cn(
clickOutsideClose ? "" : "cursor-not-allowed",
"relative ml-8 h-40 w-full rounded",
overlayStyle
)}>
<div
className={cn(
"absolute h-16 w-16 rounded bg-slate-700",
"absolute h-16 w-16 cursor-default rounded bg-slate-700",
getPlacementStyle(currentPlacement)
)}></div>
</div>

View File

@@ -10,6 +10,8 @@ export default function Modal({
placement,
previewMode,
highlightBorderColor,
clickOutsideClose,
darkOverlay,
borderRadius,
background,
}: {
@@ -18,12 +20,15 @@ export default function Modal({
placement: TPlacement;
previewMode: string;
highlightBorderColor: string | null | undefined;
clickOutsideClose: boolean;
darkOverlay: boolean;
borderRadius?: number;
background?: string;
}) {
const [show, setShow] = useState(false);
const [show, setShow] = useState(true);
const modalRef = useRef<HTMLDivElement | null>(null);
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
const [overlayVisible, setOverlayVisible] = useState(true);
const calculateScaling = () => {
let scaleValue = "1";
@@ -61,6 +66,7 @@ export default function Modal({
};
const scalingClasses = calculateScaling();
const overlayStyle = overlayVisible && darkOverlay ? "bg-gray-700/80" : "bg-white/50";
useEffect(() => {
const handleResize = () => setWindowWidth(window.innerWidth);
@@ -68,11 +74,36 @@ export default function Modal({
return () => window.removeEventListener("resize", handleResize);
}, []);
useEffect(() => {
if (!clickOutsideClose) {
setOverlayVisible(true);
setShow(true);
}
const previewBase = document.getElementById("preview-survey-base");
function handleClickOutside(e: MouseEvent) {
// Checks if the positioning is center, clickOutsideClose is set & if the click is inside the preview screen but outside the survey modal
if (
scalingClasses.transformOrigin === "" &&
clickOutsideClose &&
modalRef.current &&
previewBase &&
previewBase.contains(e.target as Node) &&
!modalRef.current.contains(e.target as Node)
) {
setTimeout(() => {
setOverlayVisible(false);
setShow(false);
}, 500);
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [clickOutsideClose, scalingClasses.transformOrigin]);
const highlightBorderColorStyle = useMemo(() => {
if (!highlightBorderColor)
return {
overflow: "auto",
};
if (!highlightBorderColor) return { overflow: "auto" };
return {
border: `2px solid ${highlightBorderColor}`,
@@ -103,7 +134,14 @@ export default function Modal({
: "";
return (
<div aria-live="assertive" className="relative h-full w-full overflow-hidden bg-slate-300">
<div
id="preview-survey-base"
aria-live="assertive"
className={cn(
"relative h-full w-full overflow-hidden",
overlayStyle,
"transition-all duration-500 ease-in-out"
)}>
<div
ref={modalRef}
style={{

View File

@@ -113,8 +113,12 @@ export default function PreviewSurvey({
};
const { placement: surveyPlacement } = productOverwrites || {};
const { darkOverlay: surveyDarkOverlay } = productOverwrites || {};
const { clickOutsideClose: surveyClickOutsideClose } = productOverwrites || {};
const placement = surveyPlacement || product.placement;
const darkOverlay = surveyDarkOverlay ?? product.darkOverlay;
const clickOutsideClose = surveyClickOutsideClose ?? product.clickOutsideClose;
const styling: TSurveyStyling | TProductStyling = useMemo(() => {
// allow style overwrite is disabled from the product
@@ -224,6 +228,8 @@ export default function PreviewSurvey({
placement={placement}
highlightBorderColor={styling.highlightBorderColor?.light}
previewMode="mobile"
darkOverlay={darkOverlay}
clickOutsideClose={clickOutsideClose}
borderRadius={styling?.roundness ?? 8}
background={styling?.cardBackgroundColor?.light}>
<SurveyInline
@@ -304,6 +310,8 @@ export default function PreviewSurvey({
isOpen={isModalOpen}
placement={placement}
highlightBorderColor={styling.highlightBorderColor?.light}
clickOutsideClose={clickOutsideClose}
darkOverlay={darkOverlay}
previewMode="desktop"
borderRadius={styling.roundness ?? 8}
background={styling.cardBackgroundColor?.light}>