mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
feat: add onboarding for client (#2144)
Co-authored-by: Himself65 <himself65@outlook.com>
This commit is contained in:
103
packages/component/src/components/tour-modal/TourModal.tsx
Normal file
103
packages/component/src/components/tour-modal/TourModal.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
import type { FC } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { Button, Modal, ModalCloseButton, ModalWrapper } from '../..';
|
||||
import {
|
||||
buttonContainerStyle,
|
||||
buttonStyle,
|
||||
modalStyle,
|
||||
titleStyle,
|
||||
videoContainerStyle,
|
||||
videoStyle,
|
||||
} from './index.css';
|
||||
|
||||
type TourModalProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
export const TourModal: FC<TourModalProps> = ({ open, onClose }) => {
|
||||
const [step, setStep] = useState(0);
|
||||
const handleClose = () => {
|
||||
setStep(0);
|
||||
onClose();
|
||||
};
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
wrapperPosition={['center', 'center']}
|
||||
hideBackdrop
|
||||
>
|
||||
<ModalWrapper width={545} height={442} data-testid="onboarding-modal">
|
||||
<ModalCloseButton
|
||||
top={10}
|
||||
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 Tip Please !
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{step === 1 && (
|
||||
<div className={modalStyle}>
|
||||
<div className={titleStyle}>
|
||||
Intuitive & robust block-based editing
|
||||
</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>
|
||||
<div className={buttonContainerStyle}>
|
||||
<Button
|
||||
className={buttonStyle}
|
||||
onClick={handleClose}
|
||||
data-testid="onboarding-modal-ok-button"
|
||||
>
|
||||
Okay, I Like It !
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ModalWrapper>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default TourModal;
|
||||
44
packages/component/src/components/tour-modal/index.css.ts
Normal file
44
packages/component/src/components/tour-modal/index.css.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const modalStyle = style({
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
padding: '12px 36px',
|
||||
backgroundColor: 'var(--affine-white)',
|
||||
borderRadius: '12px',
|
||||
boxShadow: 'var(--affine-popover-shadow)',
|
||||
});
|
||||
export const titleStyle = style({
|
||||
fontSize: 'var(--affine-font-h6)',
|
||||
fontWeight: '600',
|
||||
});
|
||||
export const videoContainerStyle = style({
|
||||
paddingTop: '15px',
|
||||
width: '100%',
|
||||
});
|
||||
export const videoStyle = style({
|
||||
objectFit: 'fill',
|
||||
height: '300px',
|
||||
width: '100%',
|
||||
});
|
||||
export const buttonContainerStyle = style({
|
||||
marginTop: '15px',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
});
|
||||
export const buttonStyle = style({
|
||||
borderRadius: '8px',
|
||||
backgroundColor: 'var(--affine-primary-color)',
|
||||
color: 'var(--affine-white)',
|
||||
height: '32px',
|
||||
padding: '4 20px',
|
||||
':hover': {
|
||||
backgroundColor: 'var(--affine-primary-color)',
|
||||
color: 'var(--affine-text-primary-color)',
|
||||
},
|
||||
});
|
||||
1
packages/component/src/components/tour-modal/index.ts
Normal file
1
packages/component/src/components/tour-modal/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './TourModal';
|
||||
16
packages/component/src/stories/OnboardingModal.stories.tsx
Normal file
16
packages/component/src/stories/OnboardingModal.stories.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
/* deepscan-disable USELESS_ARROW_FUNC_BIND */
|
||||
import type { StoryFn } from '@storybook/react';
|
||||
|
||||
import { TourModal } from '../components/tour-modal';
|
||||
|
||||
export default {
|
||||
title: 'AFFiNE/TourModal',
|
||||
component: TourModal,
|
||||
};
|
||||
|
||||
export const Basic: StoryFn = () => {
|
||||
return <TourModal open={true} onClose={() => {}} />;
|
||||
};
|
||||
Basic.args = {
|
||||
logoSrc: '/imgs/affine-text-logo.png',
|
||||
};
|
||||
Reference in New Issue
Block a user