feat: add novice guide for quick search arrow button (#1493)

This commit is contained in:
JimmFly
2023-03-10 14:17:26 +08:00
committed by GitHub
parent 7a54e97823
commit 3ef8e2db83
16 changed files with 238 additions and 34 deletions
+5
View File
@@ -0,0 +1,5 @@
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
export const isFirstLoadAtom = atomWithStorage<boolean>('isFirstLoad', true);
export const openTipsAtom = atom<boolean>(false);
@@ -1,7 +1,11 @@
import { Tooltip } from '@affine/component';
import { useTranslation } from '@affine/i18n';
import React, { useCallback, useState } from 'react';
import { useCallback, useState } from 'react';
import {
useIsFirstLoad,
useOpenTips,
} from '../../../hooks/affine/use-is-first-load';
import { useSidebarStatus } from '../../../hooks/affine/use-sidebar-status';
import { SidebarSwitchIcon } from './icons';
import { StyledSidebarSwitch } from './style';
@@ -17,6 +21,8 @@ export const SidebarSwitch = ({
}: SidebarSwitchProps) => {
const [open, setOpen] = useSidebarStatus();
const [tooltipVisible, setTooltipVisible] = useState(false);
const [isFirstLoad, setIsFirstLoad] = useIsFirstLoad();
const [, setOpenTips] = useOpenTips();
const { t } = useTranslation();
tooltipContent =
tooltipContent || (open ? t('Collapse sidebar') : t('Expand sidebar'));
@@ -34,7 +40,13 @@ export const SidebarSwitch = ({
onClick={useCallback(() => {
setOpen(!open);
setTooltipVisible(false);
}, [open, setOpen])}
if (isFirstLoad) {
setIsFirstLoad(false);
setTimeout(() => {
setOpenTips(true);
}, 200);
}
}, [isFirstLoad, open, setIsFirstLoad, setOpen, setOpenTips])}
onMouseEnter={useCallback(() => {
setTooltipVisible(true);
}, [])}
@@ -1,9 +1,12 @@
import { Content } from '@affine/component';
import { Content, QuickSearchTips } from '@affine/component';
import { getEnvironment } from '@affine/env';
import { ArrowDownSmallIcon } from '@blocksuite/icons';
import { assertExists } from '@blocksuite/store';
import { useSetAtom } from 'jotai';
import React from 'react';
import { openQuickSearchModalAtom } from '../../../atoms';
import { useOpenTips } from '../../../hooks/affine/use-is-first-load';
import { usePageMeta } from '../../../hooks/use-page-meta';
import { BlockSuiteWorkspace } from '../../../shared';
import { PageNotFoundError } from '../../affine/affine-error-eoundary';
@@ -11,6 +14,8 @@ import { EditorModeSwitch } from './editor-mode-switch';
import Header from './header';
import { QuickSearchButton } from './quick-search-button';
import {
StyledQuickSearchTipButton,
StyledQuickSearchTipContent,
StyledSearchArrowWrapper,
StyledSwitchWrapper,
StyledTitle,
@@ -43,6 +48,39 @@ export const BlockSuiteEditorHeader: React.FC<BlockSuiteEditorHeaderProps> = ({
assertExists(pageMeta);
const title = pageMeta.title;
const { trash: isTrash } = pageMeta;
const [openTips, setOpenTips] = useOpenTips();
const isMac = () => {
const env = getEnvironment();
return env.isBrowser && env.isMacOs;
};
const tipsContent = () => {
return (
<StyledQuickSearchTipContent>
<div>
Click button
{
<span
style={{
fontSize: '24px',
verticalAlign: 'middle',
}}
>
<ArrowDownSmallIcon />
</span>
}
or use
{isMac() ? ' ⌘ + K' : ' Ctrl + K'} to activate Quick Search. Then you
can search keywords or quickly open recently viewed pages.
</div>
<StyledQuickSearchTipButton
data-testid="quick-search-got-it"
onClick={() => setOpenTips(false)}
>
Got it
</StyledQuickSearchTipButton>
</StyledQuickSearchTipContent>
);
};
return (
<Header
rightItems={
@@ -68,13 +106,21 @@ export const BlockSuiteEditorHeader: React.FC<BlockSuiteEditorHeaderProps> = ({
/>
</StyledSwitchWrapper>
<Content ellipsis={true}>{title || 'Untitled'}</Content>
<StyledSearchArrowWrapper>
<QuickSearchButton
onClick={() => {
setOpenQuickSearch(true);
}}
/>
</StyledSearchArrowWrapper>
<QuickSearchTips
data-testid="quick-search-tips"
content={tipsContent()}
placement="bottom"
open={openTips}
offset={[0, -5]}
>
<StyledSearchArrowWrapper>
<QuickSearchButton
onClick={() => {
setOpenQuickSearch(true);
}}
/>
</StyledSearchArrowWrapper>
</QuickSearchTips>
</StyledTitleWrapper>
</StyledTitle>
)}
@@ -1,7 +1,6 @@
import { IconButton, IconButtonProps } from '@affine/component';
import { styled } from '@affine/component';
import { ArrowDownSmallIcon } from '@blocksuite/icons';
import React from 'react';
const StyledIconButtonWithAnimate = styled(IconButton)(({ theme }) => {
return {
@@ -113,3 +113,24 @@ export const StyledPageListTittleWrapper = styled(StyledTitle)(({ theme }) => {
},
};
});
export const StyledQuickSearchTipButton = styled('div')(({ theme }) => {
return {
...displayFlex('center', 'center'),
marginTop: '12px',
color: '#FFFFFF',
width: '60px',
height: ' 26px',
fontSize: theme.font.sm,
lineHeight: '22px',
background: theme.colors.primaryColor,
borderRadius: '8px',
textAlign: 'center',
cursor: 'pointer',
};
});
export const StyledQuickSearchTipContent = styled('div')(({ theme }) => {
return {
...displayFlex('center', 'flex-end'),
flexDirection: 'column',
};
});
@@ -92,8 +92,8 @@ export const QuickSearchModal: React.FC<QuickSearchModalProps> = ({
width={620}
style={{
maxHeight: '80vh',
minHeight: isPublicAndNoQuery() ? '72px' : '350px',
top: '12vh',
minHeight: isPublicAndNoQuery() ? '72px' : '412px',
top: '80px',
}}
>
<Command
@@ -2,8 +2,8 @@ import { displayFlex, styled } from '@affine/component';
export const StyledContent = styled('div')(({ theme }) => {
return {
minHeight: '220px',
maxHeight: '55vh',
minHeight: '280px',
maxHeight: '70vh',
width: '100%',
overflow: 'auto',
marginBottom: '10px',
@@ -124,6 +124,7 @@ export const WorkSpaceSliderBar: React.FC<WorkSpaceSliderBarProps> = ({
testid="sliderBar-arrowButton-collapse"
/>
</StyledSidebarWrapper>
<StyledSliderBarWrapper data-testid="sliderBar">
<WorkspaceSelector
currentWorkspace={currentWorkspace}
@@ -26,6 +26,7 @@ import {
LocalWorkspace,
RemWorkspaceFlavour,
} from '../../shared';
import { useIsFirstLoad, useOpenTips } from '../affine/use-is-first-load';
import {
useRecentlyViewed,
useSyncRecentViewsWithRouter,
@@ -314,3 +315,21 @@ describe('useRecentlyViewed', () => {
]);
});
});
describe('useIsFirstLoad', () => {
test('basic', async () => {
const firstLoad = renderHook(() => useIsFirstLoad());
const setFirstLoad = firstLoad.result.current[1];
expect(firstLoad.result.current[0]).toEqual(true);
setFirstLoad(false);
firstLoad.rerender();
expect(firstLoad.result.current[0]).toEqual(false);
});
test('useOpenTips', async () => {
const openTips = renderHook(() => useOpenTips());
const setOpenTips = openTips.result.current[1];
expect(openTips.result.current[0]).toEqual(false);
setOpenTips(true);
openTips.rerender();
expect(openTips.result.current[0]).toEqual(true);
});
});
@@ -0,0 +1,12 @@
import { useAtom } from 'jotai';
import { isFirstLoadAtom, openTipsAtom } from '../../atoms/first-load';
export function useIsFirstLoad() {
const [isFirstLoad, setIsFirstLoad] = useAtom(isFirstLoadAtom);
return [isFirstLoad, setIsFirstLoad] as const;
}
export function useOpenTips() {
const [openTips, setOpenTips] = useAtom(openTipsAtom);
return [openTips, setOpenTips] as const;
}
+6 -10
View File
@@ -1,12 +1,10 @@
# Welcome to AFFiNE
👋 Quick Start
==============
# 👋 Quick Start
> Your content should be as feature-rich as you like. We offer you an easy and simple approach to writing your content, with advanced tools that stay out of the way when you don't need them.
AFFiNE - not just a note taking app
-----------------------------------
## AFFiNE - not just a note taking app
There are lots of apps out there, so why choose AFFiNE?
@@ -18,18 +16,16 @@ AFFiNE is **privacy focused** - with a local-first approach, keep control of you
AFFiNE is **open source** - you can check us out on [GitHub: toeverything/AFFiNE](https://github.com/toeverything/affine)
Let's get started!
------------------
## Let's get started!
* Create a new page and begin editing - in `Paper` or `Edgeless`
- Create a new page and begin editing - in `Paper` or `Edgeless`
![](https://cdn.affine.pro/38928b822e78a8cf6cc1278c3cd7563967dfefcf744c2517a60c7bfe.gif)
* Head over to `Workspace Settings` to find your `General` settings, enable multiplayer with `Collaboration`, share your docs with `Publish` and download your data with `Export`
- Head over to `Workspace Settings` to find your `General` settings, enable multiplayer with `Collaboration`, share your docs with `Publish` and download your data with `Export`
![](https://cdn.affine.pro/34043644b47f7bab79255a80e1b11d6cb173ec9d2eb0e3208c7badd2.png)
Looking for more support?
-------------
## Looking for more support?
Why not come and join the awesome [AFFiNE Community](https://community.affine.pro)? Whether you want to share new ideas or interact with other like minded individuals - we look forward to having you.