feat: checkbox component (#3603)

* feat: custom checkbox component.

* improvement: checkbox component implementation in email notification settings.

* improvement: add loader in email notification settings page.
This commit is contained in:
Prateek Shourya 2024-02-09 16:37:39 +05:30 committed by GitHub
parent b86c6c906a
commit 1927fdd437
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 91 additions and 30 deletions

View File

@ -0,0 +1,67 @@
import * as React from "react";
export interface CheckboxProps extends React.InputHTMLAttributes<HTMLInputElement> {
intermediate?: boolean;
className?: string;
}
const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
const { id, name, checked, intermediate = false, disabled, className = "", ...rest } = props;
return (
<div className={`relative w-full flex gap-2 ${className}`}>
<input
id={id}
ref={ref}
type="checkbox"
name={name}
checked={checked}
className={`
appearance-none shrink-0 w-4 h-4 border rounded-[3px] focus:outline-1 focus:outline-offset-4 focus:outline-custom-primary-50
${
disabled
? "border-custom-border-200 bg-custom-background-80 cursor-not-allowed"
: `cursor-pointer ${
checked || intermediate
? "border-custom-primary-40 bg-custom-primary-100 hover:bg-custom-primary-200"
: "border-custom-border-300 hover:border-custom-border-400 bg-white"
}`
}
`}
disabled={disabled}
{...rest}
/>
<svg
className={`absolute w-4 h-4 p-0.5 pointer-events-none outline-none ${
disabled ? "stroke-custom-text-400 opacity-40" : "stroke-white"
} ${checked ? "block" : "hidden"}`}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
>
<polyline points="20 6 9 17 4 12" />
</svg>
<svg
className={`absolute w-4 h-4 p-0.5 pointer-events-none outline-none ${
disabled ? "stroke-custom-text-400 opacity-40" : "stroke-white"
} ${intermediate && !checked ? "block" : "hidden"}`}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
fill="none"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M5.75 4H2.25" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</div>
);
});
Checkbox.displayName = "form-checkbox-field";
export { Checkbox };

View File

@ -1,3 +1,4 @@
export * from "./input";
export * from "./textarea";
export * from "./input-color-picker";
export * from "./checkbox";

View File

@ -1,7 +1,7 @@
import { FC } from "react";
import React, { FC } from "react";
import { Controller, useForm } from "react-hook-form";
// ui
import { Button } from "@plane/ui";
import { Button, Checkbox } from "@plane/ui";
// hooks
import useToast from "hooks/use-toast";
// services
@ -23,6 +23,7 @@ export const EmailNotificationForm: FC<IEmailNotificationFormProps> = (props) =>
// form data
const {
handleSubmit,
watch,
control,
setValue,
formState: { isSubmitting, isDirty, dirtyFields },
@ -78,12 +79,7 @@ export const EmailNotificationForm: FC<IEmailNotificationFormProps> = (props) =>
control={control}
name="property_change"
render={({ field: { value, onChange } }) => (
<input
type="checkbox"
checked={value}
onChange={() => onChange(!value)}
className="w-3.5 h-3.5 mx-2 cursor-pointer !border-custom-border-100"
/>
<Checkbox checked={value} onChange={() => onChange(!value)} className="mx-2" />
)}
/>
</div>
@ -100,14 +96,14 @@ export const EmailNotificationForm: FC<IEmailNotificationFormProps> = (props) =>
control={control}
name="state_change"
render={({ field: { value, onChange } }) => (
<input
type="checkbox"
<Checkbox
checked={value}
intermediate={!value && watch("issue_completed")}
onChange={() => {
setValue("issue_completed", !value);
onChange(!value);
}}
className="w-3.5 h-3.5 mx-2 cursor-pointer"
className="mx-2"
/>
)}
/>
@ -123,12 +119,7 @@ export const EmailNotificationForm: FC<IEmailNotificationFormProps> = (props) =>
control={control}
name="issue_completed"
render={({ field: { value, onChange } }) => (
<input
type="checkbox"
checked={value}
onChange={() => onChange(!value)}
className="w-3.5 h-3.5 mx-2 cursor-pointer"
/>
<Checkbox checked={value} onChange={() => onChange(!value)} className="mx-2" />
)}
/>
</div>
@ -145,12 +136,7 @@ export const EmailNotificationForm: FC<IEmailNotificationFormProps> = (props) =>
control={control}
name="comment"
render={({ field: { value, onChange } }) => (
<input
type="checkbox"
checked={value}
onChange={() => onChange(!value)}
className="w-3.5 h-3.5 mx-2 cursor-pointer"
/>
<Checkbox checked={value} onChange={() => onChange(!value)} className="mx-2" />
)}
/>
</div>
@ -167,12 +153,7 @@ export const EmailNotificationForm: FC<IEmailNotificationFormProps> = (props) =>
control={control}
name="mention"
render={({ field: { value, onChange } }) => (
<input
type="checkbox"
checked={value}
onChange={() => onChange(!value)}
className="w-3.5 h-3.5 mx-2 cursor-pointer"
/>
<Checkbox checked={value} onChange={() => onChange(!value)} className="mx-2" />
)}
/>
</div>

View File

@ -2,6 +2,8 @@ import { ReactElement } from "react";
import useSWR from "swr";
// layouts
import { ProfilePreferenceSettingsLayout } from "layouts/settings-layout/profile/preferences";
// ui
import { Loader } from "@plane/ui";
// components
import { EmailNotificationForm } from "components/profile/preferences";
// services
@ -14,10 +16,20 @@ const userService = new UserService();
const ProfilePreferencesThemePage: NextPageWithLayout = () => {
// fetching user email notification settings
const { data } = useSWR("CURRENT_USER_EMAIL_NOTIFICATION_SETTINGS", () =>
const { data, isLoading } = useSWR("CURRENT_USER_EMAIL_NOTIFICATION_SETTINGS", () =>
userService.currentUserEmailNotificationSettings()
);
if (isLoading) {
return (
<Loader className="space-y-4 mt-8 px-6 lg:px-20">
<Loader.Item height="40px" />
<Loader.Item height="40px" />
<Loader.Item height="40px" />
</Loader>
);
}
if (!data) {
return null;
}