Commit c9a77057 authored by tom's avatar tom

add underlay for floating labels

parent 70bea3dd
......@@ -6,21 +6,89 @@ import type { Dict } from '@chakra-ui/utils';
import getDefaultFormColors from '../utils/getDefaultFormColors';
const activeInputStyles = {
paddingTop: '30px',
paddingBottom: '10px',
const getActiveLabelStyles = (theme: Dict, fc: string, bc: string, size: 'md' | 'lg') => {
const baseStyles = {
backgroundColor: bc,
color: getColor(theme, fc),
fontSize: 'xs',
lineHeight: '16px',
};
switch (size) {
case 'md': {
return {
...baseStyles,
padding: '10px 16px 2px 16px',
};
}
case 'lg': {
return {
...baseStyles,
padding: '16px 24px 2px 24px',
};
}
}
};
const getDefaultLabelStyles = (size: 'md' | 'lg') => {
switch (size) {
case 'md': {
return {
fontSize: 'md',
lineHeight: '20px',
padding: '18px 16px',
};
}
case 'lg': {
return {
fontSize: 'md',
lineHeight: '24px',
padding: '28px 24px',
};
}
}
};
const getPaddingX = (size: 'md' | 'lg') => {
switch (size) {
case 'md': {
return '16px';
}
case 'lg': {
return '24px';
}
}
};
const getActiveLabelStyles = (theme: Dict, fc: string) => ({
color: getColor(theme, fc),
transform: 'scale(0.75) translateY(-10px)',
});
const getActiveInputStyles = (size: 'md' | 'lg') => {
switch (size) {
case 'md': {
return {
paddingTop: '26px',
paddingBottom: '10px',
};
}
case 'lg': {
return {
paddingTop: '38px',
paddingBottom: '18px',
};
}
}
};
const variantFloating: PartsStyleFunction<typeof parts> = (props: StyleFunctionProps) => {
const { theme } = props;
const { theme, backgroundColor, size = 'md' } = props;
const { focusColor: fc, errorColor: ec } = getDefaultFormColors(props);
const bc = backgroundColor || mode('white', 'black')(props);
const activeLabelStyles = getActiveLabelStyles(theme, fc);
const px = getPaddingX(size);
const activeInputStyles = getActiveInputStyles(size);
const activeLabelStyles = getActiveLabelStyles(theme, fc, bc, size);
return {
container: {
......@@ -37,22 +105,20 @@ const variantFloating: PartsStyleFunction<typeof parts> = (props: StyleFunctionP
},
// label's styles
label: {
left: '22px',
...getDefaultLabelStyles(size),
left: '2px',
right: '2px',
top: '2px',
zIndex: 2,
position: 'absolute',
borderRadius: 'base',
boxSizing: 'border-box',
color: mode('gray.500', 'whiteAlpha.400')(props),
backgroundColor: 'transparent',
pointerEvents: 'none',
margin: 0,
transformOrigin: 'left top',
fontSize: 'md',
lineHeight: '20px',
},
'input + label': {
top: 'calc(50% - 10px);',
},
'textarea + label': {
top: '20px',
transformOrigin: 'top left',
transition: 'font-size 200ms ease, line-height 200ms ease, padding 200ms ease, top 200ms ease, background-color 200ms ease 200ms',
},
'input:not(:placeholder-shown) + label, textarea:not(:placeholder-shown) + label': {
...activeLabelStyles,
......@@ -62,7 +128,10 @@ const variantFloating: PartsStyleFunction<typeof parts> = (props: StyleFunctionP
},
// input's styles
'input, textarea': {
padding: '20px',
padding: px,
},
'input[disabled] + label, textarea[disabled] + label': {
backgroundColor: 'transparent',
},
'input:not(:placeholder-shown), textarea:not(:placeholder-shown)': {
...activeInputStyles,
......
......@@ -4,6 +4,7 @@ import {
FormControl,
FormLabel,
Input,
useColorModeValue,
} from '@chakra-ui/react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import React, { useCallback, useEffect } from 'react';
......@@ -28,6 +29,7 @@ const NAME_MAX_LENGTH = 100;
const ApiKeyForm: React.FC<Props> = ({ data, onClose }) => {
const { control, handleSubmit, formState: { errors }, setValue } = useForm<Inputs>();
const queryClient = useQueryClient();
const formBackgroundColor = useColorModeValue('white', 'gray.800');
useEffect(() => {
setValue('token', data?.api_key || '');
......@@ -88,7 +90,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose }) => {
const renderNameInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'name'>}) => {
return (
<FormControl variant="floating" id="name" isRequired>
<FormControl variant="floating" id="name" isRequired backgroundColor={ formBackgroundColor }>
<Input
{ ...field }
isInvalid={ Boolean(errors.name) }
......@@ -97,7 +99,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose }) => {
<FormLabel>Application name for API key (e.g Web3 project)</FormLabel>
</FormControl>
);
}, [ errors ]);
}, [ errors, formBackgroundColor ]);
return (
<>
......
......@@ -5,6 +5,7 @@ import {
FormLabel,
Input,
Textarea,
useColorModeValue,
} from '@chakra-ui/react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import React, { useCallback, useEffect } from 'react';
......@@ -47,6 +48,8 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose }) => {
return fetch(`/api/account/custom-abis/${ data.id }`, { method: 'PUT', body });
};
const formBackgroundColor = useColorModeValue('white', 'gray.800');
const mutation = useMutation(customAbiKey, {
onSuccess: async(data) => {
const response: CustomAbi = await data.json();
......@@ -79,7 +82,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose }) => {
const renderContractAddressInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'contract_address_hash'>}) => {
return (
<FormControl variant="floating" id="contract_address_hash" isRequired>
<FormControl variant="floating" id="contract_address_hash" isRequired backgroundColor={ formBackgroundColor }>
<Input
{ ...field }
isInvalid={ Boolean(errors.contract_address_hash) }
......@@ -87,11 +90,11 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose }) => {
<FormLabel>Smart contract address (0x...)</FormLabel>
</FormControl>
);
}, [ errors ]);
}, [ errors, formBackgroundColor ]);
const renderNameInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'name'>}) => {
return (
<FormControl variant="floating" id="name" isRequired>
<FormControl variant="floating" id="name" isRequired backgroundColor={ formBackgroundColor }>
<Input
{ ...field }
isInvalid={ Boolean(errors.name) }
......@@ -100,11 +103,11 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose }) => {
<FormLabel>Project name</FormLabel>
</FormControl>
);
}, [ errors ]);
}, [ errors, formBackgroundColor ]);
const renderAbiInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'abi'>}) => {
return (
<FormControl variant="floating" id="abi" isRequired>
<FormControl variant="floating" id="abi" isRequired backgroundColor={ formBackgroundColor }>
<Textarea
{ ...field }
size="lg"
......@@ -113,7 +116,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose }) => {
<FormLabel>{ `Custom ABI [{...}] (JSON format)` }</FormLabel>
</FormControl>
);
}, [ errors ]);
}, [ errors, formBackgroundColor ]);
return (
<>
......
import {
Box,
Button,
useColorModeValue,
} from '@chakra-ui/react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import React, { useCallback, useEffect, useState } from 'react';
......@@ -28,6 +29,7 @@ type Inputs = {
const AddressForm: React.FC<Props> = ({ data, onClose }) => {
const [ pending, setPending ] = useState(false);
const { control, handleSubmit, formState: { errors }, setValue } = useForm<Inputs>();
const formBackgroundColor = useColorModeValue('white', 'gray.800');
useEffect(() => {
setValue('address', data?.address_hash || '');
......@@ -67,12 +69,12 @@ const AddressForm: React.FC<Props> = ({ data, onClose }) => {
};
const renderAddressInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'address'>}) => {
return <AddressInput<Inputs, 'address'> field={ field } isInvalid={ Boolean(errors.address) }/>;
}, [ errors ]);
return <AddressInput<Inputs, 'address'> field={ field } isInvalid={ Boolean(errors.address) } backgroundColor={ formBackgroundColor }/>;
}, [ errors, formBackgroundColor ]);
const renderTagInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'tag'>}) => {
return <TagInput field={ field } isInvalid={ Boolean(errors.tag) }/>;
}, [ errors ]);
return <TagInput field={ field } isInvalid={ Boolean(errors.tag) } backgroundColor={ formBackgroundColor }/>;
}, [ errors, formBackgroundColor ]);
return (
<>
......
import {
Box,
Button,
useColorModeValue,
} from '@chakra-ui/react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import React, { useCallback, useEffect, useState } from 'react';
......@@ -28,6 +29,7 @@ type Inputs = {
const TransactionForm: React.FC<Props> = ({ data, onClose }) => {
const [ pending, setPending ] = useState(false);
const { control, handleSubmit, formState: { errors }, setValue } = useForm<Inputs>();
const formBackgroundColor = useColorModeValue('white', 'gray.800');
useEffect(() => {
setValue('transaction', data?.transaction_hash || '');
......@@ -68,12 +70,12 @@ const TransactionForm: React.FC<Props> = ({ data, onClose }) => {
};
const renderTransactionInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'transaction'>}) => {
return <TransactionInput field={ field } isInvalid={ Boolean(errors.transaction) }/>;
}, [ errors ]);
return <TransactionInput field={ field } isInvalid={ Boolean(errors.transaction) } backgroundColor={ formBackgroundColor }/>;
}, [ errors, formBackgroundColor ]);
const renderTagInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'tag'>}) => {
return <TagInput field={ field } isInvalid={ Boolean(errors.tag) }/>;
}, [ errors ]);
return <TagInput field={ field } isInvalid={ Boolean(errors.tag) } backgroundColor={ formBackgroundColor }/>;
}, [ errors, formBackgroundColor ]);
return (
<>
......
......@@ -12,7 +12,7 @@ interface Props {
export default function PublicTagFormComment({ control }: Props) {
const renderComment = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'comment'>}) => {
return (
<FormControl variant="floating" id={ field.name }>
<FormControl variant="floating" id={ field.name } size="lg">
<Textarea
{ ...field }
size="lg"
......
......@@ -13,7 +13,7 @@ interface Props<TInputs extends FieldValues> {
export default function PublicTagsFormInput<Inputs extends FieldValues>({ label, control, required, fieldName }: Props<Inputs>) {
const renderInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, typeof fieldName>}) => {
return (
<FormControl variant="floating" id={ field.name } isRequired={ required }>
<FormControl variant="floating" id={ field.name } isRequired={ required } size="lg">
<Input
{ ...field }
size="lg"
......
......@@ -13,6 +13,7 @@ type Props<TInputs extends FieldValues, TInputName extends Path<TInputs>> = {
isInvalid: boolean;
size?: string;
placeholder?: string;
backgroundColor?: string;
}
export default function AddressInput<Inputs extends FieldValues, Name extends Path<Inputs>>(
......@@ -21,9 +22,10 @@ export default function AddressInput<Inputs extends FieldValues, Name extends Pa
isInvalid,
size,
placeholder = 'Address (0x...)',
backgroundColor,
}: Props<Inputs, Name>) {
return (
<FormControl variant="floating" id="address" isRequired>
<FormControl variant="floating" id="address" isRequired backgroundColor={ backgroundColor } size={ size }>
<Input
{ ...field }
isInvalid={ isInvalid }
......
......@@ -11,11 +11,12 @@ const TAG_MAX_LENGTH = 35;
type Props<Field> = {
field: Field;
isInvalid: boolean;
backgroundColor?: string;
}
function TagInput<Field extends Partial<ControllerRenderProps<FieldValues, 'tag'>>>({ field, isInvalid }: Props<Field>) {
function TagInput<Field extends Partial<ControllerRenderProps<FieldValues, 'tag'>>>({ field, isInvalid, backgroundColor }: Props<Field>) {
return (
<FormControl variant="floating" id="tag" isRequired>
<FormControl variant="floating" id="tag" isRequired backgroundColor={ backgroundColor }>
<Input
{ ...field }
isInvalid={ isInvalid }
......
......@@ -11,11 +11,12 @@ const HASH_LENGTH = 66;
type Props<Field> = {
field: Field;
isInvalid: boolean;
backgroundColor?: string;
}
function AddressInput<Field extends Partial<ControllerRenderProps<FieldValues, 'transaction'>>>({ field, isInvalid }: Props<Field>) {
function AddressInput<Field extends Partial<ControllerRenderProps<FieldValues, 'transaction'>>>({ field, isInvalid, backgroundColor }: Props<Field>) {
return (
<FormControl variant="floating" id="transaction" isRequired>
<FormControl variant="floating" id="transaction" isRequired backgroundColor={ backgroundColor }>
<Input
{ ...field }
isInvalid={ isInvalid }
......
......@@ -5,6 +5,7 @@ import {
Text,
Grid,
GridItem,
useColorModeValue,
} from '@chakra-ui/react';
import React, { useCallback, useEffect } from 'react';
import type { SubmitHandler, ControllerRenderProps } from 'react-hook-form';
......@@ -30,6 +31,7 @@ type Inputs = {
const AddressForm: React.FC<Props> = ({ data }) => {
const { control, handleSubmit, formState: { errors }, setValue } = useForm<Inputs>();
const formBackgroundColor = useColorModeValue('white', 'gray.800');
useEffect(() => {
setValue('address', data?.address || '');
......@@ -41,12 +43,12 @@ const AddressForm: React.FC<Props> = ({ data }) => {
const onSubmit: SubmitHandler<Inputs> = data => console.log(data);
const renderAddressInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'address'>}) => {
return <AddressInput<Inputs, 'address'> field={ field } isInvalid={ Boolean(errors.address) }/>;
}, [ errors ]);
return <AddressInput<Inputs, 'address'> field={ field } isInvalid={ Boolean(errors.address) } backgroundColor={ formBackgroundColor }/>;
}, [ errors, formBackgroundColor ]);
const renderTagInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'tag'>}) => {
return <TagInput field={ field } isInvalid={ Boolean(errors.tag) }/>;
}, [ errors ]);
return <TagInput field={ field } isInvalid={ Boolean(errors.tag) } backgroundColor={ formBackgroundColor }/>;
}, [ errors, formBackgroundColor ]);
const renderCheckbox = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'notification'>}) => (
<Checkbox
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment