mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
fix: optimize history animation (#5973)
- adjust timing
- make sure card do not show the bottom border on transitioning
<div class='graphite__hidden'>
<div>🎥 Video uploaded on Graphite:</div>
<a href="https://app.graphite.dev/media/video/T2klNLEk0wxLh4NRDzhk/7a225ec1-eb33-45ab-bf27-646bb2519a83.mp4">
<img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/T2klNLEk0wxLh4NRDzhk/7a225ec1-eb33-45ab-bf27-646bb2519a83.mp4">
</a>
</div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/7a225ec1-eb33-45ab-bf27-646bb2519a83.mp4">Kapture 2024-03-01 at 10.56.09.mp4</video>
This commit is contained in:
@@ -17,7 +17,6 @@ import type { DialogContentProps } from '@radix-ui/react-dialog';
|
||||
import { Doc, type PageMode, Workspace } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { atom, useAtom, useSetAtom } from 'jotai';
|
||||
import { range } from 'lodash-es';
|
||||
import {
|
||||
Fragment,
|
||||
type PropsWithChildren,
|
||||
@@ -25,7 +24,6 @@ import {
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { encodeStateAsUpdate } from 'yjs';
|
||||
@@ -116,7 +114,7 @@ const HistoryEditorPreview = ({
|
||||
|
||||
const content = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.previewContent}>
|
||||
<div className={styles.previewHeader}>
|
||||
<StyledEditorModeSwitch switchLeft={mode === 'page'}>
|
||||
<PageSwitchItem
|
||||
@@ -154,7 +152,7 @@ const HistoryEditorPreview = ({
|
||||
<Loading size={24} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}, [
|
||||
mode,
|
||||
@@ -165,23 +163,23 @@ const HistoryEditorPreview = ({
|
||||
ts,
|
||||
]);
|
||||
|
||||
const previewRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
return (
|
||||
<div className={styles.previewWrapper} ref={previewRef}>
|
||||
{range(0, historyList.length).map(i => {
|
||||
<div className={styles.previewWrapper}>
|
||||
{historyList.map((item, i) => {
|
||||
const historyIndex = historyList.findIndex(h => h.timestamp === ts);
|
||||
const distance = i - historyIndex;
|
||||
const flag =
|
||||
distance === 0
|
||||
? 'current'
|
||||
: distance > 2
|
||||
? '> 2'
|
||||
: distance < 0
|
||||
? '< 0'
|
||||
: distance;
|
||||
distance > 20
|
||||
? '> 20'
|
||||
: distance < -20
|
||||
? '< -20'
|
||||
: distance.toString();
|
||||
return (
|
||||
<div data-distance={flag} key={i} className={styles.previewContainer}>
|
||||
<div
|
||||
data-distance={flag}
|
||||
key={item.id}
|
||||
className={styles.previewContainer}
|
||||
>
|
||||
{historyIndex === i ? content : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { createVar, globalStyle, style } from '@vanilla-extract/css';
|
||||
import { range } from 'lodash-es';
|
||||
|
||||
const headerHeight = createVar('header-height');
|
||||
const footerHeight = createVar('footer-height');
|
||||
const historyListWidth = createVar('history-list-width');
|
||||
@@ -35,51 +37,53 @@ export const previewWrapper = style({
|
||||
width: `calc(100% - ${historyListWidth})`,
|
||||
backgroundColor: cssVar('backgroundSecondaryColor'),
|
||||
});
|
||||
|
||||
export const previewContainer = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flexGrow: 1,
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
left: 40,
|
||||
borderTopLeftRadius: 8,
|
||||
borderTopRightRadius: 8,
|
||||
borderRadius: 8,
|
||||
overflow: 'hidden',
|
||||
boxShadow: cssVar('shadow3'),
|
||||
height: 'calc(100% - 40px)',
|
||||
height: '200%',
|
||||
width: `calc(100% - 80px)`,
|
||||
backgroundColor: cssVar('backgroundPrimaryColor'),
|
||||
transformOrigin: 'top center',
|
||||
transition: 'all 0.5s ease-in-out',
|
||||
transition: 'transform 0.3s 0.1s ease-in-out, opacity 0.3s ease-in-out',
|
||||
selectors: {
|
||||
'&[data-distance="> 2"]': {
|
||||
transform: 'scale(0.60)',
|
||||
...Object.fromEntries(
|
||||
range(-20, 20).map(i => [
|
||||
`&[data-distance="${i}"]`,
|
||||
{
|
||||
transform: `scale(${1 - 0.05 * i}) translateY(${-8 * i + 40}px)`,
|
||||
opacity: [0, 1, 2].includes(i) ? 1 : 0,
|
||||
zIndex: -i,
|
||||
pointerEvents: i === 0 ? 'auto' : 'none',
|
||||
},
|
||||
])
|
||||
),
|
||||
'&[data-distance="> 20"]': {
|
||||
transform: `scale(0) translateY(${-8 * 20 + 40}px)`,
|
||||
opacity: 0,
|
||||
zIndex: -3,
|
||||
zIndex: -20,
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
'&[data-distance="2"]': {
|
||||
transform: 'scale(0.90) translateY(-16px)',
|
||||
zIndex: -2,
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
'&[data-distance="1"]': {
|
||||
transform: 'scale(0.95) translateY(-8px)',
|
||||
zIndex: -1,
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
'&[data-distance="current"]': {
|
||||
opacity: 1,
|
||||
zIndex: 0,
|
||||
},
|
||||
'&[data-distance="< 0"]': {
|
||||
transform: 'scale(1.60) translateY(18px)',
|
||||
'&[data-distance="< -20"]': {
|
||||
transform: `scale(2) translateY(${-8 * -20 + 40}px)`,
|
||||
opacity: 0,
|
||||
zIndex: 1,
|
||||
zIndex: 20,
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const previewContent = style({
|
||||
height: '50%',
|
||||
});
|
||||
|
||||
export const previewHeader = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
|
||||
Reference in New Issue
Block a user