style: new buttons added (#470)

This commit is contained in:
Aaryan Khandelwal 2023-03-17 10:40:38 +05:30 committed by GitHub
parent 4de0abfc22
commit e7ef6275cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 392 additions and 633 deletions

View File

@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
// ui // ui
import { CheckCircleIcon } from "@heroicons/react/20/solid"; import { CheckCircleIcon } from "@heroicons/react/20/solid";
import { Button, Input } from "components/ui"; import { Input, SecondaryButton } from "components/ui";
// services // services
import authenticationService from "services/authentication.service"; import authenticationService from "services/authentication.service";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
@ -140,8 +140,8 @@ export const EmailCodeForm = ({ onSuccess }: any) => {
/> />
<button <button
type="button" type="button"
className={`text-xs mt-5 w-full flex justify-end outline-none ${ className={`mt-5 flex w-full justify-end text-xs outline-none ${
isResendDisabled ? "text-gray-400 cursor-default" : "cursor-pointer text-theme" isResendDisabled ? "cursor-default text-gray-400" : "cursor-pointer text-theme"
} `} } `}
onClick={() => { onClick={() => {
setIsCodeResending(true); setIsCodeResending(true);
@ -169,16 +169,16 @@ export const EmailCodeForm = ({ onSuccess }: any) => {
)} )}
<div> <div>
{codeSent ? ( {codeSent ? (
<Button <SecondaryButton
type="submit" type="submit"
className="w-full text-center" className="w-full text-center"
onClick={handleSubmit(handleSignin)} onClick={handleSubmit(handleSignin)}
disabled={isSubmitting || (!isValid && isDirty)} loading={isSubmitting || (!isValid && isDirty)}
> >
{isSubmitting ? "Signing in..." : "Sign in"} {isSubmitting ? "Signing in..." : "Sign in"}
</Button> </SecondaryButton>
) : ( ) : (
<Button <SecondaryButton
type="submit" type="submit"
className="w-full text-center" className="w-full text-center"
onClick={() => { onClick={() => {
@ -186,10 +186,10 @@ export const EmailCodeForm = ({ onSuccess }: any) => {
setResendCodeTimer(30); setResendCodeTimer(30);
}); });
}} }}
disabled={isSubmitting || (!isValid && isDirty)} loading={isSubmitting || (!isValid && isDirty)}
> >
{isSubmitting ? "Sending code..." : "Send code"} {isSubmitting ? "Sending code..." : "Send code"}
</Button> </SecondaryButton>
)} )}
</div> </div>
</form> </form>

View File

