Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/shared/components/ui/button/icon-button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Meta, StoryObj } from '@storybook/react'
import { IconButton } from './icon-button'
import ForwardMediumArrow from '@/assets/icons/arrow/forward-medium-arrow.svg?react'

const meta = {
title: 'Components/IconButton',
component: IconButton,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
variant: {
control: 'radio',
options: ['primary', 'secondary'],
description: '색상',
},
size: {
control: 'radio',
options: ['sm', 'md', 'lg'],
description: '버튼 크키',
},
disabled: {
control: 'boolean',
description: '비활성화 여부',
},
Icon: {
control: false,
description: '아이콘',
},
},
} satisfies Meta<typeof IconButton>

export default meta

type Story = StoryObj<typeof IconButton>

export const Default: Story = {
args: {
variant: 'secondary',
size: 'md',
Icon: <ForwardMediumArrow />,
},
}
57 changes: 57 additions & 0 deletions src/shared/components/ui/button/icon-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { cn } from '@/shared/lib/utils'
import { cva, VariantProps } from 'class-variance-authority'
import React from 'react'

const iconButtonVariants = cva(
'flex cursor-pointer items-center justify-center gap-8 border disabled:cursor-not-allowed disabled:border-gray-300 disabled:bg-gray-300',
{
variants: {
variant: {
primary:
'border-primary-500 bg-white text-primary-500 hover:bg-gray-50 focus-visible:border-primary-700 focus-visible:bg-primary-50 active:border-primary-700 active:bg-primary-700',
secondary:
'border-gray-200 bg-white text-gray-800 hover:bg-gray-50 focus-visible:border-gray-200 focus-visible:bg-gray-50 active:border-gray-200 active:bg-gray-200',
},
size: {
sm: 'size-30 rounded-8',
md: 'size-[42px] rounded-10',
lg: 'size-56 rounded-12',
},
},
defaultVariants: {
variant: 'primary',
size: 'md',
},
},
)

interface IconButtonProps
extends React.ComponentProps<'button'>,
VariantProps<typeof iconButtonVariants> {
onClick?: () => void
disabled?: boolean
Icon: React.ReactNode
className?: string
}

export function IconButton({
onClick,
disabled = false,
variant,
size,
Icon,
className,
...props
}: IconButtonProps) {
return (
<button
type={props.type ?? 'button'}
onClick={onClick}
disabled={disabled}
className={cn(iconButtonVariants({ variant, size }), className)}
{...props}
>
{Icon}
</button>
)
}