Commit adb1a307 authored by tom's avatar tom

fix input group paddings calculation

parent bb9842bc
import type { BoxProps, InputElementProps } from '@chakra-ui/react';
import { Group, InputElement } from '@chakra-ui/react';
import { debounce } from 'es-toolkit';
import * as React from 'react';
import getComponentDisplayName from '../utils/getComponentDisplayName';
......@@ -31,12 +32,9 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
const startElementRef = React.useRef<HTMLDivElement>(null);
const endElementRef = React.useRef<HTMLDivElement>(null);
const [ inlinePaddings, setInlinePaddings ] = React.useState({
start: 0,
end: 0,
});
const [ inlinePaddings, setInlinePaddings ] = React.useState<{ start?: number; end?: number }>();
React.useEffect(() => {
const calculateInlinePaddings = React.useCallback(() => {
const { width: endWidth } = endElementRef?.current?.getBoundingClientRect() ?? {};
const { width: startWidth } = startElementRef?.current?.getBoundingClientRect() ?? {};
......@@ -46,10 +44,22 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
});
}, []);
React.useEffect(() => {
calculateInlinePaddings();
const resizeHandler = debounce(calculateInlinePaddings, 300);
const resizeObserver = new ResizeObserver(resizeHandler);
resizeObserver.observe(window.document.body);
return function cleanup() {
resizeObserver.unobserve(window.document.body);
};
}, [ calculateInlinePaddings ]);
return (
<Group ref={ ref } w="100%" { ...rest }>
{ startElement && (
<InputElement pointerEvents="none" ref={ startElementRef } { ...startElementProps }>
<InputElement pointerEvents="none" ref={ startElementRef } px={ 0 } { ...startElementProps }>
{ startElement }
</InputElement>
) }
......@@ -58,12 +68,15 @@ export const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
return child;
}
return React.cloneElement(child, {
...(startElement && { ps: startOffset ?? `${ inlinePaddings.start }px` }),
...(endElement && { pe: endOffset ?? `${ inlinePaddings.end }px` }),
...(startElement && { ps: startOffset ?? (inlinePaddings?.start ? `${ inlinePaddings.start }px` : undefined) }),
...(endElement && { pe: endOffset ?? (inlinePaddings?.end ? `${ inlinePaddings.end }px` : undefined) }),
// hide input value and placeholder for the first render
value: inlinePaddings ? child.props.value : undefined,
placeholder: inlinePaddings ? child.props.placeholder : undefined,
});
}) }
{ endElement && (
<InputElement placement="end" ref={ endElementRef } { ...endElementProps }>
<InputElement placement="end" ref={ endElementRef } px={ 0 } { ...endElementProps }>
{ endElement }
</InputElement>
) }
......
......@@ -18,6 +18,11 @@ export const recipe = defineRecipe({
focusRingColor: 'var(--error-color)',
borderColor: 'var(--error-color)',
},
_readOnly: {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
_autofill: {
// FIXME: this is not working
// WebkitTextFillColor: '{colors.input.fg}',
......
......@@ -17,7 +17,7 @@ const ContractMethodAddressButton = ({ onClick, isDisabled }: Props) => {
}, [ address, onClick ]);
return (
<Tooltip content={ !address ? 'Connect your wallet to enter your address.' : undefined }>
<Tooltip content="Connect your wallet to enter your address." disabled={ Boolean(address) }>
<Button
variant="subtle"
size="xs"
......
......@@ -131,7 +131,7 @@ const ContractMethodFieldInput = ({ data, hideLabel, path: name, className, isDi
const inputEndElement = (
<Flex alignItems="center">
<ClearButton onClick={ handleClear } isDisabled={ isDisabled } boxSize={ 6 } isVisible={ field.value !== undefined && field.value !== '' }/>
<ClearButton onClick={ handleClear } isDisabled={ isDisabled } minW={ 6 } isVisible={ field.value !== undefined && field.value !== '' }/>
{ data.type === 'address' && <ContractMethodAddressButton onClick={ handleAddressButtonClick } isDisabled={ isDisabled }/> }
{ argTypeMatchInt && !isNativeCoin && (hasTimestampButton ? (
<Button
......
import { Text, Box, Input, Flex } from '@chakra-ui/react';
import { Text, Box, Flex } from '@chakra-ui/react';
import { sumBy } from 'es-toolkit';
import type { ChangeEvent } from 'react';
import React from 'react';
import type { FormattedData } from './types';
import type { TokenType } from 'types/api/token';
import { getTokenTypeName } from 'lib/token/tokenTypes';
import { InputGroup } from 'toolkit/chakra/input-group';
import { Link } from 'toolkit/chakra/link';
import FilterInput from 'ui/shared/filters/FilterInput';
import IconSvg from 'ui/shared/IconSvg';
import type { Sort } from '../utils/tokenUtils';
......@@ -21,7 +20,7 @@ interface Props {
erc1155sort: Sort;
erc404sort: Sort;
filteredData: FormattedData;
onInputChange: (event: ChangeEvent<HTMLInputElement>) => void;
onInputChange: (searchTerm: string) => void;
onSortClick: (event: React.SyntheticEvent) => void;
}
......@@ -30,12 +29,13 @@ const TokenSelectMenu = ({ erc20sort, erc1155sort, erc404sort, filteredData, onI
return (
<>
<InputGroup
startElement={ <IconSvg name="search" boxSize={ 4 } color={{ _light: 'blackAlpha.600', _dark: 'whiteAlpha.600' }}/> }
<FilterInput
placeholder="Search by token name"
size="sm"
inputProps={{ bgColor: 'dialog.bg' }}
mb={ 5 }
>
<Input placeholder="Search by token name" onChange={ onInputChange } size="sm" bgColor="dialog.bg"/>
</InputGroup>
onChange={ onInputChange }
/>
<Flex flexDir="column" rowGap={ 6 }>
{ Object.entries(filteredData).sort(sortTokenGroups).map(([ tokenType, tokenInfo ]) => {
if (tokenInfo.items.length === 0) {
......
import { mapValues } from 'es-toolkit';
import type { ChangeEvent } from 'react';
import React from 'react';
import type { FormattedData } from './types';
......@@ -13,8 +12,8 @@ export default function useTokenSelect(data: FormattedData) {
const [ erc404sort, setErc404Sort ] = React.useState<Sort>('desc');
const [ erc20sort, setErc20Sort ] = React.useState<Sort>('desc');
const onInputChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => {
setSearchTerm(event.target.value);
const onInputChange = React.useCallback((searchTerm: string) => {
setSearchTerm(searchTerm);
}, []);
const onSortClick = React.useCallback((event: React.SyntheticEvent) => {
......
......@@ -18,8 +18,8 @@ const RewardsReadOnlyInputWithCopy = ({ label, value, className, isLoading }: Pr
return (
<Skeleton loading={ isLoading } className={ className }>
<Field label={ label } floating size="xl" readOnly>
<InputGroup endElement={ <CopyToClipboard text={ value }/> }>
<Input value={ value } fontWeight="500" overflow="hidden" textOverflow="ellipsis"/>
<InputGroup endElement={ <CopyToClipboard text={ value }/> } endElementProps={{ px: 3 }}>
<Input value={ value } fontWeight="500"/>
</InputGroup>
</Field>
</Skeleton>
......
import type { ChangeEvent } from 'react';
import React, { useCallback, useState } from 'react';
import type { InputProps } from 'toolkit/chakra/input';
import { Input } from 'toolkit/chakra/input';
import { InputGroup } from 'toolkit/chakra/input-group';
import type { SkeletonProps } from 'toolkit/chakra/skeleton';
......@@ -18,9 +19,10 @@ interface Props extends Omit<SkeletonProps, 'onChange' | 'loading'> {
initialValue?: string;
type?: React.HTMLInputTypeAttribute;
name?: string;
inputProps?: InputProps;
};
const FilterInput = ({ onChange, size = 'sm', placeholder, initialValue, type, name, loading = false, onFocus, onBlur, ...rest }: Props) => {
const FilterInput = ({ onChange, size = 'sm', placeholder, initialValue, type, name, loading = false, onFocus, onBlur, inputProps, ...rest }: Props) => {
const [ filterQuery, setFilterQuery ] = useState(initialValue || '');
const inputRef = React.useRef<HTMLInputElement>(null);
......@@ -52,7 +54,7 @@ const FilterInput = ({ onChange, size = 'sm', placeholder, initialValue, type, n
startElement={ startElement }
startElementProps={{ px: 2 }}
endElement={ endElement }
endElementProps={{ px: 0, w: '32px' }}
endElementProps={{ w: '32px' }}
>
<Input
ref={ inputRef }
......@@ -67,6 +69,7 @@ const FilterInput = ({ onChange, size = 'sm', placeholder, initialValue, type, n
whiteSpace="nowrap"
type={ type }
name={ name }
{ ...inputProps }
/>
</InputGroup>
</Skeleton>
......
......@@ -205,7 +205,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck, isActive,
pb="8px"
boxShadow={ isInputStuck ? '0px 6px 3px 0px rgba(0, 0, 0, 0.05)' : 'none' }
endElement={ inputEndElement }
endElementProps={{ height: '26px', pl: '0', pr: '10px', columnGap: '2px' }}
endElementProps={{ height: '26px', pl: '0', right: '10px', columnGap: '2px' }}
>
<Input
size="xs"
......
......@@ -114,13 +114,13 @@ const InputShowcase = () => {
<SamplesStack>
<Sample label="with end element">
<Field label="Referral code" required floating size="xl" w="300px" flexShrink={ 0 }>
<InputGroup endElement={ <IconSvg name="copy" boxSize={ 5 }/> }>
<InputGroup endElement={ <IconSvg name="copy" boxSize={ 5 }/> } endElementProps={{ px: 3 }}>
<Input/>
</InputGroup>
</Field>
</Sample>
<Sample label="with start element">
<InputGroup startElement={ <IconSvg name="collection" boxSize={ 5 }/> }>
<InputGroup startElement={ <IconSvg name="collection" boxSize={ 5 }/> } startElementProps={{ px: 2 }}>
<Input placeholder="Type in something"/>
</InputGroup>
</Sample>
......
......@@ -106,6 +106,8 @@ const SearchBarInput = (
name="search"
boxSize={{ base: isHomepage ? 6 : 4, lg: 6 }}
color={{ _light: 'blackAlpha.600', _dark: 'whiteAlpha.600' }}
ml={{ base: 3, lg: 4 }}
mr="10px"
/>
);
......@@ -117,12 +119,11 @@ const SearchBarInput = (
<Center
boxSize="20px"
my="2px"
mr={{ base: 1, lg: isHomepage ? 2 : 1 }}
mr={ 3 }
borderRadius="sm"
borderWidth="1px"
borderColor="gray.400"
color="gray.400"
display={{ base: 'none', lg: 'flex' }}
>
/
</Center>
......
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