@ -1,13 +1,15 @@
import React from "react"; import React from "react";
// next
import Link from "next/link"; import Link from "next/link";
// react hook form // react hook form
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
// ui // services
import { Button, Input } from "components/ui";
import authenticationService from "services/authentication.service"; import authenticationService from "services/authentication.service";
// hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui
import { Input, SecondaryButton } from "components/ui";
// types // types
type EmailPasswordFormValues = { type EmailPasswordFormValues = {
email: string; email: string;
@ -97,13 +99,13 @@ export const EmailPasswordForm = ({ onSuccess }: any) => {
</div> </div>
</div> </div>
<div className="mt-5"> <div className="mt-5">
<Button <SecondaryButton
disabled={isSubmitting || (!isValid && isDirty)}
className="w-full text-center"
type="submit" type="submit"
className="w-full text-center"
loading={isSubmitting || (!isValid && isDirty)}
> >
{isSubmitting ? "Signing in..." : "Sign In"} {isSubmitting ? "Signing in..." : "Sign In"}
</Button> </SecondaryButton>
</div> </div>
</form> </form>
</> </>

View File

@ -20,7 +20,7 @@ import { CreateUpdateIssueModal } from "components/issues";
import { CreateUpdateCycleModal } from "components/cycles"; import { CreateUpdateCycleModal } from "components/cycles";
import { CreateUpdateModuleModal } from "components/modules"; import { CreateUpdateModuleModal } from "components/modules";
// ui // ui
import { Button } from "components/ui"; import { SecondaryButton } from "components/ui";
// icons // icons
import { import {
FolderIcon, FolderIcon,
@ -350,11 +350,7 @@ export const CommandPalette: React.FC = () => {
</Combobox> </Combobox>
<div className="flex items-center justify-end gap-2 p-3"> <div className="flex items-center justify-end gap-2 p-3">
<div> <SecondaryButton onClick={handleCommandPaletteClose}>Close</SecondaryButton>
<Button type="button" size="sm" onClick={handleCommandPaletteClose}>
Close
</Button>
</div>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -13,7 +13,7 @@ import issuesServices from "services/issues.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button } from "components/ui"; import { DangerButton, SecondaryButton } from "components/ui";
// icons // icons
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline"; import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { LayerDiagonalIcon } from "components/icons"; import { LayerDiagonalIcon } from "components/icons";
@ -211,17 +211,10 @@ export const BulkDeleteIssuesModal: React.FC<Props> = ({ isOpen, setIsOpen }) =>
{filteredIssues.length > 0 && ( {filteredIssues.length > 0 && (
<div className="flex items-center justify-end gap-2 p-3"> <div className="flex items-center justify-end gap-2 p-3">
<Button type="button" theme="secondary" size="sm" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Close <DangerButton onClick={handleSubmit(handleDelete)} loading={isSubmitting}>
</Button>
<Button
onClick={handleSubmit(handleDelete)}
theme="danger"
size="sm"
disabled={isSubmitting}
>
{isSubmitting ? "Deleting..." : "Delete selected issues"} {isSubmitting ? "Deleting..." : "Delete selected issues"}
</Button> </DangerButton>
</div> </div>
)} )}
</form> </form>

View File

@ -1,14 +1,15 @@
import React, { useState } from "react"; import React, { useState } from "react";
// headless ui
import { Combobox, Dialog, Transition } from "@headlessui/react";
// react-hook-form // react-hook-form
import { Controller, SubmitHandler, useForm } from "react-hook-form"; import { Controller, SubmitHandler, useForm } from "react-hook-form";
// hooks // hooks
import { Combobox, Dialog, Transition } from "@headlessui/react";
import { MagnifyingGlassIcon, RectangleStackIcon } from "@heroicons/react/24/outline";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// headless ui
// ui // ui
import { Button } from "components/ui"; import { PrimaryButton, SecondaryButton } from "components/ui";
// icons
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { LayerDiagonalIcon } from "components/icons"; import { LayerDiagonalIcon } from "components/icons";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
@ -180,17 +181,10 @@ export const ExistingIssuesListModal: React.FC<Props> = ({
/> />
{filteredIssues.length > 0 && ( {filteredIssues.length > 0 && (
<div className="flex items-center justify-end gap-2 p-3"> <div className="flex items-center justify-end gap-2 p-3">
<Button type="button" theme="secondary" size="sm" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton onClick={handleSubmit(onSubmit)} loading={isSubmitting}>
</Button>
<Button
type="button"
size="sm"
onClick={handleSubmit(onSubmit)}
disabled={isSubmitting}
>
{isSubmitting ? "Adding..." : "Add selected issues"} {isSubmitting ? "Adding..." : "Add selected issues"}
</Button> </PrimaryButton>
</div> </div>
)} )}
</form> </form>

View File

@ -13,8 +13,7 @@ import { Tab, Transition, Popover } from "@headlessui/react";
import fileService from "services/file.service"; import fileService from "services/file.service";
// components // components
import { Input, Spinner } from "components/ui"; import { Input, Spinner, PrimaryButton } from "components/ui";
import { PrimaryButton } from "components/ui/button/primary-button";
// hooks // hooks
import useOutsideClickDetector from "hooks/use-outside-click-detector"; import useOutsideClickDetector from "hooks/use-outside-click-detector";

View File

@ -3,16 +3,16 @@ import React, { useCallback, useState } from "react";
import NextImage from "next/image"; import NextImage from "next/image";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
// react-dropzone
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
// headless ui
import { Transition, Dialog } from "@headlessui/react"; import { Transition, Dialog } from "@headlessui/react";
// services // services
import fileServices from "services/file.service"; import fileServices from "services/file.service";
// icon
import { UserCircleIcon } from "components/icons";
// ui // ui
import { Button } from "components/ui"; import { PrimaryButton, SecondaryButton } from "components/ui";
// icons
import { UserCircleIcon } from "components/icons";
type TImageUploadModalProps = { type TImageUploadModalProps = {
value?: string | null; value?: string | null;
@ -39,12 +39,7 @@ export const ImageUploadModal: React.FC<TImageUploadModalProps> = ({
setImage(acceptedFiles[0]); setImage(acceptedFiles[0]);
}, []); }, []);
const { const { getRootProps, getInputProps, isDragActive } = useDropzone({
getRootProps,
getInputProps,
isDragActive,
open: openFileDialog,
} = useDropzone({
onDrop, onDrop,
}); });
@ -158,16 +153,10 @@ export const ImageUploadModal: React.FC<TImageUploadModalProps> = ({
</div> </div>
</div> </div>
<div className="mt-5 sm:mt-6 sm:grid sm:grid-flow-row-dense sm:grid-cols-2 sm:gap-3"> <div className="mt-5 sm:mt-6 sm:grid sm:grid-flow-row-dense sm:grid-cols-2 sm:gap-3">
<Button theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton onClick={handleSubmit} loading={isImageUploading || !image}>
</Button>
<Button
type="submit"
onClick={handleSubmit}
disabled={isImageUploading || image === null}
>
{isImageUploading ? "Uploading..." : "Upload & Save"} {isImageUploading ? "Uploading..." : "Upload & Save"}
</Button> </PrimaryButton>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -18,6 +18,8 @@ import { AllLists, AllBoards } from "components/core";
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
import StrictModeDroppable from "components/dnd/StrictModeDroppable"; import StrictModeDroppable from "components/dnd/StrictModeDroppable";
import { CreateUpdateViewModal } from "components/views"; import { CreateUpdateViewModal } from "components/views";
// ui
import { EmptySpace, EmptySpaceItem, PrimaryButton } from "components/ui";
// icons // icons
import { PlusIcon, RectangleStackIcon, TrashIcon, XMarkIcon } from "@heroicons/react/24/outline"; import { PlusIcon, RectangleStackIcon, TrashIcon, XMarkIcon } from "@heroicons/react/24/outline";
// helpers // helpers
@ -27,7 +29,6 @@ import {
CycleIssueResponse, CycleIssueResponse,
IIssue, IIssue,
IIssueFilterOptions, IIssueFilterOptions,
IView,
ModuleIssueResponse, ModuleIssueResponse,
UserAuth, UserAuth,
} from "types"; } from "types";
@ -41,8 +42,6 @@ import {
PROJECT_MEMBERS, PROJECT_MEMBERS,
STATE_LIST, STATE_LIST,
} from "constants/fetch-keys"; } from "constants/fetch-keys";
import { EmptySpace, EmptySpaceItem } from "components/ui";
import { PrimaryButton } from "components/ui/button/primary-button";
type Props = { type Props = {
type?: "issue" | "cycle" | "module"; type?: "issue" | "cycle" | "module";
@ -501,14 +500,12 @@ export const IssuesView: React.FC<Props> = ({ type = "issue", openIssuesListModa
{Object.keys(filters).length > 0 && ( {Object.keys(filters).length > 0 && (
<PrimaryButton <PrimaryButton
type="button"
onClick={() => onClick={() =>
setCreateViewModal({ setCreateViewModal({
query: filters, query: filters,
}) })
} }
className="flex items-center gap-4 text-sm" className="flex items-center gap-2 text-sm"
size="sm"
> >
<PlusIcon className="h-4 w-4" /> <PlusIcon className="h-4 w-4" />
Save view Save view

View File

@ -1,15 +1,11 @@
import React from "react"; import React from "react";
import { useRouter } from "next/router";
import { mutate } from "swr";
// react-hook-form // react-hook-form
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
// headless ui // headless ui
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
// ui // ui
import { Button, Input } from "components/ui"; import { Input, PrimaryButton, SecondaryButton } from "components/ui";
// types // types
import type { IIssueLink, ModuleLink } from "types"; import type { IIssueLink, ModuleLink } from "types";
@ -116,12 +112,10 @@ export const LinkModal: React.FC<Props> = ({ isOpen, handleClose, onFormSubmit }
</div> </div>
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={onClose}> <SecondaryButton onClick={onClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton onClick={handleSubmit(onSubmit)} loading={isSubmitting}>
</Button>
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Adding Link..." : "Add Link"} {isSubmitting ? "Adding Link..." : "Add Link"}
</Button> </PrimaryButton>
</div> </div>
</form> </form>
</Dialog.Panel> </Dialog.Panel>

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from "react"; import React, { useState } from "react";
// next // next
import { useRouter } from "next/router"; import { useRouter } from "next/router";
// swr // swr
@ -10,7 +10,7 @@ import cycleService from "services/cycles.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button } from "components/ui"; import { DangerButton, SecondaryButton } from "components/ui";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// types // types
@ -28,7 +28,6 @@ export const DeleteCycleModal: React.FC<TConfirmCycleDeletionProps> = ({
setIsOpen, setIsOpen,
data, data,
}) => { }) => {
const cancelButtonRef = useRef(null);
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const router = useRouter(); const router = useRouter();
@ -68,12 +67,7 @@ export const DeleteCycleModal: React.FC<TConfirmCycleDeletionProps> = ({
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog <Dialog as="div" className="relative z-20" onClose={handleClose}>
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -121,25 +115,11 @@ export const DeleteCycleModal: React.FC<TConfirmCycleDeletionProps> = ({
</div> </div>
</div> </div>
</div> </div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6"> <div className="flex justify-end gap-2 bg-gray-50 p-4 sm:px-6">
<Button <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
type="button" <DangerButton onClick={handleDeletion} loading={isDeleteLoading}>
onClick={handleDeletion}
theme="danger"
disabled={isDeleteLoading}
className="inline-flex sm:ml-3"
>
{isDeleteLoading ? "Deleting..." : "Delete"} {isDeleteLoading ? "Deleting..." : "Delete"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="inline-flex sm:ml-3"
onClick={handleClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -1,18 +1,19 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
// toast
import useToast from "hooks/use-toast";
// react-hook-form // react-hook-form
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
// ui
import { Button, CustomDatePicker, CustomSelect, Input, TextArea } from "components/ui";
// types
import { ICycle } from "types";
// services // services
import cyclesService from "services/cycles.service"; import cyclesService from "services/cycles.service";
// helper // hooks
import useToast from "hooks/use-toast";
// ui
import { CustomDatePicker, Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
// helpers
import { getDateRangeStatus } from "helpers/date-time.helper"; import { getDateRangeStatus } from "helpers/date-time.helper";
// types
import { ICycle } from "types";
type Props = { type Props = {
handleFormSubmit: (values: Partial<ICycle>) => Promise<void>; handleFormSubmit: (values: Partial<ICycle>) => Promise<void>;
@ -188,11 +189,8 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
</div> </div>
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton
</Button>
<Button
type="submit" type="submit"
className={ className={
checkEmptyDate checkEmptyDate
@ -201,7 +199,7 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
? "cursor-pointer" ? "cursor-pointer"
: "cursor-not-allowed" : "cursor-not-allowed"
} }
disabled={isSubmitting || checkEmptyDate ? false : isDateValid ? false : true} loading={isSubmitting || checkEmptyDate ? false : isDateValid ? false : true}
> >
{status {status
? isSubmitting ? isSubmitting
@ -210,7 +208,7 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
: isSubmitting : isSubmitting
? "Creating Cycle..." ? "Creating Cycle..."
: "Create Cycle"} : "Create Cycle"}
</Button> </PrimaryButton>
</div> </div>
</form> </form>
); );

View File

@ -13,7 +13,7 @@ import useToast from "hooks/use-toast";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// ui // ui
import { Button } from "components/ui"; import { SecondaryButton, DangerButton } from "components/ui";
// types // types
import type { CycleIssueResponse, IIssue, ModuleIssueResponse } from "types"; import type { CycleIssueResponse, IIssue, ModuleIssueResponse } from "types";
// fetch-keys // fetch-keys
@ -26,7 +26,6 @@ type Props = {
}; };
export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data }) => { export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data }) => {
const cancelButtonRef = useRef(null);
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const router = useRouter(); const router = useRouter();
@ -98,7 +97,7 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data })
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog as="div" className="relative z-20" initialFocus={cancelButtonRef} onClose={onClose}> <Dialog as="div" className="relative z-20" onClose={onClose}>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -136,34 +135,20 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data })
</span> </span>
</div> </div>
<span> <span>
<p className="text-sm leading-7 text-gray-500 break-all"> <p className="break-all text-sm leading-7 text-gray-500">
Are you sure you want to delete issue{" "} Are you sure you want to delete issue{" "}
<span className="font-semibold break-all"> <span className="break-all font-semibold">
{data?.project_detail.identifier}-{data?.sequence_id} {data?.project_detail.identifier}-{data?.sequence_id}
</span>{" "} </span>{" "}
? All of the data related to the issue will be permanently removed. This ? All of the data related to the issue will be permanently removed. This
action cannot be undone. action cannot be undone.
</p> </p>
</span> </span>
<div className="flex flex-row-reverse items-center gap-3"> <div className="flex justify-end gap-2">
<Button <SecondaryButton onClick={onClose}>Cancel</SecondaryButton>
type="button" <DangerButton onClick={handleDeletion} loading={isDeleteLoading}>
onClick={handleDeletion}
theme="danger"
disabled={isDeleteLoading}
className="rounded-lg border-none px-5 py-2 "
>
{isDeleteLoading ? "Deleting..." : "Delete Issue"} {isDeleteLoading ? "Deleting..." : "Delete Issue"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="rounded-lg border-none px-5 py-2 "
onClick={onClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</div> </div>
</Dialog.Panel> </Dialog.Panel>

View File

@ -20,8 +20,7 @@ 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 { Button, CustomMenu, Input, Loader } from "components/ui"; import { CustomMenu, Input, Loader, PrimaryButton, SecondaryButton } from "components/ui";
import { PrimaryButton } from "components/ui/button/primary-button";
// icons // icons
import { XMarkIcon } from "@heroicons/react/24/outline"; import { XMarkIcon } from "@heroicons/react/24/outline";
// helpers // helpers
@ -355,10 +354,8 @@ export const IssueForm: FC<IssueFormProps> = ({
</button> </button>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button type="button" theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Discard</SecondaryButton>
Discard <PrimaryButton type="submit" loading={isSubmitting}>
</Button>
<PrimaryButton type="submit" size="sm" loading={isSubmitting}>
{status {status
? isSubmitting ? isSubmitting
? "Updating Issue..." ? "Updating Issue..."

View File

@ -5,7 +5,7 @@ import { Combobox, Dialog, Transition } from "@headlessui/react";
// icons // icons
import { MagnifyingGlassIcon, RectangleStackIcon } from "@heroicons/react/24/outline"; import { MagnifyingGlassIcon, RectangleStackIcon } from "@heroicons/react/24/outline";
// ui // ui
import { Button } from "components/ui"; import { PrimaryButton, SecondaryButton } from "components/ui";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
import { LayerDiagonalIcon } from "components/icons"; import { LayerDiagonalIcon } from "components/icons";
@ -145,12 +145,8 @@ export const ParentIssuesListModal: React.FC<Props> = ({
)} )}
</Combobox> </Combobox>
<div className="flex items-center justify-end gap-2 p-3"> <div className="flex items-center justify-end gap-2 p-3">
<Button type="button" theme="danger" size="sm" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton onClick={() => onChange(values)}>Add issues</PrimaryButton>
</Button>
<Button type="button" size="sm" onClick={() => onChange(values)}>
Add issues
</Button>
</div> </div>
</> </>
) : ( ) : (

View File

@ -14,7 +14,7 @@ import useToast from "hooks/use-toast";
// services // services
import issuesService from "services/issues.service"; import issuesService from "services/issues.service";
// ui // ui
import { Button } from "components/ui"; import { PrimaryButton, SecondaryButton } from "components/ui";
// icons // icons
import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline"; import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { BlockedIcon, LayerDiagonalIcon } from "components/icons"; import { BlockedIcon, LayerDiagonalIcon } from "components/icons";
@ -270,14 +270,10 @@ export const SidebarBlockedSelect: React.FC<Props> = ({
{filteredIssues.length > 0 && ( {filteredIssues.length > 0 && (
<div className="flex items-center justify-end gap-2 p-3"> <div className="flex items-center justify-end gap-2 p-3">
<div> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
<Button type="button" theme="secondary" size="sm" onClick={handleClose}> <PrimaryButton onClick={handleSubmit(onSubmit)}>
Close
</Button>
</div>
<Button onClick={handleSubmit(onSubmit)} size="sm">
Add selected issues Add selected issues
</Button> </PrimaryButton>
</div> </div>
)} )}
</form> </form>

View File

@ -14,7 +14,7 @@ import useToast from "hooks/use-toast";
// services // services
import issuesServices from "services/issues.service"; import issuesServices from "services/issues.service";
// ui // ui
import { Button } from "components/ui"; import { PrimaryButton, SecondaryButton } from "components/ui";
// icons // icons
import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline"; import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { BlockerIcon, LayerDiagonalIcon } from "components/icons"; import { BlockerIcon, LayerDiagonalIcon } from "components/icons";
@ -270,14 +270,10 @@ export const SidebarBlockerSelect: React.FC<Props> = ({
{filteredIssues.length > 0 && ( {filteredIssues.length > 0 && (
<div className="flex items-center justify-end gap-2 p-3"> <div className="flex items-center justify-end gap-2 p-3">
<div> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
<Button type="button" theme="secondary" size="sm" onClick={handleClose}> <PrimaryButton onClick={handleSubmit(onSubmit)}>
Close
</Button>
</div>
<Button onClick={handleSubmit(onSubmit)} size="sm">
Add selected issues Add selected issues
</Button> </PrimaryButton>
</div> </div>
)} )}
</Dialog.Panel> </Dialog.Panel>

View File

@ -29,7 +29,7 @@ import {
SidebarStateSelect, SidebarStateSelect,
} from "components/issues"; } from "components/issues";
// ui // ui
import { Input, Button, Spinner, CustomDatePicker } from "components/ui"; import { Input, Spinner, CustomDatePicker } from "components/ui";
// icons // icons
import { import {
TagIcon, TagIcon,
@ -581,12 +581,20 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
}} }}
autoComplete="off" autoComplete="off"
/> />
<Button type="submit" theme="danger" onClick={() => setCreateLabelForm(false)}> <button
type="submit"
className="grid place-items-center rounded bg-red-500 p-2.5"
onClick={() => setCreateLabelForm(false)}
>
<XMarkIcon className="h-4 w-4 text-white" /> <XMarkIcon className="h-4 w-4 text-white" />
</Button> </button>
<Button type="submit" theme="success" disabled={isSubmitting}> <button
type="submit"
className="grid place-items-center rounded bg-green-500 p-2.5"
disabled={isSubmitting}
>
<PlusIcon className="h-4 w-4 text-white" /> <PlusIcon className="h-4 w-4 text-white" />
</Button> </button>
</form> </form>
)} )}
</div> </div>

View File

@ -210,7 +210,7 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
<a className="group flex items-center justify-between gap-2 rounded p-2 hover:bg-gray-100"> <a className="group flex items-center justify-between gap-2 rounded p-2 hover:bg-gray-100">
<div className="flex items-center gap-2 rounded text-xs"> <div className="flex items-center gap-2 rounded text-xs">
<span <span
className="block flex-shrink-0 h-1.5 w-1.5 rounded-full" className="block h-1.5 w-1.5 flex-shrink-0 rounded-full"
style={{ style={{
backgroundColor: issue.state_detail.color, backgroundColor: issue.state_detail.color,
}} }}
@ -224,7 +224,7 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
{!isNotAllowed && ( {!isNotAllowed && (
<button <button
type="button" type="button"
className="opacity-0 group-hover:opacity-100 cursor-pointer" className="cursor-pointer opacity-0 group-hover:opacity-100"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -253,6 +253,7 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
} }
optionsPosition="left" optionsPosition="left"
noBorder noBorder
noChevron
> >
<CustomMenu.MenuItem onClick={handleCreateIssueModal}>Create new</CustomMenu.MenuItem> <CustomMenu.MenuItem onClick={handleCreateIssueModal}>Create new</CustomMenu.MenuItem>
<CustomMenu.MenuItem onClick={() => setSubIssuesListModal(true)}> <CustomMenu.MenuItem onClick={() => setSubIssuesListModal(true)}>

View File

@ -13,7 +13,7 @@ import { Dialog, Popover, Transition } from "@headlessui/react";
// services // services
import issuesService from "services/issues.service"; import issuesService from "services/issues.service";
// ui // ui
import { Button, Input } from "components/ui"; import { Input, PrimaryButton, SecondaryButton } from "components/ui";
// icons // icons
import { ChevronDownIcon } from "@heroicons/react/24/outline"; import { ChevronDownIcon } from "@heroicons/react/24/outline";
// types // types
@ -171,12 +171,10 @@ export const CreateLabelModal: React.FC<Props> = ({ isOpen, projectId, handleClo
</div> </div>
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={onClose}> <SecondaryButton onClick={onClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton type="submit" loading={isSubmitting}>
</Button>
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Creating Label..." : "Create Label"} {isSubmitting ? "Creating Label..." : "Create Label"}
</Button> </PrimaryButton>
</div> </div>
</form> </form>
</Dialog.Panel> </Dialog.Panel>

View File

@ -13,7 +13,7 @@ import { Popover, Transition } from "@headlessui/react";
// services // services
import issuesService from "services/issues.service"; import issuesService from "services/issues.service";
// ui // ui
import { Button, Input } from "components/ui"; import { Input, PrimaryButton, SecondaryButton } from "components/ui";
// types // types
import { IIssueLabels } from "types"; import { IIssueLabels } from "types";
// fetch-keys // fetch-keys
@ -168,24 +168,22 @@ export const CreateUpdateLabelInline: React.FC<Props> = ({
error={errors.name} error={errors.name}
/> />
</div> </div>
<Button <SecondaryButton
type="button"
theme="secondary"
onClick={() => { onClick={() => {
reset(); reset();
setLabelForm(false); setLabelForm(false);
}} }}
> >
Cancel Cancel
</Button> </SecondaryButton>
{isUpdating ? ( {isUpdating ? (
<Button type="button" onClick={handleSubmit(handleLabelUpdate)} disabled={isSubmitting}> <PrimaryButton onClick={handleSubmit(handleLabelUpdate)} loading={isSubmitting}>
{isSubmitting ? "Updating" : "Update"} {isSubmitting ? "Updating" : "Update"}
</Button> </PrimaryButton>
) : ( ) : (
<Button type="button" onClick={handleSubmit(handleLabelCreate)} disabled={isSubmitting}> <PrimaryButton onClick={handleSubmit(handleLabelCreate)} loading={isSubmitting}>
{isSubmitting ? "Adding" : "Add"} {isSubmitting ? "Adding" : "Add"}
</Button> </PrimaryButton>
)} )}
</div> </div>
); );

View File

@ -11,7 +11,7 @@ import modulesService from "services/modules.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button } from "components/ui"; import { SecondaryButton, DangerButton } from "components/ui";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// types // types
@ -29,14 +29,10 @@ export const DeleteModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data })
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const router = useRouter(); const router = useRouter();
const { const { workspaceSlug } = router.query;
query: { workspaceSlug },
} = router;
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const cancelButtonRef = useRef(null);
const handleClose = () => { const handleClose = () => {
setIsOpen(false); setIsOpen(false);
setIsDeleteLoading(false); setIsDeleteLoading(false);
@ -67,12 +63,7 @@ export const DeleteModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data })
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog <Dialog as="div" className="relative z-20" onClose={handleClose}>
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -120,25 +111,11 @@ export const DeleteModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data })
</div> </div>
</div> </div>
</div> </div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6"> <div className="flex justify-end gap-2 bg-gray-50 p-4 sm:px-6">
<Button <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
type="button" <DangerButton onClick={handleDeletion} loading={isDeleteLoading}>
onClick={handleDeletion}
theme="danger"
disabled={isDeleteLoading}
className="inline-flex sm:ml-3"
>
{isDeleteLoading ? "Deleting..." : "Delete"} {isDeleteLoading ? "Deleting..." : "Delete"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="inline-flex sm:ml-3"
onClick={handleClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -5,7 +5,7 @@ import { Controller, useForm } from "react-hook-form";
// components // components
import { ModuleLeadSelect, ModuleMembersSelect, ModuleStatusSelect } from "components/modules"; import { ModuleLeadSelect, ModuleMembersSelect, ModuleStatusSelect } from "components/modules";
// ui // ui
import { Button, CustomDatePicker, Input, TextArea } from "components/ui"; import { CustomDatePicker, Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
// types // types
import { IModule } from "types"; import { IModule } from "types";
@ -132,10 +132,8 @@ export const ModuleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, sta
</div> </div>
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton type="submit" loading={isSubmitting}>
</Button>
<Button type="submit" disabled={isSubmitting}>
{status {status
? isSubmitting ? isSubmitting
? "Updating Module..." ? "Updating Module..."
@ -143,7 +141,7 @@ export const ModuleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, sta
: isSubmitting : isSubmitting
? "Creating Module..." ? "Creating Module..."
: "Create Module"} : "Create Module"}
</Button> </PrimaryButton>
</div> </div>
</form> </form>
); );

View File

@ -10,7 +10,7 @@ import workspaceService from "services/workspace.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button, Loader } from "components/ui"; import { DangerButton, Loader, SecondaryButton } from "components/ui";
// icons // icons
import GithubLogo from "public/logos/github-square.png"; import GithubLogo from "public/logos/github-square.png";
// types // types
@ -133,19 +133,13 @@ const OAuthPopUp = ({ integration }: any) => {
{workspaceIntegrations ? ( {workspaceIntegrations ? (
isInstalled ? ( isInstalled ? (
<Button <DangerButton onClick={handleRemoveIntegration} loading={deletingIntegration}>
theme="danger"
size="rg"
className="text-xs"
onClick={handleRemoveIntegration}
disabled={deletingIntegration}
>
{deletingIntegration ? "Removing..." : "Remove installation"} {deletingIntegration ? "Removing..." : "Remove installation"}
</Button> </DangerButton>
) : ( ) : (
<Button theme="secondary" size="rg" className="text-xs" onClick={startAuth}> <SecondaryButton onClick={startAuth} outline>
Add installation Add installation
</Button> </SecondaryButton>
) )
) : ( ) : (
<Loader> <Loader>

View File

@ -4,7 +4,7 @@ import { Dialog, Transition } from "@headlessui/react";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// ui // ui
import { Button } from "components/ui"; import { SecondaryButton, DangerButton } from "components/ui";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
@ -16,8 +16,6 @@ type Props = {
const ConfirmProjectMemberRemove: React.FC<Props> = ({ isOpen, onClose, data, handleDelete }) => { const ConfirmProjectMemberRemove: React.FC<Props> = ({ isOpen, onClose, data, handleDelete }) => {
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const cancelButtonRef = useRef(null);
const handleClose = () => { const handleClose = () => {
onClose(); onClose();
setIsDeleteLoading(false); setIsDeleteLoading(false);
@ -31,12 +29,7 @@ const ConfirmProjectMemberRemove: React.FC<Props> = ({ isOpen, onClose, data, ha
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog <Dialog as="div" className="relative z-20" onClose={handleClose}>
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -84,25 +77,11 @@ const ConfirmProjectMemberRemove: React.FC<Props> = ({ isOpen, onClose, data, ha
</div> </div>
</div> </div>
</div> </div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6"> <div className="flex justify-end gap-2 bg-gray-50 p-4 sm:px-6">
<Button <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
type="button" <DangerButton onClick={handleDeletion} loading={isDeleteLoading}>
onClick={handleDeletion}
theme="danger"
disabled={isDeleteLoading}
className="inline-flex sm:ml-3"
>
{isDeleteLoading ? "Removing..." : "Remove"} {isDeleteLoading ? "Removing..." : "Remove"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="inline-flex sm:ml-3"
onClick={handleClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -15,8 +15,7 @@ import workspaceService from "services/workspace.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { PrimaryButton } from "components/ui/button/primary-button"; import { Input, TextArea, CustomSelect, PrimaryButton, SecondaryButton } from "components/ui";
import { Button, Input, TextArea, CustomSelect } from "components/ui";
// icons // icons
import { XMarkIcon } from "@heroicons/react/24/outline"; import { XMarkIcon } from "@heroicons/react/24/outline";
// components // components
@ -311,9 +310,7 @@ export const CreateProjectModal: React.FC<Props> = (props) => {
</div> </div>
<div className="mt-5 flex justify-end gap-2 border-t-2 px-4 py-3"> <div className="mt-5 flex justify-end gap-2 border-t-2 px-4 py-3">
<Button theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel
</Button>
<PrimaryButton type="submit" size="sm" loading={isSubmitting}> <PrimaryButton type="submit" size="sm" loading={isSubmitting}>
{isSubmitting ? "Adding project..." : "Add Project"} {isSubmitting ? "Adding project..." : "Add Project"}
</PrimaryButton> </PrimaryButton>

View File

@ -11,7 +11,7 @@ import useToast from "hooks/use-toast";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// ui // ui
import { Button, Input } from "components/ui"; import { DangerButton, Input, SecondaryButton } from "components/ui";
// types // types
import type { IProject, IWorkspace } from "types"; import type { IProject, IWorkspace } from "types";
// fetch-keys // fetch-keys
@ -24,10 +24,12 @@ type TConfirmProjectDeletionProps = {
data: IProject | null; data: IProject | null;
}; };
export const DeleteProjectModal: React.FC<TConfirmProjectDeletionProps> = (props) => { export const DeleteProjectModal: React.FC<TConfirmProjectDeletionProps> = ({
const { isOpen, data, onClose, onSuccess } = props; isOpen,
data,
const cancelButtonRef = useRef(null); onClose,
onSuccess,
}) => {
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const [confirmProjectName, setConfirmProjectName] = useState(""); const [confirmProjectName, setConfirmProjectName] = useState("");
const [confirmDeleteMyProject, setConfirmDeleteMyProject] = useState(false); const [confirmDeleteMyProject, setConfirmDeleteMyProject] = useState(false);
@ -84,12 +86,7 @@ export const DeleteProjectModal: React.FC<TConfirmProjectDeletionProps> = (props
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog <Dialog as="div" className="relative z-20" onClose={handleClose}>
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -168,25 +165,11 @@ export const DeleteProjectModal: React.FC<TConfirmProjectDeletionProps> = (props
name="typeDelete" name="typeDelete"
/> />
</div> </div>
<div className="flex flex-row-reverse items-center gap-3"> <div className="flex justify-end gap-2">
<Button <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
type="button" <DangerButton onClick={handleDeletion} loading={isDeleteLoading || !canDelete}>
onClick={handleDeletion}
theme="danger"
disabled={isDeleteLoading || !canDelete}
className="rounded-lg border-none px-5 py-2"
>
{isDeleteLoading ? "Deleting..." : "Delete Project"} {isDeleteLoading ? "Deleting..." : "Delete Project"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="rounded-lg border-none px-5 py-2"
onClick={handleClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</div> </div>
</Dialog.Panel> </Dialog.Panel>

View File

@ -1,10 +1,11 @@
import React, { useState } from "react"; import React, { useState } from "react";
// headless ui
import { Transition, Dialog } from "@headlessui/react"; import { Transition, Dialog } from "@headlessui/react";
// ui // ui
import { PrimaryButton, SecondaryButton } from "components/ui";
// types
import type { IProject } from "types"; import type { IProject } from "types";
import { Button } from "components/ui";
// type // type
type TJoinProjectModalProps = { type TJoinProjectModalProps = {
@ -70,12 +71,10 @@ export const JoinProjectModal: React.FC<TJoinProjectModalProps> = ({ onClose, on
<div className="space-y-3" /> <div className="space-y-3" />
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button type="button" theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton type="submit" onClick={handleJoin} loading={isJoiningLoading}>
</Button>
<Button type="submit" onClick={handleJoin} disabled={isJoiningLoading}>
{isJoiningLoading ? "Joining..." : "Join Project"} {isJoiningLoading ? "Joining..." : "Join Project"}
</Button> </PrimaryButton>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -1,6 +1,7 @@
import { FC } from "react"; import { FC } from "react";
// ui // ui
import { Button } from "components/ui"; import { SecondaryButton } from "components/ui";
export interface JoinProjectProps { export interface JoinProjectProps {
isJoiningProject: boolean; isJoiningProject: boolean;
@ -16,9 +17,9 @@ export const JoinProject: FC<JoinProjectProps> = ({ isJoiningProject, handleJoin
below. below.
</p> </p>
<div> <div>
<Button type="button" disabled={isJoiningProject} onClick={handleJoin}> <SecondaryButton loading={isJoiningProject} onClick={handleJoin}>
{isJoiningProject ? "Joining..." : "Click to join"} {isJoiningProject ? "Joining..." : "Click to join"}
</Button> </SecondaryButton>
</div> </div>
</div> </div>
</div> </div>

View File

@ -8,7 +8,7 @@ import { useForm, Controller } from "react-hook-form";
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
// ui // ui
import { Button, CustomSelect, TextArea } from "components/ui"; import { CustomSelect, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// services // services
@ -218,12 +218,10 @@ const SendProjectInvitationModal: React.FC<Props> = ({ isOpen, setIsOpen, member
</div> </div>
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton type="submit" loading={isSubmitting}>
</Button>
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Sending Invitation..." : "Send Invitation"} {isSubmitting ? "Sending Invitation..." : "Send Invitation"}
</Button> </PrimaryButton>
</div> </div>
</form> </form>
</Dialog.Panel> </Dialog.Panel>

View File

@ -1,14 +1,15 @@
// react
import React, { useState } from "react"; import React, { useState } from "react";
// react-hook-form // react-hook-form
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
// react-color
import { TwitterPicker } from "react-color";
// headless ui // headless ui
import { Popover, Transition } from "@headlessui/react"; import { Popover, Transition } from "@headlessui/react";
// ui // ui
import { PencilIcon, RectangleGroupIcon } from "@heroicons/react/24/outline"; import { CustomMenu, Input, PrimaryButton, SecondaryButton } from "components/ui";
import { TwitterPicker } from "react-color";
import { Button, CustomMenu, Input } from "components/ui";
// icons // icons
import { PencilIcon, RectangleGroupIcon } from "@heroicons/react/24/outline";
// types // types
import { IIssueLabels } from "types"; import { IIssueLabels } from "types";
@ -110,19 +111,15 @@ const SingleLabel: React.FC<Props> = ({ label, issueLabels, editLabel, handleLab
id="labelName" id="labelName"
name="name" name="name"
register={register} register={register}
placeholder="Lable title" placeholder="Label title"
validations={{ validations={{
required: "Label title is required", required: "Label title is required",
}} }}
error={errors.name} error={errors.name}
/> />
</div> </div>
<Button type="button" theme="secondary" onClick={() => setNewLabelForm(false)}> <SecondaryButton onClick={() => setNewLabelForm(false)}>Cancel</SecondaryButton>
Cancel <PrimaryButton loading={isSubmitting}>{isSubmitting ? "Adding" : "Add"}</PrimaryButton>
</Button>
<Button type="button" disabled={isSubmitting}>
{isSubmitting ? "Adding" : "Add"}
</Button>
</div> </div>
</div> </div>
) : ( ) : (

View File

@ -13,7 +13,7 @@ import { Dialog, Popover, Transition } from "@headlessui/react";
// services // services
import stateService from "services/state.service"; import stateService from "services/state.service";
// ui // ui
import { Button, CustomSelect, Input, TextArea } from "components/ui"; import { CustomSelect, Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
// icons // icons
import { ChevronDownIcon } from "@heroicons/react/24/outline"; import { ChevronDownIcon } from "@heroicons/react/24/outline";
// types // types
@ -215,12 +215,10 @@ export const CreateStateModal: React.FC<Props> = ({ isOpen, projectId, handleClo
</div> </div>
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={onClose}> <SecondaryButton onClick={onClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton type="submit" loading={isSubmitting}>
</Button>
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Creating State..." : "Create State"} {isSubmitting ? "Creating State..." : "Create State"}
</Button> </PrimaryButton>
</div> </div>
</form> </form>
</Dialog.Panel> </Dialog.Panel>

View File

@ -15,7 +15,7 @@ import stateService from "services/state.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button, CustomSelect, Input } from "components/ui"; import { CustomSelect, Input, PrimaryButton, SecondaryButton } from "components/ui";
// types // types
import type { IState } from "types"; import type { IState } from "types";
// fetch-keys // fetch-keys
@ -217,12 +217,10 @@ export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, select
error={errors.description} error={errors.description}
autoComplete="off" autoComplete="off"
/> />
<Button theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton type="submit" loading={isSubmitting}>
</Button>
<Button theme="primary" disabled={isSubmitting} type="submit">
{isSubmitting ? (data ? "Updating..." : "Creating...") : data ? "Update" : "Create"} {isSubmitting ? (data ? "Updating..." : "Creating...") : data ? "Update" : "Create"}
</Button> </PrimaryButton>
</form> </form>
); );
}; };

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@ -14,7 +14,7 @@ import issuesServices from "services/issues.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button } from "components/ui"; import { DangerButton, SecondaryButton } from "components/ui";
// helpers // helpers
import { groupBy } from "helpers/array.helper"; import { groupBy } from "helpers/array.helper";
// types // types
@ -46,8 +46,6 @@ export const DeleteStateModal: React.FC<Props> = ({ isOpen, onClose, data }) =>
: null : null
); );
const cancelButtonRef = useRef(null);
const handleClose = () => { const handleClose = () => {
onClose(); onClose();
setIsDeleteLoading(false); setIsDeleteLoading(false);
@ -82,12 +80,7 @@ export const DeleteStateModal: React.FC<Props> = ({ isOpen, onClose, data }) =>
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog <Dialog as="div" className="relative z-20" onClose={handleClose}>
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -143,25 +136,14 @@ export const DeleteStateModal: React.FC<Props> = ({ isOpen, onClose, data }) =>
</div> </div>
</div> </div>
</div> </div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6"> <div className="flex justify-end gap-2 bg-gray-50 p-4 sm:px-6">
<Button <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
type="button" <DangerButton
onClick={handleDeletion} onClick={handleDeletion}
theme="danger" loading={isDeleteLoading || issuesWithThisStateExist}
disabled={isDeleteLoading || issuesWithThisStateExist}
className="inline-flex sm:ml-3"
> >
{isDeleteLoading ? "Deleting..." : "Delete"} {isDeleteLoading ? "Deleting..." : "Delete"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="inline-flex sm:ml-3"
onClick={handleClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -1,62 +0,0 @@
import * as React from "react";
type ButtonProps = {
onClick?: () => void;
children: React.ReactNode;
type?: "button" | "submit" | "reset";
className?: string;
theme?: "primary" | "secondary" | "success" | "danger";
size?: "sm" | "rg" | "md" | "lg";
disabled?: boolean;
largePadding?: boolean;
};
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
(
{
children,
onClick,
type = "button",
size = "sm",
className = "",
theme = "primary",
disabled = false,
largePadding,
},
ref
) => (
<button
ref={ref}
onClick={onClick}
type={type}
disabled={disabled}
className={`inline-flex items-center justify-center rounded font-medium duration-300 ${
theme === "primary"
? `${
disabled ? "opacity-70" : ""
} border border-transparent bg-gray-200 shadow-sm hover:bg-gray-300 focus:outline-none`
: theme === "secondary"
? "border border-gray-300 bg-transparent hover:bg-gray-200"
: theme === "success"
? `${
disabled ? "opacity-70" : ""
} border border-transparent bg-green-500 text-white shadow-sm hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500`
: `${
disabled ? "opacity-70" : ""
} border border-transparent bg-red-500 text-white shadow-sm hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500`
} ${
size === "sm"
? "p-2 text-xs"
: size === "md"
? "text-md px-3 py-2"
: size === "lg"
? "text-md px-4 py-2"
: "px-2.5 py-2 text-sm"
} ${largePadding ? "px-8" : ""} ${className}`}
>
{children}
</button>
)
);
Button.displayName = "Button";

View File

@ -1 +0,0 @@
export * from "./primary-button";

View File

@ -1,32 +0,0 @@
type TButtonProps = {
children: React.ReactNode;
className?: string;
onClick?: () => void;
type?: "button" | "submit" | "reset";
disabled?: boolean;
loading?: boolean;
size?: "sm" | "md" | "lg";
};
export const PrimaryButton: React.FC<TButtonProps> = (props) => {
const { children, className, onClick, type, disabled, loading, size = "md" } = props;
return (
<button
type={type}
className={`hover:bg-opacity-90 transition-colors text-white rounded-lg ${
size === "sm"
? "px-2.5 py-1.5 text-sm"
: size === "md"
? "px-3 py-2 text-base"
: "px-4 py-3 text-lg"
} ${disabled ? "bg-gray-400 cursor-not-allowed" : "bg-theme"} ${className || ""} ${
loading ? "cursor-wait" : ""
}`}
onClick={onClick}
disabled={disabled || loading}
>
<div className="flex items-center">{children}</div>
</button>
);
};

View File

@ -0,0 +1,36 @@
// types
import { ButtonProps } from "./type";
export const DangerButton: React.FC<ButtonProps> = ({
children,
className = "",
onClick,
type = "button",
disabled = false,
loading = false,
size = "sm",
outline = false,
}) => (
<button
type={type}
className={`${className} border border-red-500 font-medium duration-300 ${
size === "sm"
? "rounded px-3 py-2 text-xs"
: size === "md"
? "rounded-md px-3.5 py-2 text-sm"
: "rounded-lg px-4 py-2 text-base"
} ${
disabled
? "cursor-not-allowed border-gray-300 bg-gray-300 text-black hover:border-gray-300 hover:border-opacity-100 hover:bg-gray-300 hover:bg-opacity-100 hover:text-black"
: ""
} ${
outline
? "bg-transparent hover:bg-red-500 hover:text-white"
: "bg-red-500 text-white hover:border-opacity-90 hover:bg-opacity-90"
} ${loading ? "cursor-wait" : ""}`}
onClick={onClick}
disabled={disabled || loading}
>
{children}
</button>
);

View File

@ -0,0 +1,3 @@
export * from "./danger-button";
export * from "./primary-button";
export * from "./secondary-button";

View File

@ -0,0 +1,36 @@
// types
import { ButtonProps } from "./type";
export const PrimaryButton: React.FC<ButtonProps> = ({
children,
className = "",
onClick,
type = "button",
disabled = false,
loading = false,
size = "sm",
outline = false,
}) => (
<button
type={type}
className={`${className} border border-theme font-medium duration-300 ${
size === "sm"
? "rounded px-3 py-2 text-xs"
: size === "md"
? "rounded-md px-3.5 py-2 text-sm"
: "rounded-lg px-4 py-2 text-base"
} ${
disabled
? "cursor-not-allowed border-gray-300 bg-gray-300 text-black hover:border-gray-300 hover:border-opacity-100 hover:bg-gray-300 hover:bg-opacity-100 hover:text-black"
: ""
} ${
outline
? "bg-transparent hover:bg-theme hover:text-white"
: "bg-theme text-white hover:border-opacity-90 hover:bg-opacity-90"
} ${loading ? "cursor-wait" : ""}`}
onClick={onClick}
disabled={disabled || loading}
>
{children}
</button>
);

View File

@ -0,0 +1,36 @@
// types
import { ButtonProps } from "./type";
export const SecondaryButton: React.FC<ButtonProps> = ({
children,
className = "",
onClick,
type = "button",
disabled = false,
loading = false,
size = "sm",
outline = false,
}) => (
<button
type={type}
className={`${className} border border-gray-300 font-medium duration-300 ${
size === "sm"
? "rounded px-3 py-2 text-xs"
: size === "md"
? "rounded-md px-3.5 py-2 text-sm"
: "rounded-lg px-4 py-2 text-base"
} ${
disabled
? "cursor-not-allowed border-gray-300 bg-gray-300 hover:border-gray-300 hover:border-opacity-100 hover:bg-gray-300 hover:bg-opacity-100"
: ""
} ${
outline
? "bg-transparent hover:bg-gray-300"
: "bg-gray-300 hover:border-opacity-90 hover:bg-opacity-90"
} ${loading ? "cursor-wait" : ""}`}
onClick={onClick}
disabled={disabled || loading}
>
{children}
</button>
);

View File

@ -0,0 +1,10 @@
export type ButtonProps = {
children: React.ReactNode;
className?: string;
onClick?: () => void;
type?: "button" | "submit" | "reset";
disabled?: boolean;
loading?: boolean;
size?: "sm" | "md" | "lg";
outline?: boolean;
};

View File

@ -1,7 +1,7 @@
export * from "./buttons";
export * from "./input"; export * from "./input";
export * from "./text-area"; export * from "./text-area";
export * from "./avatar"; export * from "./avatar";
export * from "./button";
export * from "./context-menu"; export * from "./context-menu";
export * from "./custom-menu"; export * from "./custom-menu";
export * from "./custom-search-select"; export * from "./custom-search-select";

View File

@ -11,7 +11,7 @@ import viewsService from "services/views.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button } from "components/ui"; import { DangerButton, SecondaryButton } from "components/ui";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// types // types
@ -34,8 +34,6 @@ export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, onClose, onSucc
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const cancelButtonRef = useRef(null);
const handleClose = () => { const handleClose = () => {
setIsDeleteLoading(false); setIsDeleteLoading(false);
onClose(); onClose();
@ -74,12 +72,7 @@ export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, onClose, onSucc
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog <Dialog as="div" className="relative z-20" onClose={handleClose}>
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -127,25 +120,11 @@ export const DeleteViewModal: React.FC<Props> = ({ isOpen, data, onClose, onSucc
</div> </div>
</div> </div>
</div> </div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6"> <div className="flex justify-end gap-2 bg-gray-50 p-4 sm:px-6">
<Button <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
type="button" <DangerButton onClick={handleDeletion} loading={isDeleteLoading}>
onClick={handleDeletion}
theme="danger"
disabled={isDeleteLoading}
className="inline-flex sm:ml-3"
>
{isDeleteLoading ? "Deleting..." : "Delete"} {isDeleteLoading ? "Deleting..." : "Delete"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="inline-flex sm:ml-3"
onClick={handleClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -3,7 +3,7 @@ import { useEffect } from "react";
// react-hook-form // react-hook-form
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
// ui // ui
import { Button, Input, TextArea } from "components/ui"; import { Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
// types // types
import { IView } from "types"; import { IView } from "types";
@ -97,10 +97,8 @@ export const ViewForm: React.FC<Props> = ({
</div> </div>
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton type="submit" loading={isSubmitting}>
</Button>
<Button type="submit" disabled={isSubmitting}>
{status {status
? isSubmitting ? isSubmitting
? "Updating View..." ? "Updating View..."
@ -108,7 +106,7 @@ export const ViewForm: React.FC<Props> = ({
: isSubmitting : isSubmitting
? "Creating View..." ? "Creating View..."
: "Create View"} : "Create View"}
</Button> </PrimaryButton>
</div> </div>
</form> </form>
); );

View File

@ -1,10 +1,10 @@
import React, { useRef, useState } from "react"; import React, { useState } from "react";
// headless ui // headless ui
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// ui // ui
import { Button } from "components/ui"; import { DangerButton, SecondaryButton } from "components/ui";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
@ -16,8 +16,6 @@ type Props = {
const ConfirmWorkspaceMemberRemove: React.FC<Props> = ({ isOpen, onClose, data, handleDelete }) => { const ConfirmWorkspaceMemberRemove: React.FC<Props> = ({ isOpen, onClose, data, handleDelete }) => {
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const cancelButtonRef = useRef(null);
const handleClose = () => { const handleClose = () => {
onClose(); onClose();
setIsDeleteLoading(false); setIsDeleteLoading(false);
@ -31,12 +29,7 @@ const ConfirmWorkspaceMemberRemove: React.FC<Props> = ({ isOpen, onClose, data,
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog <Dialog as="div" className="relative z-20" onClose={handleClose}>
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -84,25 +77,11 @@ const ConfirmWorkspaceMemberRemove: React.FC<Props> = ({ isOpen, onClose, data,
</div> </div>
</div> </div>
</div> </div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6"> <div className="flex justify-end gap-2 bg-gray-50 p-4 sm:px-6">
<Button <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
type="button" <DangerButton onClick={handleDeletion} loading={isDeleteLoading}>
onClick={handleDeletion}
theme="danger"
disabled={isDeleteLoading}
className="inline-flex sm:ml-3"
>
{isDeleteLoading ? "Removing..." : "Remove"} {isDeleteLoading ? "Removing..." : "Remove"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="inline-flex sm:ml-3"
onClick={handleClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@ -13,7 +13,7 @@ import useToast from "hooks/use-toast";
// icons // icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// ui // ui
import { Button, Input } from "components/ui"; import { DangerButton, Input, SecondaryButton } from "components/ui";
// types // types
import type { IWorkspace } from "types"; import type { IWorkspace } from "types";
// fetch-keys // fetch-keys
@ -26,7 +26,6 @@ type Props = {
}; };
export const DeleteWorkspaceModal: React.FC<Props> = ({ isOpen, data, onClose }) => { export const DeleteWorkspaceModal: React.FC<Props> = ({ isOpen, data, onClose }) => {
const cancelButtonRef = useRef(null);
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const [confirmProjectName, setConfirmProjectName] = useState(""); const [confirmProjectName, setConfirmProjectName] = useState("");
const [confirmDeleteMyProject, setConfirmDeleteMyProject] = useState(false); const [confirmDeleteMyProject, setConfirmDeleteMyProject] = useState(false);
@ -77,12 +76,7 @@ export const DeleteWorkspaceModal: React.FC<Props> = ({ isOpen, data, onClose })
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog <Dialog as="div" className="relative z-20" onClose={handleClose}>
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
<Transition.Child <Transition.Child
as={React.Fragment} as={React.Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -166,25 +160,11 @@ export const DeleteWorkspaceModal: React.FC<Props> = ({ isOpen, data, onClose })
</div> </div>
</div> </div>
</div> </div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6"> <div className="flex justify-end gap-2 bg-gray-50 p-4 sm:px-6">
<Button <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
type="button" <DangerButton onClick={handleDeletion} loading={isDeleteLoading || !canDelete}>
onClick={handleDeletion}
theme="danger"
disabled={isDeleteLoading || !canDelete}
className="inline-flex sm:ml-3"
>
{isDeleteLoading ? "Deleting..." : "Delete"} {isDeleteLoading ? "Deleting..." : "Delete"}
</Button> </DangerButton>
<Button
type="button"
theme="secondary"
className="inline-flex sm:ml-3"
onClick={handleClose}
ref={cancelButtonRef}
>
Cancel
</Button>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</Transition.Child> </Transition.Child>

View File

@ -6,7 +6,7 @@ import { Dialog, Transition } from "@headlessui/react";
// services // services
import workspaceService from "services/workspace.service"; import workspaceService from "services/workspace.service";
// ui // ui
import { Button, CustomSelect, Input } from "components/ui"; import { CustomSelect, Input, PrimaryButton, SecondaryButton } from "components/ui";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// types // types
@ -153,12 +153,10 @@ const SendWorkspaceInvitationModal: React.FC<Props> = ({
</div> </div>
</div> </div>
<div className="mt-5 flex justify-end gap-2"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={handleClose}> <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
Cancel <PrimaryButton type="submit" loading={isSubmitting}>
</Button>
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Sending Invitation..." : "Send Invitation"} {isSubmitting ? "Sending Invitation..." : "Send Invitation"}
</Button> </PrimaryButton>
</div> </div>
</form> </form>
</Dialog.Panel> </Dialog.Panel>

View File

@ -1,5 +1,3 @@
// ui
import { Button } from "components/ui";
// icons // icons
import { Bars3Icon } from "@heroicons/react/24/outline"; import { Bars3Icon } from "@heroicons/react/24/outline";
@ -14,14 +12,13 @@ const Header: React.FC<Props> = ({ breadcrumbs, left, right, setToggleSidebar })
<div className="flex w-full flex-row items-center justify-between gap-y-4 border-b bg-white px-5 py-4 "> <div className="flex w-full flex-row items-center justify-between gap-y-4 border-b bg-white px-5 py-4 ">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="block md:hidden"> <div className="block md:hidden">
<Button <button
type="button" type="button"
theme="secondary" className="grid h-8 w-8 place-items-center rounded border border-gray-300"
className="h-8 w-8"
onClick={() => setToggleSidebar((prevData) => !prevData)} onClick={() => setToggleSidebar((prevData) => !prevData)}
> >
<Bars3Icon className="h-5 w-5" /> <Bars3Icon className="h-5 w-5" />
</Button> </button>
</div> </div>
{breadcrumbs} {breadcrumbs}
{left} {left}

View File

@ -10,7 +10,7 @@ import projectService from "services/project.service";
// hooks // hooks
import useUser from "hooks/use-user"; import useUser from "hooks/use-user";
// ui // ui
import { Button, Spinner } from "components/ui"; import { SecondaryButton, Spinner } from "components/ui";
// components // components
import { NotAuthorizedView } from "components/core"; import { NotAuthorizedView } from "components/core";
import { CommandPalette } from "components/command-palette"; import { CommandPalette } from "components/command-palette";
@ -103,17 +103,13 @@ const AppLayout: FC<AppLayoutProps> = ({
actionButton={ actionButton={
(memberType?.isViewer || memberType?.isGuest) && projectId ? ( (memberType?.isViewer || memberType?.isGuest) && projectId ? (
<Link href={`/${workspaceSlug}/projects/${projectId}/issues`}> <Link href={`/${workspaceSlug}/projects/${projectId}/issues`}>
<Button size="sm" theme="secondary"> <SecondaryButton>Go to Issues</SecondaryButton>
Go to Issues
</Button>
</Link> </Link>
) : ( ) : (
(memberType?.isViewer || memberType?.isGuest) && (memberType?.isViewer || memberType?.isGuest) &&
workspaceSlug && ( workspaceSlug && (
<Link href={`/${workspaceSlug}`}> <Link href={`/${workspaceSlug}`}>
<Button size="sm" theme="secondary"> <SecondaryButton>Go to workspace</SecondaryButton>
Go to workspace
</Button>
</Link> </Link>
) )
) )

View File

@ -6,7 +6,7 @@ import Image from "next/image";
// layouts // layouts
import DefaultLayout from "layouts/default-layout"; import DefaultLayout from "layouts/default-layout";
// ui // ui
import { Button } from "components/ui"; import { SecondaryButton } from "components/ui";
// images // images
import Image404 from "public/404.svg"; import Image404 from "public/404.svg";
// types // types
@ -33,9 +33,7 @@ const PageNotFound: NextPage = () => (
</div> </div>
<Link href="/"> <Link href="/">
<a className="block"> <a className="block">
<Button type="button" largePadding> <SecondaryButton size="md">Go to Home</SecondaryButton>
Go to Home
</Button>
</a> </a>
</Link> </Link>
</div> </div>

View File

@ -18,7 +18,7 @@ import AppLayout from "layouts/app-layout";
// components // components
import { ImageUploadModal } from "components/core"; import { ImageUploadModal } from "components/core";
// ui // ui
import { Button, Input, Spinner } from "components/ui"; import { DangerButton, Input, SecondaryButton, Spinner } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// icons // icons
import { import {
@ -205,24 +205,17 @@ const Profile: NextPage = () => {
<br /> <br />
Supported file types are .jpg and .png. Supported file types are .jpg and .png.
</p> </p>
<div className="flex items-center gap-2"> <div className="mt-4 flex items-center gap-2">
<Button <SecondaryButton onClick={() => setIsImageUploadModalOpen(true)}>
type="button"
className="mt-4"
onClick={() => setIsImageUploadModalOpen(true)}
>
Upload new Upload new
</Button> </SecondaryButton>
{myProfile.avatar && myProfile.avatar !== "" && ( {myProfile.avatar && myProfile.avatar !== "" && (
<Button <DangerButton
type="button"
className="mt-4"
theme="danger"
onClick={() => handleDelete(myProfile.avatar, true)} onClick={() => handleDelete(myProfile.avatar, true)}
disabled={isRemoving} loading={isRemoving}
> >
{isRemoving ? "Removing..." : "Remove"} {isRemoving ? "Removing..." : "Remove"}
</Button> </DangerButton>
)} )}
</div> </div>
</div> </div>
@ -269,9 +262,9 @@ const Profile: NextPage = () => {
</div> </div>
{isEditing && ( {isEditing && (
<div> <div>
<Button type="submit" disabled={isSubmitting}> <SecondaryButton type="submit" loading={isSubmitting}>
{isSubmitting ? "Updating Profile..." : "Update Profile"} {isSubmitting ? "Updating Profile..." : "Update Profile"}
</Button> </SecondaryButton>
</div> </div>
)} )}
</form> </form>

View File

@ -16,7 +16,7 @@ import workspaceService from "services/workspace.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button, CustomSelect, Loader } from "components/ui"; import { CustomSelect, Loader, SecondaryButton } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// types // types
import { IProject, IWorkspace } from "types"; import { IProject, IWorkspace } from "types";
@ -239,9 +239,9 @@ const ControlSettings: NextPage<TControlSettingsProps> = (props) => {
</div> </div>
</div> </div>
<div className="sm:text-right"> <div className="sm:text-right">
<Button type="submit" disabled={isSubmitting}> <SecondaryButton type="submit" loading={isSubmitting}>
{isSubmitting ? "Updating Project..." : "Update Project"} {isSubmitting ? "Updating Project..." : "Update Project"}
</Button> </SecondaryButton>
</div> </div>
</div> </div>
</form> </form>

View File

@ -13,14 +13,15 @@ import AppLayout from "layouts/app-layout";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button } from "components/ui"; import { SecondaryButton } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// icons
import { ContrastIcon, PeopleGroupIcon, ViewListIcon } from "components/icons";
// types // types
import { IProject, UserAuth } from "types"; import { IProject, UserAuth } from "types";
import type { NextPage, GetServerSidePropsContext } from "next"; import type { NextPage, GetServerSidePropsContext } from "next";
// fetch-keys // fetch-keys
import { PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys"; import { PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys";
import { ContrastIcon, PeopleGroupIcon, ViewListIcon } from "components/icons";
const FeaturesSettings: NextPage<UserAuth> = (props) => { const FeaturesSettings: NextPage<UserAuth> = (props) => {
const router = useRouter(); const router = useRouter();
@ -183,14 +184,10 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<a href="https://plane.so/" target="_blank" rel="noreferrer"> <a href="https://plane.so/" target="_blank" rel="noreferrer">
<Button theme="secondary" size="rg" className="text-xs"> <SecondaryButton outline>Plane is open-source, view Roadmap</SecondaryButton>
Plane is open-source, view Roadmap
</Button>
</a> </a>
<a href="https://github.com/makeplane/plane" target="_blank" rel="noreferrer"> <a href="https://github.com/makeplane/plane" target="_blank" rel="noreferrer">
<Button theme="secondary" size="rg" className="text-xs"> <SecondaryButton outline>Star us on GitHub</SecondaryButton>
Star us on GitHub
</Button>
</a> </a>
</div> </div>
</section> </section>

View File

@ -20,7 +20,14 @@ import EmojiIconPicker from "components/emoji-icon-picker";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// ui // ui
import { Button, Input, TextArea, Loader, CustomSelect, OutlineButton } from "components/ui"; import {
Input,
TextArea,
Loader,
CustomSelect,
OutlineButton,
SecondaryButton,
} from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// helpers // helpers
import { debounce } from "helpers/common.helper"; import { debounce } from "helpers/common.helper";
@ -30,7 +37,6 @@ import type { NextPage, GetServerSidePropsContext } from "next";
import { PROJECTS_LIST, PROJECT_DETAILS, WORKSPACE_DETAILS } from "constants/fetch-keys"; import { PROJECTS_LIST, PROJECT_DETAILS, WORKSPACE_DETAILS } from "constants/fetch-keys";
// constants // constants
import { NETWORK_CHOICES } from "constants/project"; import { NETWORK_CHOICES } from "constants/project";
import SettingsNavbar from "layouts/settings-navbar";
const defaultValues: Partial<IProject> = { const defaultValues: Partial<IProject> = {
name: "", name: "",
@ -288,9 +294,9 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
</div> </div>
<div className="sm:text-right"> <div className="sm:text-right">
{projectDetails ? ( {projectDetails ? (
<Button type="submit" disabled={isSubmitting}> <SecondaryButton type="submit" loading={isSubmitting}>
{isSubmitting ? "Updating Project..." : "Update Project"} {isSubmitting ? "Updating Project..." : "Update Project"}
</Button> </SecondaryButton>
) : ( ) : (
<Loader className="mt-2 w-full"> <Loader className="mt-2 w-full">
<Loader.Item height="34px" width="100px" light /> <Loader.Item height="34px" width="100px" light />

View File

@ -19,7 +19,7 @@ import {
SingleLabelGroup, SingleLabelGroup,
} from "components/labels"; } from "components/labels";
// ui // ui
import { Loader } from "components/ui"; import { Loader, PrimaryButton } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// icons // icons
import { PlusIcon } from "@heroicons/react/24/outline"; import { PlusIcon } from "@heroicons/react/24/outline";
@ -28,7 +28,6 @@ import { IIssueLabels, UserAuth } from "types";
import type { GetServerSidePropsContext, NextPage } from "next"; import type { GetServerSidePropsContext, NextPage } from "next";
// fetch-keys // fetch-keys
import { PROJECT_DETAILS, PROJECT_ISSUE_LABELS } from "constants/fetch-keys"; import { PROJECT_DETAILS, PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
import { PrimaryButton } from "components/ui/button/primary-button";
const LabelsSettings: NextPage<UserAuth> = (props) => { const LabelsSettings: NextPage<UserAuth> = (props) => {
const { isMember, isOwner, isViewer, isGuest } = props; const { isMember, isOwner, isViewer, isGuest } = props;

View File

@ -11,7 +11,7 @@ import workspaceService from "services/workspace.service";
// layouts // layouts
import AppLayout from "layouts/app-layout"; import AppLayout from "layouts/app-layout";
// ui // ui
import { Button } from "components/ui"; import { SecondaryButton } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// types // types
import type { NextPage, GetServerSideProps } from "next"; import type { NextPage, GetServerSideProps } from "next";
@ -66,9 +66,7 @@ const BillingSettings: NextPage<TBillingSettingsProps> = (props) => {
<h4 className="text-md mb-1 leading-6 text-gray-900">Current plan</h4> <h4 className="text-md mb-1 leading-6 text-gray-900">Current plan</h4>
<p className="mb-3 text-sm text-gray-500">You are currently using the free plan</p> <p className="mb-3 text-sm text-gray-500">You are currently using the free plan</p>
<a href="https://plane.so/pricing" target="_blank" rel="noreferrer"> <a href="https://plane.so/pricing" target="_blank" rel="noreferrer">
<Button theme="secondary" size="rg" className="text-xs"> <SecondaryButton outline>View Plans and Upgrade</SecondaryButton>
View Plans and Upgrade
</Button>
</a> </a>
</div> </div>
<div> <div>

View File

@ -23,7 +23,7 @@ import AppLayout from "layouts/app-layout";
import { ImageUploadModal } from "components/core"; import { ImageUploadModal } from "components/core";
import { DeleteWorkspaceModal } from "components/workspace"; import { DeleteWorkspaceModal } from "components/workspace";
// ui // ui
import { Spinner, Button, Input, CustomSelect, OutlineButton } from "components/ui"; import { Spinner, Input, CustomSelect, OutlineButton, SecondaryButton } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// helpers // helpers
import { copyTextToClipboard } from "helpers/string.helper"; import { copyTextToClipboard } from "helpers/string.helper";
@ -168,13 +168,13 @@ const WorkspaceSettings: NextPage<UserAuth> = (props) => {
)} )}
</button> </button>
<div> <div>
<Button <SecondaryButton
onClick={() => { onClick={() => {
setIsImageUploadModalOpen(true); setIsImageUploadModalOpen(true);
}} }}
> >
{isImageUploading ? "Uploading..." : "Upload"} {isImageUploading ? "Uploading..." : "Upload"}
</Button> </SecondaryButton>
</div> </div>
</div> </div>
</div> </div>
@ -195,9 +195,7 @@ const WorkspaceSettings: NextPage<UserAuth> = (props) => {
value={`app.plane.so/${activeWorkspace.slug}`} value={`app.plane.so/${activeWorkspace.slug}`}
disabled disabled
/> />
<Button <SecondaryButton
type="button"
theme="secondary"
className="h-min" className="h-min"
onClick={() => onClick={() =>
copyTextToClipboard(`https://app.plane.so/${activeWorkspace.slug}`).then(() => { copyTextToClipboard(`https://app.plane.so/${activeWorkspace.slug}`).then(() => {
@ -208,9 +206,10 @@ const WorkspaceSettings: NextPage<UserAuth> = (props) => {
}); });
}) })
} }
outline
> >
<LinkIcon className="h-[18px] w-[18px]" /> <LinkIcon className="h-[18px] w-[18px]" />
</Button> </SecondaryButton>
</div> </div>
</div> </div>
<div className="grid grid-cols-12 gap-4 sm:gap-16"> <div className="grid grid-cols-12 gap-4 sm:gap-16">
@ -259,9 +258,9 @@ const WorkspaceSettings: NextPage<UserAuth> = (props) => {
</div> </div>
</div> </div>
<div className="sm:text-right"> <div className="sm:text-right">
<Button onClick={handleSubmit(onSubmit)} disabled={isSubmitting}> <SecondaryButton onClick={handleSubmit(onSubmit)} loading={isSubmitting}>
{isSubmitting ? "Updating..." : "Update Workspace"} {isSubmitting ? "Updating..." : "Update Workspace"}
</Button> </SecondaryButton>
</div> </div>
<div className="grid grid-cols-12 gap-4 sm:gap-16"> <div className="grid grid-cols-12 gap-4 sm:gap-16">
<div className="col-span-12 sm:col-span-6"> <div className="col-span-12 sm:col-span-6">

View File

@ -15,7 +15,7 @@ import DefaultLayout from "layouts/default-layout";
// components // components
import SingleInvitation from "components/workspace/single-invitation"; import SingleInvitation from "components/workspace/single-invitation";
// ui // ui
import { Button, Spinner, EmptySpace, EmptySpaceItem } from "components/ui"; import { Spinner, EmptySpace, EmptySpaceItem, SecondaryButton, PrimaryButton } from "components/ui";
// icons // icons
import { CubeIcon, PlusIcon } from "@heroicons/react/24/outline"; import { CubeIcon, PlusIcon } from "@heroicons/react/24/outline";
// types // types
@ -112,14 +112,12 @@ const OnBoard: NextPage = () => {
<div className="mt-6 flex items-center gap-2"> <div className="mt-6 flex items-center gap-2">
<Link href="/"> <Link href="/">
<a className="w-full"> <a className="w-full">
<Button className="w-full" theme="secondary"> <SecondaryButton className="w-full">Go to Home</SecondaryButton>
Go to Home
</Button>
</a> </a>
</Link> </Link>
<Button className="w-full" onClick={submitInvitations}> <PrimaryButton className="w-full" onClick={submitInvitations}>
Accept and Continue Accept and Continue
</Button> </PrimaryButton>
</div> </div>
</div> </div>
) : workspaces && workspaces.length > 0 ? ( ) : workspaces && workspaces.length > 0 ? (