Skip to content

Commit

Permalink
feat!: remove default left icon in the input component (#537)
Browse files Browse the repository at this point in the history
  • Loading branch information
G100g committed Jul 24, 2024
1 parent 5c3c1c6 commit a684ee7
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 33 deletions.
40 changes: 29 additions & 11 deletions src/components/Input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import { cn } from '@/lib/utils'
import { cva } from 'class-variance-authority'
import { BsX, BsPersonFill, BsSearch } from '@/assets'
import { BsX, BsSearch } from '@/assets'

const leftSideVariants = cva(['flex', 'items-center', 'text-inherit'])

Expand Down Expand Up @@ -70,21 +70,38 @@ const inputVariants = cva(
}
)

type InputType =
| 'color'
| 'date'
| 'datetime-local'
| 'email'
| 'month'
| 'number'
| 'password'
| 'search'
| 'tel'
| 'text'
| 'time'
| 'url'
| 'week'
// eslint-disable-next-line @typescript-eslint/ban-types
| (string & {})

interface InputProps extends React.HTMLProps<HTMLInputElement> {
variant: 'primary' | 'error' | 'success'
type: 'text' | 'search'
type: InputType
formClassName?: string
leftSideClassName?: string
leftSideChild?: React.ReactNode
rightSideChild?: React.ReactNode
onClear: () => void
}

const convertTypeToComponent = {
left: {
text: <BsPersonFill />,
const convertTypeToLeftComponent = (type: InputType) => {
const mapping: Partial<Record<InputType, React.ReactNode>> = {
search: <BsSearch />
}
return mapping[type] ?? null
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
Expand All @@ -102,17 +119,18 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
},
ref
) => {
const leftSideComponent =
leftSideChild ?? convertTypeToComponent.left[`${type}`]
const leftSideComponent = leftSideChild ?? convertTypeToLeftComponent(type)
const rightSideComponent = rightSideChild ?? <BsX strokeWidth={0.6} />

return (
<label className={cn(formVariants({ variant }), formClassName)}>
<div className={cn(leftSideVariants(), leftSideClassName)}>
{leftSideComponent}
</div>
{leftSideComponent && (
<div className={cn(leftSideVariants(), leftSideClassName)}>
{leftSideComponent}
</div>
)}
<input
type="text" //for now only accept text
type={type}
className={cn(inputVariants({ variant }), className)}
ref={ref}
{...props}
Expand Down
47 changes: 33 additions & 14 deletions stories/Input/Docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import * as InputStories from './Input.stories'

<Meta of={InputStories} />

# Input (Text / Search)
# Input

A search is a user interface element that includes a search bar or input field, often accompanied by a search button or icon. It enables users to enter keywords or queries and initiate a search for specific content or information within an application or website. The search component helps users quickly find relevant data or resources by matching their input with the available content. This only supports search and text inputs currently. ß
A search is a user interface element that includes a search bar or input field, often accompanied by a search button or icon. It enables users to enter keywords or queries and initiate a search for specific content or information within an application or website. The search component helps users quickly find relevant data or resources by matching their input with the available content.

## Primary Text

Expand All @@ -28,17 +28,21 @@ A search is a user interface element that includes a search bar or input field,

<Canvas of={InputStories.Search} />

## Left Icon

<Canvas of={InputStories.LeftIcon} />

## Attributes

This component accepts all attributes for the input component of type text, with the addition of `onClear` function which declares the clear button functionality.

## Input

```tsx
import React from 'react'
iimport React, { HTMLInputTypeAttribute } from 'react'
import { cn } from '@/lib/utils'
import { cva } from 'class-variance-authority'
import { BsX, BsPersonFill, BsSearch } from '@/assets'
import { BsX, BsSearch } from '@/assets'

const leftSideVariants = cva(['flex', 'items-center', 'text-inherit'])

Expand Down Expand Up @@ -109,19 +113,33 @@ const inputVariants = cva(

interface InputProps extends React.HTMLProps<HTMLInputElement> {
variant: 'primary' | 'error' | 'success'
type: 'text' | 'search'
type:
| 'color'
| 'date'
| 'datetime-local'
| 'email'
| 'month'
| 'number'
| 'password'
| 'search'
| 'tel'
| 'text'
| 'time'
| 'url'
| 'week'
| (string & {})
formClassName?: string
leftSideClassName?: string
leftSideChild?: React.ReactNode
rightSideChild?: React.ReactNode
onClear: () => void
}

const convertTypeToComponent = {
left: {
text: <BsPersonFill />,
const convertTypeToLeftComponent = (type: HTMLInputTypeAttribute) => {
const mapping: Partial<Record<HTMLInputTypeAttribute, React.ReactNode>> = {
search: <BsSearch />
}
return mapping[type] ?? null
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
Expand All @@ -139,17 +157,18 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
},
ref
) => {
const leftSideComponent =
leftSideChild ?? convertTypeToComponent.left[`${type}`]
const leftSideComponent = leftSideChild ?? convertTypeToLeftComponent(type)
const rightSideComponent = rightSideChild ?? <BsX strokeWidth={0.6} />

return (
<label className={cn(formVariants({ variant }), formClassName)}>
<div className={cn(leftSideVariants(), leftSideClassName)}>
{leftSideComponent}
</div>
{leftSideComponent && (
<div className={cn(leftSideVariants(), leftSideClassName)}>
{leftSideComponent}
</div>
)}
<input
type="text" //for now only accept text
type={type}
className={cn(inputVariants({ variant }), className)}
ref={ref}
{...props}
Expand Down
6 changes: 2 additions & 4 deletions stories/Input/Input.example.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react'
import { Input, InputProps } from '@/index'

const InputDemo = ({ variant, type, disabled }: InputProps) => {
const InputDemo = (props: Omit<InputProps, 'onChange' | 'onClear'>) => {
const [value, setValue] = useState('')
const handleOnClear = () => {
setValue('')
Expand All @@ -12,11 +12,9 @@ const InputDemo = ({ variant, type, disabled }: InputProps) => {
return (
<Input
value={value}
variant={variant}
type={type}
onClear={handleOnClear}
onChange={handleOnChange}
disabled={disabled}
{...props}
/>
)
}
Expand Down
16 changes: 12 additions & 4 deletions stories/Input/Input.stories.ts → stories/Input/Input.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react'

import { InputDemo as Input } from './Input.example'
import { BsPersonFill } from 'react-icons/bs'

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
Expand All @@ -10,11 +11,10 @@ const meta = {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered'
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
// // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
argTypes: {
checked: {
options: [true, false, 'indeterminate'],
control: { type: 'radio' }
leftSideChild: {
control: false
},
className: {
controle: 'text',
Expand Down Expand Up @@ -60,3 +60,11 @@ export const Search: Story = {
type: 'search'
}
}

export const LeftIcon: Story = {
args: {
variant: 'primary',
type: 'text',
leftSideChild: <BsPersonFill />
}
}

0 comments on commit a684ee7

Please sign in to comment.