diff --git a/packages/app/src/components/header/header.tsx b/packages/app/src/components/header/header.tsx index 331f9bfd3d..1efc6ac042 100644 --- a/packages/app/src/components/header/header.tsx +++ b/packages/app/src/components/header/header.tsx @@ -13,6 +13,9 @@ import { ExportToHtmlIcon, ExportToMarkdownIcon, MoreVerticalIcon, + FavouritesIcon, + FavouritedIcon, + TrashIcon, } from '@blocksuite/icons'; import { useEditor } from '@/providers/editor-provider'; import ThemeModeSwitch from '@/components/theme-mode-switch'; @@ -22,15 +25,37 @@ import { getWarningMessage, shouldShowWarning } from './utils'; import { Menu, MenuItem } from '@/ui/menu'; import { useRouter } from 'next/router'; import { useConfirm } from '@/providers/confirm-provider'; -import { useModal } from '@/providers/global-modal-provider'; -import { useAppState } from '@/providers/app-state-provider'; import { SyncIcon } from './sync-icon'; +import { toast } from '@/components/toast'; const PopoverContent = () => { - const { editor, mode, setMode } = useEditor(); + const { + editor, + mode, + setMode, + getPageMeta, + page, + toggleFavoritePage, + toggleDeletePage, + } = useEditor(); + const { confirm } = useConfirm(); + + const { id, favorite, title } = getPageMeta(page?.id) ?? { + id: '', + favorite: false, + title: '', + }; return ( <> + { + toggleFavoritePage(id); + }} + icon={favorite ? : } + > + {favorite ? 'Remove' : 'Add'} to favourites + : } onClick={() => { @@ -66,6 +91,22 @@ const PopoverContent = () => { Export + { + confirm({ + title: 'Delete page?', + content: `${title || 'Untitled'} will be moved to Trash`, + confirmText: 'Delete', + confirmType: 'danger', + }).then(confirm => { + confirm && toggleDeletePage(id); + toast('Moved to Trash'); + }); + }} + icon={} + > + Delete + ); }; diff --git a/packages/app/src/components/page-list/index.tsx b/packages/app/src/components/page-list/index.tsx index 5fbba9d98e..08d8987bc3 100644 --- a/packages/app/src/components/page-list/index.tsx +++ b/packages/app/src/components/page-list/index.tsx @@ -6,7 +6,6 @@ import { EdgelessIcon, } from '@blocksuite/icons'; import { - StyledFavoriteButton, StyledTableContainer, StyledTableRow, StyledTitleLink, @@ -18,19 +17,31 @@ import Empty from './empty'; import { Content } from '@/ui/layout'; import React from 'react'; import DateCell from '@/components/page-list/date-cell'; -const FavoriteTag = ({ pageMeta }: { pageMeta: PageMeta }) => { +import { IconButton } from '@/ui/button'; +import { Tooltip } from '@/ui/tooltip'; +import { router } from 'next/client'; +const FavoriteTag = ({ + pageMeta: { favorite, id }, +}: { + pageMeta: PageMeta; +}) => { const { toggleFavoritePage } = useEditor(); - return ( - { - toggleFavoritePage(pageMeta.id); - }} + - {pageMeta.favorite ? : } - + { + e.stopPropagation(); + toggleFavoritePage(id); + }} + > + {favorite ? : } + + ); }; @@ -52,7 +63,7 @@ export const PageList = ({ - Documents + Title Created {isTrash ? 'Moved to Trash' : 'Updated'} @@ -63,12 +74,18 @@ export const PageList = ({ {pageList.map((pageMeta, index) => { return ( - + { + router.push({ + pathname: '/', + query: { pageId: pageMeta.id }, + }); + }} + > - + {pageMeta.mode === 'edgeless' ? ( ) : ( @@ -87,7 +104,12 @@ export const PageList = ({ dateKey={isTrash ? 'trashDate' : 'updatedDate'} backupKey={isTrash ? 'trashDate' : 'createDate'} /> - + { + e.stopPropagation(); + }} + > {isTrash ? ( ) : ( diff --git a/packages/app/src/components/page-list/operation-cell.tsx b/packages/app/src/components/page-list/operation-cell.tsx index 4f306e6d83..94ce303512 100644 --- a/packages/app/src/components/page-list/operation-cell.tsx +++ b/packages/app/src/components/page-list/operation-cell.tsx @@ -12,7 +12,7 @@ import { OpenInNewIcon, TrashIcon, } from '@blocksuite/icons'; -import React from 'react'; +import { toast } from '@/components/toast'; export const OperationCell = ({ pageMeta }: { pageMeta: PageMeta }) => { const { id, favorite } = pageMeta; @@ -41,11 +41,12 @@ export const OperationCell = ({ pageMeta }: { pageMeta: PageMeta }) => { onClick={() => { confirm({ title: 'Delete page?', - content: `${pageMeta.title} will be moved to Trash`, + content: `${pageMeta.title || 'Untitled'} will be moved to Trash`, confirmText: 'Delete', confirmType: 'danger', }).then(confirm => { confirm && toggleDeletePage(id); + toast('Moved to Trash'); }); }} icon={} @@ -57,7 +58,7 @@ export const OperationCell = ({ pageMeta }: { pageMeta: PageMeta }) => { return ( - + @@ -67,31 +68,34 @@ export const OperationCell = ({ pageMeta }: { pageMeta: PageMeta }) => { export const TrashOperationCell = ({ pageMeta }: { pageMeta: PageMeta }) => { const { id } = pageMeta; - const { permanentlyDeletePage, toggleDeletePage } = useEditor(); + const { permanentlyDeletePage, toggleDeletePage, openPage, getPageMeta } = + useEditor(); const { confirm } = useConfirm(); return ( { toggleDeletePage(id); + toast(`${getPageMeta(id)?.title || 'Untitled'} restored`); + openPage(id); }} > { confirm({ - title: 'Permanently delete', - content: - "Once deleted, you can't undo this action. Do you confirm?", + title: 'Delete permanently?', + content: "Once deleted, you can't undo this action.", confirmText: 'Delete', confirmType: 'danger', }).then(confirm => { confirm && permanentlyDeletePage(id); + toast('Permanently deleted'); }); }} > diff --git a/packages/app/src/components/page-list/styles.ts b/packages/app/src/components/page-list/styles.ts index 629f0ffbfc..68f849c6ac 100644 --- a/packages/app/src/components/page-list/styles.ts +++ b/packages/app/src/components/page-list/styles.ts @@ -23,7 +23,7 @@ export const StyledTitleWrapper = styled.div(({ theme }) => { }, }; }); -export const StyledTitleLink = styled(Link)(({ theme }) => { +export const StyledTitleLink = styled.div(({ theme }) => { return { maxWidth: '80%', marginRight: '18px', @@ -34,31 +34,12 @@ export const StyledTitleLink = styled(Link)(({ theme }) => { marginRight: '12px', color: theme.colors.iconColor, }, - ':hover': { - color: theme.colors.textColor, - '>svg': { - color: theme.colors.primaryColor, - }, - }, }; }); -export const StyledFavoriteButton = styled.button<{ favorite: boolean }>( - ({ theme, favorite }) => { - return { - width: '32px', - height: '32px', - justifyContent: 'center', - alignItems: 'center', - display: 'none', - color: favorite ? theme.colors.primaryColor : theme.colors.iconColor, - '&:hover': { - color: theme.colors.primaryColor, - }, - }; - } -); + export const StyledTableRow = styled(TableRow)(({ theme }) => { return { + cursor: 'pointer', '&:hover': { '.favorite-button': { display: 'flex', diff --git a/packages/app/src/components/workspace-slider-bar/index.tsx b/packages/app/src/components/workspace-slider-bar/index.tsx index 1c08ed90c6..be3c82b278 100644 --- a/packages/app/src/components/workspace-slider-bar/index.tsx +++ b/packages/app/src/components/workspace-slider-bar/index.tsx @@ -19,6 +19,7 @@ import { ImportIcon, TrashIcon, AddIcon, + FavouritedIcon, } from '@blocksuite/icons'; import Link from 'next/link'; import { Tooltip } from '@/ui/tooltip'; @@ -93,7 +94,7 @@ export const WorkSpaceSliderBar = () => { Favourites { setShowSubFavorite(!showSubFavorite); }} @@ -107,13 +108,16 @@ export const WorkSpaceSliderBar = () => { - { - triggerImportModal(); - }} - > - Import - + + { + // triggerImportModal(); + }} + > + Import + + diff --git a/packages/app/src/components/workspace-slider-bar/style.ts b/packages/app/src/components/workspace-slider-bar/style.ts index 08c32092ec..e32c01e86d 100644 --- a/packages/app/src/components/workspace-slider-bar/style.ts +++ b/packages/app/src/components/workspace-slider-bar/style.ts @@ -43,29 +43,33 @@ export const StyledArrowButton = styled.button<{ isShow: boolean }>( } ); -export const StyledListItem = styled.button<{ active?: boolean }>( - ({ theme, active }) => { - return { - width: '296px', - height: '32px', - marginTop: '12px', - fontSize: theme.font.sm, - color: active ? theme.colors.primaryColor : theme.colors.popoverColor, - backgroundColor: active ? theme.colors.hoverBackground : 'unset', - paddingLeft: '12px', - borderRadius: '5px', - ...displayFlex('flex-start', 'center'), - '>svg': { - fontSize: '20px', - marginRight: '12px', - }, - ':hover': { - color: theme.colors.primaryColor, - backgroundColor: theme.colors.hoverBackground, - }, - }; - } -); +export const StyledListItem = styled.button<{ + active?: boolean; + disabled?: boolean; +}>(({ theme, active, disabled }) => { + return { + width: '296px', + height: '32px', + marginTop: '12px', + fontSize: theme.font.sm, + color: active ? theme.colors.primaryColor : theme.colors.popoverColor, + paddingLeft: '12px', + borderRadius: '5px', + ...displayFlex('flex-start', 'center'), + ...(disabled + ? { cursor: 'not-allowed', color: theme.colors.borderColor } + : {}), + + '>svg': { + fontSize: '20px', + marginRight: '12px', + }, + ':hover:not([disabled])': { + color: theme.colors.primaryColor, + backgroundColor: theme.colors.hoverBackground, + }, + }; +}); export const StyledListItemForWorkspace = styled(StyledListItem)({ height: '52px', diff --git a/packages/app/src/pages/page-list/favorite.tsx b/packages/app/src/pages/page-list/favorite.tsx index 400c7692da..c29687e3b8 100644 --- a/packages/app/src/pages/page-list/favorite.tsx +++ b/packages/app/src/pages/page-list/favorite.tsx @@ -7,7 +7,7 @@ export const Favorite = () => { const { pageList: allPageList } = useEditor(); return ( <> - }>Favorites + }>Favourites p.favorite && !p.trash)} /> ); diff --git a/packages/app/src/providers/editor-provider/interface.ts b/packages/app/src/providers/editor-provider/interface.ts index afb96d1442..1fafdf56ff 100644 --- a/packages/app/src/providers/editor-provider/interface.ts +++ b/packages/app/src/providers/editor-provider/interface.ts @@ -31,7 +31,7 @@ export type EditorHandlers = { pageId: string, query?: { [key: string]: string } ) => Promise; - getPageMeta: (pageId?: string) => PageMeta | void; + getPageMeta: (pageId?: string) => PageMeta; toggleDeletePage: (pageId: string) => void; toggleFavoritePage: (pageId: string) => void; permanentlyDeletePage: (pageId: string) => void; diff --git a/packages/app/src/ui/button/icon-button.tsx b/packages/app/src/ui/button/icon-button.tsx index 79c3c48834..5166af1a3e 100644 --- a/packages/app/src/ui/button/icon-button.tsx +++ b/packages/app/src/ui/button/icon-button.tsx @@ -43,6 +43,7 @@ export type IconButtonProps = { hoverColor?: string; hoverStyle?: CSSProperties; children: ReactElement, 'svg'>; + darker?: boolean; } & HTMLAttributes; export const IconButton = forwardRef( diff --git a/packages/app/src/ui/button/styles.ts b/packages/app/src/ui/button/styles.ts index 9604266baa..efa6d2edda 100644 --- a/packages/app/src/ui/button/styles.ts +++ b/packages/app/src/ui/button/styles.ts @@ -14,6 +14,7 @@ export const StyledIconButton = styled('button', { 'hoverBackground', 'hoverColor', 'hoverStyle', + 'darker', ].includes(prop); }, })<{ @@ -24,6 +25,8 @@ export const StyledIconButton = styled('button', { hoverBackground?: CSSProperties['background']; hoverColor?: string; hoverStyle?: CSSProperties; + // In some cases, button is in a normal hover status, it should be darkened + darker?: boolean; }>( ({ theme, @@ -33,6 +36,7 @@ export const StyledIconButton = styled('button', { hoverBackground, hoverColor, hoverStyle, + darker = false, }) => { return { width, @@ -40,7 +44,7 @@ export const StyledIconButton = styled('button', { color: theme.colors.iconColor, ...displayInlineFlex('center', 'center'), position: 'relative', - ...(disabled ? { cursor: 'not-allowed', pointerEvents: 'none' } : {}), + ...(disabled ? { cursor: 'not-allowed' } : {}), transition: 'background .15s', // TODO: we need to add @emotion/babel-plugin @@ -61,7 +65,10 @@ export const StyledIconButton = styled('button', { ':hover': { color: hoverColor ?? theme.colors.primaryColor, '::after': { - background: hoverBackground ?? theme.colors.hoverBackground, + background: + hoverBackground ?? darker + ? theme.colors.innerHoverBackground + : theme.colors.hoverBackground, }, ...(hoverStyle ?? {}), }, @@ -116,7 +123,7 @@ export const StyledTextButton = styled('button', { paddingRight: padding, ...displayInlineFlex('flex-start', 'center'), position: 'relative', - ...(disabled ? { cursor: 'not-allowed', pointerEvents: 'none' } : {}), + ...(disabled ? { cursor: 'not-allowed' } : {}), transition: 'background .15s', // TODO: Implement circle shape borderRadius: shape === 'default' ? borderRadius : height / 2, @@ -171,7 +178,10 @@ export const StyledButton = styled('button', { border: '1px solid', ...displayInlineFlex('flex-start', 'center'), position: 'relative', - ...(disabled ? { cursor: 'not-allowed', pointerEvents: 'none' } : {}), + // TODO: disabled color is not decided + ...(disabled + ? { cursor: 'not-allowed', color: theme.colors.borderColor } + : {}), transition: 'background .15s', // TODO: Implement circle shape borderRadius: shape === 'default' ? borderRadius : height / 2, @@ -190,6 +200,7 @@ export const StyledButton = styled('button', { hoverStyle, }), + // TODO: disabled hover should be implemented // // ':hover': { // color: hoverColor ?? theme.colors.primaryColor, diff --git a/packages/app/src/ui/table/styles.ts b/packages/app/src/ui/table/styles.ts index c954e1b424..9850bc8b43 100644 --- a/packages/app/src/ui/table/styles.ts +++ b/packages/app/src/ui/table/styles.ts @@ -40,6 +40,13 @@ export const StyledTableCell = styled.td< export const StyledTableHead = styled.thead(({ theme }) => { return { fontWeight: 500, + tr: { + ':hover': { + td: { + background: 'unset', + }, + }, + }, }; });