Improve UX with multiple tweaks (#258)

This commit is contained in:
Johannes
2023-04-27 20:11:44 +02:00
committed by GitHub
parent b01d2409de
commit 7e9b336954
27 changed files with 161 additions and 101 deletions
@@ -34,7 +34,7 @@ export default function MultipleChoiceSingleQuestion({
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="mt-4">
<fieldset>
<legend className="sr-only">Choices</legend>
<legend className="sr-only">Options</legend>
<div className="relative space-y-2 rounded-md">
{question.choices &&
question.choices.map((choice) => (
@@ -47,6 +47,7 @@ import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import AddProductModal from "./AddProductModal";
import FaveIcon from "@/app/favicon.ico";
interface EnvironmentsNavbarProps {
environmentId: string;
@@ -113,7 +114,7 @@ export default function EnvironmentsNavbar({ environmentId, session }: Environme
links: [
{
icon: AdjustmentsVerticalIcon,
label: "Survey Settings",
label: "Product Settings",
href: `/environments/${environmentId}/settings/product`,
},
{
@@ -201,9 +202,10 @@ export default function EnvironmentsNavbar({ environmentId, session }: Environme
<div className="flex h-14 justify-between">
<div className="flex space-x-4 py-2">
<Link
href={`/environments/${environmentId}/surveys/templates`}
className="from-brand-light to-brand-dark my-1 flex items-center justify-center rounded-md bg-gradient-to-b px-1 text-white transition-all ease-in-out hover:scale-105">
<PlusIcon className="h-6 w-6" />
href={`/environments/${environmentId}/surveys/`}
className=" flex items-center justify-center rounded-md bg-gradient-to-b text-white transition-all ease-in-out hover:scale-105">
{/* <PlusIcon className="h-6 w-6" /> */}
<Image src={FaveIcon} width={30} height={30} alt="faveicon" />
</Link>
{navigation.map((item) => (
<Link
@@ -105,7 +105,7 @@ export default function PricingTable({ environmentId, session }: PricingTablePro
</div>
</div>
<div className="">
<div className="float-right -mt-2 mr-6 animate-bounce rounded-full bg-slate-700 px-3 py-1 text-xs font-semibold text-slate-50">
<div className="float-right -mt-2 mr-6 rounded-full bg-slate-700 px-3 py-1 text-xs font-semibold text-slate-50">
Limited Early Bird Deal
</div>
<div className="rounded-lg border border-slate-300 bg-slate-100 shadow-sm">
@@ -33,7 +33,7 @@ export default function AddQuestionButton({ addQuestion, environmentId }: AddQue
)}>
<Collapsible.CollapsibleTrigger asChild className="group h-full w-full">
<div className="inline-flex">
<div className="bg-brand-dark flex w-10 items-center justify-center rounded-l-lg group-aria-expanded:rounded-bl-none">
<div className="bg-brand-dark flex w-10 items-center justify-center rounded-l-lg group-aria-expanded:rounded-bl-none group-aria-expanded:rounded-br">
<PlusIcon className="h-6 w-6 text-white" />
</div>
<div className="px-4 py-3">
@@ -47,7 +47,7 @@ export default function AddQuestionButton({ addQuestion, environmentId }: AddQue
{questionTypes.map((questionType) => (
<button
key={questionType.id}
className="inline-flex items-center px-4 py-2 text-sm font-medium text-slate-700 last:mb-2 hover:bg-slate-100"
className="mx-2 inline-flex items-center rounded p-0.5 px-4 py-2 font-medium text-slate-700 last:mb-2 hover:bg-slate-100 hover:text-slate-800"
onClick={() => {
addQuestion({
id: createId(),
@@ -1,7 +1,7 @@
import type { Survey } from "@formbricks/types/surveys";
import HowToSendCard from "./HowToSendCard";
import RecontactOptionsCard from "./RecontactOptionsCard";
import ResponseOptionsCard from "./ResponseOptionsCard";
/* import ResponseOptionsCard from "./ResponseOptionsCard"; */
import WhenToSendCard from "./WhenToSendCard";
import WhoToSendCard from "./WhoToSendCard";
@@ -24,7 +24,7 @@ export default function AudienceView({ environmentId, localSurvey, setLocalSurve
environmentId={environmentId}
/>
<ResponseOptionsCard />
{/* <ResponseOptionsCard /> */}
<RecontactOptionsCard
localSurvey={localSurvey}
@@ -44,7 +44,11 @@ export default function CTAQuestionForm({
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/> */}
<Editor
getText={() => md.render(question.html || "")}
getText={() =>
md.render(
question.html || "We would love to talk to you and learn more about how you use our product."
)
}
setText={(value: string) => {
updateQuestion(questionIdx, { html: value });
}}
@@ -25,9 +25,9 @@ const options = [
},
{
id: "link",
name: "Shareable Link",
name: "Link survey",
icon: LinkIcon,
description: "Creates a personalized survey link to share around.",
description: "Creates a standalone survey to share via link.",
comingSoon: false,
},
{
@@ -52,7 +52,7 @@ interface HowToSendCardProps {
}
export default function HowToSendCard({ localSurvey, setLocalSurvey }: HowToSendCardProps) {
const [open, setOpen] = useState(true);
const [open, setOpen] = useState(false);
const setSurveyType = (type: string) => {
const updatedSurvey = JSON.parse(JSON.stringify(localSurvey));
@@ -79,7 +79,7 @@ export default function HowToSendCard({ localSurvey, setLocalSurvey }: HowToSend
<div>
<p className="font-semibold text-slate-800">How to ask</p>
<p className="mt-1 truncate text-sm text-slate-500">
Choose how you want to reach your audience.
In-app survey, link survey or email survey.
</p>
</div>
</div>
@@ -68,7 +68,7 @@ export default function MultipleChoiceMultiForm({
</div>
<div className="mt-3">
<Label htmlFor="choices">Choices</Label>
<Label htmlFor="choices">Options</Label>
<div className="mt-2 space-y-2" id="choices">
{question.choices &&
question.choices.map((choice, choiceIdx) => (
@@ -77,7 +77,7 @@ export default function MultipleChoiceMultiForm({
id={choice.id}
name={choice.id}
value={choice.label}
placeholder={`Choice ${choiceIdx + 1}`}
placeholder={`Option ${choiceIdx + 1}`}
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
/>
{question.choices && question.choices.length > 2 && (
@@ -89,7 +89,7 @@ export default function MultipleChoiceMultiForm({
</div>
))}
<Button variant="secondary" type="button" onClick={() => addChoice()}>
Add Choice
Add Option
</Button>
</div>
</div>
@@ -68,7 +68,7 @@ export default function MultipleChoiceSingleForm({
</div>
<div className="mt-3">
<Label htmlFor="choices">Choices</Label>
<Label htmlFor="choices">Options</Label>
<div className="mt-2 space-y-2" id="choices">
{question.choices &&
question.choices.map((choice, choiceIdx) => (
@@ -77,7 +77,7 @@ export default function MultipleChoiceSingleForm({
id={choice.id}
name={choice.id}
value={choice.label}
placeholder={`Choice ${choiceIdx + 1}`}
placeholder={`Option ${choiceIdx + 1}`}
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
/>
{question.choices && question.choices.length > 2 && (
@@ -89,7 +89,7 @@ export default function MultipleChoiceSingleForm({
</div>
))}
<Button variant="secondary" type="button" onClick={() => addChoice()}>
Add Choice
Add Option
</Button>
</div>
</div>
@@ -5,7 +5,13 @@ import { cn } from "@formbricks/lib/cn";
import type { Question } from "@formbricks/types/questions";
import type { Survey } from "@formbricks/types/surveys";
import { Label, Switch } from "@formbricks/ui";
import { Bars3BottomLeftIcon } from "@heroicons/react/24/solid";
import {
ListBulletIcon,
ChatBubbleBottomCenterTextIcon,
CursorArrowRippleIcon,
PresentationChartBarIcon,
QueueListIcon,
} from "@heroicons/react/24/solid";
import * as Collapsible from "@radix-ui/react-collapsible";
import { useState } from "react";
import { Draggable } from "react-beautiful-dnd";
@@ -72,7 +78,19 @@ export default function QuestionCard({
className="flex cursor-pointer justify-between p-4 hover:bg-slate-50">
<div>
<div className="inline-flex">
<Bars3BottomLeftIcon className="-ml-0.5 mr-2 h-5 w-5 text-slate-400" />
<div className="-ml-0.5 mr-2 h-5 w-5 text-slate-400">
{question.type === "openText" ? (
<ChatBubbleBottomCenterTextIcon />
) : question.type === "multipleChoiceSingle" ? (
<QueueListIcon />
) : question.type === "multipleChoiceMulti" ? (
<ListBulletIcon />
) : question.type === "nps" ? (
<PresentationChartBarIcon />
) : question.type === "cta" ? (
<CursorArrowRippleIcon />
) : null}
</div>
<div>
<p className="text-sm font-semibold">
{question.headline || getQuestionTypeName(question.type)}
@@ -4,7 +4,7 @@ import SurveyStatusDropdown from "@/components/shared/SurveyStatusDropdown";
import { useSurveyMutation } from "@/lib/surveys/mutateSurveys";
import type { Survey } from "@formbricks/types/surveys";
import { Button, Input } from "@formbricks/ui";
import { UserGroupIcon } from "@heroicons/react/24/solid";
import { UserGroupIcon, ArrowLeftIcon } from "@heroicons/react/24/solid";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
@@ -43,6 +43,9 @@ export default function SurveyMenuBar({
return (
<div className="border-b border-slate-200 bg-white px-5 py-3 sm:flex sm:items-center sm:justify-between">
<div className="flex space-x-2 whitespace-nowrap">
<Button variant="minimal" className="px-0" onClick={() => router.back()}>
<ArrowLeftIcon className="h-5 w-5 text-slate-700" />
</Button>
<Input
defaultValue={localSurvey.name}
onChange={(e) => {
@@ -60,9 +63,6 @@ export default function SurveyMenuBar({
</div>
</div>
<div className="mt-3 flex sm:ml-4 sm:mt-0">
<Button variant="minimal" className="mr-3" onClick={() => router.back()}>
Cancel
</Button>
<Button
variant="secondary"
className="mr-3"
@@ -4,7 +4,15 @@ import LoadingSpinner from "@/components/shared/LoadingSpinner";
import { useEventClasses } from "@/lib/eventClasses/eventClasses";
import { cn } from "@formbricks/lib/cn";
import type { Survey } from "@formbricks/types/surveys";
import { Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@formbricks/ui";
import {
Button,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
SelectSeparator,
} from "@formbricks/ui";
import { CheckCircleIcon, PlusIcon, TrashIcon } from "@heroicons/react/24/solid";
import * as Collapsible from "@radix-ui/react-collapsible";
import { useEffect, useState } from "react";
@@ -99,9 +107,6 @@ export default function WhenToSendCard({ environmentId, localSurvey, setLocalSur
<SelectValue />
</SelectTrigger>
<SelectContent>
{eventClasses.map((eventClass) => (
<SelectItem value={eventClass.id}>{eventClass.name}</SelectItem>
))}
<button
className="flex w-full items-center space-x-2 rounded-md p-1 text-sm font-semibold text-slate-800 hover:bg-slate-100 hover:text-slate-500"
value="none"
@@ -111,6 +116,10 @@ export default function WhenToSendCard({ environmentId, localSurvey, setLocalSur
<PlusIcon className="mr-1 h-5 w-5" />
Add Action
</button>
<SelectSeparator />
{eventClasses.map((eventClass) => (
<SelectItem value={eventClass.id}>{eventClass.name}</SelectItem>
))}
</SelectContent>
</Select>
<p className="mx-2 text-sm">action is performed</p>
@@ -29,7 +29,7 @@ interface WhoToSendToCardProps {
}
export default function WhoToSendToCard({ localSurvey }: WhoToSendToCardProps) {
const [open, setOpen] = useState(false);
const [open, setOpen] = useState(true);
if (localSurvey.type === "link") {
return null;
@@ -50,9 +50,7 @@ export default function WhoToSendToCard({ localSurvey }: WhoToSendToCardProps) {
</div>
<div>
<p className="font-semibold text-slate-800">Who to ask</p>
<p className="mt-1 truncate text-sm text-slate-500">
Decide which group of you users can be surveyed.
</p>
<p className="mt-1 truncate text-sm text-slate-500">Filter your users based on attributes.</p>
</div>
</div>
</Collapsible.CollapsibleTrigger>
@@ -1,6 +1,5 @@
import Modal from "@/components/shared/Modal";
import { Survey } from "@formbricks/types/surveys";
import { Button } from "@formbricks/ui";
import { CheckIcon } from "@heroicons/react/24/outline";
import { ClipboardDocumentIcon } from "@heroicons/react/24/solid";
import toast from "react-hot-toast";
@@ -25,7 +24,9 @@ export default function LinkSurveyModal({ survey, open, setOpen }: LinkSurveyMod
<p className="relative mt-3 w-full rounded-lg border border-teal-300 bg-teal-50 p-3 text-center text-slate-800">
{`${window.location.protocol}//${window.location.host}/s/${survey.id}`}
<ClipboardDocumentIcon
className="absolute right-3 top-1/3 h-4 w-4 cursor-pointer text-slate-500 hover:text-slate-700"
className="absolute right-3 top-1/3 h-5 w-5 cursor-pointer text-slate-700 hover:text-slate-900"
title="Copy survey link to clipboard"
aria-label="Copy survey link to clipboard"
onClick={() => {
navigator.clipboard.writeText(
`${window.location.protocol}//${window.location.host}/s/${survey.id}`
@@ -37,11 +38,6 @@ export default function LinkSurveyModal({ survey, open, setOpen }: LinkSurveyMod
</div>
</div>
</div>
<div className="mt-5 sm:mt-6">
<Button variant="primary" onClick={() => setOpen(false)} className="w-full justify-center">
Close
</Button>
</div>
</Modal>
);
}
@@ -126,10 +126,9 @@ export default function SummaryMetadata({ surveyId, environmentId }) {
<ShareIcon className="h-5 w-5" />
</Button>
)}
{environment.widgetSetupCompleted ||
(survey.type === "link" && (
<SurveyStatusDropdown surveyId={surveyId} environmentId={environmentId} />
))}
{environment.widgetSetupCompleted && (
<SurveyStatusDropdown surveyId={surveyId} environmentId={environmentId} />
)}
<Button className="ml-1.5 h-full" href={`/environments/${environmentId}/surveys/${surveyId}/edit`}>
<PencilSquareIcon className="mr-2 h-5 w-5 text-white" /> Edit Survey
</Button>
@@ -59,6 +59,23 @@ export default function TemplateList({ environmentId }: { environmentId: string
))}
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<button
type="button"
onClick={() => {
const newTemplate = replacePresetPlaceholders(customSurvey, product);
setActiveTemplate(newTemplate);
setActiveQuestionId(newTemplate.preset.questions[0].id);
}}
className={cn(
activeTemplate?.name === customSurvey.name
? "ring-brand border-transparent ring-2"
: "hover:border-brand-dark border-dashed border-slate-300",
"duration-120 group relative rounded-lg border-2 bg-transparent p-8 transition-colors duration-150"
)}>
<PlusCircleIcon className="text-brand-dark h-8 w-8 transition-all duration-150 group-hover:scale-110" />
<h3 className="text-md mb-1 mt-3 text-left font-bold text-slate-700 ">{customSurvey.name}</h3>
<p className="text-left text-xs text-slate-600 ">{customSurvey.description}</p>
</button>
{templates
.filter((template) => selectedFilter === "All" || template.category === selectedFilter)
.map((template: Template) => (
@@ -82,21 +99,6 @@ export default function TemplateList({ environmentId }: { environmentId: string
<p className="text-left text-xs text-slate-600">{template.description}</p>
</button>
))}
<button
type="button"
onClick={() => {
const newTemplate = replacePresetPlaceholders(customSurvey, product);
setActiveTemplate(newTemplate);
setActiveQuestionId(newTemplate.preset.questions[0].id);
}}
className={cn(
activeTemplate?.name === customSurvey.name && "ring-brand ring-2",
"duration-120 hover:border-brand-dark group relative rounded-lg border-2 border-dashed border-slate-300 bg-transparent p-8 transition-colors duration-150"
)}>
<PlusCircleIcon className="text-brand-dark h-8 w-8 transition-all duration-150 group-hover:scale-110" />
<h3 className="text-md mb-1 mt-3 text-left font-bold text-slate-700 ">{customSurvey.name}</h3>
<p className="text-left text-xs text-slate-600 ">{customSurvey.description}</p>
</button>
</div>
</main>
<aside className="group relative hidden h-full flex-1 flex-shrink-0 overflow-hidden border-l border-slate-200 bg-slate-200 shadow-inner md:flex md:flex-col">
@@ -1,8 +1,9 @@
"use client";
import { Button } from "@formbricks/ui";
import type { Template } from "@formbricks/types/templates";
import { createSurvey } from "@/lib/surveys/surveys";
import type { Template } from "@formbricks/types/templates";
import { Button } from "@formbricks/ui";
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/solid";
import { useRouter } from "next/navigation";
import { useState } from "react";
@@ -22,16 +23,19 @@ export default function TemplateMenuBar({ activeTemplate, environmentId }: Templ
return (
<div className="border-b border-slate-200 bg-white px-5 py-3 sm:flex sm:items-center sm:justify-between">
<h1 className="font-slate-700 text-lg font-semibold">Start with a template</h1>
<div className="mt-3 flex sm:ml-4 sm:mt-0">
<Button variant="secondary" className="mr-3" onClick={() => router.back()}>
Cancel
<div className="flex items-center space-x-4">
<Button variant="minimal" className="px-0" onClick={() => router.back()}>
<ArrowLeftIcon className="h-5 w-5 text-slate-700" />
</Button>
<h1 className="font-slate-700 text-lg font-semibold">Start with a template</h1>
</div>
<div className="mt-3 flex sm:ml-4 sm:mt-0">
<Button
variant="highlight"
disabled={activeTemplate === null}
loading={loading}
onClick={() => addSurvey(activeTemplate)}>
onClick={() => addSurvey(activeTemplate)}
EndIcon={ArrowRightIcon}>
Create Survey
</Button>
</div>
@@ -43,7 +43,7 @@ export default function MultipleChoiceMultiQuestion({
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="mt-4">
<fieldset>
<legend className="sr-only">Choices</legend>
<legend className="sr-only">Options</legend>
<div className="relative space-y-2 rounded-md bg-white">
{question.choices &&
question.choices.map((choice) => (
@@ -33,7 +33,7 @@ export default function MultipleChoiceSingleQuestion({
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="mt-4">
<fieldset>
<legend className="sr-only">Choices</legend>
<legend className="sr-only">Options</legend>
<div className="relative space-y-2 rounded-md">
{question.choices &&
question.choices.map((choice, idx) => (
@@ -12,8 +12,15 @@ import {
SelectTrigger,
SelectValue,
} from "@formbricks/ui";
import { CheckCircleIcon, PauseCircleIcon, PlayCircleIcon } from "@heroicons/react/24/solid";
import {
CheckCircleIcon,
PauseCircleIcon,
PlayCircleIcon,
PencilSquareIcon,
ArchiveBoxIcon,
} from "@heroicons/react/24/solid";
import toast from "react-hot-toast";
import { Badge } from "@formbricks/ui";
export default function SurveyStatusDropdown({
surveyId,
@@ -40,10 +47,24 @@ export default function SurveyStatusDropdown({
{survey.status === "draft" || survey.status === "archived" ? (
<div className="flex items-center">
<SurveyStatusIndicator status={survey.status} environmentId={environmentId} />
<span className="mr-3 italic text-slate-500">
{survey.status === "draft" && "Survey drafted"}
{survey.status === "archived" && "Survey archived"}
</span>
{survey.status === "draft" && (
<Badge
text="Draft"
type="gray"
size="normal"
StartIcon={PencilSquareIcon}
startIconClassName="mr-2"
/>
)}
{survey.status === "archived" && (
<Badge
text="Archived"
type="gray"
size="normal"
StartIcon={ArchiveBoxIcon}
startIconClassName="mr-2"
/>
)}
</div>
) : (
<Select
@@ -72,7 +93,7 @@ export default function SurveyStatusDropdown({
<div className="flex items-center">
<SurveyStatusIndicator status={survey.status} environmentId={environmentId} />
<span className="ml-2 text-sm text-slate-700">
{survey.status === "draft" && "Survey drafted"}
{survey.status === "draft" && "Survey draft"}
{survey.status === "inProgress" && "Collecting insights"}
{survey.status === "paused" && "Survey paused"}
{survey.status === "completed" && "Survey complete"}
@@ -33,8 +33,8 @@ export default function WidgetStatusIndicator({ environmentId, type }: WidgetSta
notImplemented: {
icon: ArrowDownIcon,
color: "slate",
title: "Not implemented yet.",
subtitle: "Formbricks widget not yet implemented.",
title: "Connect Formbricks to your app.",
subtitle: "You have not yet connected Formbricks to your app. Follow setup guide.",
},
running: { icon: CheckIcon, color: "green", title: "Receiving data.", subtitle: "Last action received:" },
issue: {
+22 -15
View File
@@ -1,8 +1,9 @@
import {
Bars3BottomLeftIcon,
ChartPieIcon,
ListBulletIcon,
ArrowRightOnRectangleIcon,
ChatBubbleBottomCenterTextIcon,
CursorArrowRippleIcon,
PresentationChartBarIcon,
QueueListIcon,
} from "@heroicons/react/24/solid";
import { createId } from "@paralleldrive/cuid2";
import { replaceQuestionPresetPlaceholders } from "./templates";
@@ -18,42 +19,46 @@ export type QuestionType = {
export const questionTypes: QuestionType[] = [
{
id: "openText",
label: "Open text",
label: "Free text",
description: "A single line of text",
icon: Bars3BottomLeftIcon,
icon: ChatBubbleBottomCenterTextIcon,
preset: {
placeholder: "Type your answer here...",
},
},
{
id: "multipleChoiceSingle",
label: "Multiple Choice Single-Select",
label: "Single-Select",
description: "A single choice from a list of options (radio buttons)",
icon: ListBulletIcon,
icon: QueueListIcon,
preset: {
headline: "What do you do?",
subheader: "Can't do both.",
choices: [
{ id: createId(), label: "" },
{ id: createId(), label: "" },
{ id: createId(), label: "Eat the cake 🍰" },
{ id: createId(), label: "Have the cake 🎂" },
],
},
},
{
id: "multipleChoiceMulti",
label: "Multiple Choice Multi-Select",
label: "Multi-Select",
description: "Number of choices from a list of options (checkboxes)",
icon: ListBulletIcon,
preset: {
headline: "What's important on vacay?",
choices: [
{ id: createId(), label: "" },
{ id: createId(), label: "" },
{ id: createId(), label: "Sun ☀️" },
{ id: createId(), label: "Ocean 🌊" },
{ id: createId(), label: "Palms 🌴" },
],
},
},
{
id: "nps",
label: "Net Promoter Score (NPS)",
label: "Net Promoter Score® (NPS)",
description: "Rate satisfaction on a 0-10 scale",
icon: ChartPieIcon,
icon: PresentationChartBarIcon,
preset: {
headline: "How likely are you to recommend {{productName}} to a friend or colleague?",
lowerLabel: "Not at all likely",
@@ -64,8 +69,10 @@ export const questionTypes: QuestionType[] = [
id: "cta",
label: "Call-to-Action",
description: "Ask your users to perform an action",
icon: ArrowRightOnRectangleIcon,
icon: CursorArrowRippleIcon,
preset: {
headline: "You are one of our power users!",
buttonLabel: "Book interview",
buttonExternal: false,
dismissButtonLabel: "Skip",
},
@@ -41,7 +41,7 @@ export default function MultipleChoiceMultiQuestion({
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="fb-mt-4">
<fieldset>
<legend className="fb-sr-only">Choices</legend>
<legend className="fb-sr-only">Options</legend>
<div className="fb-relative fb-space-y-2 fb-rounded-md fb-bg-white">
{question.choices &&
question.choices.map((choice) => (
@@ -33,7 +33,7 @@ export default function MultipleChoiceSingleQuestion({
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="fb-mt-4">
<fieldset>
<legend className="fb-sr-only">Choices</legend>
<legend className="fb-sr-only">Options</legend>
<div className="fb-relative fb-space-y-2 fb-rounded-md fb-bg-white">
{question.choices &&
question.choices.map((choice, idx) => (
+1 -1
View File
@@ -31,7 +31,7 @@ export default function NPSQuestion({ question, onSubmit, lastQuestion, brandCol
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="fb-my-4">
<fieldset>
<legend className="fb-sr-only">Choices</legend>
<legend className="fb-sr-only">Options</legend>
<div className="fb-flex">
{Array.from({ length: 11 }, (_, i) => i).map((number) => (
<label
+1 -3
View File
@@ -137,9 +137,7 @@ export const Button: React.ForwardRefExoticComponent<
</svg>
</div>
)}
{EndIcon && (
<EndIcon className={cn("-mr-1 inline h-5 w-5 ltr:ml-2 rtl:mr-2", endIconClassName || "")} />
)}
{EndIcon && <EndIcon className={cn("-mr-1 ml-2 inline h-5 w-5 rtl:mr-2", endIconClassName || "")} />}
</>
);
return props.href ? (
+4 -2
View File
@@ -66,7 +66,7 @@ const editorConfig = {
export const Editor = (props: TextEditorProps) => {
const editable = props.editable ?? true;
return (
<div className="editor rounded-md">
<div className="editor cursor-text rounded-md">
<LexicalComposer initialConfig={{ ...editorConfig, editable }}>
<div className="editor-container rounded-md p-0">
<ToolbarPlugin
@@ -84,7 +84,9 @@ export const Editor = (props: TextEditorProps) => {
style={{ height: props.height }}>
<RichTextPlugin
contentEditable={<ContentEditable style={{ height: props.height }} className="editor-input" />}
placeholder={<div className="text-muted -mt-11 p-3 text-sm">{props.placeholder || ""}</div>}
placeholder={
<div className="text-muted -mt-11 cursor-text p-3 text-sm">{props.placeholder || ""}</div>
}
ErrorBoundary={LexicalErrorBoundary}
/>
<ListPlugin />