Skip to content

Commit

Permalink
refactor: text input 컴포넌트 추가 (#ATR-603)
Browse files Browse the repository at this point in the history
  • Loading branch information
LC-02s committed Aug 19, 2024
1 parent da536fa commit 37b8ebf
Show file tree
Hide file tree
Showing 6 changed files with 396 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
@import 'badge';
@import 'switch';
@import 'chip';
@import 'text-input';
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './checkbox'
export * from './badge'
export * from './switch'
export * from './chip'
export * from './text-input'
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/* eslint-disable tailwindcss/no-custom-classname */
import React from 'react'
import type { Meta, StoryObj } from '@storybook/react'
import TextInput from './TextInput'
import { $variable } from '../../token'

const meta: Meta<typeof TextInput> = {
title: 'Inputs/TextInput',
component: TextInput,
tags: ['autodocs'],
parameters: {
componentSubtitle: 'Attraction에서 사용되는 인풋 컴포넌트입니다.',
},
argTypes: {
state: {
description: '인풋의 상태를 지정합니다.',
control: 'select',
options: ['default', 'danger', 'warn', 'success'],
table: {
type: {
summary: ['default', 'danger', 'warn', 'success'].join(' | '),
},
defaultValue: { summary: 'default' },
},
},
size: {
description: '인풋의 크기를 지정합니다.',
control: 'select',
options: ['md', 'lg'],
table: {
type: { summary: ['md', 'lg'].join(' | ') },
defaultValue: { summary: 'md' },
},
},
round: {
description: '인풋의 모서리 형태를 지정합니다.',
control: 'select',
options: ['xs', 'sm', 'md', 'lg', 'full'],
table: {
type: { summary: ['xs', 'sm', 'md', 'lg', 'full'].join(' | ') },
defaultValue: { summary: 'sm' },
},
},
disabled: {
description: '인풋의 비활성화 상태를 지정합니다.',
control: 'boolean',
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'undefined' },
},
},
withBackground: {
description: '인풋 배경색의 기본 상태를 지정합니다.',
control: 'boolean',
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'undefined' },
},
},
required: {
description: '필수 인풋 여부를 지정합니다. label 옵션과 함께 사용됩니다.',
control: 'boolean',
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'undefined' },
},
},
label: {
description: '인풋의 label을 지정합니다.',
control: 'text',
table: {
type: { summary: 'ReactNode | string' },
defaultValue: { summary: 'undefined' },
},
},
placeholder: {
description: '인풋의 placeholder를 지정합니다.',
control: 'text',
table: {
type: { summary: 'string' },
defaultValue: { summary: 'undefined' },
},
},
description: {
description: '인풋의 설명(하단 텍스트)을 지정합니다.',
control: 'text',
table: {
type: { summary: 'ReactNode | string' },
defaultValue: { summary: 'undefined' },
},
},
},
}

export default meta

type Story = StoryObj<typeof meta>

const style: React.CSSProperties = {
display: 'block',
padding: '30px',
width: '50%',
}

export const TextInputDefault: Story = {
render: (props) => (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<div style={style}>
<TextInput {...props} />
</div>
<div
className="dark"
style={{ ...style, backgroundColor: $variable.color.gray800 }}>
<TextInput {...props} />
</div>
</div>
),
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,30 @@ export const variants = {
danger: getTextInputModifier('danger'),
warn: getTextInputModifier('warn'),
success: getTextInputModifier('success'),
info: getTextInputModifier('info'),
},
size: {
md: '',
lg: getTextInputModifier('size-lg'),
},
round: {
xs: getTextInputModifier('round-xs'),
sm: '',
md: getTextInputModifier('round-md'),
lg: getTextInputModifier('round-lg'),
full: getTextInputModifier('round-full'),
},
background: {
none: '',
with: getTextInputModifier('background'),
},
}

export const textInputVariants = cva(textInputClassName, {
variants,
defaultVariants: { state: 'default' },
defaultVariants: {
state: 'default',
size: 'md',
round: 'sm',
background: 'none',
},
})
Original file line number Diff line number Diff line change
@@ -1,15 +1,65 @@
import React from 'react'
import { cn } from '@attraction/utils'
import { textInputVariants, variants } from './TextInput.style'

type TextInputVariant = typeof variants

interface TextProps
extends React.DetailedHTMLProps<
React.InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement
extends Omit<
React.DetailedHTMLProps<
React.InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement
>,
'size'
> {
state?: keyof TextInputVariant['state']
size?: keyof TextInputVariant['size']
round?: keyof TextInputVariant['round']
withBackground?: boolean
label?: React.ReactNode | string
required?: boolean
description?: React.ReactNode | string
}

const TextInput = React.forwardRef<HTMLInputElement, TextProps>(
({ withBackground, ...props }, ref) => <input ref={ref} {...props} />,
(
{
className,
id,
type,
label,
required,
state,
size,
round,
withBackground,
style,
description,
...props
},
ref,
) => (
<div
className={cn(
textInputVariants({
state,
size,
round,
background: withBackground ? 'with' : null,
}),
className,
)}
style={style}>
{label && (
<label htmlFor={id}>
{label}
{required && <span>*</span>}
</label>
)}
<input ref={ref} id={id} type={type || 'text'} {...props} />
{description && <p>{description}</p>}
</div>
),
)

export default TextInput
Loading

0 comments on commit 37b8ebf

Please sign in to comment.