mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: added custom toggle switch everywhere (#949)
This commit is contained in:
parent
ff7f31c35b
commit
c5b034385f
@ -26,7 +26,7 @@ import {
|
|||||||
import { Popover, Transition } from "@headlessui/react";
|
import { Popover, Transition } from "@headlessui/react";
|
||||||
import { DragDropContext, Draggable, DropResult } from "react-beautiful-dnd";
|
import { DragDropContext, Draggable, DropResult } from "react-beautiful-dnd";
|
||||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||||
import { CustomMenu, Spinner } from "components/ui";
|
import { CustomMenu, Spinner, ToggleSwitch } from "components/ui";
|
||||||
// icon
|
// icon
|
||||||
import {
|
import {
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
@ -390,23 +390,10 @@ export const CalendarView: React.FC<Props> = ({ addIssueToDate }) => {
|
|||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
<div className="mt-1 flex w-52 items-center justify-between border-t border-brand-base py-2 px-1 text-sm text-brand-secondary">
|
<div className="mt-1 flex w-52 items-center justify-between border-t border-brand-base py-2 px-1 text-sm text-brand-secondary">
|
||||||
<h4>Show weekends</h4>
|
<h4>Show weekends</h4>
|
||||||
<button
|
<ToggleSwitch
|
||||||
type="button"
|
value={showWeekEnds}
|
||||||
className={`relative inline-flex h-3.5 w-6 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
onChange={() => setShowWeekEnds(!showWeekEnds)}
|
||||||
showWeekEnds ? "bg-green-500" : "bg-brand-surface-2"
|
|
||||||
}`}
|
|
||||||
role="switch"
|
|
||||||
aria-checked={showWeekEnds}
|
|
||||||
onClick={() => setShowWeekEnds(!showWeekEnds)}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Show weekends</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={`inline-block h-2.5 w-2.5 transform rounded-full bg-brand-surface-2 shadow ring-0 transition duration-200 ease-in-out ${
|
|
||||||
showWeekEnds ? "translate-x-2.5" : "translate-x-0"
|
|
||||||
}`}
|
|
||||||
/>
|
/>
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</CustomMenu>
|
</CustomMenu>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@ import { Popover, Transition } from "@headlessui/react";
|
|||||||
// components
|
// components
|
||||||
import { SelectFilters } from "components/views";
|
import { SelectFilters } from "components/views";
|
||||||
// ui
|
// ui
|
||||||
import { CustomMenu } from "components/ui";
|
import { CustomMenu, ToggleSwitch } from "components/ui";
|
||||||
// icons
|
// icons
|
||||||
import {
|
import {
|
||||||
ChevronDownIcon,
|
ChevronDownIcon,
|
||||||
@ -213,23 +213,10 @@ export const IssuesFilterView: React.FC = () => {
|
|||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h4 className="text-brand-secondary">Show empty states</h4>
|
<h4 className="text-brand-secondary">Show empty states</h4>
|
||||||
<button
|
<ToggleSwitch
|
||||||
type="button"
|
value={showEmptyGroups}
|
||||||
className={`relative inline-flex h-3.5 w-6 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
onChange={() => setShowEmptyGroups(!showEmptyGroups)}
|
||||||
showEmptyGroups ? "bg-green-500" : "bg-brand-surface-2"
|
|
||||||
}`}
|
|
||||||
role="switch"
|
|
||||||
aria-checked={showEmptyGroups}
|
|
||||||
onClick={() => setShowEmptyGroups(!showEmptyGroups)}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Show empty groups</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={`inline-block h-2.5 w-2.5 transform rounded-full bg-brand-surface-2 shadow ring-0 transition duration-200 ease-in-out ${
|
|
||||||
showEmptyGroups ? "translate-x-2.5" : "translate-x-0"
|
|
||||||
}`}
|
|
||||||
/>
|
/>
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex justify-end gap-x-3">
|
<div className="relative flex justify-end gap-x-3">
|
||||||
<button type="button" onClick={() => resetFilterToDefault()}>
|
<button type="button" onClick={() => resetFilterToDefault()}>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FC, useState } from "react";
|
import { FC } from "react";
|
||||||
|
|
||||||
// react-hook-form
|
// react-hook-form
|
||||||
import { Control, Controller, UseFormWatch } from "react-hook-form";
|
import { Control, Controller, UseFormWatch } from "react-hook-form";
|
||||||
@ -7,7 +7,7 @@ import useProjects from "hooks/use-projects";
|
|||||||
// components
|
// components
|
||||||
import { SelectRepository, TFormValues, TIntegrationSteps } from "components/integration";
|
import { SelectRepository, TFormValues, TIntegrationSteps } from "components/integration";
|
||||||
// ui
|
// ui
|
||||||
import { CustomSearchSelect, PrimaryButton, SecondaryButton } from "components/ui";
|
import { CustomSearchSelect, PrimaryButton, SecondaryButton, ToggleSwitch } from "components/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { truncateText } from "helpers/string.helper";
|
import { truncateText } from "helpers/string.helper";
|
||||||
// types
|
// types
|
||||||
@ -107,23 +107,7 @@ export const GithubImportData: FC<Props> = ({ handleStepChange, integration, con
|
|||||||
control={control}
|
control={control}
|
||||||
name="sync"
|
name="sync"
|
||||||
render={({ field: { value, onChange } }) => (
|
render={({ field: { value, onChange } }) => (
|
||||||
<button
|
<ToggleSwitch value={value} onChange={() => onChange(!value)} />
|
||||||
type="button"
|
|
||||||
className={`relative inline-flex h-3.5 w-6 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
|
||||||
value ? "bg-green-500" : "bg-gray-200"
|
|
||||||
}`}
|
|
||||||
role="switch"
|
|
||||||
aria-checked={value ? true : false}
|
|
||||||
onClick={() => onChange(!value)}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Show empty groups</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={`inline-block h-2.5 w-2.5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${
|
|
||||||
value ? "translate-x-2.5" : "translate-x-0"
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,7 +26,14 @@ import { CreateStateModal } from "components/states";
|
|||||||
import { CreateUpdateCycleModal } from "components/cycles";
|
import { CreateUpdateCycleModal } from "components/cycles";
|
||||||
import { CreateLabelModal } from "components/labels";
|
import { CreateLabelModal } from "components/labels";
|
||||||
// ui
|
// ui
|
||||||
import { CustomMenu, Input, Loader, PrimaryButton, SecondaryButton } from "components/ui";
|
import {
|
||||||
|
CustomMenu,
|
||||||
|
Input,
|
||||||
|
Loader,
|
||||||
|
PrimaryButton,
|
||||||
|
SecondaryButton,
|
||||||
|
ToggleSwitch,
|
||||||
|
} from "components/ui";
|
||||||
// icons
|
// icons
|
||||||
import { SparklesIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
import { SparklesIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||||
// helpers
|
// helpers
|
||||||
@ -449,22 +456,7 @@ export const IssueForm: FC<IssueFormProps> = ({
|
|||||||
onClick={() => setCreateMore((prevData) => !prevData)}
|
onClick={() => setCreateMore((prevData) => !prevData)}
|
||||||
>
|
>
|
||||||
<span className="text-xs">Create more</span>
|
<span className="text-xs">Create more</span>
|
||||||
<button
|
<ToggleSwitch value={createMore} onChange={() => {}} size="md" />
|
||||||
type="button"
|
|
||||||
className={`pointer-events-none relative inline-flex h-4 w-7 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent ${
|
|
||||||
createMore ? "bg-brand-accent" : "bg-gray-300"
|
|
||||||
} transition-colors duration-300 ease-in-out focus:outline-none`}
|
|
||||||
role="switch"
|
|
||||||
aria-checked="false"
|
|
||||||
>
|
|
||||||
<span className="sr-only">Create more</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={`pointer-events-none inline-block h-3 w-3 ${
|
|
||||||
createMore ? "translate-x-3" : "translate-x-0"
|
|
||||||
} transform rounded-full bg-brand-surface-2 shadow ring-0 transition duration-300 ease-in-out`}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<SecondaryButton onClick={handleClose}>Discard</SecondaryButton>
|
<SecondaryButton onClick={handleClose}>Discard</SecondaryButton>
|
||||||
|
@ -4,27 +4,38 @@ type Props = {
|
|||||||
value: boolean;
|
value: boolean;
|
||||||
onChange: (value: boolean) => void;
|
onChange: (value: boolean) => void;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
size?: "sm" | "md" | "lg";
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ToggleSwitch: React.FC<Props> = (props) => {
|
export const ToggleSwitch: React.FC<Props> = (props) => {
|
||||||
const { value, onChange, label, disabled, className } = props;
|
const { value, onChange, label, size = "sm", disabled, className } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Switch
|
<Switch
|
||||||
checked={value}
|
checked={value}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className={`relative inline-flex h-3.5 w-6 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
className={`relative inline-flex ${
|
||||||
value ? "bg-green-500" : "bg-gray-200"
|
size === "sm" ? "h-3.5 w-6" : size === "md" ? "h-4 w-7" : "h-6 w-11"
|
||||||
|
} flex-shrink-0 cursor-pointer rounded-full border-2 border-brand-base transition-colors duration-200 ease-in-out focus:outline-none ${
|
||||||
|
value ? "bg-green-500" : "bg-brand-surface-2"
|
||||||
} ${className || ""}`}
|
} ${className || ""}`}
|
||||||
>
|
>
|
||||||
<span className="sr-only">{label}</span>
|
<span className="sr-only">{label}</span>
|
||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className={`inline-block h-2.5 w-2.5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${
|
className={`inline-block ${
|
||||||
value ? "translate-x-2.5" : "translate-x-0"
|
size === "sm" ? "h-2.5 w-2.5" : size === "md" ? "h-3 w-3" : "h-5 w-5"
|
||||||
|
} transform rounded-full shadow ring-0 transition duration-200 ease-in-out ${
|
||||||
|
value
|
||||||
|
? (size === "sm"
|
||||||
|
? "translate-x-2.5"
|
||||||
|
: size === "md"
|
||||||
|
? "translate-x-3"
|
||||||
|
: "translate-x-5") + " bg-white"
|
||||||
|
: "translate-x-0 bg-brand-surface-1"
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
@ -12,7 +12,7 @@ import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
|
|||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// ui
|
// ui
|
||||||
import { SecondaryButton } from "components/ui";
|
import { SecondaryButton, ToggleSwitch } from "components/ui";
|
||||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||||
// icons
|
// icons
|
||||||
import { ContrastIcon, PeopleGroupIcon, ViewListIcon } from "components/icons";
|
import { ContrastIcon, PeopleGroupIcon, ViewListIcon } from "components/icons";
|
||||||
@ -149,16 +149,9 @@ const FeaturesSettings: NextPage = () => {
|
|||||||
<p className="text-sm text-brand-secondary">{feature.description}</p>
|
<p className="text-sm text-brand-secondary">{feature.description}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<ToggleSwitch
|
||||||
type="button"
|
value={projectDetails?.[feature.property as keyof IProject]}
|
||||||
className={`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
onChange={() => {
|
||||||
projectDetails?.[feature.property as keyof IProject]
|
|
||||||
? "bg-green-500"
|
|
||||||
: "bg-brand-surface-2"
|
|
||||||
}`}
|
|
||||||
role="switch"
|
|
||||||
aria-checked={projectDetails?.[feature.property as keyof IProject]}
|
|
||||||
onClick={() => {
|
|
||||||
trackEventServices.trackMiscellaneousEvent(
|
trackEventServices.trackMiscellaneousEvent(
|
||||||
{
|
{
|
||||||
workspaceId: (projectDetails?.workspace as any)?.id,
|
workspaceId: (projectDetails?.workspace as any)?.id,
|
||||||
@ -175,17 +168,8 @@ const FeaturesSettings: NextPage = () => {
|
|||||||
[feature.property]: !projectDetails?.[feature.property as keyof IProject],
|
[feature.property]: !projectDetails?.[feature.property as keyof IProject],
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
size="lg"
|
||||||
<span className="sr-only">Use {feature.title}</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={`inline-block h-5 w-5 transform rounded-full bg-brand-surface-1 shadow ring-0 transition duration-200 ease-in-out ${
|
|
||||||
projectDetails?.[feature.property as keyof IProject]
|
|
||||||
? "translate-x-5"
|
|
||||||
: "translate-x-0"
|
|
||||||
}`}
|
|
||||||
/>
|
/>
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user