Skip to content

Commit

Permalink
Merge pull request #95 from dnd-side-project/feat/#72
Browse files Browse the repository at this point in the history
feat: Snackbar 컴포넌트 구현 및 스토리 작성
  • Loading branch information
lsy20140 committed Sep 11, 2024
2 parents 093dccd + dfe2a24 commit 3ce5be4
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function PopularCommentsList({
/>
<CheckboxBottomSheet
isOpen={bottomSheetType === 'checkbox'}
type="report"
type="commentReport"
targetId={targetId as number}
/>
</>
Expand Down
7 changes: 4 additions & 3 deletions src/components/domain/wordDetail/CommentsList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CommentBottomSheet from '@/components/shared/CommentBottomSheet'
import CommentInput from '../CommentTextarea'
import { usePathname } from 'next/navigation'
import CheckboxBottomSheet from '@/components/shared/CheckboxBottomSheet'
import Snackbar from '@/components/shared/Snackbar'

export default function CommentsList() {
const pathname = usePathname()
Expand Down Expand Up @@ -41,7 +42,7 @@ export default function CommentsList() {
/>
</div>
<SortButton
text={sortType}
sortBy={sortType}
onClick={() => openBottomSheet('filter')}
/>
</div>
Expand Down Expand Up @@ -76,7 +77,6 @@ export default function CommentsList() {
<FilterBottomSheet
isOpen={bottomSheetType === 'filter'}
selected={sortType}
setSelected={(menu) => setSortType(menu)}
target="comments"
/>
<CommentBottomSheet
Expand All @@ -87,9 +87,10 @@ export default function CommentsList() {
/>
<CheckboxBottomSheet
isOpen={bottomSheetType === 'checkbox'}
type="report"
type="commentReport"
targetId={targetId as number}
/>
<Snackbar />
</>
)
}
5 changes: 3 additions & 2 deletions src/components/shared/CheckboxBottomSheet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Checkbox from '@/components/common/Checkbox'

type BottomSheetProps = {
isOpen: boolean
type: 'report'
type: 'commentReport'
targetId?: number
}

Expand All @@ -16,7 +16,7 @@ export default function CheckboxBottomSheet({
type,
targetId,
}: BottomSheetProps) {
const { closeBottomSheet } = useUIStore()
const { closeBottomSheet, showSnackbar } = useUIStore()
const [checked, setChecked] = useState(new Set<number>())
const { title, description, options, btnText } = CHECKBOX_MENUS[type]

Expand All @@ -34,6 +34,7 @@ export default function CheckboxBottomSheet({
console.log('checked list 전송', targetId, checked)
setChecked(new Set()) // checked 리스트 초기화
closeBottomSheet()
showSnackbar(type)
}

if (!isOpen) return null
Expand Down
46 changes: 46 additions & 0 deletions src/components/shared/Snackbar/Snackbar.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { Meta, StoryObj } from '@storybook/react'
import Snackbar from '.'
import useUIStore from '@/store/useUIStore'
import { SNACKBAR_TYPE } from '@/constants/snackbar'

const meta: Meta<typeof Snackbar> = {
title: 'components/Snackbar',
component: Snackbar,
tags: ['autodocs'],
}

export default meta

type Story = StoryObj<typeof Snackbar>

export const Default: Story = {
render: () => {
const { showSnackbar } = useUIStore()
const buttons = [
{ type: 'commentAdd', text: '댓글 등록' },
{ type: 'commentEdit', text: '댓글 수정' },
{ type: 'commentDelete', text: '댓글 삭제' },
{ type: 'commentReport', text: '댓글 신고' },
{ type: 'commentBlock', text: '댓글 차단' },
{ type: 'bookmarkAdd', text: '용어 북마크' },
]
return (
<>
<div className="h-48 flex flex-col">
<div className="flex gap-2">
{buttons.map((button, idx) => (
<button
key={idx}
onClick={() => showSnackbar(button.type as SNACKBAR_TYPE)}
className="w-fit p-2 bg-white rounded-lg"
>
{button.text}
</button>
))}
</div>
<Snackbar />
</div>
</>
)
},
}
31 changes: 31 additions & 0 deletions src/components/shared/Snackbar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client'
import { SNACKBAR } from '@/constants/snackbar'
import useUIStore from '@/store/useUIStore'
import { useEffect } from 'react'

export default function Snackbar() {
const { snackbarType, showSnackbar } = useUIStore()

useEffect(() => {
showSnackbar(snackbarType)
const timer = setTimeout(() => {
showSnackbar(null)
}, 2500)

return () => clearTimeout(timer)
}, [snackbarType, showSnackbar])

if (!snackbarType) return null
return (
<div className="fixed bottom-10 left-1/2 transform -translate-x-1/2 w-full max-w-[430px]">
<div className="flex justify-between items-center bg-gray-600 text-center py-4 px-7 rounded-lg mx-4 animate-fade-in">
<p className="text-onSurface-300 text-sub2">
{SNACKBAR[snackbarType].text}
</p>
<p className="text-sub3 text-primary-400">
{SNACKBAR[snackbarType].actionText}
</p>
</div>
</div>
)
}
2 changes: 1 addition & 1 deletion src/constants/bottomSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const COMMENT_MENUS = {

// CheckboxBottomSheet에서 표기할 메뉴 목록
export const CHECKBOX_MENUS = {
report: {
commentReport: {
title: '신고하기',
description: '중복 선택 가능',
options: [
Expand Down
35 changes: 35 additions & 0 deletions src/constants/snackbar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export type SNACKBAR_TYPE =
| 'commentAdd'
| 'commentEdit'
| 'commentDelete'
| 'commentBlock'
| 'commentReport'
| 'bookmarkAdd'

export const SNACKBAR: Record<
SNACKBAR_TYPE,
{ text: string; actionText?: string }
> = {
commentAdd: {
text: '댓글이 등록되었어요',
},
commentEdit: {
text: '댓글이 수정되었어요',
},
commentDelete: {
text: '댓글이 삭제되었어요',
},

commentBlock: {
text: '댓글이 차단되었어요',
actionText: '실행취소',
},

commentReport: {
text: '댓글이 신고되었어요',
},
bookmarkAdd: {
text: '⭐️ 별별 저장소에 등록되었어요',
actionText: '저장소 가기',
},
}
19 changes: 19 additions & 0 deletions src/hooks/useSnackbarAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useRouter } from 'next/navigation'

export default function useSnackbarAction() {
const router = useRouter()

const undoCommentBlock = () => {
alert('댓글 차단 실행 취소')
}

const goToBookmark = () => {
alert('저장소 보러가기')
router.push('/bookmarks')
}

return [
{ type: 'commentBlock', onClick: undoCommentBlock },
{ type: 'bookmarkAdd', onClick: goToBookmark },
]
}
3 changes: 2 additions & 1 deletion src/hooks/usetBottomSheetAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import useUIStore from '@/store/useUIStore'

// CommentBottom 각 목록마다 다른 액션 처리하기 위한 커스텀 훅
export default function useBottomSheetAction() {
const { openBottomSheet, closeBottomSheet } = useUIStore()
const { openBottomSheet, closeBottomSheet, showSnackbar } = useUIStore()
const editComment = () => {
// 댓글 수정 UI 상태 조작 필요
alert('댓글 수정')
closeBottomSheet()
showSnackbar('commentEdit')
}

const deleteComment = () => {
Expand Down
15 changes: 8 additions & 7 deletions src/store/useUIStore.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SNACKBAR_TYPE } from '@/constants/snackbar'
import { create } from 'zustand'

type BottomSheetType = {
Expand All @@ -11,9 +12,9 @@ type UIStoreType = {
isModalOpen: boolean
openModal: () => void
closeModal: () => void
toastMessage: string | null
showToast: (message: string) => void
hideToast: () => void
snackbarType: SNACKBAR_TYPE | null
showSnackbar: (type: SNACKBAR_TYPE | null) => void
hideSnackbar: () => void
}

const useUIStore = create<UIStoreType>((set) => ({
Expand All @@ -28,10 +29,10 @@ const useUIStore = create<UIStoreType>((set) => ({
openModal: () => set({ isModalOpen: true }),
closeModal: () => set({ isModalOpen: false }),

// Toast state
toastMessage: null,
showToast: (message: string) => set({ toastMessage: message }),
hideToast: () => set({ toastMessage: null }),
// Snackbar state
snackbarType: null,
showSnackbar: (type: SNACKBAR_TYPE | null) => set({ snackbarType: type }),
hideSnackbar: () => set({ snackbarType: null }),
}))

export default useUIStore
10 changes: 10 additions & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ const config: Config = {
xs: '360px',
},
},
// snackbar animate
keyframes: {
'fade-in': {
'0%': { opacity: '0', transform: 'translateY(-5px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
},
animation: {
'fade-in': 'fade-in 0.5s ease-out',
},
},
plugins: [],
}
Expand Down

0 comments on commit 3ce5be4

Please sign in to comment.