From 2f8a172b1206ee2034718e9fd671b189d2fd023e Mon Sep 17 00:00:00 2001 From: RustamRu <kagapov.rustam@gmail.com> Date: Tue, 11 Mar 2025 23:08:08 +0300 Subject: [PATCH] refactor: Improve car color selection UI and interaction - Refined color selection styling with more consistent hover and selection states - Added dynamic styling for selected and custom color options - Optimized layout and spacing of color selection buttons - Improved ref handling for the component --- .../form/car-color/car-color-select.tsx | 151 ++++++++++-------- 1 file changed, 82 insertions(+), 69 deletions(-) diff --git a/src/components/order-form/form/car-color/car-color-select.tsx b/src/components/order-form/form/car-color/car-color-select.tsx index cf591b2..90800ca 100644 --- a/src/components/order-form/form/car-color/car-color-select.tsx +++ b/src/components/order-form/form/car-color/car-color-select.tsx @@ -1,11 +1,5 @@ import React, { forwardRef, useState } from 'react'; -import { - Input, - Box, - Stack, - Text, - Flex, -} from '@chakra-ui/react'; +import { Input, Box, Stack, Text, Flex } from '@chakra-ui/react'; import { useTranslation } from 'react-i18next'; import { CAR_COLORS } from './helper'; @@ -18,7 +12,7 @@ interface CarColorSelectProps { } export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>( - function CarColorSelect(props) { + function CarColorSelect(props, ref) { const [customColor, setCustomColor] = useState(''); const [isCustom, setIsCustom] = useState(false); @@ -33,7 +27,9 @@ export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>( } as React.ChangeEvent<HTMLInputElement>); }; - const handleCustomColorChange = (e: React.ChangeEvent<HTMLInputElement>) => { + const handleCustomColorChange = ( + e: React.ChangeEvent<HTMLInputElement>, + ) => { const value = e.target.value; setCustomColor(value); props.onChange?.({ @@ -48,46 +44,56 @@ export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>( const currentValue = isCustom ? 'custom' : props.value; return ( - <Stack spacing={4} width="100%"> - <Flex gap={3} wrap="nowrap" overflowX="auto" pb={2}> + <Stack spacing={4} width='100%' ref={ref}> + <Flex gap={2} wrap='wrap' pb={2}> {CAR_COLORS.map(({ name, code }) => ( - <Box + <Box key={name} flexShrink={0} - as="button" - type="button" + as='button' + type='button' onClick={() => handleColorChange(name)} > - <Flex - align="center" - gap={2} - p={2} - borderRadius="full" - borderWidth="2px" - borderColor={currentValue === name ? 'primary.500' : 'gray.200'} - bg={currentValue === name ? 'primary.50' : 'white'} - _hover={{ + <Flex + align='center' + gap={2} + p={1} + borderRadius='full' + borderWidth='2px' + borderColor='gray.200' + bg='white' + _hover={{ borderColor: 'primary.500', - bg: currentValue === name ? 'primary.50' : 'gray.50' + bg: 'gray.50', }} - minW={currentValue === name ? '120px' : 'auto'} - h="48px" - justify="center" - transition="all 0.2s" + justify='center' + transition='all 0.2s' + {...(currentValue === name && { + borderColor: 'primary.500', + bg: 'primary.50', + paddingInlineEnd: 3, + _hover: { + bg: 'primary.50', + }, + })} > - <Flex align="center" gap={2}> + <Flex align='center' gap={2}> <Box - w="32px" - h="32px" - borderRadius="full" + w='32px' + h='32px' + borderRadius='full' bg={code} - border="1px" - borderColor={currentValue === name ? 'primary.500' : 'gray.200'} - transition="all 0.2s" - boxShadow={currentValue === name ? 'sm' : 'none'} + border='1px' + borderColor='gray.200' + transition='all 0.2s' + boxShadow='none' + {...(currentValue === name && { + borderColor: 'primary.500', + boxShadow: 'sm', + })} /> {currentValue === name && ( - <Text fontSize="xs" color="primary.700" fontWeight="medium"> + <Text fontSize='xs' color='primary.700' fontWeight='medium'> {t(`colors.${name}`)} </Text> )} @@ -95,60 +101,67 @@ export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>( </Flex> </Box> ))} - <Box + <Box flexShrink={0} - as="button" - type="button" + as='button' + type='button' onClick={() => handleColorChange('custom')} > - <Flex - align="center" + <Flex + align='center' gap={2} - p={2} - borderRadius="full" - borderWidth="2px" - borderColor={isCustom ? 'primary.500' : 'gray.200'} - bg={isCustom ? 'primary.50' : 'white'} - _hover={{ + p={1} + paddingInlineEnd={3} + borderRadius='full' + borderWidth='2px' + borderColor='gray.200' + bg='white' + _hover={{ borderColor: 'primary.500', - bg: isCustom ? 'primary.50' : 'gray.50' + bg: 'gray.50', }} - minW={isCustom ? '200px' : 'auto'} - h="48px" - justify="center" - transition="all 0.2s" + justify='center' + transition='all 0.2s' + {...(isCustom && { + borderColor: 'primary.500', + paddingInlineStart: 3, + bg: 'primary.50', + _hover: { + bg: 'primary.50', + }, + })} > {isCustom ? ( - <Flex gap={2} align="center"> - <Text fontSize="xs" color="primary.700" fontWeight="medium"> + <Flex gap={2} align='center'> + <Text fontSize='xs' color='primary.700' fontWeight='medium'> {t('custom-label')} </Text> <Input - size="sm" - width="120px" + size='sm' + width='120px' value={customColor} onChange={handleCustomColorChange} placeholder={t('placeholder')} onClick={(e) => e.stopPropagation()} - borderColor="primary.200" + borderColor='primary.200' _focus={{ borderColor: 'primary.500', - boxShadow: '0 0 0 1px var(--chakra-colors-primary-500)' + boxShadow: '0 0 0 1px var(--chakra-colors-primary-500)', }} /> </Flex> ) : ( - <Flex align="center" gap={2}> + <Flex align='center' gap={2}> <Box - w="32px" - h="32px" - borderRadius="full" - bg="gray.100" - border="1px" - borderColor="gray.200" - transition="all 0.2s" + w='32px' + h='32px' + borderRadius='full' + bg='gray.100' + border='1px' + borderColor='gray.200' + transition='all 0.2s' /> - <Text fontSize="xs" color="gray.500"> + <Text fontSize='xs' color='gray.500'> {t('custom')} </Text> </Flex> @@ -159,4 +172,4 @@ export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>( </Stack> ); }, -); \ No newline at end of file +);