mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-06 05:40:02 -06:00
fix: overlay & close on click outside to work in survey preview (#2436)
This commit is contained in:
committed by
GitHub
parent
294b67a6cc
commit
2fca750931
@@ -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>
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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={{
|
||||
|
||||
@@ -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}>
|
||||
|
||||
Reference in New Issue
Block a user