-
Notifications
You must be signed in to change notification settings - Fork 4
[Feat] 북마크 페이지 구현 #163
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
base: dev
Are you sure you want to change the base?
[Feat] 북마크 페이지 구현 #163
Changes from all commits
3d59f75
3b5477f
f4171b2
9e228d1
ba6799d
53a3d0e
2aef8eb
8559e50
3ef06b5
14e6a7e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,104 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { globalStyle, style } from "@vanilla-extract/css"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { themeVars } from "@/app/styles"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const page = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| width: "100%", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| maxWidth: "106rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| margin: "0 auto", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| paddingTop: `calc(${themeVars.height.header} + 8rem)`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| paddingBottom: "8rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const topRow = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| display: "flex", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| alignItems: "center", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| justifyContent: "space-between", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gap: "2rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const headerSection = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| display: "flex", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| alignItems: "center", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gap: "1.6rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const titleIcon = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| width: "6.4rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| height: "6.4rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| flexShrink: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const titleWrap = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| display: "flex", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| flexDirection: "column", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gap: "0.4rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const title = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: themeVars.color.black, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...themeVars.fontStyles.title_b_24, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const subtitle = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: themeVars.color.gray500, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...themeVars.fontStyles.body_m_16, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const actionSection = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| display: "flex", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| alignItems: "center", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gap: "1.2rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const searchWrap = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| display: "flex", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| alignItems: "center", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const deleteButtonWrap = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| display: "inline-flex", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const trashIcon = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| width: "2.4rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| height: "2.4rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| flexShrink: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| globalStyle(`${deleteButtonWrap} > button`, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| width: "4.8rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minWidth: "4.8rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| height: "4.8rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| padding: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| borderRadius: "12px", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backgroundColor: themeVars.color.blue600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| borderColor: themeVars.color.blue600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: themeVars.color.white, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| globalStyle(`${deleteButtonWrap} > button:hover:not(:disabled)`, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backgroundColor: themeVars.color.blue600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| borderColor: themeVars.color.blue600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| globalStyle(`${deleteButtonWrap} > button:active:not(:disabled)`, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backgroundColor: themeVars.color.blue600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| borderColor: themeVars.color.blue600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| globalStyle(`${deleteButtonWrap} > button:disabled`, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backgroundColor: themeVars.color.blue600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| borderColor: themeVars.color.blue600, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: themeVars.color.white, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+80
to
+94
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. 🧹 Nitpick | 🔵 Trivial 버튼 상태(hover, active, disabled)에 시각적 피드백이 없어요. 현재 ♻️ 상태별 스타일 예시 globalStyle(`${deleteButtonWrap} > button:hover:not(:disabled)`, {
- backgroundColor: themeVars.color.blue600,
- borderColor: themeVars.color.blue600,
+ backgroundColor: themeVars.color.blue700, // 또는 더 어두운 톤
+ borderColor: themeVars.color.blue700,
});
globalStyle(`${deleteButtonWrap} > button:active:not(:disabled)`, {
- backgroundColor: themeVars.color.blue600,
- borderColor: themeVars.color.blue600,
+ backgroundColor: themeVars.color.blue800, // 또는 더 어두운 톤
+ borderColor: themeVars.color.blue800,
});
globalStyle(`${deleteButtonWrap} > button:disabled`, {
- backgroundColor: themeVars.color.blue600,
- borderColor: themeVars.color.blue600,
+ backgroundColor: themeVars.color.gray300, // 비활성화 상태 표시
+ borderColor: themeVars.color.gray300,
color: themeVars.color.white,
+ cursor: "not-allowed",
});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const tableSection = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| marginTop: "5rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const paginationSection = style({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| marginTop: "4.8rem", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| display: "flex", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| justifyContent: "center", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,200 @@ | ||
| import { useMemo, useState } from "react"; | ||
| import { useNavigate } from "react-router-dom"; | ||
|
|
||
| import { ROUTES } from "@/app/routes/paths"; | ||
| import IconBookmarkBefore from "@/shared/assets/icons/icon_bookmark_before.svg?react"; | ||
| import IconTrashOff from "@/shared/assets/icons/icon_trash_off.svg?react"; | ||
| import { Button, Modal, Pagination, Search } from "@/shared/ui"; | ||
|
|
||
| import * as styles from "./bookmark-page.css"; | ||
| import { | ||
| BOOKMARK_MOCK_ROWS, | ||
| BOOKMARK_PAGE_SIZE, | ||
| } from "./config/bookmark-page.constant"; | ||
| import { BookmarkEmptyState } from "./ui/bookmark-empty-state"; | ||
| import { BookmarkTable } from "./ui/bookmark-table"; | ||
|
|
||
| const BookmarkPage = () => { | ||
| const navigate = useNavigate(); | ||
|
|
||
| const [rows, setRows] = useState(BOOKMARK_MOCK_ROWS); | ||
| const [searchInput, setSearchInput] = useState(""); | ||
| const [keyword, setKeyword] = useState(""); | ||
| const [currentPage, setCurrentPage] = useState(1); | ||
| const [selectedIds, setSelectedIds] = useState<number[]>([]); | ||
| const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); | ||
|
Comment on lines
+20
to
+25
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. 현재 mock 데이터를 사용하고 있기 때문에 필터링 기능 구현에 있어 많은 상태들이 사용되고 있는 것 같아요. 그렇지만 |
||
|
|
||
| const filteredRows = useMemo(() => { | ||
| if (!keyword) return rows; | ||
|
|
||
| const normalizedKeyword = keyword.toLowerCase(); | ||
| return rows.filter((row) => | ||
| row.companyName.toLowerCase().includes(normalizedKeyword) | ||
| ); | ||
| }, [keyword, rows]); | ||
|
|
||
| const totalPage = Math.ceil(filteredRows.length / BOOKMARK_PAGE_SIZE); | ||
| const paginationTotalPage = Math.max(totalPage, 1); | ||
| const resolvedCurrentPage = Math.min(currentPage, paginationTotalPage); | ||
|
|
||
| const currentPageRows = useMemo(() => { | ||
| const startIndex = (resolvedCurrentPage - 1) * BOOKMARK_PAGE_SIZE; | ||
| return filteredRows.slice(startIndex, startIndex + BOOKMARK_PAGE_SIZE); | ||
| }, [filteredRows, resolvedCurrentPage]); | ||
|
|
||
| const visibleIds = useMemo( | ||
| () => currentPageRows.map((row) => row.id), | ||
| [currentPageRows] | ||
| ); | ||
|
|
||
| const isAllSelected = | ||
| visibleIds.length > 0 && visibleIds.every((id) => selectedIds.includes(id)); | ||
|
|
||
| const isDeleteDisabled = selectedIds.length === 0; | ||
| const isBookmarkEmpty = rows.length === 0; | ||
| const isSearchResultEmpty = rows.length > 0 && filteredRows.length === 0; | ||
|
|
||
| const handleSearch = (value: string) => { | ||
| const trimmedValue = value.trim(); | ||
|
|
||
| if (value.length > 0 && trimmedValue.length === 0) { | ||
| return; | ||
| } | ||
|
Comment on lines
+60
to
+62
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. 공백만 입력한 검색어는 막는 의도 좋네요! :) 다만 현재 로직을 보면 태그한 이 조건 때문에 이 상태에서 사용자는 “검색어를 지웠다”라고 인식할 가능성이 높은데, 실제로는 이전 의도하신 UX가 아니라면, 공백만 입력된 경우에는 early return 대신 setKeyword("");로 명시적으로 초기화해주는 쪽이 사용자 기대와 더 맞을 것 같은데, 어떻게 생각하세요 ?? 예를 들어, |
||
|
|
||
| setKeyword(trimmedValue); | ||
| setCurrentPage(1); | ||
| setSelectedIds([]); | ||
| }; | ||
|
Comment on lines
+57
to
+67
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. 검색 제출 후 입력창과 실제 필터 조건이 어긋날 수 있습니다. 필터링은 수정 예시 const handleSearch = (value: string) => {
const trimmedValue = value.trim();
-
- if (value.length > 0 && trimmedValue.length === 0) {
- return;
- }
+ setSearchInput(trimmedValue);
setKeyword(trimmedValue);
setCurrentPage(1);
setSelectedIds([]);
};🤖 Prompt for AI Agents |
||
|
|
||
| const handlePageChange = (page: number) => { | ||
| setCurrentPage(page); | ||
| }; | ||
|
Comment on lines
+69
to
+71
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. 페이지를 넘기면 화면 밖 선택이 남아 삭제 대상이 숨겨집니다. 현재는 페이지 이동 시 페이지 단위 선택 UX라면 const handlePageChange = (page: number) => {
setCurrentPage(page);
+ setSelectedIds([]);
};🤖 Prompt for AI Agents |
||
|
|
||
| const handleToggleAll = (checked: boolean) => { | ||
| if (checked) { | ||
| setSelectedIds((prev) => Array.from(new Set([...prev, ...visibleIds]))); | ||
| return; | ||
| } | ||
|
|
||
| setSelectedIds((prev) => prev.filter((id) => !visibleIds.includes(id))); | ||
| }; | ||
|
|
||
| const handleToggleRow = (rowId: number, checked: boolean) => { | ||
| setSelectedIds((prev) => | ||
| checked | ||
| ? Array.from(new Set([...prev, rowId])) | ||
| : prev.filter((id) => id !== rowId) | ||
| ); | ||
| }; | ||
|
|
||
| const handleOpenDeleteModal = () => { | ||
| if (isDeleteDisabled) return; | ||
| setIsDeleteModalOpen(true); | ||
| }; | ||
|
|
||
| const handleCloseDeleteModal = () => { | ||
| setIsDeleteModalOpen(false); | ||
| }; | ||
|
|
||
| const handleDeleteConfirm = () => { | ||
| setRows((prev) => prev.filter((row) => !selectedIds.includes(row.id))); | ||
| setSelectedIds([]); | ||
| setIsDeleteModalOpen(false); | ||
| }; | ||
|
|
||
| const handleClickCompany = (companyId: number) => { | ||
| navigate(ROUTES.COMPANY(String(companyId))); | ||
| }; | ||
|
|
||
| return ( | ||
| <main className={styles.page}> | ||
| <section className={styles.topRow}> | ||
| <div className={styles.headerSection}> | ||
| <IconBookmarkBefore className={styles.titleIcon} aria-hidden="true" /> | ||
| <div className={styles.titleWrap}> | ||
| <h1 className={styles.title}>기업 북마크</h1> | ||
| <p className={styles.subtitle}> | ||
| 최근 6개월 이내에 스크랩한 기업정보 입니다 | ||
| </p> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className={styles.actionSection}> | ||
| <div className={styles.searchWrap}> | ||
| <Search | ||
| size="small" | ||
| value={searchInput} | ||
| onChange={setSearchInput} | ||
| onSearch={handleSearch} | ||
| placeholder="기업명 검색" | ||
| inputAriaLabel="기업명 검색" | ||
| /> | ||
| </div> | ||
|
|
||
| <div className={styles.deleteButtonWrap}> | ||
| <Button | ||
| variant="secondary" | ||
| size="medium" | ||
| disabled={isDeleteDisabled} | ||
| onClick={handleOpenDeleteModal} | ||
| aria-label="북마크 삭제" | ||
| > | ||
| <IconTrashOff className={styles.trashIcon} aria-hidden="true" /> | ||
|
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. 아이콘 에셋에 지금은 버튼 enabled/disabled 여부와 관계없이 |
||
| </Button> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| <section className={styles.tableSection}> | ||
| {isBookmarkEmpty ? ( | ||
| <BookmarkEmptyState type="bookmark" /> | ||
| ) : isSearchResultEmpty ? ( | ||
| <BookmarkEmptyState type="search" /> | ||
| ) : ( | ||
| <BookmarkTable | ||
| rows={currentPageRows} | ||
| pageSize={BOOKMARK_PAGE_SIZE} | ||
| selectedIds={selectedIds} | ||
| isAllSelected={isAllSelected} | ||
| onToggleAll={handleToggleAll} | ||
| onToggleRow={handleToggleRow} | ||
| onClickCompany={handleClickCompany} | ||
| /> | ||
| )} | ||
| </section> | ||
|
|
||
| <section className={styles.paginationSection}> | ||
| <Pagination | ||
| currentPage={resolvedCurrentPage} | ||
| totalPage={paginationTotalPage} | ||
| onPageChange={handlePageChange} | ||
| /> | ||
|
Comment on lines
+167
to
+171
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. 북마크 한 기업이 없다면, 페이지네이션될 데이터 리스트가 존재하지 않기 때문에 그리고 검색 결과가 없는 경우에도 |
||
| </section> | ||
|
Comment on lines
+166
to
+172
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. 검색 결과가 empty이거나 전체 북마크가 empty인 경우에도 pagination이 항상 노출되는 구조라, '실제 화면에서
|
||
|
|
||
| <Modal isOpen={isDeleteModalOpen} onClose={handleCloseDeleteModal}> | ||
| <Modal.XButton /> | ||
| <Modal.Content> | ||
| <Modal.Title>선택한 북마크를 삭제할까요?</Modal.Title> | ||
| </Modal.Content> | ||
| <Modal.Buttons> | ||
| <Button | ||
| variant="secondary" | ||
| size="large" | ||
| onClick={handleDeleteConfirm} | ||
| > | ||
| 삭제하기 | ||
| </Button> | ||
| <Button | ||
| variant="primary" | ||
| size="large" | ||
| onClick={handleCloseDeleteModal} | ||
| > | ||
| 취소하기 | ||
|
Comment on lines
+180
to
+192
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. 삭제 모달의 버튼 의미(강조/위험도)가 반대로 배치되어 있습니다. 현재는 🛠️ 제안 diff- <Button
- variant="secondary"
- size="large"
- onClick={handleDeleteConfirm}
- >
- 삭제하기
- </Button>
- <Button variant="primary" size="large" onClick={closeDeleteModal}>
- 취소하기
- </Button>
+ <Button variant="secondary" size="large" onClick={closeDeleteModal}>
+ 취소하기
+ </Button>
+ <Button
+ variant="primary"
+ size="large"
+ onClick={handleDeleteConfirm}
+ >
+ 삭제하기
+ </Button>🤖 Prompt for AI Agents |
||
| </Button> | ||
| </Modal.Buttons> | ||
| </Modal> | ||
| </main> | ||
| ); | ||
| }; | ||
|
|
||
| export { BookmarkPage }; | ||
Uh oh!
There was an error while loading. Please reload this page.