Skip to content

Commit

Permalink
refactor: select, dimmed 컴포넌트 추가 (#ATR-603)
Browse files Browse the repository at this point in the history
  • Loading branch information
LC-02s committed Aug 27, 2024
1 parent f6dfc9a commit 5efc3fa
Show file tree
Hide file tree
Showing 17 changed files with 831 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
align-items: center;
gap: 0.5rem;
width: auto;
height: 2.5rem;
min-height: 2.5rem;
height: auto;
box-sizing: border-box;
padding: 0.5rem 0.75rem;
border: 0.0625rem solid variable.$ds-gray-100;
Expand Down Expand Up @@ -541,43 +542,48 @@
}

&--size-xs {
height: 2rem;
min-height: 2rem;
font-size: variable.$ds-font-size-100;

&.ds-button--square {
width: 2rem;
height: 2rem;
}
}
&--size-sm {
height: 2.25rem;
min-height: 2.25rem;
font-size: variable.$ds-font-size-200;

&.ds-button--square {
width: 2.25rem;
height: 2.25rem;
}
}
&--size-md {
height: 2.5rem;
min-height: 2.5rem;
font-size: variable.$ds-font-size-300;

&.ds-button--square {
width: 2.5rem;
height: 2.5rem;
}
}
&--size-lg {
height: 3rem;
min-height: 3rem;
font-size: variable.$ds-font-size-400;

&.ds-button--square {
width: 3rem;
height: 3rem;
}
}
&--size-xl {
height: 3.75rem;
min-height: 3.75rem;
font-size: variable.$ds-font-size-500;

&.ds-button--square {
width: 3.75rem;
height: 3.75rem;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { cn } from '@attraction/utils'
import React from 'react'

interface DimmedProps
extends React.DetailedHTMLProps<
React.HTMLAttributes<HTMLDivElement>,
HTMLDivElement
> {}

const Dimmed = React.forwardRef<HTMLDivElement, DimmedProps>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn('ds-dimmed', className)} {...props} />
),
)

export default Dimmed
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@use '../../token/variable';

.ds-dimmed {
position: absolute;
z-index: -1;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
padding: 0px;
margin: 0px;
border: none;
background-color: variable.$ds-dimmed-light;
.dark & {
background-color: variable.$ds-dimmed-dark;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Dimmed } from './Dimmed'
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
@import 'chip';
@import 'text-input';
@import 'search-input';
@import 'label';
@import 'select';
@import 'dimmed';
3 changes: 3 additions & 0 deletions packages/design-system/packages/core/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ export * from './chip'
export * from './text-input'
export * from './hidden-text'
export * from './search-input'
export * from './label'
export * from './select'
export * from './dimmed'
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import type { DefaultSelectState } from './Select.type'

export const SelectContext = React.createContext<DefaultSelectState | null>(
null,
)

export function useSelect() {
const context = React.useContext(SelectContext)

if (!context) {
throw new Error('useSelect is only available within SelectProvider.')
}
return context
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import React from 'react'
import type { Meta, StoryObj } from '@storybook/react'
import Select from './Select'
import { $variable } from '../../token'

const meta: Meta<typeof Select> = {
title: 'Inputs/Select',
component: Select,
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'],
table: {
type: { summary: ['xs', 'sm', 'md'].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' },
},
},
mobile: {
description: '모바일 여부를 지정합니다. 옵션의 스타일에 영향을 줍니다.',
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%',
}

type Library = 'React' | 'Vue' | 'Angular' | 'Svelte'

export const SelectDefault: Story = {
render: (props) => {
const libStore = React.useState<Library>('React')
return (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<div style={style}>
<Select {...props} store={libStore}>
<Select.Option value="React" />
<Select.Option value="Vue" />
<Select.Option value="Angular" />
<Select.Option value="Svelte" />
</Select>
</div>
<div
className="dark"
style={{ ...style, backgroundColor: $variable.color.gray800 }}>
<Select {...props}>
<Select.Option value="React" />
<Select.Option value="Vue" />
<Select.Option value="Angular" />
<Select.Option value="Svelte" />
</Select>
</div>
</div>
)
},
}

export const SelectWithScroll: Story = {
render: (props) => {
const libStore = React.useState<Library>('React')
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}>
<Select {...props} store={libStore} style={{ width: '50%' }}>
<Select.Option value="React" />
<Select.Option value="Vue" />
<Select.Option value="Angular" />
<Select.Option value="Svelte" />
</Select>
</div>
)
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { cva } from 'class-variance-authority'

const selectClassName = 'ds-select'
const getSelectModifier = (name: string) => `${selectClassName}--${name}`

export const selectInputClassName = `${selectClassName}__input`
export const selectOptionClassName = `${selectClassName}__option`
export const selectOptionClassNameWithMobileModifier = `${selectOptionClassName}--mobile`

export const variants = {
state: {
default: '',
danger: getSelectModifier('danger'),
warn: getSelectModifier('warn'),
success: getSelectModifier('success'),
},
size: {
md: '',
lg: getSelectModifier('size-lg'),
},
round: {
xs: getSelectModifier('round-xs'),
sm: '',
md: getSelectModifier('round-md'),
},
background: {
none: '',
with: getSelectModifier('background'),
},
}

export const selectVariants = cva(selectClassName, {
variants,
defaultVariants: {
state: 'default',
size: 'md',
round: 'sm',
background: 'none',
},
})
Loading

0 comments on commit 5efc3fa

Please sign in to comment.