From fbae9ce39862636d826da2f1854371887cd3aca1 Mon Sep 17 00:00:00 2001 From: moathabuhamad-cengage Date: Thu, 14 Nov 2024 16:36:41 +0100 Subject: [PATCH] fix(Input): Style update: Fix HelpLink position on inputs (#1546) --- .changeset/fix-input-help-link.md | 5 ++ .../FormFieldContainer/FormFieldContainer.tsx | 1 + .../src/components/Input/Input.stories.tsx | 19 ++++- .../src/components/Input/index.tsx | 84 +++++++++++++++++-- .../src/components/InputBase/index.tsx | 14 ++-- .../react-magma-docs/src/pages/api/input.mdx | 47 +++++++---- 6 files changed, 139 insertions(+), 31 deletions(-) create mode 100644 .changeset/fix-input-help-link.md diff --git a/.changeset/fix-input-help-link.md b/.changeset/fix-input-help-link.md new file mode 100644 index 0000000000..6c4e13b12b --- /dev/null +++ b/.changeset/fix-input-help-link.md @@ -0,0 +1,5 @@ +--- +'react-magma-dom': patch +--- + +fix(Input): Style update: Fix HelpLink position on inputs. \ No newline at end of file diff --git a/packages/react-magma-dom/src/components/FormFieldContainer/FormFieldContainer.tsx b/packages/react-magma-dom/src/components/FormFieldContainer/FormFieldContainer.tsx index 15c6ee5d31..3b4024e4f9 100644 --- a/packages/react-magma-dom/src/components/FormFieldContainer/FormFieldContainer.tsx +++ b/packages/react-magma-dom/src/components/FormFieldContainer/FormFieldContainer.tsx @@ -125,6 +125,7 @@ const StyledFormFieldContainer = styled.div<{ // Input and helper text
wrapper based on labelPosition. const StyledInputWrapper = styled.div` flex: 1 1 auto; + align-self: center; `; // If the labelPosition is set to 'left' then a
wraps the Input, errorMessage, helperMessage, and CharacterCounter for proper styling alignment. diff --git a/packages/react-magma-dom/src/components/Input/Input.stories.tsx b/packages/react-magma-dom/src/components/Input/Input.stories.tsx index bbb5805b73..7fa03756f3 100644 --- a/packages/react-magma-dom/src/components/Input/Input.stories.tsx +++ b/packages/react-magma-dom/src/components/Input/Input.stories.tsx @@ -8,6 +8,7 @@ import { IconButton } from '../IconButton'; import { InputIconPosition, InputSize, InputType } from '../InputBase'; import { LabelPosition } from '../Label'; import { Tooltip } from '../Tooltip'; +import { Spacer } from '../Spacer'; const Template: Story = args => ( <> @@ -62,6 +63,18 @@ export default { options: InputType, }, }, + labelText: { + control: 'text', + description: 'Label for the input', + }, + helperMessage: { + control: 'text', + description: 'Helper message displayed below the input', + }, + errorMessage: { + control: 'text', + description: 'Error message displayed below the input', + }, }, errorMessage: '', } as Meta; @@ -183,7 +196,7 @@ export const HelpLink = args => { /> -
+ { /> + { }; HelpLink.args = { ...Default.args, + errorMessage: '', + helperMessage: 'Helper Message', + labelText: 'Label Text', }; HelpLink.parameters = { controls: { exclude: ['isInverse', 'type', 'iconPosition','isLabelVisuallyHidden','labelPosition' ] }, diff --git a/packages/react-magma-dom/src/components/Input/index.tsx b/packages/react-magma-dom/src/components/Input/index.tsx index 342aeebf49..c71deb9f90 100644 --- a/packages/react-magma-dom/src/components/Input/index.tsx +++ b/packages/react-magma-dom/src/components/Input/index.tsx @@ -5,8 +5,75 @@ import { useGenerateId } from '../../utils'; import { FormFieldContainer, FormFieldContainerBaseProps, + FormFieldContainerProps, } from '../FormFieldContainer'; -import { InputBase, InputBaseProps, InputSize } from '../InputBase'; +import { + getHelpIconButtonSize, + InputBase, + InputBaseProps, + InputSize, + isLeftOrHidden, +} from '../InputBase'; +import { LabelPosition } from '../Label'; +import styled from '@emotion/styled'; +import { ThemeContext } from '../../theme/ThemeContext'; +import { Theme } from '@emotion/react'; + +const getLabelStyles = ( + props: FormFieldContainerProps & + React.RefAttributes & { theme?: Theme } & { + labelPosition?: LabelPosition; + InputSize?: InputSize; + } & { theme: Theme } +) => { + const marginBlock = isLeftOrHidden(props) + ? '0' + : `0 ${props.theme.spaceScale.spacing03}`; + const marginInline = isLeftOrHidden(props) + ? `0 ${props.theme.spaceScale.spacing03}` + : '0'; + const maxWidth = isLeftOrHidden(props) + ? 'auto' + : `calc(100% - ${getHelpIconButtonSize(props)} - ${ + props.theme.spaceScale.spacing03 + })`; + let minHeight: string; + if (props.labelPosition === LabelPosition.left) { + minHeight = + props.InputSize === InputSize.large + ? props.theme.spaceScale.spacing11 + : props.theme.spaceScale.spacing09; + } else { + minHeight = 'auto'; + } + const justifyContent = isLeftOrHidden(props) ? 'end' : 'start'; + + return { marginBlock, marginInline, maxWidth, minHeight, justifyContent }; +}; + +const StyledFormFieldContainer = styled(FormFieldContainer)<{ + labelPosition?: LabelPosition; + InputSize?: InputSize; +}>` + position: relative; + align-items: start; + + label { + ${props => { + const { marginBlock, marginInline, maxWidth, minHeight, justifyContent } = + getLabelStyles(props); + return ` + margin-block: ${marginBlock}; + margin-inline: ${marginInline}; + max-width: ${maxWidth}; + min-height: ${minHeight}; + justify-content: ${justifyContent}; + `; + }} + display: flex; + align-items: center; + } +`; export interface InputProps extends Omit, @@ -46,7 +113,8 @@ export const Input = React.forwardRef( const maxCharacters = typeof maxCount === 'number' ? maxCount : maxLength; - const maxLengthNum = !hasCharacterCounter && maxLength ? maxLength : undefined; + const maxLengthNum = + !hasCharacterCounter && maxLength ? maxLength : undefined; const isInverse = useIsInverse(props.isInverse); @@ -54,6 +122,8 @@ export const Input = React.forwardRef( value?.toString().length ); + const theme = React.useContext(ThemeContext); + React.useEffect(() => { setCharacterLength(value?.toString().length); }, [value]); @@ -71,7 +141,7 @@ export const Input = React.forwardRef( } return ( - ( maxCount={maxCount} messageStyle={messageStyle} testId={testId && `${testId}-formFieldContainer`} + theme={theme} + InputSize={inputSize} > ( > {children} - + ); } ); diff --git a/packages/react-magma-dom/src/components/InputBase/index.tsx b/packages/react-magma-dom/src/components/InputBase/index.tsx index 89db223788..e02a2ad1e6 100644 --- a/packages/react-magma-dom/src/components/InputBase/index.tsx +++ b/packages/react-magma-dom/src/components/InputBase/index.tsx @@ -427,7 +427,7 @@ function getHelpLinkSVGSize(props) { return `${theme.iconSizes.small}px`; } -function getHelpIconButtonSize(props) { +export function getHelpIconButtonSize(props) { const { inputSize, theme } = props; if (inputSize === InputSize.large) { @@ -570,7 +570,7 @@ function getIconSize( } } -const isLeftOrHidden = ({ +export const isLeftOrHidden = ({ labelPosition, isLabelVisuallyHidden, }: { @@ -584,16 +584,15 @@ export const HelpLinkContainer = styled.span<{ theme: ThemeInterface; isLabelVisuallyHidden?: boolean; }>` - position: relative; + position: ${props => (isLeftOrHidden(props) ? 'relative' : 'absolute')}; display: flex; align-items: center; justify-content: center; height: ${props => (isLeftOrHidden(props) ? 'auto' : 'fit-content')}; margin-inline-start: ${props => - isLeftOrHidden(props) ? `${props.theme.spaceScale.spacing03}` : 0}; - transform: translate( - ${props => (isLeftOrHidden(props) ? '0' : '-100%')}, + isLeftOrHidden(props) ? `${props.theme.spaceScale.spacing03}` : 'auto'}; + transform: translateY( ${props => isLeftOrHidden(props) ? '0' @@ -604,9 +603,10 @@ export const HelpLinkContainer = styled.span<{ width: ${props => getHelpLinkSVGSize(props)}; } button { - height: ${props => getHelpIconButtonSize(props)}; + height: ${props => getHelpIconButtonSize(props)}; width: ${props => getHelpIconButtonSize(props)}; } + inset-inline-end: ${props => (isLeftOrHidden(props) ? 'auto' : '0')}; `; export const InputBase = React.forwardRef( diff --git a/website/react-magma-docs/src/pages/api/input.mdx b/website/react-magma-docs/src/pages/api/input.mdx index efb5121048..3769d5ba5a 100644 --- a/website/react-magma-docs/src/pages/api/input.mdx +++ b/website/react-magma-docs/src/pages/api/input.mdx @@ -287,7 +287,6 @@ export function Example() { icon={} type={InputType.email} /> - } /> - - + } onClick={onHelpLinkClick} - type={InputType.button} - size="small" - variant="link" + size={ButtonSize.small} + variant={ButtonVariant.link} /> - - + + } onClick={onHelpLinkClick} - type={InputType.button} - size="small" - variant="link" + size={ButtonSize.small} + variant={ButtonVariant.link} /> - + + } onClick={onHelpLinkClick} - type={InputType.button} - size="small" - variant="link" + size={ButtonSize.small} + variant={ButtonVariant.link} />