-
Notifications
You must be signed in to change notification settings - Fork 1
[feat] add infinte scroll #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
8b3a94f
622a3ea
c503a16
8ce5c9f
1c444d6
c0b7e0d
d87aa26
7f4250a
d5addda
cabd90c
48cf5e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| .card { | ||
| padding: 16px; | ||
| border-radius: 6px; | ||
| border: 1px solid var(--gray-300); | ||
| background: var(--white); | ||
| margin-bottom: 20px; | ||
| height: 150px; | ||
| } | ||
|
|
||
| .card.dragging { | ||
| margin: 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import React from 'react'; | ||
| import { Draggable } from 'react-beautiful-dnd'; | ||
| import { CardData } from '@/types/dashboardView'; | ||
| import styles from './Card.module.css'; | ||
|
|
||
| interface Props { | ||
| item: CardData; | ||
| index: number; | ||
| } | ||
|
|
||
| function Card({ item, index }: Props) { | ||
| if (!item || !item.id) { | ||
| return null; | ||
| } | ||
|
|
||
| return ( | ||
| <Draggable draggableId={`${item.id}`} index={index}> | ||
|
||
| {(provided, snapshot) => ( | ||
| <div | ||
| ref={provided.innerRef} | ||
| {...provided.draggableProps} | ||
| {...provided.dragHandleProps} | ||
| className={`${styles.card} ${snapshot.isDragging ? styles.dragging : ''}`} | ||
| > | ||
| <div>{item.id}</div> | ||
| </div> | ||
| )} | ||
| </Draggable> | ||
| ); | ||
| } | ||
|
|
||
| export default React.memo(Card); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| .column { | ||
| display: flex; | ||
| flex-direction: column; | ||
| width: 354px; | ||
| height: 1010px; | ||
| padding: 20px; | ||
| border-right: 1px solid var(--gray-200); | ||
| } | ||
|
|
||
| .header { | ||
| display: flex; | ||
| justify-content: space-between; | ||
| align-items: center; | ||
| } | ||
|
|
||
| .status { | ||
| display: flex; | ||
| align-items: center; | ||
| } | ||
|
|
||
| .dot { | ||
| width: 8px; | ||
| height: 8px; | ||
| border-radius: 50%; | ||
| } | ||
|
|
||
| .title { | ||
| color: var(--black-100); | ||
| font-size: 18px; | ||
| font-weight: 700; | ||
| margin-left: 8px; | ||
| margin-right: 12px; | ||
| } | ||
|
|
||
| .totalCount { | ||
| display: flex; | ||
| width: 20px; | ||
| height: 20px; | ||
| padding: 3px 6px; | ||
| flex-direction: column; | ||
| justify-content: center; | ||
| align-items: center; | ||
| gap: 10px; | ||
| flex-shrink: 0; | ||
| border-radius: 4px; | ||
| background: var(--gray-200); | ||
| color: var(--gray-500); | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| } | ||
|
|
||
| .settingsWrapper { | ||
| width: 24px; | ||
| height: 24px; | ||
| } | ||
|
|
||
| .settings { | ||
| background-color: transparent; | ||
| width: 100%; | ||
| height: 100%; | ||
| } | ||
|
|
||
| .createCardSection { | ||
| margin-top: 25px; | ||
| margin-bottom: 16px; | ||
| } | ||
|
|
||
| .createCard { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| width: 314px; | ||
| height: 40px; | ||
| border: 1px solid var(--gray-300); | ||
| background: var(--white); | ||
| font-size: 18px; | ||
| font-weight: 700; | ||
| color: var(--black-100); | ||
| line-height: 26px; | ||
| gap: 12px; | ||
| border-radius: 8px; | ||
| } | ||
|
|
||
| .createCardIcon { | ||
| display: flex; | ||
| flex-shrink: 0; | ||
| align-items: center; | ||
| justify-content: center; | ||
| padding: 3px; | ||
| border-radius: 4px; | ||
| background: var(--violet-light); | ||
| } | ||
|
|
||
| .scrollContext { | ||
| overflow-x: hidden; | ||
| overflow-y: auto; | ||
| max-height: calc(100vh - 124px); | ||
| height: auto; | ||
| display: flex; | ||
| flex-direction: column; | ||
| } | ||
|
|
||
| .scrollContext::-webkit-scrollbar { | ||
| width: 0; | ||
| } | ||
|
|
||
| .dropContext { | ||
| min-height: auto; | ||
| display: flex; | ||
| flex-direction: column; | ||
| flex-grow: 1; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| import React, { useRef, useEffect, useState } from 'react'; | ||
| import { Droppable } from 'react-beautiful-dnd'; | ||
| import { ColumnData } from '@/types/dashboardView'; | ||
| import Button from '@/components/Button'; | ||
| import Image from 'next/image'; | ||
| import Card from './Card'; | ||
| import styles from './Column.module.css'; | ||
|
|
||
| function Column({ | ||
| color, | ||
| title, | ||
| totalCount, | ||
| id, | ||
| items, | ||
| loadMoreData, | ||
| }: ColumnData) { | ||
| const observerRef = useRef<IntersectionObserver | null>(null); | ||
| const loadMoreRef = useRef<HTMLDivElement | null>(null); | ||
| const columnRef = useRef<HTMLDivElement | null>(null); | ||
| const [minHeight, setMinHeight] = useState<string>('auto'); | ||
|
|
||
| useEffect(() => { | ||
| observerRef.current = new IntersectionObserver( | ||
| (entries) => { | ||
| const entry = entries[0]; | ||
| if (entry.isIntersecting) { | ||
| loadMoreData(id); | ||
| } | ||
|
Comment on lines
+26
to
+31
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μ»΄ν¬λνΈκ° λ λλ§ λ λλ§λ€ IntersectionObserver κ°μ²΄κ° μλ‘ μμ±λλκ² λ§λμ? μ΄λ°μμΌλ‘ λ§μ μ£Όλκ²μ μΆμ²λλ €μ!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μλ‘ μμ±λλ κ² λ§μ΅λλ€ ! |
||
| }, | ||
| { | ||
| root: document.querySelector('.scrollContext'), | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μ€.. μ΄κ±° styles.scrollContext μ΄λ κ² ν΄λμ€λͺ
λ£μ΄λ²λ¦¬λ©΄ λ λλ§λ html보면 ν΄μκ° μ΄μ©κ³ λ‘ λ°λλλ°
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. root: ~λ DOM λ
Έλλ‘ μ€μ νλ©΄ λλ€κ³ ν΄μ μ λ κ² λ°λ‘ λ£μκ³ , |
||
| threshold: 0.4, | ||
| } | ||
| ); | ||
|
|
||
| const loadMoreElement = loadMoreRef.current; | ||
|
|
||
| if (totalCount === 0) return; | ||
|
|
||
| if (loadMoreElement && observerRef.current && totalCount >= 10) { | ||
| observerRef.current.observe(loadMoreElement); | ||
| } | ||
|
|
||
| return () => { | ||
| if (loadMoreElement && observerRef.current) { | ||
| observerRef.current.unobserve(loadMoreElement); | ||
| } | ||
| }; | ||
| }, [id, loadMoreData]); | ||
|
Comment on lines
+51
to
+52
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. totalCountκ° λλ½λ κ² κ°μλ° μλ νμ 건κ°μ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ν μ¬μμ± λ§κ³ , μ΄κ±° μΆκ°ν΄μ λΆκ° 쑰건λ μΆκ°ν΄λ³Όκ²μ. |
||
|
|
||
| useEffect(() => { | ||
| if (items.length === 0 || items.length <= 5) { | ||
| setMinHeight('866px'); | ||
| } else { | ||
| setMinHeight('auto'); | ||
| } | ||
| }, [items]); | ||
|
|
||
| return ( | ||
| <div className={styles.column} ref={columnRef}> | ||
| <div className={styles.header}> | ||
| <div className={styles.status}> | ||
| <div style={{ background: color }} className={styles.dot}></div> | ||
| <div className={styles.title}>{title}</div> | ||
| <div className={styles.totalCount}>{totalCount}</div> | ||
| </div> | ||
|
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. νκ·Έ μ€κ°μ€κ°μ μν°λ μμΌλ©΄ λμ’μκ²κ°μμ...γ γ |
||
| <div className={styles.settingsWrapper}> | ||
| <Button | ||
| type="button" | ||
| aria-label="μ»¬λΌ μ€μ λ²νΌ" | ||
| className={styles.settings} | ||
| > | ||
| <Image src="/icons/settings.svg" width={24} height={24} alt="" /> | ||
| </Button> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className={styles.createCardSection}> | ||
| <Button | ||
| type="button" | ||
| className={styles.createCard} | ||
| aria-label="μ»¬λΌ μμ± λ²νΌ" | ||
| > | ||
| <Image | ||
| src="/icons/add.svg" | ||
| width={22} | ||
| height={22} | ||
| alt="" | ||
| className={styles.createCardIcon} | ||
| /> | ||
| </Button> | ||
| </div> | ||
|
|
||
| <div className={styles.scrollContext}> | ||
| <Droppable | ||
| droppableId={`${id}`} | ||
| isDropDisabled={false} | ||
| isCombineEnabled={false} | ||
| ignoreContainerClipping={true} | ||
| direction="vertical" | ||
| > | ||
| {(provided) => ( | ||
| <div | ||
| className={styles.dropContext} | ||
| ref={provided.innerRef} | ||
| {...provided.droppableProps} | ||
| style={{ minHeight }} | ||
| > | ||
| {items.map((item, index) => | ||
| item ? <Card key={item.id} item={item} index={index} /> : null | ||
| )} | ||
|
|
||
| {provided.placeholder} | ||
|
|
||
| <div ref={loadMoreRef} style={{ height: '1px' }} /> | ||
| </div> | ||
| )} | ||
| </Droppable> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| export default React.memo(Column); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
μ κ° cardμͺ½ κ°μ Έλ€ μ°λ©΄μ λ μλ¬ΈμΈλ° μ΄κ±° μΈν°νμ΄μ€ λ€μ Dataμ λΆμ΄μ κ±°μμ..?γ γ γ
λͺ¨λ κ² λ°μ΄ν°μΈλ°.. μ¬κΈ°λ§ λΆμ΄μκΈΈλ γ γ γ μλΆμμκΉ... νλ μλ¬Έ...?π
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
μ μ²μμ κ·Έλ₯ cardλ‘ μ°λ€κ° μ΄λ¦ μ€λ³΅μ΄λΌκ³ μλ¬ λ¨κΈΈλ μμλ‘ λλκΈ° 보μν κ±°μμ γ γ μ μΌ λ§μ΄ μΈ κ±° κ°μμ κΈΈκ² μ΄λ€λ κ² γ γ γ