๐ŸŽจ TagBadge ๋ฆฌํŒฉํ„ฐ๋ง: ํŒ€ ๊ฐ„ UI ์ผ๊ด€์„ฑ์„ ์œ„ํ•œ ๋‹จ์ผ ์ปดํฌ๋„ŒํŠธํ™”

์กฐ์ค€ํ˜•ยท2025๋…„ 10์›” 29์ผ

์ต๋ช… ๊ณ ๋ฏผํ•จ

๋ชฉ๋ก ๋ณด๊ธฐ
6/6

1. ๋ฌธ์ œ ์ธ์‹

ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๋‹ค๋ฅธ ํŒ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” โ€˜ํƒœ๊ทธ ๋ฑƒ์ง€(TagBadge)โ€™ ์Šคํƒ€์ผ์ด ์กฐ๊ธˆ์”ฉ ๋‹ฌ๋ผ์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, best ํƒœ๊ทธ์™€ author(๊ธ€์“ด์ด) ํƒœ๊ทธ๊ฐ€ ๊ฐ๊ฐ ๋ณ„๋„๋กœ ๋งŒ๋“ค์–ด์ ธ ์žˆ์—ˆ๊ณ , ์Šคํƒ€์ผ์ด ๋น„์Šทํ•จ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ์—ˆ๋‹ค.

์ด๋Ÿฐ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๋‚ณ๋Š”๋‹ค.

  • ์ฝ”๋“œ ์ค‘๋ณต ์ฆ๊ฐ€
  • ์œ ์ง€๋ณด์ˆ˜ ๋‚œ์ด๋„ ์ƒ์Šน (์ƒ‰์ƒ, ์—ฌ๋ฐฑ ๋“ฑ ์ˆ˜์ • ์‹œ ์—ฌ๋Ÿฌ ๊ณณ์„ ๊ณ ์ณ์•ผ ํ•จ)
  • ๋””์ž์ธ ์‹œ์Šคํ…œ ์ผ๊ด€์„ฑ ๋ถ•๊ดด

๊ทธ๋ž˜์„œ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•˜๋‚˜๋กœ ํ†ตํ•ฉํ•˜๊ณ , variant prop์œผ๋กœ ์ƒํƒœ๋ฅผ ๊ตฌ๋ถ„ํ•˜๋„๋ก ๋ฆฌํŒฉํ„ฐ๋งํ–ˆ๋‹ค.


2. ๋ฆฌํŒฉํ„ฐ๋ง ๋ชฉํ‘œ

๋ฆฌํŒฉํ„ฐ๋ง์˜ ํ•ต์‹ฌ์€ "ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๋‹ค์–‘ํ•œ ์ƒํƒœ๋ฅผ ํ‘œํ˜„" ํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.

๊ตฌ์ฒด์ ์ธ ๋ชฉํ‘œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • variant๋ฅผ ํ†ตํ•ด ํƒœ๊ทธ ํƒ€์ž…(default, author) ๊ตฌ๋ถ„
  • ํฌ๊ธฐ ํ”„๋ฆฌ์…‹(size) ์œ ์ง€
  • ์„ ํƒ ์ƒํƒœ(selected)๋Š” ์‹œ๊ฐ์ ์ธ ๊ฐ•์กฐ ํ‘œ์‹œ ์šฉ๋„๋กœ ์‚ฌ์šฉ
  • ํŒ€ ๊ฐ„ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ

3. ๊ตฌํ˜„ ๊ณผ์ •

๐Ÿ’ก ๊ธฐ์กด ๊ตฌ์กฐ

๊ธฐ์กด TagBadge๋Š” ๋‹จ์ผ ์ƒ‰์ƒ ์ฒด๊ณ„๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋‹ค.

selected ? colorMap.main : colorMap.neutral

์ฆ‰, ์„ ํƒ ์ƒํƒœ๋งŒ ๊ตฌ๋ถ„ ๊ฐ€๋Šฅํ–ˆ์„ ๋ฟ,

โ€˜๊ธ€์“ด์ด(author)โ€™๋‚˜ โ€˜๋ฒ ์ŠคํŠธ(best)โ€™์ฒ˜๋Ÿผ ๋ณ„๋„์˜ ์‹œ๊ฐ์  ์Šคํƒ€์ผ์„ ์ ์šฉํ•  ๋ฐฉ๋ฒ•์ด ์—†์—ˆ๋‹ค.


๐Ÿ’ก ๊ฐœ์„  ๋ฐฉํ–ฅ

variant prop์„ ์ถ”๊ฐ€ํ•˜๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ƒ‰์ƒ ๋งคํ•‘์„ ๋‹ฌ๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ƒํƒœ๋ณ„๋กœ ์™„์ „ํžˆ ๋‹ค๋ฅธ ์Šคํƒ€์ผ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉด์„œ๋„,

