feat: create formlayout and create collection form

This commit is contained in:
Sonny
2024-04-28 19:34:15 +02:00
committed by Sonny
parent 602813ec05
commit 97044907ee
13 changed files with 333 additions and 42 deletions

View File

@@ -0,0 +1,27 @@
import styled from '@emotion/styled';
const Button = styled.button(({ theme }) => ({
cursor: 'pointer',
width: '100%',
textTransform: 'uppercase',
fontSize: '14px',
color: theme.colors.white,
background: theme.colors.primary,
padding: '0.75em',
border: `1px solid ${theme.colors.primary}`,
borderRadius: theme.border.radius,
transition: theme.transition.delay,
'&:disabled': {
cursor: 'not-allowed',
opacity: '0.75',
},
'&:not(:disabled):hover': {
boxShadow: `${theme.colors.darkBlue} 0 0 3px 1px`,
background: theme.colors.darkBlue,
color: theme.colors.white,
},
}));
export default Button;

View File

@@ -0,0 +1,10 @@
import styled from '@emotion/styled';
const Form = styled.form({
width: '100%',
display: 'flex',
gap: '0.5em',
flexDirection: 'column',
});
export default Form;

View File

@@ -0,0 +1,25 @@
import styled from '@emotion/styled';
const FormField = styled('div', {
shouldForwardProp: (propName) => propName !== 'required',
})<{ required?: boolean }>(({ required, theme }) => ({
display: 'flex',
gap: '0.25em',
flexDirection: 'column',
'& label': {
position: 'relative',
userSelect: 'none',
width: 'fit-content',
},
'& label::after': {
position: 'absolute',
top: 0,
right: '-0.75em',
color: theme.colors.red,
content: (required ? '"*"' : '""') as any,
},
}));
export default FormField;

View File

@@ -0,0 +1,23 @@
import styled from '@emotion/styled';
const Input = styled.input(({ theme }) => ({
width: '100%',
color: theme.colors.font,
backgroundColor: theme.colors.white,
padding: '0.75em',
border: `1px solid ${theme.colors.lightestGrey}`,
borderBottom: `2px solid ${theme.colors.lightestGrey}`,
borderRadius: theme.border.radius,
transition: theme.transition.delay,
'&:focus': {
borderBottom: `2px solid ${theme.colors.primary}`,
},
'&::placeholder': {
fontStyle: 'italic',
color: theme.colors.lightestGrey,
},
}));
export default Input;

View File

@@ -0,0 +1,44 @@
import { ChangeEvent, InputHTMLAttributes, useState } from 'react';
import FormField from '~/components/common/form/_form_field';
import Input from '~/components/common/form/_input';
interface InputProps
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'> {
label: string;
name: string;
value?: string;
onChange?: (name: string, value: string) => void;
}
export default function TextBox({
name,
label,
value = '',
onChange,
required = false,
...props
}: InputProps): JSX.Element {
const [inputValue, setInputValue] = useState<string>(value);
function _onChange({ target }: ChangeEvent<HTMLInputElement>) {
setInputValue(target.value);
if (onChange) {
onChange(target.name, target.value);
}
}
return (
<FormField required={required}>
<label htmlFor={name} title={label}>
{label}
</label>
<Input
{...props}
name={name}
onChange={_onChange}
value={inputValue}
placeholder={props.placeholder ?? 'Type something...'}
/>
</FormField>
);
}