Skip to content

Commit

Permalink
feat(ui): implemented new input component
Browse files Browse the repository at this point in the history
  • Loading branch information
akhilmhdh committed Jan 23, 2023
1 parent 68f1887 commit b80504a
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
66 changes: 66 additions & 0 deletions frontend/src/components/v2/Input/Input.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { faEye, faMailBulk } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import type { Meta, StoryObj } from '@storybook/react';

import { Input } from './Input';

const meta: Meta<typeof Input> = {
title: 'Components/Input',
component: Input,
tags: ['v2'],
argTypes: {
isRounded: {
defaultValue: true,
type: 'boolean'
},
placeholder: {
defaultValue: 'Type anything',
type: 'string'
}
}
};

export default meta;
type Story = StoryObj<typeof Input>;

// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
export const Filled: Story = {
args: {}
};

export const Outline: Story = {
args: {
variant: 'outline'
}
};

export const Plain: Story = {
args: {
variant: 'plain'
}
};

export const Error: Story = {
args: {
isError: true
}
};

export const AutoWidth: Story = {
args: {
isFullWidth: false,
className: 'w-auto'
}
};

export const RightIcon: Story = {
args: {
rightIcon: <FontAwesomeIcon icon={faEye} />
}
};

export const LeftIcon: Story = {
args: {
leftIcon: <FontAwesomeIcon icon={faMailBulk} />
}
};
102 changes: 102 additions & 0 deletions frontend/src/components/v2/Input/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { forwardRef, InputHTMLAttributes, ReactNode } from 'react';
import { cva, VariantProps } from 'cva';
import { twMerge } from 'tailwind-merge';

type Props = {
placeholder?: string;
isFullWidth?: boolean;
isRequired?: boolean;
leftIcon?: ReactNode;
rightIcon?: ReactNode;
};

const inputVariants = cva(
'input w-full py-2 text-gray-400 placeholder-gray-500 placeholder-opacity-50',
{
variants: {
size: {
xs: ['text-xs'],
sm: ['text-sm'],
md: ['text-md'],
lg: ['text-lg']
},
isRounded: {
true: ['rounded-md'],
false: ''
},
variant: {
filled: ['bg-bunker-800', 'text-gray-400'],
outline: ['bg-transparent'],
plain: 'bg-transparent outline-none'
},
isError: {
true: 'focus:ring-red/50 placeholder-red-300',
false: 'focus:ring-primary/50'
}
},
compoundVariants: []
}
);

const inputParentContainerVariants = cva('inline-flex items-center border relative', {
variants: {
isRounded: {
true: ['rounded-md'],
false: ''
},
isError: {
true: 'border-red',
false: 'border-mineshaft-400'
},
isFullWidth: {
true: 'w-full',
false: ''
},
variant: {
filled: ['bg-bunker-800', 'text-gray-400'],
outline: ['bg-transparent'],
plain: 'border-none'
}
}
});

export type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> &
VariantProps<typeof inputVariants> &
Props;

export const Input = forwardRef<HTMLInputElement, InputProps>(
(
{
className,
isRounded = true,
isFullWidth = true,
isError = false,
isRequired,
leftIcon,
rightIcon,
variant = 'filled',
size = 'md',
...props
},
ref
): JSX.Element => {
return (
<div className={inputParentContainerVariants({ isRounded, isError, isFullWidth, variant })}>
{leftIcon && <span className="absolute left-0 ml-2">{leftIcon}</span>}
<input
{...props}
required={isRequired}
ref={ref}
className={twMerge(
leftIcon ? 'pl-9' : 'pl-4',
rightIcon ? 'pr-9' : 'pr-4',
inputVariants({ className, isError, size, isRounded, variant })
)}
/>
{rightIcon && <span className="absolute right-0 mr-2">{rightIcon}</span>}
</div>
);
}
);

Input.displayName = 'Input';
2 changes: 2 additions & 0 deletions frontend/src/components/v2/Input/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { InputProps } from './Input';
export { Input } from './Input';

0 comments on commit b80504a

Please sign in to comment.