๊ณตํ†ต๋œ ์ปดํฌ๋„ŒํŠธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.


4. ์ตœ์ข… ์ฝ”๋“œ

import { memo, type ComponentPropsWithoutRef, type ReactNode } from 'react'

type TagBadgeProps = ComponentPropsWithoutRef<'button'> & {
  children: ReactNode
  selected?: boolean
  size?: 'sm' | 'md'
  variant?: 'default' | 'author'
}

// size / color ๋งคํ•‘
const sizeMap = {
  sm: 'h-6 px-2.5 text-[10px]',
  md: 'py-1 px-3 text-xs',
} as const

const colorMap = {
  neutral: 'bg-muted/50 text-muted-foreground hover:bg-muted',
  main: 'bg-primary text-primary-foreground',
  author: 'bg-secondary/20 text-secondary',
} as const

function TagBadgeBase({
  children,
  selected = false,
  size = 'md',
  variant = 'default',
  className,
  ...rest
}: TagBadgeProps) {
  const tone =
    variant === 'author'
      ? colorMap.author
      : selected
      ? colorMap.main
      : colorMap.neutral

  return (
    <buttontype="button"
      data-selected={selected ? '' : undefined}
      data-variant={variant}
      className={[
        'inline-flex items-center justify-center gap-1.5',
        'rounded-[14px] select-none whitespace-nowrap',
        'cursor-pointer',
        tone,
        'transition-colors duration-200',
        sizeMap[size],
        className ?? '',
      ].join(' ')}
      {...rest}
    >
      {children}
    </button>
  )
}

export default memo(TagBadgeBase)

5. ์‚ฌ์šฉ ์˜ˆ์‹œ

<TagBadgeBase>์ผ๋ฐ˜ ํƒœ๊ทธ</TagBadgeBase>

<TagBadgeBase selected>์„ ํƒ๋œ ํƒœ๊ทธ</TagBadgeBase>

<TagBadgeBase variant="author">๊ธ€์“ด์ด</TagBadgeBase>

<TagBadgeBase variant="author" size="sm">
  ์ž‘์„ฑ์ž
</TagBadgeBase>
Prop ์กฐํ•ฉ์„ค๋ช…
default์ผ๋ฐ˜์ ์ธ ์ค‘๋ฆฝ ํƒœ๊ทธ
selected๊ฐ•์กฐ(ํ™œ์„ฑ) ์ƒํƒœ ํ‘œํ˜„
author๊ธ€์“ด์ด ์ „์šฉ ์Šคํƒ€์ผ

6. ๋ฆฌํŒฉํ„ฐ๋ง ํšจ๊ณผ

๋ฆฌํŒฉํ„ฐ๋ง ์ดํ›„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐœ์„ ์ด ์ด๋ฃจ์–ด์กŒ๋‹ค:

  • ๐Ÿ’ก variant ๊ธฐ๋ฐ˜์œผ๋กœ ํƒœ๊ทธ ์ƒํƒœ๋ฅผ ๋ช…ํ™•ํžˆ ํ‘œํ˜„
  • ๐Ÿงฉ ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๋‹ค์–‘ํ•œ ์ƒํ™ฉ ๋Œ€์‘
  • ๐ŸŽจ ๋””์ž์ธ ํ† ํฐ๊ณผ ํ†ต์ผ๋œ ์ƒ‰์ƒ ์ฒด๊ณ„ ์œ ์ง€
  • ๐Ÿง  ํŒ€ ๊ฐ„ ์ปดํฌ๋„ŒํŠธ ์ค‘๋ณต ์ œ๊ฑฐ๋กœ ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ

7. ๋งˆ๋ฌด๋ฆฌ

์ด๋ฒˆ ๋ฆฌํŒฉํ„ฐ๋ง์˜ ํ•ต์‹ฌ์€ โ€œ์กฐ๊ฑด ๋ถ„๊ธฐ๋ฅผ JSX๊ฐ€ ์•„๋‹Œ ์Šคํƒ€์ผ ๋ ˆ๋ฒจ์—์„œ ํ•ด๊ฒฐํ•˜๊ธฐโ€์˜€๋‹ค.

variant๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์Šคํƒ€์ผ์„ ๊ด€๋ฆฌํ•˜๋ฉด, ์ƒˆ๋กœ์šด ํƒœ๊ทธ ํƒ€์ž…์ด ์ถ”๊ฐ€๋˜๋”๋ผ๋„ ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š” ์—†์ด ํ™•์žฅ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

profile
์ฝ”๋ฆฐ์ด

0๊ฐœ์˜ ๋Œ“๊ธ€