From 888dbbcfd2f0b23c4e86035e176635176540a0a0 Mon Sep 17 00:00:00 2001 From: Matti Nannt Date: Tue, 14 Nov 2023 17:39:30 +0100 Subject: [PATCH 1/5] feat: add toggle for in-app formbricks branding (#1616) Co-authored-by: Johannes Co-authored-by: review-agent-prime[bot] <147289438+review-agent-prime[bot]@users.noreply.github.com> --- .../lookandfeel/components/EditBranding.tsx | 83 +++++++++++++++++++ .../lookandfeel/components/EditSignature.tsx | 67 --------------- .../settings/lookandfeel/page.tsx | 38 +++++---- .../components/shareEmbedTabs/LinkTab.tsx | 2 +- .../surveys/components/PreviewSurvey.tsx | 8 +- apps/web/app/lib/api/clientSettings.ts | 4 +- .../s/[surveyId]/components/LinkSurvey.tsx | 2 +- .../api/v1/client/surveys/[surveyId]/index.ts | 6 +- .../migration.sql | 9 ++ packages/database/schema.prisma | 3 +- packages/js/package.json | 2 +- packages/js/src/lib/widget.ts | 3 +- packages/js/tests/__mocks__/apiMock.ts | 3 +- packages/lib/product/service.ts | 3 +- ...ksSignature.tsx => FormbricksBranding.tsx} | 2 +- packages/surveys/src/components/Survey.tsx | 6 +- .../surveys/src/components/SurveyInline.tsx | 4 +- .../surveys/src/components/SurveyModal.tsx | 4 +- packages/surveys/src/types/props.ts | 2 +- packages/types/product.ts | 3 +- packages/ui/Survey/index.tsx | 14 ++-- 21 files changed, 153 insertions(+), 115 deletions(-) create mode 100644 apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/EditBranding.tsx delete mode 100644 apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/EditSignature.tsx create mode 100644 packages/database/migrations/20231114143459_rename_branding/migration.sql rename packages/surveys/src/components/{FormbricksSignature.tsx => FormbricksBranding.tsx} (88%) diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/EditBranding.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/EditBranding.tsx new file mode 100644 index 0000000000..a7615e5bb0 --- /dev/null +++ b/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/EditBranding.tsx @@ -0,0 +1,83 @@ +"use client"; + +import { TProduct, TProductUpdateInput } from "@formbricks/types/product"; +import { Alert, AlertDescription } from "@formbricks/ui/Alert"; +import { Label } from "@formbricks/ui/Label"; +import { Switch } from "@formbricks/ui/Switch"; +import Link from "next/link"; +import { useState } from "react"; +import toast from "react-hot-toast"; +import { updateProductAction } from "../actions"; + +interface EditFormbricksBrandingProps { + type: "linkSurvey" | "inAppSurvey"; + product: TProduct; + canRemoveBranding: boolean; + environmentId: string; +} + +export function EditFormbricksBranding({ + type, + product, + canRemoveBranding, + environmentId, +}: EditFormbricksBrandingProps) { + const [isBrandingEnabled, setIsBrandingEnabled] = useState( + type === "linkSurvey" ? product.linkSurveyBranding : product.inAppSurveyBranding + ); + const [updatingBranding, setUpdatingBranding] = useState(false); + + const toggleBranding = async () => { + try { + setUpdatingBranding(true); + const newBrandingState = !isBrandingEnabled; + setIsBrandingEnabled(newBrandingState); + let inputProduct: Partial = { + [type === "linkSurvey" ? "linkSurveyBranding" : "inAppSurveyBranding"]: newBrandingState, + }; + await updateProductAction(product.id, inputProduct); + toast.success( + newBrandingState ? "Formbricks branding will be shown." : "Formbricks branding will now be hidden." + ); + } catch (error) { + toast.error(`Error: ${error.message}`); + } finally { + setUpdatingBranding(false); + } + }; + + return ( +
+ {!canRemoveBranding && ( +
+ + + To remove the Formbricks branding from the {type} surveys + , please{" "} + {type === "linkSurvey" ? ( + + upgrade your plan. + + ) : ( + + add your creditcard. + + )} + + +
+ )} +
+ + +
+
+ ); +} diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/EditSignature.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/EditSignature.tsx deleted file mode 100644 index aadcdd78a2..0000000000 --- a/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/EditSignature.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client"; - -import { Alert, AlertDescription } from "@formbricks/ui/Alert"; -import { updateProductAction } from "../actions"; -import { TProduct, TProductUpdateInput } from "@formbricks/types/product"; -import { Label } from "@formbricks/ui/Label"; -import { Switch } from "@formbricks/ui/Switch"; -import { useState } from "react"; -import toast from "react-hot-toast"; -import Link from "next/link"; - -interface EditSignatureProps { - product: TProduct; - canRemoveSignature: boolean; - environmentId: string; -} - -export function EditFormbricksSignature({ product, canRemoveSignature, environmentId }: EditSignatureProps) { - const [formbricksSignature, setFormbricksSignature] = useState(product.formbricksSignature); - const [updatingSignature, setUpdatingSignature] = useState(false); - - const toggleSignature = async () => { - try { - setUpdatingSignature(true); - const newSignatureState = !formbricksSignature; - setFormbricksSignature(newSignatureState); - let inputProduct: Partial = { - formbricksSignature: newSignatureState, - }; - await updateProductAction(product.id, inputProduct); - toast.success( - newSignatureState ? "Formbricks signature will be shown." : "Formbricks signature will now be hidden." - ); - } catch (error) { - toast.error(`Error: ${error.message}`); - } finally { - setUpdatingSignature(false); - } - }; - - return ( -
- {!canRemoveSignature && ( -
- - - To remove the Formbricks branding from the link surveys, please{" "} - - upgrade - {" "} - your plan. - - -
- )} -
- - -
-
- ); -} diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/page.tsx b/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/page.tsx index 4cb46b599a..f764d0e541 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/page.tsx @@ -1,20 +1,19 @@ export const revalidate = REVALIDATION_INTERVAL; -import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; -import { REVALIDATION_INTERVAL } from "@formbricks/lib/constants"; -import SettingsCard from "../components/SettingsCard"; -import SettingsTitle from "../components/SettingsTitle"; -import { EditFormbricksSignature } from "./components/EditSignature"; -import { EditBrandColor } from "./components/EditBrandColor"; -import { EditPlacement } from "./components/EditPlacement"; -import { EditHighlightBorder } from "./components/EditHighlightBorder"; -import { DEFAULT_BRAND_COLOR } from "@formbricks/lib/constants"; import { authOptions } from "@formbricks/lib/authOptions"; -import { getServerSession } from "next-auth"; -import { getTeamByEnvironmentId } from "@formbricks/lib/team/service"; +import { DEFAULT_BRAND_COLOR, REVALIDATION_INTERVAL } from "@formbricks/lib/constants"; import { getMembershipByUserIdTeamId } from "@formbricks/lib/membership/service"; import { getAccessFlags } from "@formbricks/lib/membership/utils"; +import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; +import { getTeamByEnvironmentId } from "@formbricks/lib/team/service"; import { ErrorComponent } from "@formbricks/ui/ErrorComponent"; +import { getServerSession } from "next-auth"; +import SettingsCard from "../components/SettingsCard"; +import SettingsTitle from "../components/SettingsTitle"; +import { EditBrandColor } from "./components/EditBrandColor"; +import { EditHighlightBorder } from "./components/EditHighlightBorder"; +import { EditPlacement } from "./components/EditPlacement"; +import { EditFormbricksBranding } from "./components/EditBranding"; export default async function ProfileSettingsPage({ params }: { params: { environmentId: string } }) { const [session, team, product] = await Promise.all([ @@ -33,8 +32,10 @@ export default async function ProfileSettingsPage({ params }: { params: { enviro throw new Error("Team not found"); } + const canRemoveLinkBranding = team.billing.features.linkSurvey.status !== "inactive"; + const canRemoveInAppBranding = team.billing.features.inAppSurvey.status !== "inactive"; + const currentUserMembership = await getMembershipByUserIdTeamId(session?.user.id, team.id); - const canRemoveSignature = team.billing.features.linkSurvey.status !== "inactive"; const { isDeveloper, isViewer } = getAccessFlags(currentUserMembership?.role); const isBrandColorEditDisabled = isDeveloper ? true : isViewer; @@ -68,11 +69,18 @@ export default async function ProfileSettingsPage({ params }: { params: { enviro /> - + diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/shareEmbedTabs/LinkTab.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/shareEmbedTabs/LinkTab.tsx index d2eabca2db..091bfc5512 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/shareEmbedTabs/LinkTab.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/shareEmbedTabs/LinkTab.tsx @@ -56,7 +56,7 @@ export default function LinkTab({ surveyUrl, survey, brandColor }: EmailTabProps @@ -219,7 +219,7 @@ export default function PreviewSurvey({ survey={survey} brandColor={brandColor} activeQuestionId={activeQuestionId || undefined} - formbricksSignature={product.formbricksSignature} + isBrandingEnabled={product.linkSurveyBranding} onActiveQuestionChange={setActiveQuestionId} /> @@ -274,7 +274,7 @@ export default function PreviewSurvey({ survey={survey} brandColor={brandColor} activeQuestionId={activeQuestionId || undefined} - formbricksSignature={product.formbricksSignature} + isBrandingEnabled={product.linkSurveyBranding} onActiveQuestionChange={setActiveQuestionId} isRedirectDisabled={true} /> @@ -287,7 +287,7 @@ export default function PreviewSurvey({ survey={survey} brandColor={brandColor} activeQuestionId={activeQuestionId || undefined} - formbricksSignature={product.formbricksSignature} + isBrandingEnabled={product.linkSurveyBranding} onActiveQuestionChange={setActiveQuestionId} isRedirectDisabled={true} /> diff --git a/apps/web/app/lib/api/clientSettings.ts b/apps/web/app/lib/api/clientSettings.ts index ffd84cd9de..a1d2e4d3e9 100644 --- a/apps/web/app/lib/api/clientSettings.ts +++ b/apps/web/app/lib/api/clientSettings.ts @@ -208,7 +208,7 @@ export const getSettings = async (environmentId: string, personId: string): Prom product: { select: { brandColor: true, - formbricksSignature: true, + linkSurveyBranding: true, placement: true, darkOverlay: true, clickOutsideClose: true, @@ -217,7 +217,7 @@ export const getSettings = async (environmentId: string, personId: string): Prom }, }); - const formbricksSignature = environmentProdut?.product.formbricksSignature; + const formbricksSignature = environmentProdut?.product.linkSurveyBranding; const brandColor = environmentProdut?.product.brandColor; const placement = environmentProdut?.product.placement; const darkOverlay = environmentProdut?.product.darkOverlay; diff --git a/apps/web/app/s/[surveyId]/components/LinkSurvey.tsx b/apps/web/app/s/[surveyId]/components/LinkSurvey.tsx index 92b906cbd2..a1c42e326b 100644 --- a/apps/web/app/s/[surveyId]/components/LinkSurvey.tsx +++ b/apps/web/app/s/[surveyId]/components/LinkSurvey.tsx @@ -136,7 +136,7 @@ export default function LinkSurvey({ { if (!isPreview) { const api = new FormbricksAPI({ diff --git a/apps/web/pages/api/v1/client/surveys/[surveyId]/index.ts b/apps/web/pages/api/v1/client/surveys/[surveyId]/index.ts index 01269d2ac7..984e6c07ec 100644 --- a/apps/web/pages/api/v1/client/surveys/[surveyId]/index.ts +++ b/apps/web/pages/api/v1/client/surveys/[surveyId]/index.ts @@ -48,7 +48,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) }, select: { brandColor: true, - formbricksSignature: true, + linkSurveyBranding: true, }, }); @@ -57,7 +57,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) message: "Survey not running", reason: survey.status, brandColor: product?.brandColor, - formbricksSignature: product?.formbricksSignature, + formbricksSignature: product?.linkSurveyBranding, surveyClosedMessage: survey?.surveyClosedMessage, }); } @@ -66,7 +66,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) return res.status(200).json({ ...survey, brandColor: product?.brandColor, - formbricksSignature: product?.formbricksSignature, + formbricksSignature: product?.linkSurveyBranding, }); } diff --git a/packages/database/migrations/20231114143459_rename_branding/migration.sql b/packages/database/migrations/20231114143459_rename_branding/migration.sql new file mode 100644 index 0000000000..c70bb6cdf5 --- /dev/null +++ b/packages/database/migrations/20231114143459_rename_branding/migration.sql @@ -0,0 +1,9 @@ +/* + Warnings: + + - You are about to drop the column `formbricksSignature` on the `Product` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Product" RENAME COLUMN "formbricksSignature" TO "linkSurveyBranding"; +ALTER TABLE "Product" ADD COLUMN "inAppSurveyBranding" BOOLEAN NOT NULL DEFAULT true; diff --git a/packages/database/schema.prisma b/packages/database/schema.prisma index 210defb3d4..7f7199bd61 100644 --- a/packages/database/schema.prisma +++ b/packages/database/schema.prisma @@ -397,7 +397,8 @@ model Product { brandColor String @default("#64748b") highlightBorderColor String? recontactDays Int @default(7) - formbricksSignature Boolean @default(true) + linkSurveyBranding Boolean @default(true) // Determines if the survey branding should be displayed in link surveys + inAppSurveyBranding Boolean @default(true) // Determines if the survey branding should be displayed in in-app surveys placement WidgetPlacement @default(bottomRight) clickOutsideClose Boolean @default(true) darkOverlay Boolean @default(false) diff --git a/packages/js/package.json b/packages/js/package.json index 4db7ddb6de..6dc9b9fb32 100644 --- a/packages/js/package.json +++ b/packages/js/package.json @@ -1,7 +1,7 @@ { "name": "@formbricks/js", "license": "MIT", - "version": "1.2.0", + "version": "1.2.1", "description": "Formbricks-js allows you to connect your app to Formbricks, display surveys and trigger events.", "keywords": [ "Formbricks", diff --git a/packages/js/src/lib/widget.ts b/packages/js/src/lib/widget.ts index 8540943cba..67a1ae179a 100644 --- a/packages/js/src/lib/widget.ts +++ b/packages/js/src/lib/widget.ts @@ -48,12 +48,13 @@ export const renderWidget = (survey: TSurveyWithTriggers) => { const clickOutside = productOverwrites.clickOutside ?? product.clickOutsideClose; const darkOverlay = productOverwrites.darkOverlay ?? product.darkOverlay; const placement = productOverwrites.placement ?? product.placement; + const isBrandingEnabled = product.inAppSurveyBranding; setTimeout(() => { renderSurveyModal({ survey: survey, brandColor, - formbricksSignature: true, + isBrandingEnabled: isBrandingEnabled, clickOutside, darkOverlay, highlightBorderColor, diff --git a/packages/js/tests/__mocks__/apiMock.ts b/packages/js/tests/__mocks__/apiMock.ts index ddbd1ab833..e833bb8f81 100644 --- a/packages/js/tests/__mocks__/apiMock.ts +++ b/packages/js/tests/__mocks__/apiMock.ts @@ -79,7 +79,8 @@ export const mockInitResponse = () => { product: { noCodeEvents: [], brandColor: "#20b398", - formbricksSignature: true, + linkSurveyBranding: true, + inAppBranding: true, placement: "bottomRight", darkOverlay: false, clickOutsideClose: true, diff --git a/packages/lib/product/service.ts b/packages/lib/product/service.ts index 7eeb1bd848..753b1b7b7a 100644 --- a/packages/lib/product/service.ts +++ b/packages/lib/product/service.ts @@ -25,7 +25,8 @@ const selectProduct = { brandColor: true, highlightBorderColor: true, recontactDays: true, - formbricksSignature: true, + linkSurveyBranding: true, + inAppSurveyBranding: true, placement: true, clickOutsideClose: true, darkOverlay: true, diff --git a/packages/surveys/src/components/FormbricksSignature.tsx b/packages/surveys/src/components/FormbricksBranding.tsx similarity index 88% rename from packages/surveys/src/components/FormbricksSignature.tsx rename to packages/surveys/src/components/FormbricksBranding.tsx index 5323ec2d50..fd8564dd13 100644 --- a/packages/surveys/src/components/FormbricksSignature.tsx +++ b/packages/surveys/src/components/FormbricksBranding.tsx @@ -1,4 +1,4 @@ -export default function FormbricksSignature() { +export default function FormbricksBranding() { return ( {}, onActiveQuestionChange = () => {}, @@ -180,7 +180,7 @@ export function Survey({ )}
- {formbricksSignature && } + {isBrandingEnabled && }
diff --git a/packages/surveys/src/components/SurveyInline.tsx b/packages/surveys/src/components/SurveyInline.tsx index e814889eaf..22ba535f3a 100644 --- a/packages/surveys/src/components/SurveyInline.tsx +++ b/packages/surveys/src/components/SurveyInline.tsx @@ -4,7 +4,7 @@ import { Survey } from "./Survey"; export function SurveyInline({ survey, brandColor, - formbricksSignature, + isBrandingEnabled, activeQuestionId, onDisplay = () => {}, onActiveQuestionChange = () => {}, @@ -18,7 +18,7 @@ export function SurveyInline({ void; onResponse?: (response: TResponseUpdate) => void; diff --git a/packages/types/product.ts b/packages/types/product.ts index fe7cd9ff9e..d5aac85ea1 100644 --- a/packages/types/product.ts +++ b/packages/types/product.ts @@ -11,7 +11,8 @@ export const ZProduct = z.object({ brandColor: ZColor, highlightBorderColor: ZColor.nullable(), recontactDays: z.number().int(), - formbricksSignature: z.boolean(), + inAppSurveyBranding: z.boolean(), + linkSurveyBranding: z.boolean(), placement: ZPlacement, clickOutsideClose: z.boolean(), darkOverlay: z.boolean(), diff --git a/packages/ui/Survey/index.tsx b/packages/ui/Survey/index.tsx index b5bf58579b..0b80c6eb0a 100644 --- a/packages/ui/Survey/index.tsx +++ b/packages/ui/Survey/index.tsx @@ -8,7 +8,7 @@ const createContainerId = () => `formbricks-survey-container`; interface SurveyProps { survey: TSurvey; brandColor: string; - formbricksSignature: boolean; + isBrandingEnabled: boolean; activeQuestionId?: string; onDisplay?: () => void; onResponse?: (response: TResponseUpdate) => void; @@ -30,7 +30,7 @@ interface SurveyModalProps extends SurveyProps { export const SurveyInline = ({ survey, brandColor, - formbricksSignature, + isBrandingEnabled, activeQuestionId, onDisplay = () => {}, onResponse = () => {}, @@ -45,7 +45,7 @@ export const SurveyInline = ({ renderSurveyInline({ survey, brandColor, - formbricksSignature, + isBrandingEnabled, containerId, onDisplay, onResponse, @@ -60,7 +60,7 @@ export const SurveyInline = ({ activeQuestionId, brandColor, containerId, - formbricksSignature, + isBrandingEnabled, onActiveQuestionChange, onClose, onDisplay, @@ -76,7 +76,7 @@ export const SurveyInline = ({ export const SurveyModal = ({ survey, brandColor, - formbricksSignature, + isBrandingEnabled, activeQuestionId, placement = "bottomRight", clickOutside = false, @@ -93,7 +93,7 @@ export const SurveyModal = ({ renderSurveyModal({ survey, brandColor, - formbricksSignature, + isBrandingEnabled, placement, clickOutside, darkOverlay, @@ -111,7 +111,7 @@ export const SurveyModal = ({ brandColor, clickOutside, darkOverlay, - formbricksSignature, + isBrandingEnabled, highlightBorderColor, onActiveQuestionChange, onClose, From 32268a8ec3fde0939fe31a9136117647d333c24d Mon Sep 17 00:00:00 2001 From: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com> Date: Wed, 15 Nov 2023 17:05:01 +0530 Subject: [PATCH 2/5] fix: auto focus issue (#1618) --- packages/surveys/src/components/OpenTextQuestion.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/surveys/src/components/OpenTextQuestion.tsx b/packages/surveys/src/components/OpenTextQuestion.tsx index dbe97789ef..3837808e90 100644 --- a/packages/surveys/src/components/OpenTextQuestion.tsx +++ b/packages/surveys/src/components/OpenTextQuestion.tsx @@ -40,8 +40,11 @@ export default function OpenTextQuestion({ currentElement.focus(); } }, - [autoFocus] + [question] ); + const isInputEmpty = (value: string) => { + return question.required && !value?.trim(); + }; return (
handleInputChange(e.currentTarget.value)} autoFocus={autoFocus} onKeyDown={(e) => { - if (e.key == "Enter") onSubmit({ [question.id]: value }); + if (e.key === "Enter" && isInputEmpty(value as string)) { + e.preventDefault(); // Prevent form submission + } else if (e.key === "Enter") { + onSubmit({ [question.id]: value }); + } }} pattern={question.inputType === "phone" ? "[+][0-9 ]+" : ".*"} title={question.inputType === "phone" ? "Enter a valid phone number" : undefined} From 3eeea7d1b287acbe8c67e7d67f1099c0f2ee5a83 Mon Sep 17 00:00:00 2001 From: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com> Date: Wed, 15 Nov 2023 18:33:28 +0530 Subject: [PATCH 3/5] fix: survey editor issue (#1619) --- packages/surveys/src/components/OpenTextQuestion.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/surveys/src/components/OpenTextQuestion.tsx b/packages/surveys/src/components/OpenTextQuestion.tsx index 3837808e90..5bc5098bcb 100644 --- a/packages/surveys/src/components/OpenTextQuestion.tsx +++ b/packages/surveys/src/components/OpenTextQuestion.tsx @@ -40,7 +40,7 @@ export default function OpenTextQuestion({ currentElement.focus(); } }, - [question] + [question.id] ); const isInputEmpty = (value: string) => { return question.required && !value?.trim(); From 9d4e21f8a7aafff4a1c507b51277fc07bb104acf Mon Sep 17 00:00:00 2001 From: Midka Date: Wed, 15 Nov 2023 17:29:27 +0200 Subject: [PATCH 4/5] feat(packages/surveys): ability to customize colors & other improvements (#916) Co-authored-by: Matthias Nannt Co-authored-by: Neil Chauhan --- apps/demo/styles/globals.css | 23 ++++++++ packages/surveys/package.json | 3 +- packages/surveys/src/components/Progress.tsx | 9 ---- .../components/{ => buttons}/BackButton.tsx | 4 +- .../components/{ => buttons}/SubmitButton.tsx | 10 +--- .../{ => general}/FormbricksBranding.tsx | 4 +- .../src/components/{ => general}/Headline.tsx | 9 ++-- .../src/components/{ => general}/HtmlBody.tsx | 4 +- .../src/components/general/Progress.tsx | 9 ++++ .../components/{ => general}/ProgressBar.tsx | 7 ++- .../{ => general}/QuestionConditional.tsx | 29 ++++------ .../{ => general}/RedirectCountdown.tsx | 2 +- .../src/components/{ => general}/Smileys.tsx | 0 .../components/{ => general}/Subheader.tsx | 2 +- .../src/components/{ => general}/Survey.tsx | 20 +++---- .../components/{ => general}/SurveyInline.tsx | 6 +-- .../components/{ => general}/SurveyModal.tsx | 8 ++- .../components/{ => general}/ThankYouCard.tsx | 12 ++--- .../components/{ => general}/WelcomeCard.tsx | 11 ++-- .../{ => questions}/CTAQuestion.tsx | 13 ++--- .../{ => questions}/ConsentQuestion.tsx | 16 +++--- .../MultipleChoiceMultiQuestion.tsx | 37 +++++++------ .../MultipleChoiceSingleQuestion.tsx | 38 ++++++------- .../{ => questions}/NPSQuestion.tsx | 19 +++---- .../{ => questions}/OpenTextQuestion.tsx | 26 +++------ .../PictureSelectionQuestion.tsx | 36 ++++++------- .../{ => questions}/RatingQuestion.tsx | 38 ++++++------- .../{ => wrappers}/AutoCloseWrapper.tsx | 9 ++-- .../src/components/{ => wrappers}/Modal.tsx | 4 +- packages/surveys/src/index.ts | 16 +++--- packages/surveys/src/lib/styles.ts | 17 +++++- packages/surveys/src/styles/global.css | 54 +++++++++++++++++++ packages/surveys/src/types/props.ts | 1 - packages/surveys/tailwind.config.js | 23 ++++++++ packages/surveys/tsconfig.json | 6 ++- packages/surveys/vite.config.ts | 3 +- pnpm-lock.yaml | 37 +++++++++++++ 37 files changed, 334 insertions(+), 231 deletions(-) delete mode 100644 packages/surveys/src/components/Progress.tsx rename packages/surveys/src/components/{ => buttons}/BackButton.tsx (59%) rename packages/surveys/src/components/{ => buttons}/SubmitButton.tsx (65%) rename packages/surveys/src/components/{ => general}/FormbricksBranding.tsx (69%) rename packages/surveys/src/components/{ => general}/Headline.tsx (52%) rename packages/surveys/src/components/{ => general}/HtmlBody.tsx (70%) create mode 100644 packages/surveys/src/components/general/Progress.tsx rename packages/surveys/src/components/{ => general}/ProgressBar.tsx (89%) rename packages/surveys/src/components/{ => general}/QuestionConditional.tsx (77%) rename packages/surveys/src/components/{ => general}/RedirectCountdown.tsx (93%) rename packages/surveys/src/components/{ => general}/Smileys.tsx (100%) rename packages/surveys/src/components/{ => general}/Subheader.tsx (61%) rename packages/surveys/src/components/{ => general}/Survey.tsx (92%) rename packages/surveys/src/components/{ => general}/SurveyInline.tsx (83%) rename packages/surveys/src/components/{ => general}/SurveyModal.tsx (90%) rename packages/surveys/src/components/{ => general}/ThankYouCard.tsx (75%) rename packages/surveys/src/components/{ => general}/WelcomeCard.tsx (92%) rename packages/surveys/src/components/{ => questions}/CTAQuestion.tsx (82%) rename packages/surveys/src/components/{ => questions}/ConsentQuestion.tsx (79%) rename packages/surveys/src/components/{ => questions}/MultipleChoiceMultiQuestion.tsx (82%) rename packages/surveys/src/components/{ => questions}/MultipleChoiceSingleQuestion.tsx (78%) rename packages/surveys/src/components/{ => questions}/NPSQuestion.tsx (82%) rename packages/surveys/src/components/{ => questions}/OpenTextQuestion.tsx (83%) rename packages/surveys/src/components/{ => questions}/PictureSelectionQuestion.tsx (79%) rename packages/surveys/src/components/{ => questions}/RatingQuestion.tsx (86%) rename packages/surveys/src/components/{ => wrappers}/AutoCloseWrapper.tsx (83%) rename packages/surveys/src/components/{ => wrappers}/Modal.tsx (94%) diff --git a/apps/demo/styles/globals.css b/apps/demo/styles/globals.css index b5c61c9567..640abab484 100644 --- a/apps/demo/styles/globals.css +++ b/apps/demo/styles/globals.css @@ -1,3 +1,26 @@ @tailwind base; @tailwind components; @tailwind utilities; + +/* Example on overriding packages/js colors */ +.dark { + --fb-brand-color: red; + --fb-brand-text-color: white; + --fb-border-color: green; + --fb-border-color-highlight: var(--slate-500); + --fb-focus-color: red; + --fb-heading-color: yellow; + --fb-subheading-color: green; + --fb-info-text-color: orange; + --fb-signature-text-color: blue; + --fb-survey-background-color: black; + --fb-accent-background-color: rgb(13, 13, 12); + --fb-accent-background-color-selected: red; + --fb-placeholder-color: white; + --fb-shadow-color: yellow; + --fb-rating-fill: var(--yellow-300); + --fb-rating-hover: var(--yellow-500); + --fb-back-btn-border: currentColor; + --fb-submit-btn-border: transparent; + --fb-rating-selected: black; +} diff --git a/packages/surveys/package.json b/packages/surveys/package.json index 80de10b8b8..9d1e91e49c 100644 --- a/packages/surveys/package.json +++ b/packages/surveys/package.json @@ -33,6 +33,7 @@ "tailwindcss": "^3.3.3", "terser": "^5.22.0", "vite": "^4.4.11", - "vite-plugin-dts": "^3.6.0" + "vite-plugin-dts": "^3.6.0", + "vite-tsconfig-paths": "^4.2.1" } } diff --git a/packages/surveys/src/components/Progress.tsx b/packages/surveys/src/components/Progress.tsx deleted file mode 100644 index c57e4af124..0000000000 --- a/packages/surveys/src/components/Progress.tsx +++ /dev/null @@ -1,9 +0,0 @@ -export default function Progress({ progress, brandColor }: { progress: number; brandColor: string }) { - return ( -
-
-
- ); -} diff --git a/packages/surveys/src/components/BackButton.tsx b/packages/surveys/src/components/buttons/BackButton.tsx similarity index 59% rename from packages/surveys/src/components/BackButton.tsx rename to packages/surveys/src/components/buttons/BackButton.tsx index a031cb46bc..ae9b402b15 100644 --- a/packages/surveys/src/components/BackButton.tsx +++ b/packages/surveys/src/components/buttons/BackButton.tsx @@ -1,4 +1,4 @@ -import { cn } from "../../../lib/cn"; +import { cn } from "@/lib/utils"; interface BackButtonProps { onClick: () => void; @@ -12,7 +12,7 @@ export function BackButton({ onClick, backButtonLabel, tabIndex = 2 }: BackButto tabIndex={tabIndex} type={"button"} className={cn( - "flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2" + "border-back-button-border text-heading focus:ring-focus flex items-center rounded-md border px-3 py-3 text-base font-medium leading-4 shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2" )} onClick={onClick}> {backButtonLabel || "Back"} diff --git a/packages/surveys/src/components/SubmitButton.tsx b/packages/surveys/src/components/buttons/SubmitButton.tsx similarity index 65% rename from packages/surveys/src/components/SubmitButton.tsx rename to packages/surveys/src/components/buttons/SubmitButton.tsx index d0de273ec8..7c9e265c6c 100644 --- a/packages/surveys/src/components/SubmitButton.tsx +++ b/packages/surveys/src/components/buttons/SubmitButton.tsx @@ -1,11 +1,8 @@ import { useCallback } from "preact/hooks"; -import { cn } from "../../../lib/cn"; -import { isLight } from "../lib/utils"; interface SubmitButtonProps { buttonLabel: string | undefined; isLastQuestion: boolean; - brandColor: string; onClick: () => void; focus?: boolean; tabIndex?: number; @@ -15,7 +12,6 @@ interface SubmitButtonProps { function SubmitButton({ buttonLabel, isLastQuestion, - brandColor, onClick, tabIndex = 1, focus = false, @@ -38,11 +34,7 @@ function SubmitButton({ type={type} tabIndex={tabIndex} autoFocus={focus} - className={cn( - "flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2", - isLight(brandColor) ? "text-black" : "text-white" - )} - style={{ backgroundColor: brandColor }} + className="bg-brand border-submit-button-border text-on-brand focus:ring-focus flex items-center rounded-md border px-3 py-3 text-base font-medium leading-4 shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2" onClick={onClick}> {buttonLabel || (isLastQuestion ? "Finish" : "Next")} diff --git a/packages/surveys/src/components/FormbricksBranding.tsx b/packages/surveys/src/components/general/FormbricksBranding.tsx similarity index 69% rename from packages/surveys/src/components/FormbricksBranding.tsx rename to packages/surveys/src/components/general/FormbricksBranding.tsx index fd8564dd13..52516555a7 100644 --- a/packages/surveys/src/components/FormbricksBranding.tsx +++ b/packages/surveys/src/components/general/FormbricksBranding.tsx @@ -5,10 +5,10 @@ export default function FormbricksBranding() { target="_blank" tabIndex={-1} className="mb-5 mt-2 flex justify-center"> -

+

Powered by{" "} - Formbricks + Formbricks

diff --git a/packages/surveys/src/components/Headline.tsx b/packages/surveys/src/components/general/Headline.tsx similarity index 52% rename from packages/surveys/src/components/Headline.tsx rename to packages/surveys/src/components/general/Headline.tsx index 9b1869aa71..f9072f3ed7 100644 --- a/packages/surveys/src/components/Headline.tsx +++ b/packages/surveys/src/components/general/Headline.tsx @@ -7,11 +7,14 @@ interface HeadlineProps { export default function Headline({ headline, questionId, style, required = true }: HeadlineProps) { return ( -