mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 10:19:51 -06:00
fix: tweak responsiveness of mobile surveys (#4580)
Co-authored-by: Dhruwang <dhruwangjariwala18@gmail.com> Co-authored-by: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com>
This commit is contained in:
@@ -192,12 +192,12 @@ export const HiddenFieldsCard = ({
|
||||
toast.success(t("environments.surveys.edit.hidden_field_added_successfully"));
|
||||
setHiddenField("");
|
||||
}}>
|
||||
<Label htmlFor="headline">{t("common.hidden_field")}</Label>
|
||||
<div className="mt-2 flex gap-2">
|
||||
<Label htmlFor="hiddenField">{t("common.hidden_field")}</Label>
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<Input
|
||||
autoFocus
|
||||
id="headline"
|
||||
name="headline"
|
||||
id="hiddenField"
|
||||
name="hiddenField"
|
||||
value={hiddenField}
|
||||
onChange={(e) => setHiddenField(e.target.value.trim())}
|
||||
placeholder={t("environments.surveys.edit.type_field_id") + "..."}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { SurveyStatusDropdown } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/SurveyStatusDropdown";
|
||||
import { getFormattedErrorMessage } from "@/lib/utils/helper";
|
||||
import { createSegmentAction } from "@/modules/ee/contacts/segments/actions";
|
||||
import { AlertDialog } from "@/modules/ui/components/alert-dialog";
|
||||
@@ -115,13 +114,6 @@ export const SurveyMenuBar = ({
|
||||
if (localSurvey.status !== "draft" && containsEmptyTriggers) return true;
|
||||
}, [containsEmptyTriggers, isSurveySaving, localSurvey.status]);
|
||||
|
||||
// write a function which updates the local survey status
|
||||
const updateLocalSurveyStatus = (status: TSurvey["status"]) => {
|
||||
const updatedSurvey = { ...localSurvey };
|
||||
updatedSurvey.status = status;
|
||||
setLocalSurvey(updatedSurvey);
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
const { updatedAt, ...localSurveyRest } = localSurvey;
|
||||
const { updatedAt: _, ...surveyRest } = survey;
|
||||
@@ -355,13 +347,6 @@ export const SurveyMenuBar = ({
|
||||
</div>
|
||||
)}
|
||||
<div className="mt-3 flex sm:ml-4 sm:mt-0">
|
||||
<div className="mr-4 flex items-center">
|
||||
<SurveyStatusDropdown
|
||||
survey={survey}
|
||||
environment={environment}
|
||||
updateLocalSurveyStatus={updateLocalSurveyStatus}
|
||||
/>
|
||||
</div>
|
||||
{!isCxMode && (
|
||||
<Button
|
||||
disabled={disableSave}
|
||||
|
||||
@@ -62,7 +62,7 @@ export const UpdateQuestionId = ({
|
||||
return (
|
||||
<div>
|
||||
<Label htmlFor="questionId">{t("common.question_id")}</Label>
|
||||
<div className="mt-2 inline-flex w-full space-x-2">
|
||||
<div className="mt-2 inline-flex w-full items-center space-x-2">
|
||||
<Input
|
||||
id="questionId"
|
||||
name="questionId"
|
||||
|
||||
@@ -60,7 +60,7 @@ export const ShareEmbedSurvey = ({
|
||||
|
||||
const [activeId, setActiveId] = useState(survey.type === "link" ? tabs[0].id : tabs[3].id);
|
||||
const [showView, setShowView] = useState<"start" | "embed" | "panel">("start");
|
||||
const [surveyUrl, setSurveyUrl] = useState("");
|
||||
const [surveyUrl, setSurveyUrl] = useState(webAppUrl + "/s/" + survey.id);
|
||||
|
||||
useEffect(() => {
|
||||
if (survey.type !== "link") {
|
||||
|
||||
@@ -67,9 +67,9 @@ export const LinkSurveyWrapper = ({
|
||||
isBrandingEnabled={isBrandingEnabled}
|
||||
/>
|
||||
<MediaBackground survey={survey} project={project} onBackgroundLoaded={handleBackgroundLoaded}>
|
||||
<div className="flex max-h-dvh min-h-dvh items-end justify-center overflow-clip sm:items-center">
|
||||
<div className="flex max-h-dvh min-h-dvh items-center justify-center overflow-clip">
|
||||
{!styling.isLogoHidden && project.logo?.url && <ClientLogo project={project} />}
|
||||
<div className="h-full w-full space-y-6 p-0 sm:max-w-lg">
|
||||
<div className="h-full w-full max-w-lg space-y-6 px-1.5">
|
||||
{isPreview && (
|
||||
<div className="fixed left-0 top-0 flex w-full items-center justify-between bg-slate-600 p-2 px-4 text-center text-sm text-white shadow-sm">
|
||||
<div />
|
||||
|
||||
@@ -27,7 +27,7 @@ export const SurveyInactive = async ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-between bg-gradient-to-br from-slate-200 to-slate-50 py-8 text-center">
|
||||
<div className="flex h-full flex-col items-center justify-between bg-gradient-to-br from-slate-200 to-slate-50 px-4 py-8 text-center">
|
||||
<div></div>
|
||||
<div className="flex flex-col items-center space-y-3 text-slate-300">
|
||||
{icons[status]}
|
||||
|
||||
@@ -116,7 +116,7 @@ export const VerifyEmail = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center text-center">
|
||||
<div className="flex h-full w-full flex-col items-center justify-center p-2 text-center">
|
||||
<Toaster />
|
||||
<StackedCardsContainer
|
||||
cardArrangement={
|
||||
@@ -175,12 +175,12 @@ export const VerifyEmail = ({
|
||||
</FormProvider>
|
||||
{!emailSent && showPreviewQuestions && (
|
||||
<div>
|
||||
<p className="text-4xl font-bold">{t("s.question_preview")}</p>
|
||||
<p className="text-2xl font-bold">{t("s.question_preview")}</p>
|
||||
<div className="mt-4 flex w-full flex-col justify-center rounded-lg border border-slate-200 bg-slate-50 bg-opacity-20 p-8 text-slate-700">
|
||||
{localSurvey.questions.map((question, index) => (
|
||||
<p
|
||||
key={index}
|
||||
className="my-1">{`${(index + 1).toString()}. ${getLocalizedValue(question.headline, languageCode)}`}</p>
|
||||
className="my-1 text-sm">{`${(index + 1).toString()}. ${getLocalizedValue(question.headline, languageCode)}`}</p>
|
||||
))}
|
||||
</div>
|
||||
<Button variant="ghost" className="mt-6" onClick={handlePreviewClick}>
|
||||
|
||||
@@ -12,7 +12,7 @@ const buttonVariants = cva(
|
||||
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
||||
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
||||
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
||||
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
||||
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/50",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
|
||||
@@ -277,7 +277,7 @@ export const PreviewSurvey = ({
|
||||
/>
|
||||
</Modal>
|
||||
) : (
|
||||
<div className="flex h-full w-full flex-col justify-end">
|
||||
<div className="flex h-full w-full flex-col justify-center px-1">
|
||||
<div className="absolute left-5 top-5">
|
||||
{!styling.isLogoHidden && (
|
||||
<ClientLogo environmentId={environment.id} project={project} previewSurvey />
|
||||
|
||||
@@ -409,7 +409,7 @@ export function Survey({
|
||||
<AutoCloseWrapper survey={localSurvey} onClose={onClose} offset={offset}>
|
||||
<div
|
||||
className={cn(
|
||||
"fb-no-scrollbar sm:fb-rounded-custom fb-rounded-t-custom fb-bg-survey-bg fb-flex fb-h-full fb-w-full fb-flex-col fb-justify-between fb-overflow-hidden fb-transition-all fb-duration-1000 fb-ease-in-out",
|
||||
"fb-no-scrollbar fb-rounded-custom fb-bg-survey-bg fb-flex fb-h-full fb-w-full fb-flex-col fb-justify-between fb-overflow-hidden fb-transition-all fb-duration-1000 fb-ease-in-out",
|
||||
cardArrangement === "simple" ? "fb-survey-shadow" : "",
|
||||
offset === 0 || cardArrangement === "simple" ? "fb-opacity-100" : "fb-opacity-0"
|
||||
)}>
|
||||
|
||||
@@ -7,11 +7,9 @@ interface ScrollableContainerProps {
|
||||
}
|
||||
|
||||
export function ScrollableContainer({ children }: ScrollableContainerProps) {
|
||||
const [isOverflowHidden, setIsOverflowHidden] = useState(true);
|
||||
const [isAtBottom, setIsAtBottom] = useState(false);
|
||||
const [isAtTop, setIsAtTop] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const isSurveyPreview = Boolean(document.getElementById("survey-preview"));
|
||||
|
||||
const checkScroll = () => {
|
||||
@@ -23,18 +21,6 @@ export function ScrollableContainer({ children }: ScrollableContainerProps) {
|
||||
setIsAtTop(scrollTop === 0);
|
||||
};
|
||||
|
||||
const toggleOverflow = (hide: boolean) => {
|
||||
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
||||
if (hide) {
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
setIsOverflowHidden(true);
|
||||
}, 1000);
|
||||
} else {
|
||||
setIsOverflowHidden(false);
|
||||
checkScroll();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const element = containerRef.current;
|
||||
if (!element) return;
|
||||
@@ -56,7 +42,7 @@ export function ScrollableContainer({ children }: ScrollableContainerProps) {
|
||||
return (
|
||||
<div className="fb-relative">
|
||||
{!isAtTop && (
|
||||
<div className="fb-from-survey-bg fb-absolute fb-left-0 fb-right-2 fb-top-0 fb-z-10 fb-h-4 fb-bg-gradient-to-b fb-to-transparent" />
|
||||
<div className="fb-from-survey-bg fb-absolute fb-left-0 fb-right-2 fb-top-0 fb-z-10 fb-h-6 fb-bg-gradient-to-b fb-to-transparent" />
|
||||
)}
|
||||
<div
|
||||
ref={containerRef}
|
||||
@@ -64,16 +50,7 @@ export function ScrollableContainer({ children }: ScrollableContainerProps) {
|
||||
scrollbarGutter: "stable both-edges",
|
||||
maxHeight: isSurveyPreview ? "40dvh" : "60dvh",
|
||||
}}
|
||||
className={cn(
|
||||
"fb-overflow-auto fb-px-4 fb-pb-1",
|
||||
isOverflowHidden ? "fb-no-scrollbar" : "fb-bg-survey-bg"
|
||||
)}
|
||||
onMouseEnter={() => {
|
||||
toggleOverflow(false);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
toggleOverflow(true);
|
||||
}}>
|
||||
className={cn("fb-overflow-auto fb-px-4 fb-pb-1 fb-bg-survey-bg")}>
|
||||
{children}
|
||||
</div>
|
||||
{!isAtBottom && (
|
||||
|
||||
@@ -114,6 +114,7 @@ export const StackedCard = ({
|
||||
style={{
|
||||
opacity: contentOpacity,
|
||||
transition: "opacity 300ms ease-in-out",
|
||||
height: "100%",
|
||||
}}>
|
||||
{delayedOffset === 0 ? getCardContent(dynamicQuestionIndex, offset) : getDummyCardContent()}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user