Merge pull request #193 from snowball-tools/main

storybook and project settings styling
This commit is contained in:
Vivian Phung 2024-05-21 07:50:36 -04:00 committed by GitHub
commit 8533c41c58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 591 additions and 160 deletions

View File

@ -19,7 +19,7 @@ const AddEnvironmentVariableRow = ({
isDeleteDisabled, isDeleteDisabled,
}: AddEnvironmentVariableRowProps) => { }: AddEnvironmentVariableRowProps) => {
return ( return (
<div className="flex py-4 self-stretch"> <div className="flex gap-2 py-1 self-stretch items-end">
<Input <Input
size="md" size="md"
{...register(`variables.${index}.key`, { {...register(`variables.${index}.key`, {
@ -34,16 +34,9 @@ const AddEnvironmentVariableRow = ({
required: 'Value field cannot be empty', required: 'Value field cannot be empty',
})} })}
/> />
<div className="self-end"> <Button size="md" iconOnly onClick={onDelete} disabled={isDeleteDisabled}>
<Button <TrashIcon />
size="md" </Button>
iconOnly
onClick={onDelete}
disabled={isDeleteDisabled}
>
<TrashIcon />
</Button>
</div>
</div> </div>
); );
}; };

View File

@ -1,20 +1,13 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { Project } from 'gql-client';
import { import { useGQLClient } from 'context/GQLClientContext';
Button,
Dialog,
DialogHeader,
DialogBody,
DialogFooter,
Input,
Typography,
} from '@snowballtools/material-tailwind-react-fork';
import { useGQLClient } from '../../../../context/GQLClientContext';
import { useToast } from 'components/shared/Toast'; import { useToast } from 'components/shared/Toast';
import { Modal } from 'components/shared/Modal';
import { Button } from 'components/shared/Button';
import { Input } from 'components/shared/Input';
import { Project } from 'gql-client';
interface DeleteProjectDialogProp { interface DeleteProjectDialogProp {
open: boolean; open: boolean;
@ -60,51 +53,36 @@ const DeleteProjectDialog = ({
}, [client, project, handleOpen]); }, [client, project, handleOpen]);
return ( return (
<Dialog open={open} handler={handleOpen}> <Modal open={open} onOpenChange={handleOpen}>
<DialogHeader className="flex justify-between"> <Modal.Content>
<div>Delete project?</div> <Modal.Header>Delete project?</Modal.Header>
<Button <form onSubmit={handleSubmit(deleteProjectHandler)}>
variant="outlined" <Modal.Body>
onClick={handleOpen} <Input
className="mr-1 rounded-3xl" label={
> "Deleting your project is irreversible. Enter your project's name " +
X project.name +
</Button> ' below to confirm you want to permanently delete it:'
</DialogHeader> }
<form onSubmit={handleSubmit(deleteProjectHandler)}> id="input"
<DialogBody className="flex flex-col gap-2"> {...register('projectName', {
<Typography variant="paragraph"> required: 'Project name is required',
Deleting your project is irreversible. Enter your projects validate: (value) => value === project.name,
name&nbsp; })}
<span className="bg-blue-100 text-blue-700">({project.name})</span> helperText="Deleting your project is irreversible."
&nbsp;below to confirm you want to permanently delete it: />
</Typography> </Modal.Body>
<Input <Modal.Footer className="flex justify-start">
id="input" <Button onClick={handleOpen} variant="tertiary">
{...register('projectName', { Cancel
required: 'Project name is required', </Button>
validate: (value) => value === project.name, <Button variant="danger" type="submit" disabled={!isValid}>
})} Yes, delete project
/> </Button>
<Typography variant="small" color="red"> </Modal.Footer>
^ Deleting your project is irreversible. </form>
</Typography> </Modal.Content>
</DialogBody> </Modal>
<DialogFooter className="flex justify-start">
<Button variant="outlined" onClick={handleOpen} className="mr-1">
Cancel
</Button>
<Button
variant="gradient"
color="red"
type="submit"
disabled={!isValid}
>
Yes, Delete project
</Button>
</DialogFooter>
</form>
</Dialog>
); );
}; };

View File

