From 0b30e64e0d4576369a4fc7a8df5d0107b308e73e Mon Sep 17 00:00:00 2001 From: JinJu Date: Wed, 19 Jun 2024 14:57:18 +0900 Subject: [PATCH] DESIGN-1 Feat Chips Component --- src/core/components/Chips/Chips.stories.tsx | 40 +++++++++++++++++++++ src/core/components/Chips/index.tsx | 35 ++++++++++++++++++ src/core/components/Chips/types/index.ts | 8 +++++ 3 files changed, 83 insertions(+) create mode 100644 src/core/components/Chips/Chips.stories.tsx create mode 100644 src/core/components/Chips/index.tsx create mode 100644 src/core/components/Chips/types/index.ts diff --git a/src/core/components/Chips/Chips.stories.tsx b/src/core/components/Chips/Chips.stories.tsx new file mode 100644 index 0000000..349f783 --- /dev/null +++ b/src/core/components/Chips/Chips.stories.tsx @@ -0,0 +1,40 @@ +import { Meta } from '@storybook/react'; +import { useRef, useState } from 'react'; +import { Plus } from '@phosphor-icons/react'; + +import Chips from '@/core/components/Chips/index'; +import IconButton from '@/core/components/Button/IconButton'; + +const meta = { + title: 'core/Chips', + component: Chips, +} satisfies Meta; + +export default meta; + +export const Default = () => { + const [values, setValues] = useState(['test', 'test2', 'test3']); + const chipsRef = useRef(null); + + const handleDelete = (item: string) => { + setValues((prevValue) => prevValue.filter((v) => v !== item)); + }; + + const handleAdd = () => { + setValues((prevValues) => [...prevValues, `test${prevValues.length + 1}`]); + }; + + return ( +
+ + } + className={'flex-shrink-0'} + onClick={handleAdd} + /> +
+ ); +}; diff --git a/src/core/components/Chips/index.tsx b/src/core/components/Chips/index.tsx new file mode 100644 index 0000000..76babc9 --- /dev/null +++ b/src/core/components/Chips/index.tsx @@ -0,0 +1,35 @@ +import { useEffect } from 'react'; +import clsx from 'clsx'; + +import { ChipsParams } from '@/core/components/Chips/types'; +import Chip from '@/core/components/Chip'; + +const Chips = ({ className, rootRef, items, onDelete }: ChipsParams) => { + useEffect(() => { + if (!rootRef.current) return; + + rootRef.current.scrollTo({ + left: rootRef.current.scrollWidth, + behavior: 'smooth', + }); + }, [rootRef, items]); + + return ( +
    + {items.map((item) => ( + onDelete(item))} + className={'whitespace-nowrap px-3'} + /> + ))} +
+ ); +}; + +export default Chips; diff --git a/src/core/components/Chips/types/index.ts b/src/core/components/Chips/types/index.ts new file mode 100644 index 0000000..24efdd7 --- /dev/null +++ b/src/core/components/Chips/types/index.ts @@ -0,0 +1,8 @@ +import { HTMLAttributes, RefObject } from 'react'; + +export interface ChipsParams + extends Pick, 'className'> { + rootRef: RefObject; + items: string[]; + onDelete?: (item: string) => void; +}