diff --git a/apps/core/package.json b/apps/core/package.json index 6e781a7ee2..106c6f28ac 100644 --- a/apps/core/package.json +++ b/apps/core/package.json @@ -28,7 +28,7 @@ "@blocksuite/blocks": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/editor": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/global": "0.0.0-20230829150056-df43987c-nightly", - "@blocksuite/icons": "^2.1.31", + "@blocksuite/icons": "^2.1.32", "@blocksuite/lit": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/store": "0.0.0-20230829150056-df43987c-nightly", "@dnd-kit/core": "^6.0.8", @@ -40,7 +40,7 @@ "@mui/material": "^5.14.7", "@radix-ui/react-select": "^1.2.2", "@react-hookz/web": "^23.1.0", - "@toeverything/components": "^0.0.25", + "@toeverything/components": "^0.0.31", "async-call-rpc": "^6.3.1", "cmdk": "^0.2.0", "css-spring": "^4.1.0", diff --git a/apps/core/src/components/affine/language-menu/index.tsx b/apps/core/src/components/affine/language-menu/index.tsx index 0ee1e289e1..c697daf967 100644 --- a/apps/core/src/components/affine/language-menu/index.tsx +++ b/apps/core/src/components/affine/language-menu/index.tsx @@ -1,138 +1,69 @@ -import { - Menu, - MenuItem, - type MenuProps, - MenuTrigger, - styled, -} from '@affine/component'; -import { LOCALES, useI18N } from '@affine/i18n'; -import { assertExists } from '@blocksuite/global/utils'; -import type { ButtonProps } from '@toeverything/components/button'; -import { useCallback, useEffect, useState } from 'react'; - -export const StyledListItem = styled(MenuItem)(() => ({ - height: '38px', - textTransform: 'capitalize', -})); - -interface LanguageMenuContentProps { - currentLanguage: string; - currentLanguageIndex: number; -} +import { LOCALES } from '@affine/i18n'; +import { useI18N } from '@affine/i18n'; +import { Menu, MenuItem, MenuTrigger } from '@toeverything/components/menu'; +import type { ReactElement } from 'react'; +import { useCallback, useMemo, useRef } from 'react'; +// Fixme: keyboard focus should be supported by Menu component const LanguageMenuContent = ({ currentLanguage, - currentLanguageIndex, -}: LanguageMenuContentProps) => { - const i18n = useI18N(); - const changeLanguage = useCallback( - (targetLanguage: string) => { - console.assert( - LOCALES.some(item => item.tag === targetLanguage), - 'targetLanguage should be one of the LOCALES' - ); - i18n.changeLanguage(targetLanguage).catch(err => { - console.error('Failed to change language', err); - }); - }, - [i18n] - ); - - const [focusedOptionIndex, setFocusedOptionIndex] = useState( - currentLanguageIndex ?? 0 - ); - - const handleKeyDown = useCallback( - (event: KeyboardEvent) => { - switch (event.key) { - case 'ArrowUp': - event.preventDefault(); - setFocusedOptionIndex(prevIndex => - prevIndex > 0 ? prevIndex - 1 : 0 - ); - break; - case 'ArrowDown': - event.preventDefault(); - setFocusedOptionIndex(prevIndex => - prevIndex < LOCALES.length - 1 ? prevIndex + 1 : LOCALES.length - ); - break; - case 'Enter': - if (focusedOptionIndex !== -1) { - const selectedOption = LOCALES[focusedOptionIndex]; - changeLanguage(selectedOption.tag); - } - break; - default: - break; - } - }, - [changeLanguage, focusedOptionIndex] - ); - - useEffect(() => { - document.addEventListener('keydown', handleKeyDown); - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [handleKeyDown]); - + onSelect, +}: { + currentLanguage?: string; + onSelect: (value: string) => void; +}) => { return ( <> - {LOCALES.map((option, optionIndex) => { + {LOCALES.map(option => { return ( - { - changeLanguage(option.tag); - }} + onSelect={() => onSelect(option.tag)} > {option.originalName} - + ); })} ); }; -interface LanguageMenuProps extends Omit { - triggerProps?: ButtonProps; -} - -export const LanguageMenu = ({ - triggerProps, - ...menuProps -}: LanguageMenuProps) => { +export const LanguageMenu = () => { const i18n = useI18N(); - - const currentLanguageIndex = LOCALES.findIndex( - item => item.tag === i18n.language + const ref = useRef(null); + const currentLanguage = useMemo( + () => LOCALES.find(item => item.tag === i18n.language), + [i18n.language] + ); + const onSelect = useCallback( + (event: string) => { + return i18n.changeLanguage(event); + }, + [i18n] ); - const currentLanguage = LOCALES[currentLanguageIndex]; - assertExists(currentLanguage, 'currentLanguage should exist'); - return ( + items={ + ( + + ) as ReactElement } - placement="bottom-end" - trigger="click" - disablePortal={true} - {...menuProps} + portalOptions={{ + container: ref.current, + }} > - {currentLanguage.originalName} + {currentLanguage?.originalName || ''} ); diff --git a/apps/core/src/components/affine/language-menu/style.css.ts b/apps/core/src/components/affine/language-menu/style.css.ts new file mode 100644 index 0000000000..d841c77ec7 --- /dev/null +++ b/apps/core/src/components/affine/language-menu/style.css.ts @@ -0,0 +1,5 @@ +import { style } from '@vanilla-extract/css'; + +export const hoveredLanguageItem = style({ + background: 'var(--affine-hover-color)', +}); diff --git a/apps/core/src/components/affine/new-workspace-setting-detail/members.tsx b/apps/core/src/components/affine/new-workspace-setting-detail/members.tsx index ad07afd2da..06fa051845 100644 --- a/apps/core/src/components/affine/new-workspace-setting-detail/members.tsx +++ b/apps/core/src/components/affine/new-workspace-setting-detail/members.tsx @@ -1,4 +1,3 @@ -import { Menu, MenuItem } from '@affine/component'; import { InviteModal, type InviteModalProps, @@ -12,6 +11,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { MoreVerticalIcon } from '@blocksuite/icons'; import { Avatar } from '@toeverything/components/avatar'; import { Button, IconButton } from '@toeverything/components/button'; +import { Menu, MenuItem } from '@toeverything/components/menu'; import { Tooltip } from '@toeverything/components/tooltip'; import clsx from 'clsx'; import { useSetAtom } from 'jotai/react'; @@ -190,14 +190,11 @@ const MemberItem = ({ : 'Pending'} {operationButtonInfo.leaveOrRevokeText} } - placement="bottom" - disablePortal={true} - trigger="click" > { - onSelect(option); - }} + selected={currentOption === option} + onSelect={() => onSelect(option)} > {dayjs(new Date()).format(option)} @@ -37,6 +35,7 @@ const DateFormatMenuContent = ({ }; export const DateFormatSetting = () => { + const ref = useRef(null); const [appearanceSettings, setAppSettings] = useAppSetting(); const handleSelect = useCallback( (option: DateFormats) => { @@ -47,17 +46,15 @@ export const DateFormatSetting = () => { return ( } - placement="bottom-end" - trigger="click" - disablePortal={true} + portalOptions={{ container: ref.current }} > - + {dayjs(new Date()).format(appearanceSettings.dateFormat)} diff --git a/apps/core/src/components/affine/setting-modal/general-setting/appearance/index.tsx b/apps/core/src/components/affine/setting-modal/general-setting/appearance/index.tsx index c0314655af..c1d3d02c74 100644 --- a/apps/core/src/components/affine/setting-modal/general-setting/appearance/index.tsx +++ b/apps/core/src/components/affine/setting-modal/general-setting/appearance/index.tsx @@ -113,17 +113,7 @@ export const AppearanceSettings = () => { desc={t['com.affine.settings.appearance.language-description']()} >
- +
{environment.isDesktop ? ( diff --git a/apps/core/src/components/blocksuite/block-suite-header-title/operation-menu.tsx b/apps/core/src/components/blocksuite/block-suite-header-title/operation-menu.tsx index 5eff34ee68..48516dc8ea 100644 --- a/apps/core/src/components/blocksuite/block-suite-header-title/operation-menu.tsx +++ b/apps/core/src/components/blocksuite/block-suite-header-title/operation-menu.tsx @@ -1,4 +1,4 @@ -import { FlexWrapper, Menu, MenuItem } from '@affine/component'; +import { FlexWrapper } from '@affine/component'; import { Export, MoveToTrash } from '@affine/component/page-list'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { assertExists } from '@blocksuite/global/utils'; @@ -12,14 +12,19 @@ import { PageIcon, } from '@blocksuite/icons'; import type { PageMeta } from '@blocksuite/store'; -import { Divider } from '@toeverything/components/divider'; +import { + Menu, + MenuIcon, + MenuItem, + MenuSeparator, +} from '@toeverything/components/menu'; import { useBlockSuitePageMeta, usePageMetaHelper, } from '@toeverything/hooks/use-block-suite-page-meta'; import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper'; import { useAtom, useSetAtom } from 'jotai'; -import { useCallback, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; import { applyUpdate, encodeStateAsUpdate } from 'yjs'; import { pageSettingFamily, setPageModeAtom } from '../../../atoms'; @@ -34,9 +39,10 @@ type PageMenuProps = { rename?: () => void; pageId: string; }; - +// fixme: refactor this file export const PageMenu = ({ rename, pageId }: PageMenuProps) => { const t = useAFFiNEI18N(); + const ref = useRef(null); // fixme(himself65): remove these hooks ASAP const [workspace] = useCurrentWorkspace(); @@ -105,17 +111,25 @@ export const PageMenu = ({ rename, pageId }: PageMenuProps) => { const EditMenu = ( <> } + preFix={ + + + + } data-testid="editor-option-menu-rename" - onClick={rename} + onSelect={rename} style={menuItemStyle} > {t['Rename']()} : } + preFix={ + + {mode === 'page' ? : } + + } data-testid="editor-option-menu-edgeless" - onClick={handleSwitchMode} + onSelect={handleSwitchMode} style={menuItemStyle} > {t['Convert to ']()} @@ -123,14 +137,16 @@ export const PageMenu = ({ rename, pageId }: PageMenuProps) => { - ) : ( - - ) + preFix={ + + {favorite ? ( + + ) : ( + + )} + } > {favorite ? t['Remove from favorites']() : t['Add to Favorites']()} @@ -144,28 +160,36 @@ export const PageMenu = ({ rename, pageId }: PageMenuProps) => { > {t['com.affine.header.option.add-tag']()} */} - + } + preFix={ + + + + } data-testid="editor-option-menu-duplicate" - onClick={duplicate} + onSelect={duplicate} style={menuItemStyle} > {t['com.affine.header.option.duplicate']()} } + preFix={ + + + + } data-testid="editor-option-menu-import" - onClick={importFile} + onSelect={importFile} style={menuItemStyle} > {t['Import']()} - + { + onSelect={() => { setOpenConfirm(true); }} /> @@ -176,21 +200,19 @@ export const PageMenu = ({ rename, pageId }: PageMenuProps) => { } return ( <> - + -
- -
+
{ - return { - svg: { - transition: 'transform 0.15s ease-in-out', - }, - ':hover': { - svg: { - transform: 'translateY(3px)', - }, - backgroundColor: 'transparent !important', - }, - }; -}); +import { headerMenuTrigger } from './styles.css'; -// fixme(himself65): need to refactor -export const HeaderDropDownButton = ({ - onClick, - ...props -}: Omit) => { +export const HeaderDropDownButton = forwardRef< + HTMLButtonElement, + Omit +>((props, ref) => { return ( - { - onClick?.(e); - }} + data-testid="header-dropDownButton" + className={headerMenuTrigger} + withoutHoverStyle={true} + type="plain" > - +
); -}; +}); + +HeaderDropDownButton.displayName = 'HeaderDropDownButton'; diff --git a/apps/core/src/components/pure/header-drop-down-button/styles.css.ts b/apps/core/src/components/pure/header-drop-down-button/styles.css.ts new file mode 100644 index 0000000000..abc35a4926 --- /dev/null +++ b/apps/core/src/components/pure/header-drop-down-button/styles.css.ts @@ -0,0 +1,10 @@ +import { globalStyle, style } from '@vanilla-extract/css'; + +export const headerMenuTrigger = style({}); + +globalStyle(`${headerMenuTrigger} svg`, { + transition: 'transform 0.15s ease-in-out', +}); +globalStyle(`${headerMenuTrigger}:hover svg`, { + transform: 'translateY(3px)', +}); diff --git a/apps/core/src/components/pure/workspace-list-modal/index.tsx b/apps/core/src/components/pure/workspace-list-modal/index.tsx index ed16caf3fc..8325e5f83f 100644 --- a/apps/core/src/components/pure/workspace-list-modal/index.tsx +++ b/apps/core/src/components/pure/workspace-list-modal/index.tsx @@ -1,4 +1,3 @@ -import { Menu, MenuItem } from '@affine/component'; import { WorkspaceList } from '@affine/component/workspace-list'; import type { AffineCloudWorkspace, @@ -19,6 +18,7 @@ import type { DragEndEvent } from '@dnd-kit/core'; import { Popover } from '@mui/material'; import { IconButton } from '@toeverything/components/button'; import { Divider } from '@toeverything/components/divider'; +import { Menu, MenuIcon, MenuItem } from '@toeverything/components/menu'; import { useSetAtom } from 'jotai'; // eslint-disable-next-line @typescript-eslint/no-restricted-imports import { signOut, useSession } from 'next-auth/react'; @@ -35,6 +35,7 @@ import { StyledCreateWorkspaceCardPillContent, StyledCreateWorkspaceCardPillIcon, StyledImportWorkspaceCardPill, + StyledItem, StyledModalBody, StyledModalContent, StyledModalFooterContent, @@ -68,13 +69,12 @@ const AccountMenu = () => { const setOpen = useSetAtom(openSettingModalAtom); return (
- {/*
Unlimted
- - } data-testid="editor-option-menu-import"> - {t['com.affine.workspace.cloud.join']()} - */} } + preFix={ + + + + } data-testid="editor-option-menu-import" onClick={useCallback(() => { setOpen(prev => ({ ...prev, open: true, activeTab: 'account' })); @@ -84,7 +84,11 @@ const AccountMenu = () => { } + preFix={ + + + + } data-testid="editor-option-menu-import" onClick={useCallback(() => { signOut().catch(console.error); @@ -188,11 +192,7 @@ export const WorkspaceListModal = ({ {!isLoggedIn ? ( - { if (!runtimeConfig.enableCloud) { setDisableCloudOpen(true); @@ -218,7 +218,7 @@ export const WorkspaceListModal = ({ - + @@ -227,12 +227,7 @@ export const WorkspaceListModal = ({ {session?.user.email} - } - zIndex={1000} - > + }> } @@ -287,14 +282,7 @@ export const WorkspaceListModal = ({ {runtimeConfig.enableSQLiteProvider && environment.isDesktop ? ( - + @@ -303,20 +291,13 @@ export const WorkspaceListModal = ({

{t['com.affine.workspace.local.import']()}

- + ) : null} - + @@ -325,7 +306,7 @@ export const WorkspaceListModal = ({

{t['New Workspace']()}

-
+
diff --git a/apps/core/src/components/pure/workspace-list-modal/styles.ts b/apps/core/src/components/pure/workspace-list-modal/styles.ts index 0e7d76672b..e11f35270d 100644 --- a/apps/core/src/components/pure/workspace-list-modal/styles.ts +++ b/apps/core/src/components/pure/workspace-list-modal/styles.ts @@ -241,3 +241,32 @@ export const StyledWorkspaceFlavourTitle = styled('div')(() => { marginBottom: '4px', }; }); +export const StyledItem = styled('button')<{ + active?: boolean; +}>(({ active = false }) => { + return { + height: 'auto', + padding: '8px 12px', + width: '100%', + borderRadius: '5px', + fontSize: 'var(--affine-font-sm)', + ...displayFlex('flex-start', 'center'), + cursor: 'pointer', + position: 'relative', + backgroundColor: 'transparent', + color: 'var(--affine-text-primary-color)', + svg: { + color: 'var(--affine-icon-color)', + }, + + ':hover': { + backgroundColor: 'var(--affine-hover-color)', + }, + + ...(active + ? { + backgroundColor: 'var(--affine-hover-color)', + } + : {}), + }; +}); diff --git a/apps/core/src/components/pure/workspace-slider-bar/collections/collections-list.tsx b/apps/core/src/components/pure/workspace-slider-bar/collections/collections-list.tsx index 6f33be68c2..28edbb5c8d 100644 --- a/apps/core/src/components/pure/workspace-slider-bar/collections/collections-list.tsx +++ b/apps/core/src/components/pure/workspace-slider-bar/collections/collections-list.tsx @@ -1,5 +1,4 @@ -import { Menu } from '@affine/component'; -import { MenuItem } from '@affine/component/app-sidebar'; +import { MenuItem as CollectionItem } from '@affine/component/app-sidebar'; import { EditCollectionModel, useCollectionManager, @@ -21,6 +20,13 @@ import type { PageMeta, Workspace } from '@blocksuite/store'; import type { DragEndEvent } from '@dnd-kit/core'; import { useDroppable } from '@dnd-kit/core'; import * as Collapsible from '@radix-ui/react-collapsible'; +import { IconButton } from '@toeverything/components/button'; +import { + Menu, + MenuIcon, + MenuItem, + type MenuItemProps, +} from '@toeverything/components/menu'; import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta'; import type { ReactElement } from 'react'; import React, { useCallback, useMemo, useState } from 'react'; @@ -60,7 +66,7 @@ const CollectionOperations = ({ icon: ReactElement; name: string; click: () => void; - className?: string; + type?: MenuItemProps['type']; element?: undefined; } | { @@ -70,12 +76,20 @@ const CollectionOperations = ({ >( () => [ { - icon: , + icon: ( + + + + ), name: t['Edit Filter'](), click: showUpdateCollection, }, { - icon: , + icon: ( + + + + ), name: t['Unpin'](), click: () => { return setting.updateCollection({ @@ -88,12 +102,16 @@ const CollectionOperations = ({ element:
, }, { - icon: , + icon: ( + + + + ), name: t['Delete'](), click: () => { return setting.deleteCollection(view.id); }, - className: styles.deleteFolder, + type: 'danger', }, ], [setting, showUpdateCollection, t, view] @@ -108,8 +126,8 @@ const CollectionOperations = ({ {action.name} @@ -181,6 +199,7 @@ const CollectionRenderer = ({ const pagesToRender = pages.filter( page => filterPage(collection, page) && !page.trash ); + return ( showUpdateCollection(false)} /> - } postfix={ showUpdateCollection(true)} @@ -210,9 +227,13 @@ const CollectionRenderer = ({ /> } > -
+ -
+
} collapsed={pagesToRender.length > 0 ? collapsed : undefined} @@ -227,7 +248,7 @@ const CollectionRenderer = ({ >
{collection.name}
-
+
{pagesToRender.map(page => { @@ -260,13 +281,13 @@ export const CollectionsList = ({ workspace }: CollectionsListProps) => { const t = useAFFiNEI18N(); if (pinedCollections.length === 0) { return ( - } disabled > {t['Create a collection']()} - + ); } return ( diff --git a/apps/core/src/components/pure/workspace-slider-bar/collections/page.tsx b/apps/core/src/components/pure/workspace-slider-bar/collections/page.tsx index 8d550e8cff..019b8a2153 100644 --- a/apps/core/src/components/pure/workspace-slider-bar/collections/page.tsx +++ b/apps/core/src/components/pure/workspace-slider-bar/collections/page.tsx @@ -1,5 +1,4 @@ -import { Menu } from '@affine/component'; -import { MenuItem } from '@affine/component/app-sidebar'; +import { MenuItem as CollectionItem } from '@affine/component/app-sidebar'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { DeleteIcon, @@ -11,6 +10,13 @@ import { } from '@blocksuite/icons'; import type { PageMeta, Workspace } from '@blocksuite/store'; import * as Collapsible from '@radix-ui/react-collapsible'; +import { IconButton } from '@toeverything/components/button'; +import { + Menu, + MenuIcon, + MenuItem, + type MenuItemProps, +} from '@toeverything/components/menu'; import { useBlockSuitePageReferences } from '@toeverything/hooks/use-block-suite-page-references'; import { useAtomValue } from 'jotai/index'; import type { ReactElement } from 'react'; @@ -46,7 +52,7 @@ export const PageOperations = ({ icon: ReactElement; name: string; click: () => void; - className?: string; + type?: MenuItemProps['type']; element?: undefined; } | { @@ -58,7 +64,11 @@ export const PageOperations = ({ ...(inAllowList ? [ { - icon: , + icon: ( + + + + ), name: t['Remove special filter'](), click: () => removeFromAllowList(page.id), }, @@ -67,7 +77,11 @@ export const PageOperations = ({ ...(!inExcludeList ? [ { - icon: , + icon: ( + + + + ), name: t['Exclude from filter'](), click: () => addToExcludeList(page.id), }, @@ -77,12 +91,16 @@ export const PageOperations = ({ element:
, }, { - icon: , + icon: ( + + + + ), name: t['Delete'](), click: () => { removeToTrash(page.id); }, - className: styles.deleteFolder, + type: 'danger', }, ], [ @@ -105,8 +123,8 @@ export const PageOperations = ({ {action.name} @@ -133,6 +151,7 @@ export const Page = ({ workspace: Workspace; allPageMeta: Record; }) => { + const ref = React.useRef(null); const [collapsed, setCollapsed] = React.useState(true); const params = useParams(); const { jumpToPage } = useNavigateHelper(); @@ -148,7 +167,7 @@ export const Page = ({ const referencesToRender = references.filter(id => !allPageMeta[id]?.trash); return ( - 0 ? collapsed : undefined} onCollapsedChange={setCollapsed} + ref={ref} postfix={ - -
+ items={ + } + portalOptions={{ + container: ref.current, + }} > -
- -
+ + +
} > {page.title || t['Untitled']()} - + {referencesToRender.map(id => { return ( diff --git a/apps/prototype/package.json b/apps/prototype/package.json index 4e5111511e..c8cdf9f763 100644 --- a/apps/prototype/package.json +++ b/apps/prototype/package.json @@ -22,7 +22,7 @@ "@blocksuite/blocks": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/editor": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/global": "0.0.0-20230829150056-df43987c-nightly", - "@blocksuite/icons": "^2.1.31", + "@blocksuite/icons": "^2.1.32", "@blocksuite/lit": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/store": "0.0.0-20230829150056-df43987c-nightly", "@toeverything/hooks": "workspace:*", diff --git a/apps/storybook/package.json b/apps/storybook/package.json index fa5d461c19..4537e6cfa2 100644 --- a/apps/storybook/package.json +++ b/apps/storybook/package.json @@ -35,7 +35,7 @@ "@blocksuite/blocks": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/editor": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/global": "0.0.0-20230829150056-df43987c-nightly", - "@blocksuite/icons": "^2.1.31", + "@blocksuite/icons": "^2.1.32", "@blocksuite/lit": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/store": "0.0.0-20230829150056-df43987c-nightly", "@tomfreudenberg/next-auth-mock": "^0.5.6", diff --git a/packages/component/package.json b/packages/component/package.json index 70b90f61c6..a8c429e339 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -55,7 +55,7 @@ "@blocksuite/blocks": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/editor": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/global": "0.0.0-20230829150056-df43987c-nightly", - "@blocksuite/icons": "^2.1.31", + "@blocksuite/icons": "^2.1.32", "@blocksuite/lit": "0.0.0-20230829150056-df43987c-nightly", "@blocksuite/store": "0.0.0-20230829150056-df43987c-nightly", "@types/react": "^18.2.21", diff --git a/packages/component/src/components/app-sidebar/menu-item/index.css.ts b/packages/component/src/components/app-sidebar/menu-item/index.css.ts index 70328c16ac..067ce7c814 100644 --- a/packages/component/src/components/app-sidebar/menu-item/index.css.ts +++ b/packages/component/src/components/app-sidebar/menu-item/index.css.ts @@ -62,10 +62,10 @@ export const content = style({ export const postfix = style({ justifySelf: 'flex-end', - display: 'none', + visibility: 'hidden', selectors: { [`${root}:hover &`]: { - display: 'flex', + visibility: 'visible', }, }, }); diff --git a/packages/component/src/components/page-list/components/dropdown.css.ts b/packages/component/src/components/page-list/components/dropdown.css.ts new file mode 100644 index 0000000000..96d5de7bf0 --- /dev/null +++ b/packages/component/src/components/page-list/components/dropdown.css.ts @@ -0,0 +1,54 @@ +import { style } from '@vanilla-extract/css'; + +export const divider = style({ + width: '0.5px', + height: '16px', + background: 'var(--affine-divider-color)', + // fix dropdown button click area + margin: '0 4px', + marginRight: 0, +}); + +export const dropdownWrapper = style({ + width: '100%', + height: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + paddingLeft: '4px', + paddingRight: '10px', +}); + +export const dropdownIcon = style({ + borderRadius: '4px', + selectors: { + [`${dropdownWrapper}:hover &`]: { + background: 'var(--affine-hover-color)', + }, + }, +}); + +export const dropdownBtn = style({ + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + padding: '0 10px', + // fix dropdown button click area + paddingRight: 0, + color: 'var(--affine-text-primary-color)', + fontWeight: 600, + background: 'var(--affine-button-gray-color)', + boxShadow: 'var(--affine-float-button-shadow)', + borderRadius: '8px', + fontSize: 'var(--affine-font-sm)', + // width: '100%', + height: '32px', + userSelect: 'none', + whiteSpace: 'nowrap', + cursor: 'pointer', + selectors: { + '&:hover': { + background: 'var(--affine-hover-color-filled)', + }, + }, +}); diff --git a/packages/component/src/components/page-list/components/dropdown.tsx b/packages/component/src/components/page-list/components/dropdown.tsx new file mode 100644 index 0000000000..a2970eaf83 --- /dev/null +++ b/packages/component/src/components/page-list/components/dropdown.tsx @@ -0,0 +1,36 @@ +import { ArrowDownSmallIcon } from '@blocksuite/icons'; +import { + type ButtonHTMLAttributes, + forwardRef, + type MouseEventHandler, +} from 'react'; + +import * as styles from './dropdown.css'; + +type DropdownButtonProps = { + onClickDropDown?: MouseEventHandler; +} & ButtonHTMLAttributes; + +export const DropdownButton = forwardRef< + HTMLButtonElement, + DropdownButtonProps +>(({ onClickDropDown, children, ...props }, ref) => { + const handleClickDropDown: MouseEventHandler = e => { + e.stopPropagation(); + onClickDropDown?.(e); + }; + return ( + + ); +}); +DropdownButton.displayName = 'DropdownButton'; diff --git a/packages/component/src/components/page-list/components/new-page-buttton.tsx b/packages/component/src/components/page-list/components/new-page-buttton.tsx index 86a03782bf..9428aa48c4 100644 --- a/packages/component/src/components/page-list/components/new-page-buttton.tsx +++ b/packages/component/src/components/page-list/components/new-page-buttton.tsx @@ -1,10 +1,11 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { EdgelessIcon, ImportIcon, PageIcon } from '@blocksuite/icons'; +import { Menu } from '@toeverything/components/menu'; import { useState } from 'react'; -import { DropdownButton } from '../../../ui/button/dropdown'; -import { Menu } from '../../../ui/menu/menu'; +// import { Menu } from '../../../ui/menu/menu'; import { BlockCard } from '../../card/block-card'; +import { DropdownButton } from './dropdown'; type NewPageButtonProps = { createNewPage: () => void; @@ -32,18 +33,21 @@ export const CreateNewPagePopup = ({ desc={t['com.affine.write_with_a_blank_page']()} right={} onClick={createNewPage} + data-testid="new-page-button-in-all-page" /> } onClick={createNewEdgeless} + data-testid="new-edgeless-button-in-all-page" /> } onClick={importFile} + data-testid="import-button-in-all-page" /> {/* TODO Import */} @@ -59,18 +63,10 @@ export const NewPageButton = ({ const [open, setOpen] = useState(false); return ( { - setOpen(false); + rootOptions={{ + open, }} - menuStyles={{ - padding: '0px', - background: 'var(--affine-background-overlay-panel-color)', - }} - content={ + items={ { createNewPage(); diff --git a/packages/component/src/components/page-list/components/tags.tsx b/packages/component/src/components/page-list/components/tags.tsx index 41be6e3d36..273a313f21 100644 --- a/packages/component/src/components/page-list/components/tags.tsx +++ b/packages/component/src/components/page-list/components/tags.tsx @@ -1,8 +1,9 @@ import type { Tag } from '@affine/env/filter'; +import { Menu } from '@toeverything/components/menu'; -import Menu from '../../../ui/menu/menu'; import * as styles from './tags.css'; +// fixme: This component should use popover instead of menu export const Tags = ({ value }: { value: Tag[] }) => { const list = value.map(tag => { return ( @@ -16,10 +17,7 @@ export const Tags = ({ value }: { value: Tag[] }) => { ); }); return ( - {list}} - > + {list}}>
{list}
); diff --git a/packages/component/src/components/page-list/filter/condition.tsx b/packages/component/src/components/page-list/filter/condition.tsx index 3b025676bd..f7cc964093 100644 --- a/packages/component/src/components/page-list/filter/condition.tsx +++ b/packages/component/src/components/page-list/filter/condition.tsx @@ -1,9 +1,9 @@ import type { Filter, Literal } from '@affine/env/filter'; import type { PropertiesMeta } from '@affine/env/filter'; +import { Menu, MenuItem } from '@toeverything/components/menu'; import type { ReactNode } from 'react'; import { useMemo } from 'react'; -import { Menu, MenuItem } from '../../../ui/menu'; import { FilterTag } from './filter-tag-translation'; import * as styles from './index.css'; import { literalMatcher } from './literal-matcher'; @@ -50,8 +50,7 @@ export const Condition = ({ style={{ display: 'flex', userSelect: 'none', alignItems: 'center' }} > { +const useFilterTag = ({ name }: FilterTagProps) => { const t = useAFFiNEI18N(); switch (name) { case 'Created': @@ -41,3 +41,9 @@ export const FilterTag = ({ name }: FilterTagProps) => { return name; } }; + +export const FilterTag = ({ name }: FilterTagProps) => { + const tag = useFilterTag({ name }); + + return {tag}; +}; diff --git a/packages/component/src/components/page-list/filter/multi-select.tsx b/packages/component/src/components/page-list/filter/multi-select.tsx index 013f96c089..9d0509bb4f 100644 --- a/packages/component/src/components/page-list/filter/multi-select.tsx +++ b/packages/component/src/components/page-list/filter/multi-select.tsx @@ -1,8 +1,7 @@ -import { DoneIcon } from '@blocksuite/icons'; +import { Menu, MenuItem } from '@toeverything/components/menu'; import type { MouseEvent } from 'react'; import { useMemo } from 'react'; -import Menu from '../../../ui/menu/menu'; import * as styles from './multi-select.css'; export const MultiSelect = ({ @@ -21,10 +20,10 @@ export const MultiSelect = ({ () => Object.fromEntries(options.map(v => [v.value, v])), [options] ); + return ( {options.map(option => { const selected = value.includes(option.value); @@ -37,25 +36,14 @@ export const MultiSelect = ({ } }; return ( -
-
{option.label}
-
- -
-
+ {option.label} + ); })} diff --git a/packages/component/src/components/page-list/filter/vars.tsx b/packages/component/src/components/page-list/filter/vars.tsx index 019fcaf875..454bc7658b 100644 --- a/packages/component/src/components/page-list/filter/vars.tsx +++ b/packages/component/src/components/page-list/filter/vars.tsx @@ -5,10 +5,10 @@ import type { VariableMap, } from '@affine/env/filter'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; +import { MenuIcon, MenuItem } from '@toeverything/components/menu'; import dayjs from 'dayjs'; import type { ReactNode } from 'react'; -import { MenuItem } from '../../../ui/menu'; import { FilterTag } from './filter-tag-translation'; import * as styles from './index.css'; import { tBoolean, tDate, tTag } from './logical/custom-type'; @@ -92,7 +92,7 @@ export const VariableSelect = ({ // .filter(v => !selected.find(filter => filter.left.name === v.name)) .map(v => ( {variableDefineMap[v.name].icon}} key={v.name} onClick={() => { onSelect(createDefaultFilter(v, propertiesMeta)); diff --git a/packages/component/src/components/page-list/operation-cell.tsx b/packages/component/src/components/page-list/operation-cell.tsx index bca48006cc..8b1f8fde7d 100644 --- a/packages/component/src/components/page-list/operation-cell.tsx +++ b/packages/component/src/components/page-list/operation-cell.tsx @@ -9,10 +9,11 @@ import { ResetIcon, } from '@blocksuite/icons'; import { IconButton } from '@toeverything/components/button'; +import { Menu, MenuIcon, MenuItem } from '@toeverything/components/menu'; import { Tooltip } from '@toeverything/components/tooltip'; import { useState } from 'react'; -import { Confirm, FlexWrapper, Menu, MenuItem } from '../../..'; +import { Confirm, FlexWrapper } from '../../..'; import { DisablePublicSharing, MoveToTrash } from './operation-menu-items'; export interface OperationCellProps { @@ -43,31 +44,40 @@ export const OperationCell = ({ {isPublic && ( { + onSelect={() => { setOpenDisableShared(true); }} /> )} - ) : ( - - ) + preFix={ + + {favorite ? ( + + ) : ( + + )} + } > {favorite ? t['Remove from favorites']() : t['Add to Favorites']()} {!isDesktop && ( - }> + + + + } + > {t['Open in new tab']()} )} { + onSelect={() => { setOpen(true); }} /> @@ -76,13 +86,8 @@ export const OperationCell = ({ return ( <> - - + + diff --git a/packages/component/src/components/page-list/operation-menu-items/copy-link.tsx b/packages/component/src/components/page-list/operation-menu-items/copy-link.tsx deleted file mode 100644 index 6f5516a909..0000000000 --- a/packages/component/src/components/page-list/operation-menu-items/copy-link.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { useAFFiNEI18N } from '@affine/i18n/hooks'; -import { CopyIcon } from '@blocksuite/icons'; -import { useCallback } from 'react'; - -import { MenuItem, toast } from '../../..'; -import type { CommonMenuItemProps } from './types'; - -export const CopyLink = ({ onItemClick, onSelect }: CommonMenuItemProps) => { - const t = useAFFiNEI18N(); - - const copyUrl = useCallback(() => { - navigator.clipboard - .writeText(window.location.href) - .then(() => { - toast(t['Copied link to clipboard']()); - }) - .catch(err => { - // TODO add error toast here - console.error(err); - }); - }, [t]); - - return ( - { - copyUrl(); - onItemClick?.(); - onSelect?.(); - }} - icon={} - > - {t['Copy Link']()} - - ); -}; diff --git a/packages/component/src/components/page-list/operation-menu-items/disable-public-sharing.tsx b/packages/component/src/components/page-list/operation-menu-items/disable-public-sharing.tsx index f905aa02fe..e89b37d76d 100644 --- a/packages/component/src/components/page-list/operation-menu-items/disable-public-sharing.tsx +++ b/packages/component/src/components/page-list/operation-menu-items/disable-public-sharing.tsx @@ -1,48 +1,27 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { ShareIcon } from '@blocksuite/icons'; +import { + MenuIcon, + MenuItem, + type MenuItemProps, +} from '@toeverything/components/menu'; -import { MenuItem, styled } from '../../../'; import { PublicLinkDisableModal } from '../../share-menu'; -import type { CommonMenuItemProps } from './types'; -const StyledMenuItem = styled(MenuItem)(({ theme }) => { - return { - div: { - color: theme.palette.error.main, - svg: { - color: theme.palette.error.main, - }, - }, - ':hover': { - div: { - color: theme.palette.error.main, - svg: { - color: theme.palette.error.main, - }, - }, - }, - }; -}); -export const DisablePublicSharing = ({ - onSelect, - onItemClick, - ...props -}: CommonMenuItemProps) => { +export const DisablePublicSharing = (props: MenuItemProps) => { const t = useAFFiNEI18N(); return ( - <> - { - onItemClick?.(); - onSelect?.(); - }} - style={{ color: 'red' }} - icon={} - > - {t['Disable Public Sharing']()} - - + + + + } + {...props} + > + {t['Disable Public Sharing']()} + ); }; diff --git a/packages/component/src/components/page-list/operation-menu-items/export.tsx b/packages/component/src/components/page-list/operation-menu-items/export.tsx index 61b7299ad4..eb91331169 100644 --- a/packages/component/src/components/page-list/operation-menu-items/export.tsx +++ b/packages/component/src/components/page-list/operation-menu-items/export.tsx @@ -2,36 +2,22 @@ import { pushNotificationAtom } from '@affine/component/notification-center'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import type { PageBlockModel } from '@blocksuite/blocks'; import { - ArrowRightSmallIcon, ExportIcon, ExportToHtmlIcon, ExportToMarkdownIcon, ExportToPdfIcon, ExportToPngIcon, } from '@blocksuite/icons'; +import { MenuIcon, MenuItem, MenuSub } from '@toeverything/components/menu'; import { useSetAtom } from 'jotai'; import { useCallback } from 'react'; -import { Menu, MenuItem } from '../../..'; import { getContentParser } from './get-content-parser'; import type { CommonMenuItemProps } from './types'; -type ExportMenuItemProps = { - iconSize?: number; - gap?: string; - fontSize?: string; -}; -const MenuItemStyle = { - padding: '4px 12px', -}; - export const ExportToPdfMenuItem = ({ onSelect, - style = MenuItemStyle, - iconSize, - gap, - fontSize, -}: CommonMenuItemProps<{ type: 'pdf' }> & ExportMenuItemProps) => { +}: CommonMenuItemProps<{ type: 'pdf' }>) => { const t = useAFFiNEI18N(); const { currentEditor } = globalThis; const setPushNotification = useSetAtom(pushNotificationAtom); @@ -89,12 +75,12 @@ export const ExportToPdfMenuItem = ({ return ( } - style={style} - iconSize={iconSize} - gap={gap} - fontSize={fontSize} + onSelect={onClickDownloadPDF} + preFix={ + + + + } > {t['Export to PDF']()} @@ -103,11 +89,7 @@ export const ExportToPdfMenuItem = ({ export const ExportToHtmlMenuItem = ({ onSelect, - style = MenuItemStyle, - iconSize, - gap, - fontSize, -}: CommonMenuItemProps<{ type: 'html' }> & ExportMenuItemProps) => { +}: CommonMenuItemProps<{ type: 'html' }>) => { const t = useAFFiNEI18N(); const { currentEditor } = globalThis; const setPushNotification = useSetAtom(pushNotificationAtom); @@ -140,12 +122,12 @@ export const ExportToHtmlMenuItem = ({ <> } - style={style} - iconSize={iconSize} - gap={gap} - fontSize={fontSize} + onSelect={onClickExportHtml} + preFix={ + + + + } > {t['Export to HTML']()} @@ -155,11 +137,7 @@ export const ExportToHtmlMenuItem = ({ export const ExportToPngMenuItem = ({ onSelect, - style = MenuItemStyle, - iconSize, - gap, - fontSize, -}: CommonMenuItemProps<{ type: 'png' }> & ExportMenuItemProps) => { +}: CommonMenuItemProps<{ type: 'png' }>) => { const t = useAFFiNEI18N(); const { currentEditor } = globalThis; const setPushNotification = useSetAtom(pushNotificationAtom); @@ -194,12 +172,12 @@ export const ExportToPngMenuItem = ({ <> } - style={style} - iconSize={iconSize} - gap={gap} - fontSize={fontSize} + onSelect={onClickDownloadPNG} + preFix={ + + + + } > {t['Export to PNG']()} @@ -209,11 +187,7 @@ export const ExportToPngMenuItem = ({ export const ExportToMarkdownMenuItem = ({ onSelect, - style = MenuItemStyle, - iconSize, - gap, - fontSize, -}: CommonMenuItemProps<{ type: 'markdown' }> & ExportMenuItemProps) => { +}: CommonMenuItemProps<{ type: 'markdown' }>) => { const t = useAFFiNEI18N(); const { currentEditor } = globalThis; const setPushNotification = useSetAtom(pushNotificationAtom); @@ -246,12 +220,12 @@ export const ExportToMarkdownMenuItem = ({ <> } - style={style} - iconSize={iconSize} - gap={gap} - fontSize={fontSize} + onSelect={onClickExportMarkdown} + preFix={ + + + + } > {t['Export to Markdown']()} @@ -259,16 +233,12 @@ export const ExportToMarkdownMenuItem = ({ ); }; -export const Export = ({ - onItemClick, -}: CommonMenuItemProps<{ type: 'markdown' | 'html' | 'pdf' | 'png' }>) => { +// fixme: refactor this file, export function may should be passed by 'props', this file is just a ui component +export const Export = () => { const t = useAFFiNEI18N(); return ( - @@ -276,24 +246,16 @@ export const Export = ({ } - menuStyles={{ - borderRadius: '8px', - padding: '8px', - background: 'var(--affine-background-overlay-panel-color)', + triggerOptions={{ + preFix: ( + + + + ), + ['data-testid' as string]: 'export-menu', }} > - } - endIcon={} - style={MenuItemStyle} - onClick={e => { - e.stopPropagation(); - onItemClick?.(); - }} - > - {t.Export()} - - + {t.Export()} + ); }; diff --git a/packages/component/src/components/page-list/operation-menu-items/index.ts b/packages/component/src/components/page-list/operation-menu-items/index.ts index 6669204a19..472153ef7d 100644 --- a/packages/component/src/components/page-list/operation-menu-items/index.ts +++ b/packages/component/src/components/page-list/operation-menu-items/index.ts @@ -1,4 +1,3 @@ -export * from './copy-link'; export * from './disable-public-sharing'; export * from './export'; // export * from './MoveTo'; diff --git a/packages/component/src/components/page-list/operation-menu-items/move-to-trash.tsx b/packages/component/src/components/page-list/operation-menu-items/move-to-trash.tsx index 3cc3331c48..f98d31663e 100644 --- a/packages/component/src/components/page-list/operation-menu-items/move-to-trash.tsx +++ b/packages/component/src/components/page-list/operation-menu-items/move-to-trash.tsx @@ -1,31 +1,28 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { DeleteTemporarilyIcon } from '@blocksuite/icons'; +import { + MenuIcon, + MenuItem, + type MenuItemProps, +} from '@toeverything/components/menu'; import type { ConfirmProps } from '../../..'; -import { Confirm, MenuItem } from '../../..'; -import { moveToTrashStyle } from './index.css'; -import type { CommonMenuItemProps } from './types'; -export const MoveToTrash = ({ - onSelect, - onItemClick, - ...props -}: CommonMenuItemProps) => { +import { Confirm } from '../../..'; +export const MoveToTrash = (props: MenuItemProps) => { const t = useAFFiNEI18N(); return ( - <> - { - onItemClick?.(); - onSelect?.(); - }} - icon={} - className={moveToTrashStyle} - > - {t['Move to Trash']()} - - + + + + } + type="danger" + {...props} + > + {t['Move to Trash']()} + ); }; diff --git a/packages/component/src/components/page-list/view/collection-list.tsx b/packages/component/src/components/page-list/view/collection-list.tsx index e598fb8b84..cb51598b55 100644 --- a/packages/component/src/components/page-list/view/collection-list.tsx +++ b/packages/component/src/components/page-list/view/collection-list.tsx @@ -6,13 +6,12 @@ import type { GetPageInfoById } from '@affine/env/page-info'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { FilteredIcon, FolderIcon, ViewLayersIcon } from '@blocksuite/icons'; import { Button } from '@toeverything/components/button'; +import { Menu, MenuIcon, MenuItem } from '@toeverything/components/menu'; import { Tooltip } from '@toeverything/components/tooltip'; import clsx from 'clsx'; import type { MouseEvent } from 'react'; -import { useCallback, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; -import { MenuItem } from '../../..'; -import Menu from '../../../ui/menu/menu'; import { CreateFilterMenu } from '../filter/vars'; import type { useCollectionManager } from '../use-collection-manager'; import * as styles from './collection-list.css'; @@ -40,7 +39,11 @@ const CollectionOption = ({ return ( } + preFix={ + + + + } onClick={selectCollection} key={collection.id} className={styles.viewMenu} @@ -107,6 +110,7 @@ export const CollectionList = ({ getPageInfo: GetPageInfoById; propertiesMeta: PropertiesMeta; }) => { + const ref = useRef(null); const t = useAFFiNEI18N(); const [collection, setCollection] = useState(); const onChange = useCallback( @@ -134,14 +138,20 @@ export const CollectionList = ({ [closeUpdateCollectionModal, setting] ); return ( - + {setting.savedCollections.length > 0 && ( } + preFix={ + + + + } onClick={setting.backToAll} className={styles.viewMenu} > @@ -184,17 +194,22 @@ export const CollectionList = ({ )} } + portalOptions={{ + container: ref.current, + }} > - diff --git a/packages/component/src/components/share-menu/share-export.tsx b/packages/component/src/components/share-menu/share-export.tsx index ff4d23ff4e..be16ff74d2 100644 --- a/packages/component/src/components/share-menu/share-export.tsx +++ b/packages/component/src/components/share-menu/share-export.tsx @@ -17,26 +17,10 @@ export const ShareExport = () => { {t['com.affine.share-menu.ShareViaExport']()}
- - - - + + + +
diff --git a/packages/component/src/components/share-menu/share-menu.tsx b/packages/component/src/components/share-menu/share-menu.tsx index c64c75b01f..d138fb2c6c 100644 --- a/packages/component/src/components/share-menu/share-menu.tsx +++ b/packages/component/src/components/share-menu/share-menu.tsx @@ -8,12 +8,10 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import type { Page } from '@blocksuite/store'; import { Button } from '@toeverything/components/button'; import { Divider } from '@toeverything/components/divider'; -import { useAtom } from 'jotai'; -import { useCallback } from 'react'; +import { Menu } from '@toeverything/components/menu'; +import { useRef } from 'react'; -import { Menu } from '../../ui/menu/menu'; import * as styles from './index.css'; -import { enableShareMenuAtom } from './index.jotai'; import { ShareExport } from './share-export'; import { SharePage } from './share-page'; @@ -35,11 +33,11 @@ export interface ShareMenuProps< export const ShareMenu = (props: ShareMenuProps) => { const { useIsSharedPage } = props; + const ref = useRef(null); const isSharedPage = useIsSharedPage( props.workspace.id, props.currentPage.id ); - const [open, setOpen] = useAtom(enableShareMenuAtom); const t = useAFFiNEI18N(); const content = (
@@ -52,28 +50,12 @@ export const ShareMenu = (props: ShareMenuProps) => { ); return ( { - setOpen(false); - }, [setOpen])} > - - ); - } -); -MenuTrigger.displayName = 'MenuTrigger'; diff --git a/packages/component/src/ui/menu/menu.tsx b/packages/component/src/ui/menu/menu.tsx deleted file mode 100644 index 5fd6f18c20..0000000000 --- a/packages/component/src/ui/menu/menu.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import type { TooltipProps } from '@mui/material'; -import type { CSSProperties } from 'react'; - -import { Popper, type PopperProps } from '../popper'; -import { StyledMenuWrapper } from './styles'; - -export type MenuProps = { - width?: CSSProperties['width']; - menuStyles?: CSSProperties; -} & PopperProps & - Omit; -export const Menu = (props: MenuProps) => { - const { - width, - menuStyles, - content, - placement = 'bottom-start', - children, - ...popperProps - } = props; - return content ? ( - - {content} - - } - > - {children} - - ) : null; -}; - -export default Menu; diff --git a/plugins/bookmark/package.json b/plugins/bookmark/package.json index 4f9bf16e30..b026a44271 100644 --- a/plugins/bookmark/package.json +++ b/plugins/bookmark/package.json @@ -20,7 +20,7 @@ "dependencies": { "@affine/component": "workspace:*", "@affine/sdk": "workspace:*", - "@blocksuite/icons": "^2.1.31", + "@blocksuite/icons": "^2.1.32", "foxact": "^0.2.20", "link-preview-js": "^3.0.5" }, diff --git a/plugins/copilot/package.json b/plugins/copilot/package.json index 604258f89e..27467bd9cc 100644 --- a/plugins/copilot/package.json +++ b/plugins/copilot/package.json @@ -16,7 +16,7 @@ "dependencies": { "@affine/component": "workspace:*", "@affine/sdk": "workspace:*", - "@toeverything/components": "^0.0.25", + "@toeverything/components": "^0.0.31", "idb": "^7.1.1", "langchain": "^0.0.138", "marked": "^7.0.5", diff --git a/plugins/hello-world/package.json b/plugins/hello-world/package.json index ef868e545e..534932a0b8 100644 --- a/plugins/hello-world/package.json +++ b/plugins/hello-world/package.json @@ -17,8 +17,8 @@ "dependencies": { "@affine/component": "workspace:*", "@affine/sdk": "workspace:*", - "@blocksuite/icons": "^2.1.31", - "@toeverything/components": "^0.0.25" + "@blocksuite/icons": "^2.1.32", + "@toeverything/components": "^0.0.31" }, "devDependencies": { "@affine/plugin-cli": "workspace:*" diff --git a/plugins/image-preview/package.json b/plugins/image-preview/package.json index 49341af065..ebf2188196 100644 --- a/plugins/image-preview/package.json +++ b/plugins/image-preview/package.json @@ -17,7 +17,7 @@ "@affine/component": "workspace:*", "@affine/sdk": "workspace:*", "@blocksuite/icons": "^2.1.31", - "@toeverything/components": "^0.0.25", + "@toeverything/components": "^0.0.31", "@toeverything/theme": "^0.7.15", "clsx": "^2.0.0", "foxact": "^0.2.20", diff --git a/plugins/outline/package.json b/plugins/outline/package.json index 776d17dc7b..dff54e1cae 100644 --- a/plugins/outline/package.json +++ b/plugins/outline/package.json @@ -17,8 +17,8 @@ "dependencies": { "@affine/component": "workspace:*", "@affine/sdk": "workspace:*", - "@blocksuite/icons": "^2.1.31", - "@toeverything/components": "^0.0.25" + "@blocksuite/icons": "^2.1.32", + "@toeverything/components": "^0.0.31" }, "devDependencies": { "@affine/plugin-cli": "workspace:*", diff --git a/tests/affine-local/e2e/all-page.spec.ts b/tests/affine-local/e2e/all-page.spec.ts index 061392eed0..039a3a375e 100644 --- a/tests/affine-local/e2e/all-page.spec.ts +++ b/tests/affine-local/e2e/all-page.spec.ts @@ -29,7 +29,7 @@ function getAllPage(page: Page) { .locator('table') .getByRole('button', { name: 'New Page' }); const newPageDropdown = newPageButton.locator('svg'); - const edgelessBlockCard = page.locator('table').getByText('New Edgeless'); + const edgelessBlockCard = page.getByTestId('new-edgeless-button-in-all-page'); async function clickNewPageButton() { return newPageButton.click(); @@ -106,11 +106,8 @@ test('allow creation of filters by created time', async ({ page }) => { await fillDatePicker(page, today); await checkPagesCount(page, 0); // change filter - await page.locator('[data-testid="filter-name"]').click(); - await page - .locator('[data-testid="filter-name-select"]') - .locator('button', { hasText: 'before' }) - .click(); + await page.getByTestId('filter-name').click(); + await page.getByTestId('filler-tag-before').click(); const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); await fillDatePicker(page, tomorrow); @@ -142,10 +139,7 @@ test('creation of filters by created time, then click date picker to modify the await checkPagesCount(page, 0); // change filter await page.locator('[data-testid="filter-name"]').click(); - await page - .locator('[data-testid="filter-name-select"]') - .locator('button', { hasText: 'before' }) - .click(); + await page.getByTestId('filler-tag-before').click(); const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); await selectDateFromDatePicker(page, tomorrow); @@ -196,11 +190,11 @@ test('allow creation of filters by tags', async ({ page }) => { await createFirstFilter(page, 'Tags'); await checkFilterName(page, 'is not empty'); await checkPagesCount(page, pagesWithTagsCount + 2); - await changeFilter(page, /^contains all/); + await changeFilter(page, 'contains all'); await checkPagesCount(page, pageCount + 2); await selectTag(page, 'A'); await checkPagesCount(page, 1); - await changeFilter(page, /^does not contains all/); + await changeFilter(page, 'does not contains all'); await selectTag(page, 'B'); await checkPagesCount(page, pageCount + 1); }); diff --git a/tests/affine-local/e2e/local-first-collections-items.spec.ts b/tests/affine-local/e2e/local-first-collections-items.spec.ts index 53596a9bf4..0066f4e477 100644 --- a/tests/affine-local/e2e/local-first-collections-items.spec.ts +++ b/tests/affine-local/e2e/local-first-collections-items.spec.ts @@ -29,10 +29,7 @@ const createAndPinCollection = async ( }); await expect(cell).toBeVisible(); await page.getByTestId('create-first-filter').click(); - await page - .getByTestId('variable-select') - .locator('button', { hasText: 'Created' }) - .click(); + await page.getByTestId(`filler-tag-Created`).click(); await page.getByTestId('save-as-collection').click(); const title = page.getByTestId('input-collection-title'); await title.isVisible(); @@ -156,7 +153,8 @@ test('create temporary filter by click tag', async ({ page }) => { await expect(cell).toBeVisible(); expect(await page.getByTestId('title').count()).toBe(1); await page.getByTestId('filter-arg').click(); - await page.getByRole('tooltip').getByText('TODO Tag').click(); + + await page.getByTestId('multi-select-TODO Tag').click(); expect(await page.getByTestId('title').count()).toBeGreaterThanOrEqual(2); }); diff --git a/tests/affine-local/e2e/local-first-favorite-page.spec.ts b/tests/affine-local/e2e/local-first-favorite-page.spec.ts index 92d08c2b91..744fe2e064 100644 --- a/tests/affine-local/e2e/local-first-favorite-page.spec.ts +++ b/tests/affine-local/e2e/local-first-favorite-page.spec.ts @@ -38,7 +38,7 @@ test('Export to html, markdown and png', async ({ page }) => { await waitForEditorLoad(page); { await clickPageMoreActions(page); - await page.getByTestId('export-menu').click(); + await page.getByTestId('export-menu').hover(); const downloadPromise = page.waitForEvent('download'); await page.getByTestId('export-to-markdown').click(); await downloadPromise; diff --git a/tests/affine-local/e2e/local-first-openpage-newtab.spec.ts b/tests/affine-local/e2e/local-first-openpage-newtab.spec.ts index 59da8aa440..8049b2d6cc 100644 --- a/tests/affine-local/e2e/local-first-openpage-newtab.spec.ts +++ b/tests/affine-local/e2e/local-first-openpage-newtab.spec.ts @@ -25,7 +25,7 @@ test('click btn bew page and open in tab', async ({ page, workspace }) => { .click(); const [newTabPage] = await Promise.all([ page.waitForEvent('popup'), - page.getByRole('button', { name: 'Open in new tab' }).click(), + page.getByRole('menuitem', { name: 'Open in new tab' }).click(), ]); expect(newTabPage.url()).toBe(newPageUrl); diff --git a/tests/affine-local/e2e/settings.spec.ts b/tests/affine-local/e2e/settings.spec.ts index a522dd7e15..5a28768c0a 100644 --- a/tests/affine-local/e2e/settings.spec.ts +++ b/tests/affine-local/e2e/settings.spec.ts @@ -39,18 +39,6 @@ test('change language using keyboard', async ({ page }) => { const newName = await locator.textContent(); expect(oldName).not.toBe(newName); } - await locator.click(); - await page.waitForTimeout(200); - await page.keyboard.press('ArrowUp', { - delay: 50, - }); - await page.keyboard.press('Enter', { - delay: 50, - }); - { - const newName = await locator.textContent(); - expect(oldName).toBe(newName); - } }); test('Change theme', async ({ page }) => { diff --git a/tests/kit/utils/filter.ts b/tests/kit/utils/filter.ts index bcb3a204c0..66541d35d1 100644 --- a/tests/kit/utils/filter.ts +++ b/tests/kit/utils/filter.ts @@ -200,20 +200,12 @@ export const createPageWithTag = async ( await page.keyboard.press('Escape'); }; -export const changeFilter = async (page: Page, to: string | RegExp) => { +export const changeFilter = async (page: Page, to: string) => { await page.getByTestId('filter-name').click(); - await page - .getByTestId('filter-name-select') - .locator('button', { hasText: to }) - .click(); + await page.getByTestId(`filler-tag-${to}`).click(); }; export async function selectTag(page: Page, name: string | RegExp) { await page.getByTestId('filter-arg').click(); - await page - .getByTestId('multi-select') - .getByTestId('select-option') - .getByText(name, { exact: true }) - .click(); - await page.getByTestId('filter-arg').click(); + await page.getByTestId(`multi-select-${name}`).click(); } diff --git a/yarn.lock b/yarn.lock index 15d9453c73..f24d8573f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -121,7 +121,7 @@ __metadata: "@affine/component": "workspace:*" "@affine/plugin-cli": "workspace:*" "@affine/sdk": "workspace:*" - "@blocksuite/icons": ^2.1.31 + "@blocksuite/icons": ^2.1.32 foxact: ^0.2.20 link-preview-js: ^3.0.5 languageName: unknown @@ -154,7 +154,7 @@ __metadata: "@blocksuite/blocks": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/editor": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/global": 0.0.0-20230829150056-df43987c-nightly - "@blocksuite/icons": ^2.1.31 + "@blocksuite/icons": ^2.1.32 "@blocksuite/lit": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/store": 0.0.0-20230829150056-df43987c-nightly "@dnd-kit/core": ^6.0.8 @@ -212,7 +212,7 @@ __metadata: "@affine/component": "workspace:*" "@affine/plugin-cli": "workspace:*" "@affine/sdk": "workspace:*" - "@toeverything/components": ^0.0.25 + "@toeverything/components": ^0.0.31 "@types/marked": ^5.0.1 idb: ^7.1.1 jotai: ^2.4.1 @@ -247,7 +247,7 @@ __metadata: "@blocksuite/blocks": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/editor": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/global": 0.0.0-20230829150056-df43987c-nightly - "@blocksuite/icons": ^2.1.31 + "@blocksuite/icons": ^2.1.32 "@blocksuite/lit": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/store": 0.0.0-20230829150056-df43987c-nightly "@dnd-kit/core": ^6.0.8 @@ -264,7 +264,7 @@ __metadata: "@sentry/webpack-plugin": ^2.7.0 "@svgr/webpack": ^8.1.0 "@swc/core": ^1.3.81 - "@toeverything/components": ^0.0.25 + "@toeverything/components": ^0.0.31 "@types/lodash-es": ^4.17.9 "@types/webpack-env": ^1.18.1 async-call-rpc: ^6.3.1 @@ -439,8 +439,8 @@ __metadata: "@affine/component": "workspace:*" "@affine/plugin-cli": "workspace:*" "@affine/sdk": "workspace:*" - "@blocksuite/icons": ^2.1.31 - "@toeverything/components": ^0.0.25 + "@blocksuite/icons": ^2.1.32 + "@toeverything/components": ^0.0.31 languageName: unknown linkType: soft @@ -466,7 +466,7 @@ __metadata: "@affine/plugin-cli": "workspace:*" "@affine/sdk": "workspace:*" "@blocksuite/icons": ^2.1.31 - "@toeverything/components": ^0.0.25 + "@toeverything/components": ^0.0.31 "@toeverything/theme": ^0.7.15 clsx: ^2.0.0 foxact: ^0.2.20 @@ -584,8 +584,8 @@ __metadata: "@affine/component": "workspace:*" "@affine/plugin-cli": "workspace:*" "@affine/sdk": "workspace:*" - "@blocksuite/icons": ^2.1.31 - "@toeverything/components": ^0.0.25 + "@blocksuite/icons": ^2.1.32 + "@toeverything/components": ^0.0.31 jotai: ^2.4.1 react: 18.2.0 react-dom: 18.2.0 @@ -626,7 +626,7 @@ __metadata: "@blocksuite/blocks": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/editor": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/global": 0.0.0-20230829150056-df43987c-nightly - "@blocksuite/icons": ^2.1.31 + "@blocksuite/icons": ^2.1.32 "@blocksuite/lit": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/store": 0.0.0-20230829150056-df43987c-nightly "@toeverything/hooks": "workspace:*" @@ -762,7 +762,7 @@ __metadata: "@blocksuite/blocks": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/editor": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/global": 0.0.0-20230829150056-df43987c-nightly - "@blocksuite/icons": ^2.1.31 + "@blocksuite/icons": ^2.1.32 "@blocksuite/lit": 0.0.0-20230829150056-df43987c-nightly "@blocksuite/store": 0.0.0-20230829150056-df43987c-nightly "@storybook/addon-actions": ^7.4.0 @@ -3525,7 +3525,7 @@ __metadata: languageName: node linkType: hard -"@blocksuite/icons@npm:^2.1.30, @blocksuite/icons@npm:^2.1.31": +"@blocksuite/icons@npm:^2.1.31": version: 2.1.31 resolution: "@blocksuite/icons@npm:2.1.31" peerDependencies: @@ -3535,6 +3535,26 @@ __metadata: languageName: node linkType: hard +"@blocksuite/icons@npm:^2.1.32": + version: 2.1.32 + resolution: "@blocksuite/icons@npm:2.1.32" + peerDependencies: + "@types/react": ^18.0.25 + react: ^18.2.0 + checksum: 76179a20fd67c9a5c7756439b25636bd550509ddc34951243a6a42a7f95cd7427591e16b87a2ebbac09e3fadef1a62e4ec30de31d419872c27f1130cb58f4c38 + languageName: node + linkType: hard + +"@blocksuite/icons@npm:^2.1.33": + version: 2.1.33 + resolution: "@blocksuite/icons@npm:2.1.33" + peerDependencies: + "@types/react": ^18.0.25 + react: ^18.2.0 + checksum: b29f5ffb19f09937a9053028b1fd70e497f54be82673b91889a2b9d2b23e2f853872415bd638f81dc4917370f555c330573139e4a58d88c588d04a0111f5117b + languageName: node + linkType: hard + "@blocksuite/lit@npm:0.0.0-20230829150056-df43987c-nightly": version: 0.0.0-20230829150056-df43987c-nightly resolution: "@blocksuite/lit@npm:0.0.0-20230829150056-df43987c-nightly" @@ -12451,11 +12471,11 @@ __metadata: languageName: node linkType: hard -"@toeverything/components@npm:^0.0.25": - version: 0.0.25 - resolution: "@toeverything/components@npm:0.0.25" +"@toeverything/components@npm:^0.0.31": + version: 0.0.31 + resolution: "@toeverything/components@npm:0.0.31" dependencies: - "@blocksuite/icons": ^2.1.30 + "@blocksuite/icons": ^2.1.33 "@radix-ui/react-dropdown-menu": ^2.0.5 "@radix-ui/react-tooltip": ^1.0.6 peerDependencies: @@ -12463,7 +12483,7 @@ __metadata: clsx: ^2 react: ^18 react-dom: ^18 - checksum: e4f5b49c81c9ef78e72ccb5e097d36796793865302f346d64f9eb5016e9ef6e1936047439aa698fde9e52d96ec5a1c5e6f4877bc04c71f69e7091c60c427e981 + checksum: a47263e25c9b6f987cc97d75cbf515a41ca7cce26f67c7c2017ad0e1331d5e4e59c50b1b511970fd28210e3437dfb19a83016678c3c633f0110065b6156ce289 languageName: node linkType: hard