feat: add animation to mode switch when hover (#1489)

Co-authored-by: Yifeng Wang <doodlewind@toeverything.info>
Co-authored-by: himself65 <himself65@outlook.com>
This commit is contained in:
Qi
2023-03-10 14:44:33 +08:00
committed by GitHub
parent afd113b1f1
commit 7eeff9d470
9 changed files with 143 additions and 13 deletions
+2
View File
@@ -34,6 +34,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-is": "^18.2.0",
"react-lottie": "^1.2.3",
"swr": "^2.0.4",
"y-indexeddb": "^9.0.9",
"y-protocols": "^1.0.5",
@@ -47,6 +48,7 @@
"@swc-jotai/react-refresh": "^0.0.4",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@types/react-lottie": "^1.2.6",
"@types/webpack-env": "^1.18.0",
"dotenv": "^16.0.3",
"eslint": "^8.35.0",
@@ -22,6 +22,9 @@ import { useWorkspacesHelper } from '../../hooks/use-workspaces';
import { ThemeProvider } from '../../providers/ThemeProvider';
import { pathGenerator, RemWorkspaceFlavour } from '../../shared';
import { WorkSpaceSliderBar } from '../pure/workspace-slider-bar';
vi.mock('react-lottie', () => ({
default: (props: React.PropsWithChildren) => <>{props.children}</>,
}));
const fetchMocker = createFetchMock(vi);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,5 +1,4 @@
import { toast } from '@affine/component';
import { EdgelessIcon, PaperIcon } from '@blocksuite/icons';
import { assertExists } from '@blocksuite/store';
import { CSSProperties } from 'react';
@@ -8,7 +7,8 @@ import {
usePageMetaHelper,
} from '../../../../hooks/use-page-meta';
import { BlockSuiteWorkspace } from '../../../../shared';
import { StyledEditorModeSwitch, StyledSwitchItem } from './style';
import { StyledEditorModeSwitch } from './style';
import { EdgelessSwitchItem, PageSwitchItem } from './switch-items';
export type EditorModeSwitchProps = {
// todo(himself65): combine these two properties
@@ -35,7 +35,7 @@ export const EditorModeSwitch = ({
switchLeft={mode === 'page'}
showAlone={trash}
>
<StyledSwitchItem
<PageSwitchItem
data-testid="switch-page-mode-button"
active={mode === 'page'}
hide={trash && mode !== 'page'}
@@ -43,10 +43,8 @@ export const EditorModeSwitch = ({
setPageMeta(pageId, { mode: 'page' });
toast('Page mode');
}}
>
<PaperIcon />
</StyledSwitchItem>
<StyledSwitchItem
/>
<EdgelessSwitchItem
data-testid="switch-edgeless-mode-button"
active={mode === 'edgeless'}
hide={trash && mode !== 'edgeless'}
@@ -54,9 +52,7 @@ export const EditorModeSwitch = ({
setPageMeta(pageId, { mode: 'edgeless' });
toast('Edgeless mode');
}}
>
<EdgelessIcon />
</StyledSwitchItem>
/>
</StyledEditorModeSwitch>
);
};
@@ -40,9 +40,9 @@ export const StyledEditorModeSwitch = styled('div')<{
});
export const StyledSwitchItem = styled('button')<{
active: boolean;
active?: boolean;
hide?: boolean;
}>(({ theme, active, hide = false }) => {
}>(({ theme, active = false, hide = false }) => {
return {
width: '24px',
height: '24px',
@@ -54,5 +54,8 @@ export const StyledSwitchItem = styled('button')<{
position: 'relative',
zIndex: 2,
fontSize: '20px',
path: {
fill: 'currentColor',
},
};
});
@@ -0,0 +1,79 @@
import React, { cloneElement, HTMLAttributes, useState } from 'react';
import Lottie from 'react-lottie';
import * as edgelessHoverAnimationData from './animation-data/edgeless-hover.json';
import * as pageHoverAnimationData from './animation-data/page-hover.json';
import { StyledSwitchItem } from './style';
type HoverAnimateControllerProps = {
active?: boolean;
hide?: boolean;
children: React.ReactElement;
} & HTMLAttributes<HTMLButtonElement>;
const HoverAnimateController = ({
active,
hide,
children,
...props
}: HoverAnimateControllerProps) => {
const [startAnimate, setStartAnimate] = useState(false);
return (
<StyledSwitchItem
hide={hide}
active={active}
onMouseEnter={() => {
setStartAnimate(true);
}}
onMouseLeave={() => {
setStartAnimate(false);
}}
{...props}
>
{cloneElement(children, {
isStopped: !startAnimate,
speed: 5,
width: 20,
height: 20,
})}
</StyledSwitchItem>
);
};
export const PageSwitchItem = (
props: Omit<HoverAnimateControllerProps, 'children'>
) => {
return (
<HoverAnimateController {...props}>
<Lottie
options={{
loop: false,
autoplay: false,
animationData: pageHoverAnimationData,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice',
},
}}
/>
</HoverAnimateController>
);
};
export const EdgelessSwitchItem = (
props: Omit<HoverAnimateControllerProps, 'children'>
) => {
return (
<HoverAnimateController {...props}>
<Lottie
options={{
loop: false,
autoplay: false,
animationData: edgelessHoverAnimationData,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice',
},
}}
/>
</HoverAnimateController>
);
};
@@ -42,6 +42,9 @@ import {
useSyncRouterWithCurrentWorkspaceAndPage,
} from '../use-sync-router-with-current-workspace-and-page';
import { useWorkspaces, useWorkspacesHelper } from '../use-workspaces';
vi.mock('react-lottie', () => ({
default: (props: React.PropsWithChildren) => <>{props.children}</>,
}));
let blockSuiteWorkspace: BlockSuiteWorkspace;
beforeAll(() => {
+43 -1
View File
@@ -154,6 +154,7 @@ importers:
'@swc-jotai/react-refresh': ^0.0.4
'@types/react': ^18.0.28
'@types/react-dom': ^18.0.11
'@types/react-lottie': ^1.2.6
'@types/webpack-env': ^1.18.0
cmdk: ^0.1.22
css-spring: ^4.1.0
@@ -172,6 +173,7 @@ importers:
react: ^18.2.0
react-dom: ^18.2.0
react-is: ^18.2.0
react-lottie: ^1.2.3
redux: ^4.2.1
swc-plugin-coverage-instrument: ^0.0.14
swr: ^2.0.4
@@ -207,6 +209,7 @@ importers:
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
react-is: 18.2.0
react-lottie: 1.2.3_react@18.2.0
swr: 2.0.4_react@18.2.0
y-indexeddb: 9.0.9_yjs@13.5.48
y-protocols: 1.0.5
@@ -219,6 +222,7 @@ importers:
'@swc-jotai/react-refresh': 0.0.4
'@types/react': 18.0.28
'@types/react-dom': 18.0.11
'@types/react-lottie': 1.2.6
'@types/webpack-env': 1.18.0
dotenv: 16.0.3
eslint: 8.35.0
@@ -5171,6 +5175,12 @@ packages:
'@types/react': 18.0.28
dev: false
/@types/react-lottie/1.2.6:
resolution: {integrity: sha512-fvGJHD7SeUdVESHo7f7erRnXkTWaa/6Mo5TB+R0/ieSftKoFspA4sMlF2qMH6BljXI7ehFJbBtrD5bzDxPCkGg==}
dependencies:
'@types/react': 18.0.28
dev: true
/@types/react-transition-group/4.4.5:
resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==}
dependencies:
@@ -5364,7 +5374,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.19.6_@babel+core@7.21.0
magic-string: 0.27.0
react-refresh: 0.14.0
vite: 4.1.4
vite: 4.1.4_@types+node@18.14.4
transitivePeerDependencies:
- supports-color
dev: true
@@ -6004,6 +6014,13 @@ packages:
- supports-color
dev: true
/babel-runtime/6.26.0:
resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==}
dependencies:
core-js: 2.6.12
regenerator-runtime: 0.11.1
dev: false
/balanced-match/1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -6569,6 +6586,12 @@ packages:
browserslist: 4.21.5
dev: true
/core-js/2.6.12:
resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==}
deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
requiresBuild: true
dev: false
/core-util-is/1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
@@ -9590,6 +9613,10 @@ packages:
dependencies:
js-tokens: 4.0.0
/lottie-web/5.10.2:
resolution: {integrity: sha512-d0PFIGiwuMsJYaF4uPo+qG8dEorlI+xFI2zrrFtE1bGO4WoLIz+NjremxEq1swpR7juR10aeOtmNh3d6G3ub0A==}
dev: false
/loupe/2.3.6:
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
dependencies:
@@ -10960,6 +10987,17 @@ packages:
/react-is/18.2.0:
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
/react-lottie/1.2.3_react@18.2.0:
resolution: {integrity: sha512-qLCERxUr8M+4mm1LU0Ruxw5Y5Fn/OmYkGfnA+JDM/dZb3oKwVAJCjwnjkj9TMHtzR2U6sMEUD3ZZ1RaHagM7kA==}
engines: {npm: ^3.0.0}
peerDependencies:
react: ^0.14.7 || ^15.0.0 || ^16.0.0
dependencies:
babel-runtime: 6.26.0
lottie-web: 5.10.2
react: 18.2.0
dev: false
/react-refresh/0.14.0:
resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==}
engines: {node: '>=0.10.0'}
@@ -11150,6 +11188,10 @@ packages:
resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
dev: true
/regenerator-runtime/0.11.1:
resolution: {integrity: sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==}
dev: false
/regenerator-runtime/0.13.11:
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}