I have two button
component. Each of the button
component has its own button
submit. There can only be one button
component to be selected. Do i need to attach an onClick
on each button and set the selected button to a state? I wonder what’s the recommended way of doing this in Remix?
export const action = async ({ request, context }: ActionFunctionArgs) => {
const formData = await request.formData();
const { actionType, userInput1, userInput2 } = Object.fromEntries(formData);
if (actionType === 'task1') {
console.log(userInput1);
return null;
}
if (actionType === 'task2') {
console.log(userInput2);
return null;
}
return null;
};
export default function GenericRoute() {
const actionData = useActionData<typeof action>();
const data = useLoaderData<typeof loader>();
const [selectedTask, setSelectedTask] = useState<string>('task1');
const handleSelect = (task: string) => {
setSelectedTask(task);
};
return (
<Form method="post">
<div className="container flex h-screen w-full items-center justify-center relative">
<div className="flex flex-col justify-center gap-4 h-full overflow-y-auto w-full max-w-xl mx-auto">
<button
className={`group relative rounded-xl bg-white border shadow-sm p-6 transition-all ${
selectedTask === 'task1' ? 'border-primary' : 'border-zinc-200 hover:border-primary'
}`}
type="button"
onClick={() => handleSelect('task1')}
>
<div className="flex justify-between">
<div className="flex text-left items-center gap-4">
<Avatar className="h-12 w-12">
<div className="bg-slate-100"><AppWindow className="h-5 w-5 text-slate-600"/></div>
</Avatar>
<div className="grid gap-0.5">
<div className="font-medium text-slate-800">Perform Task 1</div>
<div className="font-normal text-sm text-slate-500">Description of what task 1 entails.</div>
</div>
</div>
<div className={`${selectedTask === "task1" ? 'bg-primary' : 'bg-white border border-black'} rounded-full p-1 w-6 h-6 flex items-center justify-center transition-transform transform scale-110`}>
{selectedTask === 'task1' && <Check className="h-4 w-4 text-white" />}
</div>
</div>
{selectedTask === 'task1' && (
<div className="mt-6 flex flex-col gap-2 text-left transition-opacity opacity-100">
<Label className="text-slate-600 text-sm font-medium">Input 1</Label>
<Input
placeholder="Enter input for task 1"
name="userInput1"
defaultValue=""
/>
</div>
)}
{selectedTask === 'task1' && (
<div className="flex justify-end mt-6 transition-opacity opacity-100">
<Button type="submit" name="actionType" value="task1">Submit</Button>
</div>
)}
</button>
<button
className={`group relative rounded-xl bg-white border shadow-sm p-6 transition-all ${
selectedTask === 'task2' ? 'border-primary' : 'border-zinc-200 hover:border-primary'
}`}
type="button"
onClick={() => handleSelect('task2')}
>
<div className="flex justify-between">
<div className="flex text-left items-center gap-4">
<Avatar className="h-12 w-12">
<div className="bg-slate-100"><MessageCircleQuestion className="h-5 w-5 text-slate-600"/></div>
</Avatar>
<div className="grid gap-0.5">
<div className="font-medium text-slate-800">Perform Task 2</div>
<div className="font-normal text-sm text-slate-500">Description of what task 2 entails.</div>
</div>
</div>
<div className={`${selectedTask === "task2" ? 'bg-primary' : 'bg-white border border-black'} rounded-full p-1 w-6 h-6 flex items-center justify-center transition-transform transform scale-110`}>
{selectedTask === 'task2' && <Check className="h-4 w-4 text-white" />}
</div>
</div>
{selectedTask === 'task2' && (
<div className="mt-6 flex flex-col gap-2 text-left transition-opacity opacity-100">
<Label className="text-slate-600 text-sm font-medium">Input 2</Label>
<Textarea
placeholder="Enter input for task 2"
name="userInput2"
defaultValue=""
/>
</div>
)}
{selectedTask === 'task2' && (
<div className="flex justify-end mt-6 transition-opacity opacity-100">
<Button type="submit" name="actionType" value="task2">Submit</Button>
</div>
)}
</button>
</div>
</div>
</Form>
);
}