Skip to content

Instantly share code, notes, and snippets.

@sb-bilal-dev
Last active October 23, 2020 16:26
Show Gist options
  • Save sb-bilal-dev/037fa6966ea74e9abc8b10e2d2fdb590 to your computer and use it in GitHub Desktop.
Save sb-bilal-dev/037fa6966ea74e9abc8b10e2d2fdb590 to your computer and use it in GitHub Desktop.
Input.tsx (Code Sample)
import React, { MouseEvent, ChangeEvent, forwardRef, FocusEvent } from 'react';
import classNames from 'classnames';
import { IconName } from 'app/design-system/types/Icon';
import { Palette } from 'app/design-system/constants/Palette';
import styles from './styles.module.scss';
import { InputSize } from './types';
import IconButton from './IconButton';
import { ICON_SIZE_BY_NAME } from './constants';
export type InputProps = {
// main props
name?: string;
type?: 'text' | 'tel' | 'email' | 'password' | 'color' | 'number' | 'search' | 'url' | 'time';
value: string;
// actions
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
onFocus?: (e: FocusEvent<HTMLInputElement>) => void;
onBlur?: (e: FocusEvent<HTMLInputElement>) => void;
onMouseDown?: (e: MouseEvent<HTMLInputElement>) => void;
onMouseUp?: (e: MouseEvent<HTMLInputElement>) => void;
// additional attributes
disabled?: boolean;
placeholder?: string;
id?: string;
readOnly?: boolean;
required?: boolean;
autoComplete?: 'off' | 'on';
autoFocus?: boolean;
maxLength?: number;
minLength?: number;
// min and max work only for numeric or date-time inputs
max?: number;
min?: number;
// style attributes
size?: InputSize;
error?: boolean;
iconLeft?: IconName;
iconRight?: IconName;
onIconLeftClick?: (event: MouseEvent) => void;
onIconRightClick?: (event: MouseEvent) => void;
className?: string;
};
const Input = forwardRef<HTMLInputElement, InputProps>(({
name,
value,
type = 'text',
onChange,
onFocus,
onBlur,
onMouseDown,
onMouseUp,
disabled = false,
placeholder,
id,
readOnly,
required,
autoComplete,
autoFocus,
maxLength,
minLength,
max,
min,
size = InputSize.MEDIUM,
error = false,
iconLeft,
iconRight,
onIconLeftClick,
onIconRightClick,
className,
}, ref) => {
const rootClassName = classNames(
styles.root,
styles[size],
styles.input,
{
[styles.hasIconLeft]: iconLeft,
[styles.hasIconRight]: iconRight,
[styles.error]: error,
[styles.disabled]: disabled,
},
className,
);
return (
<div className={rootClassName}>
{iconLeft && (
<IconButton
className={styles.iconLeft}
icon={iconLeft}
size={ICON_SIZE_BY_NAME[size]}
color={disabled ? Palette.grayscale3 : undefined}
onClick={onIconLeftClick}
disabled={disabled} />
)}
<input
ref={ref}
id={id}
placeholder={placeholder}
disabled={disabled}
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
type={type}
name={name}
value={value}
required={required}
readOnly={readOnly}
autoComplete={autoComplete}
autoFocus={autoFocus}
maxLength={maxLength}
minLength={minLength}
max={max}
min={min} />
{iconRight && (
<IconButton
className={styles.iconRight}
icon={iconRight}
size={ICON_SIZE_BY_NAME[size]}
color={disabled ? Palette.grayscale3 : undefined}
onClick={onIconRightClick}
disabled={disabled} />
)}
</div>
);
});
export default Input;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment