feat: custom placeholder label for other option in single & multi select (#1971)

Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com>
This commit is contained in:
Shubham Palriwala
2024-01-30 14:51:01 +05:30
committed by GitHub
parent 0122ccb797
commit 16cbc3365b
5 changed files with 79 additions and 47 deletions
@@ -217,29 +217,44 @@ export default function MultipleChoiceMultiForm({
{question.choices &&
question.choices.map((choice, choiceIdx) => (
<div key={choiceIdx} className="inline-flex w-full items-center">
<Input
ref={choiceIdx === question.choices.length - 1 ? lastChoiceRef : null}
id={choice.id}
name={choice.id}
value={choice.label}
className={cn(choice.id === "other" && "border-dashed")}
placeholder={choice.id === "other" ? "Other" : `Option ${choiceIdx + 1}`}
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
onBlur={() => {
const duplicateLabel = findDuplicateLabel();
if (duplicateLabel) {
setisInvalidValue(duplicateLabel);
} else if (findEmptyLabel()) {
setisInvalidValue("");
} else {
setisInvalidValue(null);
<div className="flex w-full space-x-2">
<Input
ref={choiceIdx === question.choices.length - 1 ? lastChoiceRef : null}
id={choice.id}
name={choice.id}
value={choice.label}
className={cn(choice.id === "other" && "border-dashed")}
placeholder={choice.id === "other" ? "Other" : `Option ${choiceIdx + 1}`}
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
onBlur={() => {
const duplicateLabel = findDuplicateLabel();
if (duplicateLabel) {
setisInvalidValue(duplicateLabel);
} else if (findEmptyLabel()) {
setisInvalidValue("");
} else {
setisInvalidValue(null);
}
}}
isInvalid={
(isInvalidValue === "" && choice.label.trim() === "") ||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim())
}
}}
isInvalid={
(isInvalidValue === "" && choice.label.trim() === "") ||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim())
}
/>
/>
{choice.id === "other" && (
<Input
id="otherInputLabel"
name="otherInputLabel"
value={question.otherOptionPlaceholder ?? "Please specify"}
placeholder={question.otherOptionPlaceholder ?? "Please specify"}
className={cn(choice.id === "other" && "border-dashed")}
onChange={(e) => {
if (e.target.value.trim() == "") e.target.value = "";
updateQuestion(questionIdx, { otherOptionPlaceholder: e.target.value });
}}
/>
)}
</div>
{question.choices && question.choices.length > 2 && (
<TrashIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
@@ -216,30 +216,45 @@ export default function MultipleChoiceSingleForm({
<div className="mt-2 space-y-2" id="choices">
{question.choices &&
question.choices.map((choice, choiceIdx) => (
<div key={choiceIdx} className="inline-flex w-full items-center">
<Input
ref={choiceIdx === question.choices.length - 1 ? lastChoiceRef : null}
id={choice.id}
name={choice.id}
value={choice.label}
className={cn(choice.id === "other" && "border-dashed")}
placeholder={choice.id === "other" ? "Other" : `Option ${choiceIdx + 1}`}
onBlur={() => {
const duplicateLabel = findDuplicateLabel();
if (duplicateLabel) {
setisInvalidValue(duplicateLabel);
} else if (findEmptyLabel()) {
setisInvalidValue("");
} else {
setisInvalidValue(null);
<div key={choiceIdx} className="flex w-full items-center">
<div className="flex w-full space-x-2">
<Input
ref={choiceIdx === question.choices.length - 1 ? lastChoiceRef : null}
id={choice.id}
name={choice.id}
value={choice.label}
className={cn(choice.id === "other" && "border-dashed")}
placeholder={choice.id === "other" ? "Other" : `Option ${choiceIdx + 1}`}
onBlur={() => {
const duplicateLabel = findDuplicateLabel();
if (duplicateLabel) {
setisInvalidValue(duplicateLabel);
} else if (findEmptyLabel()) {
setisInvalidValue("");
} else {
setisInvalidValue(null);
}
}}
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
isInvalid={
(isInvalidValue === "" && choice.label.trim() === "") ||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim())
}
}}
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
isInvalid={
(isInvalidValue === "" && choice.label.trim() === "") ||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim())
}
/>
/>
{choice.id === "other" && (
<Input
id="otherInputLabel"
name="otherInputLabel"
value={question.otherOptionPlaceholder ?? "Please specify"}
placeholder={question.otherOptionPlaceholder ?? "Please specify"}
className={cn(choice.id === "other" && "border-dashed")}
onChange={(e) => {
if (e.target.value.trim() == "") e.target.value = "";
updateQuestion(questionIdx, { otherOptionPlaceholder: e.target.value });
}}
/>
)}
</div>
{question.choices && question.choices.length > 2 && (
<TrashIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
@@ -231,7 +231,7 @@ export default function MultipleChoiceMultiQuestion({
}, 100);
}
}}
placeholder="Please specify"
placeholder={question.otherOptionPlaceholder ?? "Please specify"}
className="placeholder:text-placeholder border-border bg-survey-bg text-heading focus:ring-focus mt-3 flex h-10 w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
required={question.required}
aria-labelledby={`${otherOption.id}-label`}
@@ -182,7 +182,7 @@ export default function MultipleChoiceSingleQuestion({
}, 100);
}
}}
placeholder="Please specify"
placeholder={question.otherOptionPlaceholder ?? "Please specify"}
className="placeholder:text-placeholder border-border bg-survey-bg text-heading focus:ring-focus mt-3 flex h-10 w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
required={question.required}
aria-labelledby={`${otherOption.id}-label`}
+2
View File
@@ -277,6 +277,7 @@ export const ZSurveyMultipleChoiceSingleQuestion = ZSurveyQuestionBase.extend({
choices: z.array(ZSurveyChoice),
logic: z.array(ZSurveyMultipleChoiceSingleLogic).optional(),
shuffleOption: z.enum(["none", "all", "exceptLast"]).optional(),
otherOptionPlaceholder: z.string().optional(),
});
export type TSurveyMultipleChoiceSingleQuestion = z.infer<typeof ZSurveyMultipleChoiceSingleQuestion>;
@@ -286,6 +287,7 @@ export const ZSurveyMultipleChoiceMultiQuestion = ZSurveyQuestionBase.extend({
choices: z.array(ZSurveyChoice),
logic: z.array(ZSurveyMultipleChoiceMultiLogic).optional(),
shuffleOption: z.enum(["none", "all", "exceptLast"]).optional(),
otherOptionPlaceholder: z.string().optional(),
});
export type TSurveyMultipleChoiceMultiQuestion = z.infer<typeof ZSurveyMultipleChoiceMultiQuestion>;