Skip to content

Commit

Permalink
Adicionado novo estilo do input (#169)
Browse files Browse the repository at this point in the history
* added new input style

* fix defaultValue input mask
  • Loading branch information
mdlucas authored Jan 12, 2024
1 parent 04db8e7 commit 590f654
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 79 deletions.
140 changes: 99 additions & 41 deletions src/components/TextInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,44 @@ import {
FC,
FocusEvent,
InputHTMLAttributes,
MouseEvent,
Ref,
RefObject,
useRef,
} from 'react';
import { IMaskMixin, ReactElementProps } from 'react-imask';
import Icons from '../Icons';
import {
IconWrapperLeft,
IconWrapperRight,
Input,
Message,
PlaceholderLabel,
Wrapper,
} from './styles';

import { Input, Label, Message, PlaceholderLabel, Wrapper } from './styles';
type IconsType = keyof typeof Icons;

type InputMaskProps = ReactElementProps<any> & {
inputRef: Ref<any>;
hasError?: boolean;
hasIconLeft?: boolean;
hasIconRight?: boolean;
};

const InputMask = IMaskMixin(
({ inputRef, hasError, ...props }: InputMaskProps) => (
({
inputRef,
hasError,
hasIconRight,
hasIconLeft,
...props
}: InputMaskProps) => (
<Input
{...props}
$hasError={!!hasError}
hasIconLeft={!!hasIconLeft}
hasIconRight={!!hasIconRight}
ref={inputRef as RefObject<HTMLInputElement> | undefined}
/>
),
Expand All @@ -30,14 +50,18 @@ export type TextInputType = InputHTMLAttributes<HTMLInputElement> & {
style?: any;
textInputStyle?: any;
maskOptions?: any;
label: string;
label?: string;
message?: string;
error?: string;
name: string;
id: string;
maxLength?: number;
value: string;
autoFocus?: boolean;
iconRight?: IconsType;
iconLeft?: IconsType;
onClickIconRight?: (event: MouseEvent<HTMLElement>) => void;
onClickIconLeft?: (event: MouseEvent<HTMLElement>) => void;
onChange: (e: Partial<ChangeEvent<any>>) => void;
onBlur?: (
e:
Expand All @@ -59,6 +83,8 @@ const TextInput: FC<TextInputType> = ({
onChange,
onBlur,
onFocus,
onClickIconLeft,
onClickIconRight,
style,
label,
textInputStyle,
Expand All @@ -68,11 +94,16 @@ const TextInput: FC<TextInputType> = ({
maxLength,
autoFocus,
maskOptions,
iconRight,
iconLeft,
...rest
}) => {
const hasValue = value?.length > 0;
const hasError = error ? error.length > 0 : false;

const RightIconComponent: any = iconRight && Icons[iconRight];
const LeftIconComponent: any = iconLeft && Icons[iconLeft];

const onAccept = (_, __, event?: InputEvent | undefined) => {
onChange(event as Partial<ChangeEvent<any>>);
};
Expand All @@ -82,44 +113,71 @@ const TextInput: FC<TextInputType> = ({

return (
<Wrapper style={style}>
<Label>
{maskOptions ? (
<InputMask
{...maskOptions}
id={id}
name={name}
data-testid={id}
style={textInputStyle}
ref={ref}
inputRef={inputRef}
onAccept={onAccept}
autoFocus={autoFocus}
hasError={hasError}
{...rest}
/>
) : (
<Input
id={id}
data-testid={id}
name={name}
value={value}
style={textInputStyle}
onBlur={onBlur}
onFocus={onFocus}
onChange={onChange}
maxLength={maxLength}
autoFocus={autoFocus}
$hasError={hasError}
{...rest}
/>
)}
<PlaceholderLabel $hasError={hasError} $hasValue={hasValue}>
{label}
</PlaceholderLabel>
{error || message ? (
<Message $hasError={hasError}>{error || message}</Message>
) : null}
</Label>
{iconLeft && (
<IconWrapperLeft
clickable={!!onClickIconLeft}
onClick={onClickIconLeft}
>
<LeftIconComponent accessibility="ícone do botão" />
</IconWrapperLeft>
)}
{maskOptions ? (
<InputMask
{...maskOptions}
id={id}
name={name}
data-testid={id}
style={textInputStyle}
ref={ref}
inputRef={inputRef}
onAccept={onAccept}
autoFocus={autoFocus}
hasError={hasError}
hasIconLeft={!!iconLeft}
hasIconRight={!!iconRight}
defaultValue={value}
{...rest}
/>
) : (
<Input
id={id}
data-testid={id}
name={name}
value={value}
style={textInputStyle}
onBlur={onBlur}
onFocus={onFocus}
onChange={onChange}
maxLength={maxLength}
autoFocus={autoFocus}
$hasError={hasError}
hasIconLeft={!!iconLeft}
hasIconRight={!!iconRight}
{...rest}
/>
)}
{iconRight && (
<IconWrapperRight
clickable={!!onClickIconRight}
onClick={onClickIconRight}
>
<RightIconComponent accessibility="ícone do botão" />
</IconWrapperRight>
)}
<PlaceholderLabel
className="text-input-label"
hasIconLeft={!!iconLeft}
hasIconRight={!!iconRight}
$hasError={hasError}
$hasValue={hasValue}
>
{label}
</PlaceholderLabel>
{error || message ? (
<Message className="error-text-input" $hasError={hasError}>
{error || message}
</Message>
) : null}
</Wrapper>
);
};
Expand Down
94 changes: 56 additions & 38 deletions src/components/TextInput/styles.tsx
Original file line number Diff line number Diff line change
@@ -1,83 +1,101 @@
import styled from 'styled-components';
import { getTheme, ifStyle } from '@platformbuilders/theme-toolkit';
import { getTheme, ifStyle, pxToRem } from '@platformbuilders/theme-toolkit';

type HasIcon = {
hasIconLeft?: boolean;
hasIconRight?: boolean;
};

type PlaceholderLabelProps = {
$hasValue: boolean;
$hasError: boolean;
};
} & HasIcon;

type MessageProps = {
$hasError: boolean;
};

type InputProps = {
$hasError: boolean;
};
} & HasIcon;

const primaryMain = getTheme('brand.primary.main');
const dangerMain = getTheme('danger.main');
const textMain = getTheme('danger.main');
const fontSizeSm = getTheme('fontSizes.sm');
const fontSizeMd = getTheme('fontSizes.md');
const spacingXs = getTheme('spacing.xs');
const spacingSm = getTheme('spacing.sm');
const spacingMd = getTheme('spacing.md');
const spacingLg = getTheme('spacing.lg');
const textMain = getTheme('text.main');
const borderRadiusMd = getTheme('borderRadius.md');

const hasError = ifStyle('$hasError');

export const PlaceholderLabel = styled.span<PlaceholderLabelProps>`
position: absolute;
top: 0.9375rem;
left: 0.875rem;
top: ${pxToRem(16)};
left: ${pxToRem(14)};
line-height: 147.6%;
color: rgba(19, 19, 21, 0.6);
transition: top 0.2s;
${({ hasIconLeft }) => !!hasIconLeft && `left: ${pxToRem(36)};`}
${(props) =>
props.$hasValue &&
`top: 0; font-size: 0.9375rem; margin-bottom: 40px; color: ${primaryMain(
props,
)};`}
props.$hasValue && `top: 0; font-size: ${fontSizeMd}; margin-bottom: 40px;`}
color: ${(props) => hasError(dangerMain(props), primaryMain(props))(props)};
`;

export const Input = styled.input<InputProps>`
border: none;
border-bottom: 0.125rem solid rgba(19, 19, 21, 0.6);
width: 100%;
height: 3.5rem;
font-size: 1.0625rem;
padding-left: 0.875rem;
font-size: ${fontSizeMd}px;
line-height: 147.6%;
padding-top: 0.825rem;
padding-bottom: 0.5rem;
border-color: ${(props) => hasError(dangerMain(props), '#121212')(props)};
&:hover {
background: rgba(73, 133, 224, 0.12);
}
display: flex;
height: ${pxToRem(44)};
padding: ${spacingXs}px ${spacingSm}px ${spacingXs}px ${spacingMd}px;
${({ hasIconRight }) => !!hasIconRight && `padding-right: ${pxToRem(36)};`}
${({ hasIconLeft }) => !!hasIconLeft && `padding-left: ${pxToRem(36)};`}
align-items: center;
gap: ${pxToRem(12)};
background: ${(props) =>
!!props.$hasError ? `${dangerMain(props)}10` : `${textMain(props)}10`};
border-radius: ${borderRadiusMd}px;
border: none;
font-size: ${fontSizeSm}px;
font-style: normal;
font-weight: 400;
line-height: 150%;
&:focus {
border-color: ${(props) =>
hasError(dangerMain(props), primaryMain(props))(props)};
outline: none;
}
&:focus + ${PlaceholderLabel} {
top: 0;
font-size: 0.9375rem;
margin-bottom: 40px;
color: ${(props) => hasError(dangerMain(props), primaryMain(props))(props)};
}
background: #eff1f2;
`;

export const Message = styled.span<MessageProps>`
font-size: 0.9375rem;
font-size: ${fontSizeMd}px;
color: ${(props) => hasError(dangerMain(props), textMain(props))(props)};
letter-spacing: 0.0275rem;
margin: 0.125rem 0.875rem;
margin: ${spacingXs}px ${spacingMd}px;
`;

export const Label = styled.label``;

export const Wrapper = styled.div`
margin-bottom: 1.5rem;
margin-bottom: ${spacingLg}px;
position: relative;
`;

export const IconWrapperLeft = styled.div<{ clickable?: boolean }>`
position: absolute;
left: ${pxToRem(14)};
top: ${pxToRem(22)};
transform: translateY(-50%);
cursor: ${({ clickable }) => (!!clickable ? 'pointer' : 'default')};
`;

export const IconWrapperRight = styled.div<{ clickable?: boolean }>`
position: absolute;
right: ${pxToRem(14)};
top: ${pxToRem(22)};
transform: translateY(-50%);
cursor: ${({ clickable }) => (!!clickable ? 'pointer' : 'default')};
`;

0 comments on commit 590f654

Please sign in to comment.