mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
refactor: tour modal (#2297)
This commit is contained in:
@@ -7,38 +7,90 @@ export const modalStyle = style({
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
padding: '12px 36px',
|
||||
backgroundColor: 'var(--affine-white)',
|
||||
borderRadius: '12px',
|
||||
boxShadow: 'var(--affine-popover-shadow)',
|
||||
backgroundColor: 'var(--affine-background-secondary-color)',
|
||||
borderRadius: '16px',
|
||||
});
|
||||
export const titleStyle = style({
|
||||
fontSize: 'var(--affine-font-h6)',
|
||||
fontWeight: '600',
|
||||
marginTop: '12px',
|
||||
});
|
||||
export const containerStyle = style({
|
||||
paddingTop: '25px',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
});
|
||||
export const videoContainerStyle = style({
|
||||
paddingTop: '15px',
|
||||
paddingTop: '25px',
|
||||
height: '300px',
|
||||
width: 'calc(100% - 72px)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'space-between',
|
||||
position: 'relative',
|
||||
});
|
||||
export const videoSlideStyle = style({
|
||||
width: '100%',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
});
|
||||
export const videoStyle = style({
|
||||
position: 'absolute',
|
||||
objectFit: 'fill',
|
||||
height: '300px',
|
||||
width: '100%',
|
||||
border: '1px solid var(--affine-border-color)',
|
||||
transition: 'opacity 0.5s ease-in-out',
|
||||
});
|
||||
export const buttonContainerStyle = style({
|
||||
export const videoActiveStyle = style({
|
||||
opacity: 0,
|
||||
});
|
||||
export const arrowStyle = style({
|
||||
wordBreak: 'break-all',
|
||||
wordWrap: 'break-word',
|
||||
width: '36px',
|
||||
fontSize: '32px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '240px',
|
||||
flexGrow: 0.2,
|
||||
cursor: 'pointer',
|
||||
});
|
||||
export const descriptionStyle = style({
|
||||
marginTop: '15px',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
padding: '0 56px',
|
||||
fontSize: 'var(--affine-font-sm)',
|
||||
lineHeight: '18px',
|
||||
marginBottom: '20px',
|
||||
});
|
||||
export const buttonStyle = style({
|
||||
borderRadius: '8px',
|
||||
backgroundColor: 'var(--affine-primary-color)',
|
||||
color: 'var(--affine-white)',
|
||||
height: '32px',
|
||||
padding: '4 20px',
|
||||
export const tabStyle = style({
|
||||
width: '40px',
|
||||
height: '20px',
|
||||
content: '""',
|
||||
borderBottom: '2px solid var(--affine-text-primary-color)',
|
||||
opacity: 0.2,
|
||||
margin: '0 10px 20px 0',
|
||||
transition: 'all 0.15s ease-in-out',
|
||||
':hover': {
|
||||
backgroundColor: 'var(--affine-primary-color)',
|
||||
color: 'var(--affine-white)',
|
||||
opacity: 1,
|
||||
},
|
||||
});
|
||||
export const tabActiveStyle = style({
|
||||
opacity: 1,
|
||||
});
|
||||
export const tabContainerStyle = style({
|
||||
width: '100%',
|
||||
marginTop: '20px',
|
||||
position: 'relative',
|
||||
height: '2px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
});
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { ArrowLeftSmallIcon, ArrowRightSmallIcon } from '@blocksuite/icons';
|
||||
import clsx from 'clsx';
|
||||
import type { FC } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { Button, Modal, ModalCloseButton, ModalWrapper } from '../..';
|
||||
import { Modal, ModalCloseButton, ModalWrapper } from '../..';
|
||||
import {
|
||||
buttonContainerStyle,
|
||||
buttonStyle,
|
||||
arrowStyle,
|
||||
containerStyle,
|
||||
descriptionStyle,
|
||||
modalStyle,
|
||||
tabActiveStyle,
|
||||
tabContainerStyle,
|
||||
tabStyle,
|
||||
titleStyle,
|
||||
videoActiveStyle,
|
||||
videoContainerStyle,
|
||||
videoSlideStyle,
|
||||
videoStyle,
|
||||
} from './index.css';
|
||||
|
||||
@@ -17,6 +26,7 @@ type TourModalProps = {
|
||||
};
|
||||
|
||||
export const TourModal: FC<TourModalProps> = ({ open, onClose }) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const [step, setStep] = useState(0);
|
||||
const handleClose = () => {
|
||||
setStep(0);
|
||||
@@ -27,73 +37,85 @@ export const TourModal: FC<TourModalProps> = ({ open, onClose }) => {
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
wrapperPosition={['center', 'center']}
|
||||
hideBackdrop
|
||||
>
|
||||
<ModalWrapper width={545} height={442} data-testid="onboarding-modal">
|
||||
<ModalWrapper
|
||||
width={545}
|
||||
style={{ minHeight: '480px' }}
|
||||
data-testid="onboarding-modal"
|
||||
>
|
||||
<ModalCloseButton
|
||||
top={10}
|
||||
top={6}
|
||||
right={10}
|
||||
onClick={handleClose}
|
||||
data-testid="onboarding-modal-close-button"
|
||||
/>
|
||||
{step === 0 && (
|
||||
<div className={modalStyle}>
|
||||
<div className={titleStyle}>Hyper merged whiteboard and docs</div>
|
||||
<div className={videoContainerStyle}>
|
||||
<video
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
className={videoStyle}
|
||||
data-testid="onboarding-modal-switch-video"
|
||||
>
|
||||
<source src="/switchVideo.mp4" type="video/mp4" />
|
||||
<source src="/switchVideo.webm" type="video/webm" />
|
||||
Easily switch between Page mode for structured document creation
|
||||
and Whiteboard mode for the freeform visual expression of
|
||||
creative ideas.
|
||||
</video>
|
||||
</div>
|
||||
<div className={buttonContainerStyle}>
|
||||
<Button
|
||||
className={buttonStyle}
|
||||
onClick={() => setStep(1)}
|
||||
data-testid="onboarding-modal-next-button"
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
<div className={modalStyle}>
|
||||
<div className={titleStyle}>
|
||||
{step === 1
|
||||
? t['com.affine.onboarding.title2']()
|
||||
: t['com.affine.onboarding.title1']()}
|
||||
</div>
|
||||
)}
|
||||
{step === 1 && (
|
||||
<div className={modalStyle}>
|
||||
<div className={titleStyle}>
|
||||
Intuitive & robust block-based editing
|
||||
<div className={containerStyle}>
|
||||
<div
|
||||
className={arrowStyle}
|
||||
onClick={() => setStep(0)}
|
||||
data-testid="onboarding-modal-pre-button"
|
||||
>
|
||||
<ArrowLeftSmallIcon />
|
||||
</div>
|
||||
<div className={videoContainerStyle}>
|
||||
<video
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
className={videoStyle}
|
||||
data-testid="onboarding-modal-editing-video"
|
||||
>
|
||||
<source src="/editingVideo.mp4" type="video/mp4" />
|
||||
<source src="/editingVideo.webm" type="video/webm" />
|
||||
Create structured documents with ease, using a modular interface
|
||||
to drag and drop blocks of text, images, and other content.
|
||||
</video>
|
||||
<div className={videoSlideStyle}>
|
||||
<video
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
className={clsx(videoStyle, {
|
||||
[videoActiveStyle]: step === 0,
|
||||
})}
|
||||
data-testid="onboarding-modal-editing-video"
|
||||
>
|
||||
<source src="/editingVideo.mp4" type="video/mp4" />
|
||||
<source src="/editingVideo.webm" type="video/webm" />
|
||||
</video>
|
||||
<video
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
className={clsx(videoStyle, {
|
||||
[videoActiveStyle]: step === 1,
|
||||
})}
|
||||
data-testid="onboarding-modal-switch-video"
|
||||
>
|
||||
<source src="/switchVideo.mp4" type="video/mp4" />
|
||||
<source src="/switchVideo.webm" type="video/webm" />
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
<div className={buttonContainerStyle}>
|
||||
<Button
|
||||
className={buttonStyle}
|
||||
onClick={handleClose}
|
||||
data-testid="onboarding-modal-ok-button"
|
||||
>
|
||||
Okay, I Like It !
|
||||
</Button>
|
||||
<div
|
||||
className={arrowStyle}
|
||||
onClick={() => setStep(1)}
|
||||
data-testid="onboarding-modal-next-button"
|
||||
>
|
||||
<ArrowRightSmallIcon />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<ul className={tabContainerStyle}>
|
||||
<li
|
||||
className={clsx(tabStyle, { [tabActiveStyle]: step === 0 })}
|
||||
onClick={() => setStep(0)}
|
||||
></li>
|
||||
<li
|
||||
className={clsx(tabStyle, { [tabActiveStyle]: step === 1 })}
|
||||
onClick={() => setStep(1)}
|
||||
></li>
|
||||
</ul>
|
||||
<div className={descriptionStyle}>
|
||||
{step === 1
|
||||
? t['com.affine.onboarding.videoDescription2']()
|
||||
: t['com.affine.onboarding.videoDescription1']()}
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@ export const ModalWrapper = styled('div')<{
|
||||
height,
|
||||
minHeight,
|
||||
backgroundColor: 'var(--affine-background-secondary-color)',
|
||||
boxShadow: 'var(--affine-popover-shadow)',
|
||||
boxShadow: 'var(--affine-shadow-3)',
|
||||
borderRadius: '16px',
|
||||
position: 'relative',
|
||||
maxHeight: 'calc(100vh - 32px)',
|
||||
|
||||
Reference in New Issue
Block a user