Consolidate forms & other minor fixes

This commit is contained in:
Sacha Weatherstone
2022-03-04 19:19:36 +11:00
parent 4dc39623dc
commit ea5ab9376f
42 changed files with 1426 additions and 1160 deletions
+24 -33
View File
@@ -1,7 +1,6 @@
import type React from 'react';
import { m } from 'framer-motion';
import Draggable from 'react-draggable';
export interface CardProps {
className?: string;
@@ -9,49 +8,41 @@ export interface CardProps {
actions?: React.ReactNode;
children: React.ReactNode;
border?: boolean;
draggable?: boolean;
}
export const Card = ({
className,
title,
actions,
draggable,
border,
children,
}: CardProps): JSX.Element => {
return (
<Draggable handle=".handle" disabled={!draggable}>
<div
className={`flex h-full w-full flex-col rounded-md drop-shadow-md ${
border ? 'border border-gray-400 dark:border-gray-600' : ''
} ${className ?? ''}`}
>
{(title || actions) && (
<div
className={`w-full select-none justify-between rounded-t-md border-b border-gray-400 bg-gray-200 p-2 px-2 text-lg font-medium dark:border-gray-600 dark:bg-tertiaryDark dark:text-white ${
draggable ? 'cursor-move' : ''
}`}
>
<div className="handle flex h-8 justify-between">
<div className="my-auto ml-2 truncate">{title}</div>
{actions}
</div>
<div
className={`flex h-full w-full flex-col rounded-md drop-shadow-md ${
border ? 'border border-gray-400 dark:border-gray-600' : ''
} ${className ?? ''}`}
>
{(title || actions) && (
<div className="w-full select-none justify-between rounded-t-md border-b border-gray-400 bg-gray-200 p-2 px-2 text-lg font-medium dark:border-gray-600 dark:bg-tertiaryDark dark:text-white">
<div className="handle flex h-8 justify-between">
<div className="my-auto ml-2 truncate">{title}</div>
{actions}
</div>
)}
</div>
)}
<m.div
className={`flex flex-grow select-none flex-col gap-4 bg-white p-4 dark:bg-primaryDark ${
title || actions ? 'rounded-b-md' : 'rounded-md'
}`}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.1 }}
>
{children}
</m.div>
</div>
</Draggable>
<m.div
className={`flex flex-grow select-none flex-col gap-4 bg-white p-4 dark:bg-primaryDark ${
title || actions ? 'rounded-b-md' : 'rounded-md'
}`}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.1 }}
>
{children}
</m.div>
</div>
);
};
+2 -4
View File
@@ -3,11 +3,10 @@ import type React from 'react';
import { AnimatePresence, m } from 'framer-motion';
import { FiX } from 'react-icons/fi';
import { IconButton } from '@components/generic/button/IconButton';
import { Card, CardProps } from '@components/generic/Card';
import { useAppSelector } from '@hooks/useAppSelector';
import { IconButton } from './button/IconButton';
import { Card, CardProps } from './Card';
export interface ModalProps extends CardProps {
open: boolean;
bgDismiss?: boolean;
@@ -51,7 +50,6 @@ export const Modal = ({
<div className="inline-block w-full max-w-3xl align-middle">
<Card
border
draggable
actions={
<div className="flex gap-2">
{actions}
@@ -7,12 +7,14 @@ import { FiArrowUp } from 'react-icons/fi';
export interface CollapsibleSectionProps {
title: string;
icon?: JSX.Element;
status?: boolean;
children: JSX.Element;
}
export const CollapsibleSection = ({
title,
icon,
status,
children,
}: CollapsibleSectionProps): JSX.Element => {
const [open, setOpen] = useState(false);
@@ -21,6 +23,7 @@ export const CollapsibleSection = ({
<m.div>
<m.div
layout
onClick={toggleOpen}
className={`w-full cursor-pointer select-none overflow-hidden border-l-4 border-b bg-gray-200 p-2 text-sm font-medium dark:border-primaryDark dark:bg-tertiaryDark dark:text-gray-400 ${
open
? 'border-l-primary dark:border-l-primary'
@@ -29,13 +32,25 @@ export const CollapsibleSection = ({
>
<m.div
layout
onClick={toggleOpen}
whileHover={{ scale: 1.01 }}
whileTap={{ scale: 0.99 }}
className="flex justify-between gap-2 "
className="my-auto flex justify-between gap-2"
>
<m.div className="flex gap-2 ">
<m.div className="my-auto">{icon}</m.div>
<m.div className="flex gap-2">
<m.div className="my-auto flex gap-2">
{status !== undefined ? (
<>
{icon}
<div
className={`h-3 w-3 rounded-full ${
status ? 'bg-green-500' : 'bg-red-500'
}`}
/>
</>
) : (
<>{icon}</>
)}
</m.div>
{title}
</m.div>
<m.div
+17 -3
View File
@@ -1,22 +1,36 @@
import type React from 'react';
import { FiSave } from 'react-icons/fi';
import { IconButton } from '@components/generic/button/IconButton';
import { Loading } from '@components/generic/Loading';
export interface FormProps {
loading?: boolean;
submit: () => Promise<void>;
loading: boolean;
dirty: boolean;
children: React.ReactNode;
}
export const Form = ({ loading, children }: FormProps): JSX.Element => {
export const Form = ({
submit,
loading,
dirty,
children,
}: FormProps): JSX.Element => {
return (
<form
onSubmit={(e): void => {
e.preventDefault();
}}
className="relative flex-grow gap-3 p-2"
>
{loading && <Loading />}
{children}
<div className="flex w-full bg-white dark:bg-secondaryDark">
<div className="ml-auto p-2">
<IconButton disabled={dirty} onClick={submit} icon={<FiSave />} />
</div>
</div>
</form>
);
};