@ -1,16 +1,20 @@
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
import { EnvironmentVariable } from 'gql-client';
import {
IconButton,
Typography,
} from '@snowballtools/material-tailwind-react-fork';
import { useGQLClient } from 'context/GQLClientContext'; import { useGQLClient } from 'context/GQLClientContext';
import { DeleteVariableDialog } from 'components/projects/Dialog/DeleteVariableDialog'; import { DeleteVariableDialog } from 'components/projects/Dialog/DeleteVariableDialog';
import { Input } from 'components/shared/Input'; import { Input } from 'components/shared/Input';
import { Button } from 'components/shared/Button';
import {
CheckRoundFilledIcon,
CrossIcon,
EditBigIcon,
HideEyeOffIcon,
ShowEyeIcon,
TrashIcon,
} from 'components/shared/CustomIcon';
import { EnvironmentVariable } from 'gql-client';
import { useToast } from 'components/shared/Toast';
const ShowPasswordIcon = ({ const ShowPasswordIcon = ({
handler, handler,
@ -26,19 +30,24 @@ const ShowPasswordIcon = ({
}} }}
className="cursor-pointer" className="cursor-pointer"
> >
{isVisible ? '-' : '+'} {isVisible ? <ShowEyeIcon size={16} /> : <HideEyeOffIcon size={16} />}
</span> </span>
); );
}; };
export interface EditEnvironmentVariableRowProps {
variable: EnvironmentVariable;
onUpdate: () => Promise<void>;
isFirstVariable?: boolean;
}
const EditEnvironmentVariableRow = ({ const EditEnvironmentVariableRow = ({
variable, variable,
onUpdate, onUpdate,
}: { isFirstVariable = false,
variable: EnvironmentVariable; }: EditEnvironmentVariableRowProps) => {
onUpdate: () => Promise<void>;
}) => {
const client = useGQLClient(); const client = useGQLClient();
const { toast, dismiss } = useToast();
const { handleSubmit, register, reset } = useForm({ const { handleSubmit, register, reset } = useForm({
defaultValues: { defaultValues: {
@ -58,9 +67,19 @@ const EditEnvironmentVariableRow = ({
if (isEnvironmentVariableRemoved) { if (isEnvironmentVariableRemoved) {
await onUpdate(); await onUpdate();
setDeleteDialogOpen((preVal) => !preVal); setDeleteDialogOpen((preVal) => !preVal);
toast.success('Variable deleted'); toast({
id: 'variable_deleted',
title: 'Variable deleted',
variant: 'success',
onDismiss: dismiss,
});
} else { } else {
toast.error('Variable not deleted'); toast({
id: 'variable_not_deleted',
title: 'Variable not deleted',
variant: 'error',
onDismiss: dismiss,
});
} }
}, [variable, onUpdate]); }, [variable, onUpdate]);
@ -71,10 +90,21 @@ const EditEnvironmentVariableRow = ({
if (isEnvironmentVariableUpdated) { if (isEnvironmentVariableUpdated) {
await onUpdate(); await onUpdate();
toast.success('Variable edited'); toast({
id: 'variable_updated',
title: 'Variable edited',
variant: 'success',
onDismiss: dismiss,
});
setEdit((preVal) => !preVal); setEdit((preVal) => !preVal);
} else { } else {
toast.error('Variable not edited'); toast({
id: 'variable_not_updated',
title: 'Variable not edited',
variant: 'error',
onDismiss: dismiss,
});
} }
}, },
[variable, onUpdate], [variable, onUpdate],
@ -86,71 +116,55 @@ const EditEnvironmentVariableRow = ({
return ( return (
<> <>
<div className="flex gap-1 p-2"> <div className="flex gap-1 items-end">
<div> <Input
<Typography variant="small">Key</Typography> disabled={!edit}
<Input disabled={!edit} {...register(`key`)} /> {...register(`key`)}
</div> label={isFirstVariable ? 'Key' : undefined}
<div> />
<Typography variant="small">Value</Typography> <Input
<Input disabled={!edit}
disabled={!edit} type={showPassword || edit ? 'text' : 'password'}
type={showPassword ? 'text' : 'password'} label={isFirstVariable ? 'Value' : undefined}
leftIcon={ rightIcon={
<ShowPasswordIcon <ShowPasswordIcon
handler={() => { handler={() => {
setShowPassword((prevShowPassword) => !prevShowPassword); setShowPassword((prevShowPassword) => !prevShowPassword);
}} }}
isVisible={showPassword} isVisible={showPassword || edit}
/> />
}
{...register(`value`)}
/>
<Button
iconOnly
size="md"
onClick={() => {
edit
? handleSubmit(updateEnvironmentVariableHandler)()
: setEdit((preVal) => !preVal);
}}
>
{edit ? (
<CheckRoundFilledIcon size={16} />
) : (
<EditBigIcon size={16} />
)}
</Button>
<Button
iconOnly
size="md"
onClick={() => {
if (edit) {
reset();
setEdit((preVal) => !preVal);
} else {
setDeleteDialogOpen((preVal) => !preVal);
} }
{...register(`value`)} }}
/> >
</div> {edit ? <CrossIcon size={16} /> : <TrashIcon size={16} />}
{edit ? ( </Button>
<>
<div className="self-end">
<IconButton
onClick={handleSubmit(updateEnvironmentVariableHandler)}
size="sm"
>
{'S'}
</IconButton>
</div>
<div className="self-end">
<IconButton
size="sm"
onClick={() => {
reset();
setEdit((preVal) => !preVal);
}}
>
{'C'}
</IconButton>
</div>
</>
) : (
<>
<div className="self-end">
<IconButton
size="sm"
onClick={() => {
setEdit((preVal) => !preVal);
}}
>
{'E'}
</IconButton>
</div>
<div className="self-end">
<IconButton
size="sm"
onClick={() => setDeleteDialogOpen((preVal) => !preVal)}
>
{'D'}
</IconButton>
</div>
</>
)}
</div> </div>
<DeleteVariableDialog <DeleteVariableDialog
handleCancel={() => setDeleteDialogOpen((preVal) => !preVal)} handleCancel={() => setDeleteDialogOpen((preVal) => !preVal)}

View File

@ -80,7 +80,7 @@ const MemberCard = ({
return ( return (
<div <div
className={`flex p-1 items-center ${!isFirstCard && 'mt-1 border-t border-gray-300'}`} className={`flex py-1 items-center ${!isFirstCard && 'mt-1 border-t border-gray-300'}`}
> >
<div className="basis-1/2"> <div className="basis-1/2">
{member.name && ( {member.name && (

View File

@ -30,7 +30,7 @@ abbr[title] {
@apply !text-elements-disabled !bg-transparent; @apply !text-elements-disabled !bg-transparent;
} }
.react-calendar__month-view__days__day--neighboringMonth { .react-calendar__month-view__days__day--neighboringMonth:focus-visible {
@apply !text-elements-disabled !bg-transparent; @apply !text-elements-disabled !bg-transparent;
} }

View File

@ -0,0 +1,26 @@
import { CustomIcon, CustomIconProps } from './CustomIcon';
export const EditBigIcon: React.FC<CustomIconProps> = (props) => {
return (
<CustomIcon
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
{...props}
>
<g>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M4.61304 1.99935L7.5 1.99935C7.77614 1.99935 8 2.22321 8 2.49935C8 2.77549 7.77614 2.99935 7.5 2.99935H4.63333C4.25171 2.99935 3.99557 2.99974 3.79832 3.01585C3.6069 3.03149 3.51538 3.05941 3.45501 3.09018C3.29821 3.17007 3.17072 3.29755 3.09083 3.45436C3.06007 3.51473 3.03214 3.60625 3.01651 3.79767C3.00039 3.99492 3 4.25106 3 4.63268V11.366C3 11.7476 3.00039 12.0038 3.01651 12.201C3.03214 12.3924 3.06007 12.484 3.09083 12.5443C3.17072 12.7011 3.29821 12.8286 3.45501 12.9085C3.51538 12.9393 3.6069 12.9672 3.79832 12.9828C3.99557 12.999 4.25171 12.9993 4.63333 12.9993H11.3667C11.7483 12.9993 12.0044 12.999 12.2017 12.9828C12.3931 12.9672 12.4846 12.9393 12.545 12.9085C12.7018 12.8286 12.8293 12.7011 12.9092 12.5443C12.9399 12.484 12.9679 12.3924 12.9835 12.201C12.9996 12.0038 13 11.7476 13 11.366V8.49935C13 8.22321 13.2239 7.99935 13.5 7.99935C13.7761 7.99935 14 8.22321 14 8.49935V11.3863C14 11.7424 14 12.0396 13.9802 12.2825C13.9595 12.5357 13.9147 12.7735 13.8002 12.9983C13.6244 13.3433 13.3439 13.6238 12.999 13.7995C12.7741 13.9141 12.5364 13.9588 12.2831 13.9795C12.0403 13.9994 11.7431 13.9994 11.387 13.9993H4.61303C4.25693 13.9994 3.95971 13.9994 3.71689 13.9795C3.46363 13.9588 3.22586 13.9141 3.00102 13.7995C2.65605 13.6238 2.37559 13.3433 2.19982 12.9983C2.08526 12.7735 2.04052 12.5357 2.01983 12.2825C1.99999 12.0396 1.99999 11.7424 2 11.3863V4.61239C1.99999 4.25629 1.99999 3.95906 2.01983 3.71624C2.04052 3.46298 2.08526 3.22521 2.19982 3.00037C2.37559 2.6554 2.65605 2.37494 3.00102 2.19917C3.22586 2.08461 3.46363 2.03987 3.71689 2.01918C3.95971 1.99934 4.25694 1.99934 4.61304 1.99935Z"
fill="currentColor"
/>
<path
d="M13.963 1.92174C13.2471 1.20578 12.0863 1.20578 11.3703 1.92174L5.67504 7.617C5.45625 7.83579 5.33333 8.13254 5.33333 8.44196V10.1658C5.33333 10.442 5.55719 10.6658 5.83333 10.6658H7.55719C7.86661 10.6658 8.16336 10.5429 8.38215 10.3241L14.0774 4.62884C14.7934 3.91288 14.7934 2.75208 14.0774 2.03612L13.963 1.92174Z"
fill="currentColor"
/>
</g>
</CustomIcon>
);
};

View File

@ -0,0 +1,18 @@
import { CustomIcon, CustomIconProps } from './CustomIcon';
export const HideEyeOffIcon: React.FC<CustomIconProps> = (props) => {
return (
<CustomIcon
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
{...props}
>
<path
d="M2.02012 1.31246C1.82486 1.1172 1.50828 1.1172 1.31301 1.31246C1.11775 1.50772 1.11775 1.82431 1.31301 2.01957L2.02012 1.31246ZM1.62744 7.42685L1.1887 7.18704L1.62744 7.42685ZM11.7196 11.719L12.0731 11.3655L11.7196 11.719ZM13.9797 14.6862C14.1749 14.8815 14.4915 14.8815 14.6868 14.6862C14.8821 14.491 14.8821 14.1744 14.6868 13.9791L13.9797 14.6862ZM1.62804 8.57302L1.18932 8.81287H1.18932L1.62804 8.57302ZM5.2498 3.12216C4.99958 3.23898 4.89145 3.53652 5.00828 3.78674C5.1251 4.03695 5.42264 4.14508 5.67286 4.02826L5.2498 3.12216ZM14.3718 7.42567L14.8105 7.18582L14.3718 7.42567ZM12.3668 10.4904C12.1743 10.6884 12.1786 11.0049 12.3766 11.1975C12.5745 11.39 12.891 11.3857 13.0836 11.1877L12.3668 10.4904ZM14.3724 8.57183L13.9336 8.33203V8.33203L14.3724 8.57183ZM6.58569 6.58512L6.93924 6.23157C6.74398 6.03631 6.4274 6.03631 6.23213 6.23157L6.58569 6.58512ZM9.41411 9.41355L9.76767 9.7671C9.86144 9.67334 9.91411 9.54616 9.91411 9.41355C9.91411 9.28094 9.86144 9.15377 9.76767 9.06L9.41411 9.41355ZM1.31301 2.01957L3.92667 4.63323L4.63378 3.92612L2.02012 1.31246L1.31301 2.01957ZM2.06618 7.66665C2.78183 6.35732 3.64551 5.3672 4.57648 4.68246L3.98397 3.87689C2.91986 4.65956 1.96456 5.76756 1.1887 7.18704L2.06618 7.66665ZM3.92667 4.63323L11.366 12.0726L12.0731 11.3655L4.63378 3.92612L3.92667 4.63323ZM11.366 12.0726L13.9797 14.6862L14.6868 13.9791L12.0731 11.3655L11.366 12.0726ZM1.18932 8.81287C2.47954 11.1728 4.26886 12.674 6.21987 13.243C8.17733 13.8138 10.2399 13.428 12.0158 12.1218L11.4233 11.3162C9.88108 12.4506 8.13835 12.7608 6.49983 12.283C4.85485 11.8033 3.25748 10.5112 2.06675 8.33317L1.18932 8.81287ZM1.1887 7.18704C0.911724 7.69378 0.912792 8.30707 1.18932 8.81287L2.06675 8.33317C1.95313 8.12535 1.95308 7.87358 2.06618 7.66665L1.1887 7.18704ZM5.67286 4.02826C7.09829 3.36272 8.63166 3.32591 10.0669 3.91426C11.5069 4.50457 12.8795 5.7385 13.933 7.66553L14.8105 7.18582C13.6688 5.09759 12.1371 3.68216 10.4462 2.98899C8.75047 2.29385 6.92622 2.33943 5.2498 3.12216L5.67286 4.02826ZM13.0836 11.1877C13.7227 10.5308 14.305 9.7376 14.8111 8.81164L13.9336 8.33203C13.4669 9.18586 12.9371 9.90419 12.3668 10.4904L13.0836 11.1877ZM13.933 7.66553C14.0467 7.87336 14.0467 8.12511 13.9336 8.33203L14.8111 8.81164C15.0881 8.30489 15.087 7.69161 14.8105 7.18582L13.933 7.66553ZM7.9999 9.49934C7.17147 9.49934 6.4999 8.82776 6.4999 7.99934H5.4999C5.4999 9.38005 6.61919 10.4993 7.9999 10.4993V9.49934ZM6.4999 7.99934C6.4999 7.58499 6.66725 7.21067 6.93924 6.93868L6.23213 6.23157C5.78027 6.68343 5.4999 7.30912 5.4999 7.99934H6.4999ZM6.23213 6.93868L9.06056 9.7671L9.76767 9.06L6.93924 6.23157L6.23213 6.93868ZM9.06056 9.06C8.78857 9.33199 8.41425 9.49934 7.9999 9.49934V10.4993C8.69012 10.4993 9.3158 10.219 9.76767 9.7671L9.06056 9.06Z"
fill="currentColor"
/>
</CustomIcon>
);
};

View File

@ -0,0 +1,18 @@
import { CustomIcon, CustomIconProps } from './CustomIcon';
export const ShowEyeIcon: React.FC<CustomIconProps> = (props) => {
return (
<CustomIcon
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
{...props}
>
<path
d="M1.62774 7.42694L2.06646 7.66677L1.62774 7.42694ZM14.3721 7.42686L13.9333 7.66669V7.66669L14.3721 7.42686ZM1.62774 8.5731L2.06646 8.33327H2.06646L1.62774 8.5731ZM14.3721 8.57302L14.8108 8.81285L14.8108 8.81285L14.3721 8.57302ZM2.06646 7.66677C3.61474 4.83447 5.84609 3.50002 7.99991 3.5C10.1537 3.49998 12.3851 4.8344 13.9333 7.66669L14.8108 7.18703C13.1325 4.11679 10.6049 2.49998 7.9999 2.5C5.39486 2.50002 2.86735 4.11687 1.18901 7.18711L2.06646 7.66677ZM1.18901 8.81293C2.86735 11.8832 5.39486 13.5 7.99991 13.5C10.6049 13.4999 13.1325 11.8831 14.8108 8.81285L13.9333 8.33319C12.3851 11.1655 10.1537 12.4999 7.9999 12.5C5.84609 12.5 3.61473 11.1656 2.06646 8.33327L1.18901 8.81293ZM1.18901 7.18711C0.912257 7.69338 0.912257 8.30665 1.18901 8.81293L2.06646 8.33327C1.95311 8.1259 1.95311 7.87414 2.06646 7.66677L1.18901 7.18711ZM13.9333 7.66669C14.0467 7.87406 14.0467 8.12582 13.9333 8.33319L14.8108 8.81285C15.0875 8.30658 15.0875 7.69331 14.8108 7.18703L13.9333 7.66669ZM9.4999 8C9.4999 8.82843 8.82833 9.5 7.9999 9.5V10.5C9.38062 10.5 10.4999 9.38071 10.4999 8H9.4999ZM7.9999 9.5C7.17148 9.5 6.4999 8.82843 6.4999 8H5.4999C5.4999 9.38071 6.61919 10.5 7.9999 10.5V9.5ZM6.4999 8C6.4999 7.17157 7.17148 6.5 7.9999 6.5V5.5C6.61919 5.5 5.4999 6.61929 5.4999 8H6.4999ZM7.9999 6.5C8.82833 6.5 9.4999 7.17157 9.4999 8H10.4999C10.4999 6.61929 9.38062 5.5 7.9999 5.5V6.5Z"
fill="currentColor"
/>
</CustomIcon>
);
};

View File

@ -73,6 +73,9 @@ export * from './SwitchIcon';
export * from './CollaboratorsIcon'; export * from './CollaboratorsIcon';
export * from './ChevronUpSmallIcon'; export * from './ChevronUpSmallIcon';
export * from './ChevronDownSmallIcon'; export * from './ChevronDownSmallIcon';
export * from './EditBigIcon';
export * from './ShowEyeIcon';
export * from './HideEyeOffIcon';
// Templates // Templates
export * from './templates'; export * from './templates';

View File

@ -166,7 +166,7 @@ const GeneralTabPanel = () => {
setSelectedTransferOrganization(org.org); setSelectedTransferOrganization(org.org);
setOpenTransferDialog(!openTransferDialog); setOpenTransferDialog(!openTransferDialog);
})} })}
className="self-stretch space-y-3 px-2" className="self-stretch space-y-3"
> >
<Heading className="text-sky-950 text-lg font-medium leading-normal"> <Heading className="text-sky-950 text-lg font-medium leading-normal">
Transfer project Transfer project
@ -197,7 +197,7 @@ const GeneralTabPanel = () => {
from={project.organization.name} from={project.organization.name}
to={selectedUserOrgName} to={selectedUserOrgName}
/> />
<div className="self-stretch space-y-3 px-2"> <div className="self-stretch space-y-3">
<Heading className="text-sky-950 text-lg font-medium leading-normal"> <Heading className="text-sky-950 text-lg font-medium leading-normal">
Delete project Delete project
</Heading> </Heading>

View File

@ -0,0 +1,29 @@
import { Meta, StoryObj } from '@storybook/react';
import { EditBigIcon } from 'components/shared/CustomIcon';
const meta: Meta<typeof EditBigIcon> = {
title: 'Icons/EditBigIcon',
component: EditBigIcon,
tags: ['autodocs'],
argTypes: {
size: {
control: 'text',
},
name: {
control: 'text',
},
},
};
export default meta;
type Story = StoryObj<typeof EditBigIcon>;
export const Default: Story = {
render: ({ size, name }) => <EditBigIcon size={size} name={name} />,
args: {
size: '24px',
name: 'plus',
},
};

View File

@ -0,0 +1,29 @@
import { Meta, StoryObj } from '@storybook/react';
import { HideEyeOffIcon } from 'components/shared/CustomIcon';
const meta: Meta<typeof HideEyeOffIcon> = {
title: 'Icons/HideEyeOffIcon',
component: HideEyeOffIcon,
tags: ['autodocs'],
argTypes: {
size: {
control: 'text',
},
name: {
control: 'text',
},
},
};
export default meta;
type Story = StoryObj<typeof HideEyeOffIcon>;
export const Default: Story = {
render: ({ size, name }) => <HideEyeOffIcon size={size} name={name} />,
args: {
size: '24px',
name: 'plus',
},
};

View File

@ -0,0 +1,29 @@
import { Meta, StoryObj } from '@storybook/react';
import { ShowEyeIcon } from 'components/shared/CustomIcon';
const meta: Meta<typeof ShowEyeIcon> = {
title: 'Icons/ShowEyeIcon',
component: ShowEyeIcon,
tags: ['autodocs'],
argTypes: {
size: {
control: 'text',
},
name: {
control: 'text',
},
},
};
export default meta;
type Story = StoryObj<typeof ShowEyeIcon>;
export const Default: Story = {
render: ({ size, name }) => <ShowEyeIcon size={size} name={name} />,
args: {
size: '24px',
name: 'plus',
},
};

View File

@ -0,0 +1,114 @@
import {
User,
Project,
Organization,
Role,
OrganizationMember,
ProjectMember,
EnvironmentVariable,
Deployment,
DeploymentStatus,
DomainStatus,
Domain,
Environment,
} from 'gql-client';
export const user: User = {
id: '1',
email: 'helloworld@helloworld.com',
isVerified: true,
createdAt: '2021-08-01T00:00:00.000Z',
name: 'Hello World',
updatedAt: '2021-08-01T00:00:00.000Z',
gitHubToken: 'GitHub Token',
};
export const organizationMember: OrganizationMember = {
id: '1',
member: user,
role: Role.Owner,
createdAt: '2021-08-01T00:00:00.000Z',
updatedAt: '2021-08-01T00:00:00.000Z',
};
export const organization: Organization = {
id: '1',
name: 'Organization',
slug: 'organization',
createdAt: '2021-08-01T00:00:00.000Z',
updatedAt: '2021-08-01T00:00:00.000Z',
members: [organizationMember],
projects: [],
};
export const member: ProjectMember = {
id: '1',
member: user,
permissions: [],
isPending: false,
createdAt: '2021-08-01T00:00:00.000Z',
updatedAt: '2021-08-01T00:00:00.000Z',
};
export const environmentVariable0: EnvironmentVariable = {
id: '1',
key: 'API_KEY',
value: '123456',
environment: Environment.Development,
createdAt: '2021-08-01T00:00:00.000Z',
updatedAt: '2021-08-01T00:00:00.000Z',
};
export const environmentVariable1: EnvironmentVariable = {
id: '2',
key: 'API_KEY_2',
value: '123456',
environment: Environment.Development,
createdAt: '2021-08-01T00:00:00.000Z',
updatedAt: '2021-08-01T00:00:00.000Z',
};
export const domain0: Domain = {
id: '1',
name: 'Domain',
createdAt: '2021-08-01T00:00:00.000Z',
updatedAt: '2021-08-01T00:00:00.000Z',
branch: 'Branch',
status: DomainStatus.Live,
redirectTo: null,
};
export const deployment0: Deployment = {
id: '1',
url: 'https://deployment.com',
status: DeploymentStatus.Ready,
createdAt: '2021-08-01T00:00:00.000Z',
updatedAt: '2021-08-01T00:00:00.000Z',
branch: 'Branch',
environment: Environment.Development,
isCurrent: true,
commitHash: 'Commit Hash',
domain: domain0,
commitMessage: 'Commit Message',
createdBy: user,
};
export const project: Project = {
id: '1',
name: 'GithubUsername-ProjectName',
owner: user,
deployments: [deployment0],
repository: 'Repository',
prodBranch: 'Prod Branch',
description: 'Description',
createdAt: '2021-08-01T00:00:00.000Z',
updatedAt: '2021-08-01T00:00:00.000Z',
framework: 'NextJS',
environmentVariables: [environmentVariable0, environmentVariable1],
organization: organization,
template: 'Template',
members: [member],
webhooks: ['beepboop'],
icon: 'Icon',
subDomain: 'SubDomain',
};

View File

@ -21,10 +21,45 @@ const meta: Meta<typeof AddEnvironmentVariableRow> = {
}, },
}), }),
}, },
} as Meta<typeof AddEnvironmentVariableRow>; argTypes: {
onDelete: {
action: 'delete',
},
register: {
action: 'register',
},
index: {
type: 'number',
},
isDeleteDisabled: {
type: 'boolean',
},
},
args: {
isDeleteDisabled: false,
},
};
export default meta; export default meta;
type Story = StoryObj<typeof AddEnvironmentVariableRow>; type Story = StoryObj<typeof AddEnvironmentVariableRow>;
export const Default: Story = {}; export const Default: Story = {};
export const DisabledDelete: Story = {
args: {
isDeleteDisabled: true,
},
};
export const First: Story = {
args: {
index: 0,
},
};
export const Second: Story = {
args: {
index: 1,
},
};

View File

@ -0,0 +1,31 @@
import { Meta, StoryObj } from '@storybook/react';
import AddMemberDialog from 'components/projects/project/settings/AddMemberDialog';
const meta: Meta<typeof AddMemberDialog> = {
title: 'Project/Settings/AddMemberDialog',
component: AddMemberDialog,
tags: ['autodocs'],
argTypes: {
open: {
control: {
type: 'boolean',
},
},
handleOpen: {
action: 'open',
},
handleAddMember: {
action: 'addMember',
},
},
args: {
open: true,
},
};
export default meta;
type Story = StoryObj<typeof AddMemberDialog>;
export const Default: Story = {};

View File

@ -0,0 +1,50 @@
import { Meta, StoryObj } from '@storybook/react';
import {
reactRouterParameters,
withRouter,
} from 'storybook-addon-remix-react-router';
import DeleteProjectDialog from 'components/projects/project/settings/DeleteProjectDialog';
import { project } from '../../MockStoriesData';
const meta: Meta<typeof DeleteProjectDialog> = {
title: 'Project/Settings/DeleteProjectDialog',
component: DeleteProjectDialog,
tags: ['autodocs'],
decorators: [withRouter],
parameters: {
reactRouter: reactRouterParameters({
location: {
pathParams: { userId: 'me' },
},
routing: {
path: '/snowball-tools-1/projects/6bb3bec2-d71b-4fc0-9e32-4767f68668f4/settings',
},
}),
},
argTypes: {
open: {
control: {
type: 'boolean',
},
},
handleOpen: {
action: 'open',
},
project: {
control: {
type: 'object',
},
},
},
args: {
open: true,
project: project,
},
};
export default meta;
type Story = StoryObj<typeof DeleteProjectDialog>;
export const Default: Story = {};

View File

@ -0,0 +1,38 @@
import { Meta, StoryObj } from '@storybook/react';
import DisplayEnvironmentVariables from 'components/projects/project/settings/DisplayEnvironmentVariables';
import {
environmentVariable0,
environmentVariable1,
} from '../../MockStoriesData';
import { Environment } from 'gql-client';
const meta: Meta<typeof DisplayEnvironmentVariables> = {
title: 'Project/Settings/DisplayEnvironmentVariables',
component: DisplayEnvironmentVariables,
argTypes: {
environment: {
control: {
type: 'object',
},
},
variables: {
control: {
type: 'object',
},
},
onUpdate: {
action: 'update',
},
},
args: {
environment: Environment.Development,
variables: [environmentVariable0, environmentVariable1],
},
};
export default meta;
type Story = StoryObj<typeof DisplayEnvironmentVariables>;
export const Default: Story = {};

View File

@ -0,0 +1,28 @@
import { Meta, StoryObj } from '@storybook/react';
import EditEnvironmentVariableRow from 'components/projects/project/settings/EditEnvironmentVariableRow';
import { environmentVariable0 } from '../../MockStoriesData';
const meta: Meta<typeof EditEnvironmentVariableRow> = {
title: 'Project/Settings/EditEnvironmentVariableRow',
component: EditEnvironmentVariableRow,
argTypes: {
variable: {
control: {
type: 'object',
},
},
onUpdate: {
action: 'update',
},
},
args: {
variable: environmentVariable0,
},
};
export default meta;
type Story = StoryObj<typeof EditEnvironmentVariableRow>;
export const Default: Story = {};

View File

@ -17,7 +17,7 @@ const meta: Meta<typeof SetupDomain> = {
pathParams: { userId: 'me' }, pathParams: { userId: 'me' },
}, },
routing: { routing: {
path: '/snowball-tools-1/projects/6bb3bec2-d71b-4fc0-9e32-4767f68668f4/settings/domains/add', path: '/snowball-tools-1/projects/6bb3bec2-d71b-4fc0-9e32-4767f68668f4/settings/domains',
}, },
}), }),
}, },

View File

@ -14,9 +14,6 @@ export default withMT({
xxs: '400px', xxs: '400px',
xs: '480px', xs: '480px',
}, },
zIndex: {
tooltip: '52',
},
letterSpacing: { letterSpacing: {
tight: '-0.084px', tight: '-0.084px',
}, },
@ -178,6 +175,7 @@ export default withMT({
4.5: '1.125rem', 4.5: '1.125rem',
}, },
zIndex: { zIndex: {
tooltip: '52',
toast: '9999', toast: '9999',
}, },
animation: { animation: {

View File

@ -1,9 +1,9 @@
import { defineConfig } from 'vite'; import { defineConfig, PluginOption } from 'vite';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()] as PluginOption[],
resolve: { resolve: {
alias: { alias: {
utils: '/src/utils', utils: '/src/utils',