Files
explore/theme/components/Form.ts
T
2022-10-04 10:42:23 +03:00

138 lines
3.4 KiB
TypeScript

import { formAnatomy as parts } from '@chakra-ui/anatomy';
import { createMultiStyleConfigHelpers } from '@chakra-ui/styled-system';
import type { StyleFunctionProps } from '@chakra-ui/theme-tools';
import { getColor, mode } from '@chakra-ui/theme-tools';
import getDefaultFormColors from '../utils/getDefaultFormColors';
import FormLabel from './FormLabel';
import Input from './Input';
import Textarea from './Textarea';
const { definePartsStyle, defineMultiStyleConfig } =
createMultiStyleConfigHelpers(parts.keys);
function getFloatingVariantStylesForSize(size: 'md' | 'lg', props: StyleFunctionProps) {
const { theme } = props;
const { focusColor: fc, errorColor: ec } = getDefaultFormColors(props);
const activeLabelStyles = {
...FormLabel.variants?.floating?.(props)._focusWithin,
...FormLabel.sizes?.[size](props)._focusWithin,
} || {};
const activeInputStyles = (() => {
switch (size) {
case 'md': {
return {
paddingTop: '26px',
paddingBottom: '10px',
};
}
case 'lg': {
return {
paddingTop: '38px',
paddingBottom: '18px',
};
}
}
})();
const inputPx = (() => {
switch (size) {
case 'md': {
return '16px';
}
case 'lg': {
return '24px';
}
}
})();
return {
container: {
// active styles
_focusWithin: {
label: activeLabelStyles,
'input, textarea': activeInputStyles,
},
// label styles
label: FormLabel.sizes?.[size](props) || {},
'input:not(:placeholder-shown) + label, textarea:not(:placeholder-shown) + label': activeLabelStyles,
'input[aria-invalid=true] + label, textarea[aria-invalid=true] + label': {
color: getColor(theme, ec),
},
// input styles
input: Input.sizes?.[size].field,
textarea: Textarea.sizes?.[size],
'input, textarea': {
padding: inputPx,
},
'input:not(:placeholder-shown), textarea:not(:placeholder-shown)': activeInputStyles,
'input[disabled] + label, textarea[disabled] + label': {
backgroundColor: 'transparent',
},
// indicator styles
'input:not(:placeholder-shown) + label .chakra-form__required-indicator, textarea:not(:placeholder-shown) + label .chakra-form__required-indicator': {
color: getColor(theme, fc),
},
'input[aria-invalid=true] + label .chakra-form__required-indicator, textarea[aria-invalid=true] + label .chakra-form__required-indicator': {
color: getColor(theme, ec),
},
},
};
}
const baseStyle = definePartsStyle((props) => {
return {
requiredIndicator: {
marginStart: 0,
color: mode('gray.500', 'whiteAlpha.400')(props),
},
};
});
const variantFloating = definePartsStyle((props) => {
return {
container: {
label: FormLabel.variants?.floating(props) || {},
},
};
});
const sizes = {
lg: definePartsStyle((props) => {
if (props.variant === 'floating') {
return getFloatingVariantStylesForSize('lg', props);
}
return {};
}),
md: definePartsStyle((props) => {
if (props.variant === 'floating') {
return getFloatingVariantStylesForSize('md', props);
}
return {};
}),
};
const variants = {
floating: variantFloating,
};
const Form = defineMultiStyleConfig({
baseStyle,
variants,
sizes,
defaultProps: {
size: 'md',
},
});
export default Form;