diff --git a/packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-modal.css.ts b/packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-popup.css.ts similarity index 85% rename from packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-modal.css.ts rename to packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-popup.css.ts index 97b91d6725..6da30a5e15 100644 --- a/packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-modal.css.ts +++ b/packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-popup.css.ts @@ -25,32 +25,20 @@ const contentHide = keyframes({ }, }); -export const modalOverlay = style({ +export const anchor = style({ position: 'fixed', - inset: 0, - backgroundColor: 'transparent', - zIndex: cssVar('zIndexModal'), -}); - -export const modalContentWrapper = style({ - position: 'fixed', - inset: 0, - display: 'flex', - alignItems: 'flex-start', - justifyContent: 'flex-end', - zIndex: cssVar('zIndexModal'), right: '28px', top: '80px', + zIndex: cssVar('zIndexModal'), }); -export const modalContent = style({ +export const contentContainer = style({ width: 400, height: 48, backgroundColor: cssVar('backgroundOverlayPanelColor'), borderRadius: '8px', boxShadow: cssVar('shadow3'), minHeight: 48, - // :focus-visible will set outline outline: 'none', display: 'flex', gap: 8, @@ -116,6 +104,7 @@ export const input = style({ height: '100%', width: '100%', color: 'transparent', + fontSize: '15px', }); export const inputHack = style([ @@ -134,19 +123,22 @@ export const count = style({ userSelect: 'none', }); +export const arrowButtonContainer = style({ + border: '1px solid', + borderColor: cssVarV2('layer/insideBorder/border'), + flexShrink: 0, + borderRadius: '4px', + overflow: 'hidden', +}); + export const arrowButton = style({ width: 32, height: 32, - flexShrink: 0, - border: '1px solid', - borderColor: cssVarV2('layer/insideBorder/border'), + borderRadius: 0, selectors: { - '&.backward': { - borderRadius: '4px 0 0 4px', - }, - '&.forward': { - borderLeft: 'none', - borderRadius: '0 4px 4px 0', + '&:first-child': { + borderRight: '1px solid', + borderColor: cssVarV2('layer/insideBorder/border'), }, }, }); diff --git a/packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-modal.tsx b/packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-popup.tsx similarity index 57% rename from packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-modal.tsx rename to packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-popup.tsx index 550987abac..5d66dc4548 100644 --- a/packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-modal.tsx +++ b/packages/frontend/core/src/desktop/pages/root/find-in-page/find-in-page-popup.tsx @@ -6,7 +6,7 @@ import { CloseIcon, SearchIcon, } from '@blocksuite/icons/rc'; -import * as Dialog from '@radix-ui/react-dialog'; +import * as Popover from '@radix-ui/react-popover'; import { useLiveData, useService } from '@toeverything/infra'; import { assignInlineVars } from '@vanilla-extract/dynamic'; import clsx from 'clsx'; @@ -21,7 +21,7 @@ import { } from 'react'; import { useTransition } from 'react-transition-state'; -import * as styles from './find-in-page-modal.css'; +import * as styles from './find-in-page-popup.css'; const animationTimeout = 120; @@ -36,8 +36,10 @@ const drawText = ( } const dpr = window.devicePixelRatio || 1; - canvas.width = canvas.getBoundingClientRect().width * dpr; - canvas.height = canvas.getBoundingClientRect().height * dpr; + // the container will be animated, + // so we need to use clientWidth and clientHeight instead of getBoundingClientRect + canvas.width = canvas.clientWidth * dpr; + canvas.height = canvas.clientHeight * dpr; const rootStyles = getComputedStyle(document.documentElement); const textColor = rootStyles @@ -46,15 +48,13 @@ const drawText = ( ctx.scale(dpr, dpr); ctx.clearRect(0, 0, canvas.width, canvas.height); + const offsetX = -scrollLeft; ctx.fillStyle = textColor; ctx.font = '15px Inter'; - - const offsetX = -scrollLeft; // Offset based on scrollLeft - - ctx.fillText(text, offsetX, 22); - + ctx.letterSpacing = '0.01em'; ctx.textAlign = 'left'; - ctx.textBaseline = 'middle'; + ctx.textBaseline = 'alphabetic'; + ctx.fillText(text, offsetX, 22); }; const CanvasText = ({ @@ -80,7 +80,7 @@ const CanvasText = ({ return ; }; -export const FindInPageModal = () => { +export const FindInPagePopup = () => { const [value, setValue] = useState(''); const findInPage = useService(FindInPageService).findInPage; @@ -123,22 +123,6 @@ export const FindInPageModal = () => { setActive(false); }, []); - useEffect(() => { - if (visible) { - setValue(findInPage.searchText$.value || ''); - const onEsc = (e: KeyboardEvent) => { - if (e.key === 'Escape') { - findInPage.onChangeVisible(false); - } - }; - window.addEventListener('keydown', onEsc); - return () => { - window.removeEventListener('keydown', onEsc); - }; - } - return () => {}; - }, [findInPage, findInPage.searchText$.value, visible]); - useEffect(() => { const unsub = findInPage.isSearching$.subscribe(() => { inputRef.current?.focus(); @@ -169,6 +153,7 @@ export const FindInPageModal = () => { }, [findInPage] ); + const handleDone = useCallback(() => { onChangeVisible(false); }, [onChangeVisible]); @@ -207,79 +192,87 @@ export const FindInPageModal = () => { ); return ( - - - -
- + + + { + // do not close the popup when focus outside (like focus in the editor) + e.preventDefault(); + }} + onPointerDownOutside={e => { + // do not close the popup when clicking outside (like clicking at the sidebar) + e.preventDefault(); + }} + > +
-
- -
- - -
-
- {value.length > 0 && result && result.matches !== 0 ? ( - <> - {result?.activeMatchOrdinal || 0} - / - {result?.matches || 0} - - ) : value.length ? ( - No matches - ) : null} -
-
- -
- } + +
+ - } +
+
+ {value.length > 0 && result && result.matches !== 0 ? ( + <> + {result?.activeMatchOrdinal || 0} + / + {result?.matches || 0} + + ) : value.length ? ( + No matches + ) : null} +
+
- } /> - -
- - +
+ } + /> + } + /> +
+ + } /> +
+
+ ); }; diff --git a/packages/frontend/core/src/desktop/pages/root/index.tsx b/packages/frontend/core/src/desktop/pages/root/index.tsx index 1f0e011600..0558602d6c 100644 --- a/packages/frontend/core/src/desktop/pages/root/index.tsx +++ b/packages/frontend/core/src/desktop/pages/root/index.tsx @@ -6,7 +6,7 @@ import { Outlet } from 'react-router-dom'; import { GlobalDialogs } from '../../dialogs'; import { CustomThemeModifier } from './custom-theme'; -import { FindInPageModal } from './find-in-page/find-in-page-modal'; +import { FindInPagePopup } from './find-in-page/find-in-page-popup'; export const RootWrapper = () => { const defaultServerService = useService(DefaultServerService); @@ -30,7 +30,7 @@ export const RootWrapper = () => { - {BUILD_CONFIG.isElectron && } + {BUILD_CONFIG.isElectron && } ); };