/* eslint-disable max-lines */ import * as LabelPrimitive from "@radix-ui/react-label"; import { css, customScrollbars, styled } from "../../theme"; import { pxToRem } from "../../utils"; import { Text, typographyVariants } from "../text"; import { Flex } from "../flex"; import { Box } from "../box"; import { INPUT_PADDING, TEXTAREA_DEFAULT_HEIGHT, TEXTAREA_MAX_HEIGHT } from "./consts"; import type { CSS } from "../../theme"; import type { SpaceTokenKey } from "../../theme/spacings"; const placeholderMgmt = { "&::placeholder": { color: "transparent", transition: "color 200ms cubic-bezier(0, 0, 0.2, 1)", }, "&:focus": { "&::placeholder": { color: "$off-white-72", }, }, }; const FIELDSET_BORDER_WIDTH = pxToRem(1); const FIELDSET_BORDER_WIDTH_FOCUS = pxToRem(2); /** * Extra space the element is pushed down, then lifted back up. * This is part of a workaround for Safari bug when it thinks there are things rendered on the right to the input * (fieldset and label are causing this) and this is causing horizontal scrolling. * A solution was to apply overflow, but that is cutting the top of the container too (and the raised label is rendered * with some px above the container). The solution is to push the contents down and lift back up the parent element * of the element that has overflow. * * If the workaround is no longer needed: * - remove every style that uses SAFARI_BUG_WORKAROUND_EXTRA_SPACE * - move `flexDirection` & `gap` from StyledRootContent to StyledRoot * - remove StyledRootContent * - make `StyledRoot` style Flex, not Box */ export const SAFARI_BUG_WORKAROUND_EXTRA_SPACE = pxToRem(20); const raisedLabelVariant = css({ variants: { raisedLabel: { true: { "&::placeholder": { color: "$off-white-72", }, }, }, }, }); export const LEGEND_PADDING: SpaceTokenKey = "$1"; export const StyledFieldSetContent = styled(Box, { width: "100%", position: "relative", top: SAFARI_BUG_WORKAROUND_EXTRA_SPACE, }); export const StyledFieldSet = styled("fieldset", { position: "relative", border: `${FIELDSET_BORDER_WIDTH} solid $off-white-18`, borderRadius: "$xs", height: pxToRem(TEXTAREA_DEFAULT_HEIGHT), maxHeight: pxToRem(TEXTAREA_MAX_HEIGHT), width: "100%", variants: { focus: { true: { borderWidth: FIELDSET_BORDER_WIDTH_FOCUS, legend: { marginLeft: `calc($4 - ${FIELDSET_BORDER_WIDTH_FOCUS} - ${LEGEND_PADDING})` }, }, }, }, }); const inputBase: CSS = { height: pxToRem(TEXTAREA_DEFAULT_HEIGHT), width: "100%", border: `${pxToRem(INPUT_PADDING)} solid transparent`, color: "$light-off-white", }; export const StyledInput = styled( "input", { minWidth: 0, position: "relative", "&:-webkit-autofill": { "-webkit-background-clip": "text", "-webkit-text-fill-color": "#FFF8F8", caretColor: "$light-off-white", }, "&:-webkit-autofill:hover": { "-webkit-background-clip": "text", "-webkit-text-fill-color": "#FFF8F8", caretColor: "$light-off-white", }, "&:-webkit-autofill:focus": { "-webkit-background-clip": "text", "-webkit-text-fill-color": "#FFF8F8", caretColor: "$light-off-white", }, "&:-webkit-autofill:active": { "-webkit-background-clip": "text", "-webkit-text-fill-color": "#FFF8F8", caretColor: "$light-off-white", }, "&::-webkit-inner-spin-button": { "-webkit-appearance": "none", margin: 0, }, "&::-webkit-outer-spin-button": { "-webkit-appearance": "none", margin: 0, }, "&[type=number]": { "-moz-appearance": "textfield", }, ...inputBase, ...placeholderMgmt, ...typographyVariants.body3, }, raisedLabelVariant ); export const StyledTextArea = styled( "textarea", { maxHeight: pxToRem(TEXTAREA_MAX_HEIGHT), resize: "none", overflowWrap: "break-word", pt: pxToRem(2), ...inputBase, ...placeholderMgmt, ...typographyVariants.body3, ...customScrollbars, }, raisedLabelVariant ); export const StyledLabel = styled(LabelPrimitive.Root, { position: "absolute", top: "50%", left: "$4", transform: "translateY(-50%)", transition: `all 200ms cubic-bezier(0, 0, 0.2, 1)`, color: "$off-white-72", ...typographyVariants.body4, }); export const StyledLegend = styled("legend", { visibility: "hidden", maxWidth: "0px", height: 0, transition: "max-width 50ms cubic-bezier(0.0, 0, 0.2, 1)", marginLeft: `calc($4 - ${FIELDSET_BORDER_WIDTH} - ${LEGEND_PADDING})`, whiteSpace: "nowrap", ...typographyVariants.body5, }); export const StyledInfoText = styled(Text, { pl: "$4", color: "$off-white-72", overflowWrap: "anywhere", position: "relative", top: SAFARI_BUG_WORKAROUND_EXTRA_SPACE, }); export const InputFieldContainer = styled(Flex, { position: "absolute", width: "100%", justifyContent: "space-between", alignItems: "center", top: SAFARI_BUG_WORKAROUND_EXTRA_SPACE, }); export const StyledRootContent = styled(Flex, { flexDirection: "column", gap: "$2", position: "relative", width: "100%", overflow: "hidden", top: `-${SAFARI_BUG_WORKAROUND_EXTRA_SPACE}`, paddingBottom: SAFARI_BUG_WORKAROUND_EXTRA_SPACE, marginBottom: `-${SAFARI_BUG_WORKAROUND_EXTRA_SPACE}`, }); export const StyledRoot = styled(Box, { position: "relative", width: "100%", ...typographyVariants.body4, [`${StyledLabel}`]: { color: "$off-white-72", }, [`${StyledFieldSet}`]: { borderColor: "$off-white-18", }, [`${StyledInfoText}`]: { color: "$off-white-72", }, ["&:not(:where([data-disabled=true]))"]: { [`:where(${InputFieldContainer}:hover + div) ${StyledFieldSet}`]: { border: `${FIELDSET_BORDER_WIDTH} solid $off-white-36-opaque`, }, }, "&:focus-within": { [`& ${StyledFieldSet}`]: { border: `${FIELDSET_BORDER_WIDTH_FOCUS} solid $off-white-36-opaque`, }, [`& ${StyledLegend}`]: { marginLeft: `calc($4 - ${FIELDSET_BORDER_WIDTH_FOCUS} - ${LEGEND_PADDING})`, }, }, "&[data-disabled=true]": { opacity: "$disabled", cursor: "not-allowed", }, variants: { error: { true: { [`${StyledFieldSet}`]: { borderColor: "$light-red", borderWidth: FIELDSET_BORDER_WIDTH_FOCUS, }, [`${StyledLabel}`]: { color: "$light-red", }, [`${StyledInfoText}`]: { color: "$light-red", }, }, }, }, });