diff --git a/apps/ligo-virgo/package.json b/apps/ligo-virgo/package.json index e8a18e071c..270901439f 100644 --- a/apps/ligo-virgo/package.json +++ b/apps/ligo-virgo/package.json @@ -10,6 +10,7 @@ "keywords": [], "author": "AFFiNE ", "dependencies": { + "@emotion/babel-plugin": "^11.10.2", "@mui/icons-material": "^5.8.4" }, "devDependencies": { diff --git a/apps/venus/package.json b/apps/venus/package.json index 87065b9d79..1d8a1287bb 100644 --- a/apps/venus/package.json +++ b/apps/venus/package.json @@ -7,6 +7,7 @@ "keywords": [], "author": "DarkSky ", "dependencies": { + "@emotion/babel-plugin": "^11.10.2", "@emotion/react": "^11.10.0", "@emotion/styled": "^11.10.0", "@mui/joy": "^5.0.0-alpha.42", diff --git a/apps/venus/src/app/AboutUs.tsx b/apps/venus/src/app/AboutUs.tsx index 18eea69853..193f87be0f 100644 --- a/apps/venus/src/app/AboutUs.tsx +++ b/apps/venus/src/app/AboutUs.tsx @@ -10,7 +10,7 @@ export const AboutUs = () => { return ( <> - + (({ width }) => ({ - position: 'relative', - width: '24em', - height: '128px', - transform: 'translateY(-8px)', - overflowY: 'hidden', - '@media (max-width: 1024px)': { - width, - height: '48px', - transform: 'translateY(0)', - }, - '& .scroll-element': { - width: 'inherit', - height: 'inherit', - position: 'absolute', - left: '0%', - top: '0%', - lineHeight: '96px', - '@media (max-width: 1024px)': { - lineHeight: '32px', - }, - }, - '& .scroll-element.active': { - animation: 'primary 500ms linear infinite', - }, - '.primary.active': { - animation: 'primary 500ms linear infinite', - }, - '.secondary.active': { - animation: 'secondary 500ms linear infinite', - }, - '@keyframes primary': { - from: { - top: '0%', - }, - to: { - top: '-100%', - }, - }, - '@keyframes secondary': { - from: { - top: '100%', - }, - to: { - top: '0%', - }, - }, -})); - -const _alternatives = ['Notion', 'Miro', 'Monday']; -const _alternativesSize = [8, 6, 10]; - -const Product = () => { - const [idx, setIdx] = useState(0); - const [last, current] = useMemo( - () => [ - _alternatives[idx], - _alternatives[idx + 1] ? _alternatives[idx + 1] : _alternatives[0], - ], - [idx] - ); - const maxWidth = useMemo(() => _alternativesSize[idx], [idx]); - const [active, setActive] = useState(false); - const matches = useMediaQuery('(max-width: 1024px)'); - - useEffect(() => { - const handle = setInterval(() => { - setActive(true); - setTimeout( - () => { - setIdx(idx => (_alternatives[idx + 1] ? idx + 1 : 0)); - setActive(false); - }, - matches ? 450 : 380 - ); - }, 2000); - return () => clearInterval(handle); - }, [matches]); - - return ( - - - - {last} - - - - - {current} - - - - ); -}; - -const AFFiNEOnline = (props: { center?: boolean; flat?: boolean }) => { - const matches = useMediaQuery('(max-width: 1024px)'); - const { t } = useTranslation(); - return ( - - ); -}; - -export function App() { - const matches = useMediaQuery('(max-width: 1024px)'); - const navigate = useNavigate(); - const { t, i18n } = useTranslation(); - - const changeLanguage = (event: any) => { - i18n.changeLanguage(event); - }; - return ( - <> - - - - - {t('Open Source')}, - - - {t('Privacy First')} - - - - - - - - {t('Alternative')} - - - - - - - {t('description1.part1')} - - - - - - - - - - - - - - - - - - {t('description1.part2')} - - - - - - - {t('description1.part3')} - - - {t('description1.part4')} - - - - - - - - {t('description2.part1')} - - - {t('description2.part2')} - - - {t('description2.part3')} - - - - - - - - - - - - - - {t('description3.part1')} - - - {t('description3.part2')} - - - {t('description3.part3')} - - - {t('description3.part4')} - - - - - - - - - - - - - {t('description4.part1')} - - - {t('description4.part2')} - - - {t('description4.part3')} - - - - - - - - - - - ); -} diff --git a/apps/venus/src/app/IndexPage/Alternatives.tsx b/apps/venus/src/app/IndexPage/Alternatives.tsx new file mode 100644 index 0000000000..17403e01c9 --- /dev/null +++ b/apps/venus/src/app/IndexPage/Alternatives.tsx @@ -0,0 +1,153 @@ +import { Box, Typography } from '@mui/joy'; +import { styled } from '@mui/joy/styles'; +import clsx from 'clsx'; +import { useEffect, useMemo, useState } from 'react'; +// eslint-disable-next-line no-restricted-imports +import { useMediaQuery } from '@mui/material'; + +const Alternatives = styled(Box)<{ width: string }>(({ width }) => ({ + position: 'relative', + width: '20em', + height: '128px', + transform: 'translateY(-8px)', + overflowY: 'hidden', + '@media (max-width: 1024px)': { + width, + height: '48px', + transform: 'translateY(0)', + }, + '& .scroll-element': { + width: 'inherit', + height: 'inherit', + position: 'absolute', + left: '0', + top: '0', + paddingTop: '22px', + lineHeight: '96px', + '@media (max-width: 1024px)': { + lineHeight: '32px', + }, + }, + '& .scroll-element.active': { + animation: 'primary 500ms linear infinite', + }, + '.primary.active': { + animation: 'primary 500ms linear infinite', + }, + '.secondary.active': { + animation: 'secondary 500ms linear infinite', + }, + '@keyframes primary': { + from: { + top: '0%', + }, + to: { + top: '-100%', + }, + }, + '@keyframes secondary': { + from: { + top: '100%', + }, + to: { + top: '0%', + }, + }, +})); + +const _alternatives = ['Notion', 'Miro', 'Monday']; +const _alternativesSize = [8, 6, 10]; + +export const AlternativesProduct = () => { + const [idx, setIdx] = useState(0); + const [last, current] = useMemo( + () => [ + _alternatives[idx], + _alternatives[idx + 1] ? _alternatives[idx + 1] : _alternatives[0], + ], + [idx] + ); + const maxWidth = useMemo(() => _alternativesSize[idx], [idx]); + const [active, setActive] = useState(false); + const matches = useMediaQuery('(max-width: 1024px)'); + + useEffect(() => { + const handle = setInterval(() => { + setActive(true); + setTimeout( + () => { + setIdx(idx => (_alternatives[idx + 1] ? idx + 1 : 0)); + setActive(false); + }, + matches ? 450 : 380 + ); + }, 2000); + return () => clearInterval(handle); + }, [matches]); + + return ( + + + + {last} + + + + + {current} + + + + ); +}; diff --git a/apps/venus/src/app/IndexPage/FunctionTabs.tsx b/apps/venus/src/app/IndexPage/FunctionTabs.tsx new file mode 100644 index 0000000000..7a87df1ddd --- /dev/null +++ b/apps/venus/src/app/IndexPage/FunctionTabs.tsx @@ -0,0 +1,200 @@ +import { Box, Grid, Typography } from '@mui/joy'; +import { useState } from 'react'; +// eslint-disable-next-line no-restricted-imports +import { Paper, Slide, Tab, Tabs, useMediaQuery } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import { AFFiNEImage } from '../common'; +import ShapeImage from './shape.png'; +import TaskImage from './task.png'; + +export const FunctionTabs = () => { + const matches = useMediaQuery('(max-width: 1024px)'); + const { t } = useTranslation(); + const [tab, selectTab] = useState(0); + return ( + + selectTab(value)} + centered + > + + + + + + + + + {t('description2.part1')} + + + {t('description2.part2')} + + + {t('description2.part3')} + + + + + + + + + + + + + + + + {t('description3.part1')} + + + {t('description3.part2')} + + + {t('description3.part3')} + + + {t('description3.part4')} + + + + + + + + + + + + ); +}; diff --git a/apps/venus/src/app/IndexPage/IndexPage.tsx b/apps/venus/src/app/IndexPage/IndexPage.tsx new file mode 100644 index 0000000000..71e26402e8 --- /dev/null +++ b/apps/venus/src/app/IndexPage/IndexPage.tsx @@ -0,0 +1,292 @@ +/* eslint-disable max-lines */ +/* eslint-disable @typescript-eslint/naming-convention */ +import { useTranslation } from 'react-i18next'; + +import { Box, Button, Grid, Typography } from '@mui/joy'; +import { LogoIcon } from '@toeverything/components/icons'; +// eslint-disable-next-line no-restricted-imports +import { useMediaQuery } from '@mui/material'; + +import { AFFiNEFooter, AFFiNEHeader, AFFiNEImage } from '../common'; +import { GitHub } from '../Icons'; +import { AlternativesProduct } from './Alternatives'; +import CollaborationImage from './collaboration.png'; +import { FunctionTabs } from './FunctionTabs'; +import PageImage from './page.png'; + +const AFFiNEOnline = (props: { center?: boolean; flat?: boolean }) => { + const matches = useMediaQuery('(max-width: 1024px)'); + const { t } = useTranslation(); + return ( + + ); +}; + +export function IndexPage() { + const matches = useMediaQuery('(max-width: 1024px)'); + const { t } = useTranslation(); + + return ( + <> + + + + + {t('Open Source')}, + + + {t('Privacy First')} + + + + + + + + {t('Alternative')} + + + + + + + {t('description1.part1')} + + + + + + + + + + + + + + + + + + {t('description1.part2')} + + + + + + + {t('description1.part3')} + + + {t('description1.part4')} + + + + + + + + {t('description4.part1')} + + + {t('description4.part2')} + + + {t('description4.part3')} + + + + + + + + + + + ); +} diff --git a/apps/venus/src/app/collaboration.png b/apps/venus/src/app/IndexPage/collaboration.png similarity index 100% rename from apps/venus/src/app/collaboration.png rename to apps/venus/src/app/IndexPage/collaboration.png diff --git a/apps/venus/src/app/IndexPage/index.ts b/apps/venus/src/app/IndexPage/index.ts new file mode 100644 index 0000000000..b36af73081 --- /dev/null +++ b/apps/venus/src/app/IndexPage/index.ts @@ -0,0 +1 @@ +export { IndexPage } from './IndexPage'; diff --git a/apps/venus/src/app/page.png b/apps/venus/src/app/IndexPage/page.png similarity index 100% rename from apps/venus/src/app/page.png rename to apps/venus/src/app/IndexPage/page.png diff --git a/apps/venus/src/app/shape.png b/apps/venus/src/app/IndexPage/shape.png similarity index 100% rename from apps/venus/src/app/shape.png rename to apps/venus/src/app/IndexPage/shape.png diff --git a/apps/venus/src/app/task.png b/apps/venus/src/app/IndexPage/task.png similarity index 100% rename from apps/venus/src/app/task.png rename to apps/venus/src/app/IndexPage/task.png diff --git a/apps/venus/src/app/common/Header.tsx b/apps/venus/src/app/common/Header.tsx index a1fb6aa995..1c48b71ae8 100644 --- a/apps/venus/src/app/common/Header.tsx +++ b/apps/venus/src/app/common/Header.tsx @@ -6,82 +6,141 @@ import { Button, Grid } from '@mui/joy'; import Option from '@mui/joy/Option'; import Select from '@mui/joy/Select'; // eslint-disable-next-line no-restricted-imports -import { useMediaQuery } from '@mui/material'; +import GitHubIcon from '@mui/icons-material/GitHub'; +// eslint-disable-next-line no-restricted-imports +import { styled, useMediaQuery } from '@mui/material'; +import AFFiNETextLogo from './affine-text-logo.png'; +import { HoverMenu } from './HoverMenu'; import { options } from '../i18n'; -import { GitHub } from '../Icons'; export const AFFiNEHeader = () => { const matches = useMediaQuery('(max-width: 1024px)'); const navigate = useNavigate(); - const { i18n } = useTranslation(); + const { i18n, t } = useTranslation(); const changeLanguage = (event: any) => { i18n.changeLanguage(event); }; const matchesIPAD = useMediaQuery('(max-width: 768px)'); return ( - - - - - - - + /> + + + + + + + + { + window.open(href); + }} + /> - + ); }; + +const Container = styled(Grid)({ + position: 'fixed', + top: 0, + left: '50%', + transform: 'translateX(-50%)', + width: '100%', + paddingTop: '1em', + backgroundColor: '#fff', + zIndex: 1500, + maxWidth: '1440px', + margin: 'auto', + marginTop: '0 !important', +}); + +const StyledImage = styled('img')({ + height: '24px', + marginRight: '16px', + cursor: 'pointer', +}); diff --git a/apps/venus/src/app/common/HoverMenu.tsx b/apps/venus/src/app/common/HoverMenu.tsx new file mode 100644 index 0000000000..d7bcded3ee --- /dev/null +++ b/apps/venus/src/app/common/HoverMenu.tsx @@ -0,0 +1,73 @@ +import Button from '@mui/joy/Button'; +// eslint-disable-next-line no-restricted-imports +import { styled, Tooltip, type TooltipProps } from '@mui/material'; + +interface HoverMenuProps { + title: string; + options: Array<{ title: string; value: string }>; + onSelect: (value: string) => void; +} + +export function HoverMenu({ title, options, onSelect }: HoverMenuProps) { + return ( + + {options.map(option => { + return ( + { + onSelect(option.value); + }} + > + {option.title} + + ); + })} + + } + > + + + ); +} + +const StyledTooltip = styled(({ className, ...props }: TooltipProps) => ( + +))(({ theme }) => ({ + '& .MuiTooltip-tooltip': { + backgroundColor: 'white', + boxShadow: theme.shadows[4], + color: '#272930', + zIndex: '1500', + }, +})); + +const ListItem = styled('a')({ + display: 'block', + fontSize: '16px', + lineHeight: '32px', + padding: '5px', + cursor: 'pointer', + borderRadius: '4px', + color: '#272930', + textDecoration: 'none', + + '&:hover': { + color: '#131418', + backgroundColor: '#eeeff0', + }, +}); diff --git a/apps/venus/src/app/common/affine-text-logo.png b/apps/venus/src/app/common/affine-text-logo.png new file mode 100644 index 0000000000..a136ab17fa Binary files /dev/null and b/apps/venus/src/app/common/affine-text-logo.png differ diff --git a/apps/venus/src/app/i18n/resources/en.json b/apps/venus/src/app/i18n/resources/en.json index 2cffda93bd..789a577584 100644 --- a/apps/venus/src/app/i18n/resources/en.json +++ b/apps/venus/src/app/i18n/resources/en.json @@ -1,8 +1,11 @@ { "translation": { "Blog": "Blog", - "AboutUs": "About AboutUs", + "AboutUs": "About Us", "Open Source": "Open Source", + "Docs": "Docs", + "Feedback": "Feedback", + "ContactUs": "Contact Us", "Privacy First": "Privacy First", "Alternative": "Alternative", "Check GitHub": "Check GitHub", diff --git a/apps/venus/src/app/i18n/resources/zh.json b/apps/venus/src/app/i18n/resources/zh.json index ca0a060072..9a3e51a2ca 100644 --- a/apps/venus/src/app/i18n/resources/zh.json +++ b/apps/venus/src/app/i18n/resources/zh.json @@ -4,9 +4,12 @@ "AboutUs": "关于我们", "Open Source": "开源", "Privacy First": "隐私第一", + "Docs": "文档", + "Feedback": "反馈", + "ContactUs": "联系我们", "Alternative": "的另一种选择", "Check GitHub": "GitHub中查看", - "Try it Online": "在线上试试", + "Try it Online": "在线试用", "description1": { "part1": "Affine是面向专业人士的下一代协同知识库", "part2": "它不仅仅是一个文档、白板和表格的集合。", diff --git a/apps/venus/src/app/index.tsx b/apps/venus/src/app/index.tsx index 8464ca5b4a..6064cef415 100644 --- a/apps/venus/src/app/index.tsx +++ b/apps/venus/src/app/index.tsx @@ -4,7 +4,7 @@ import { Container } from '@mui/joy'; import { CssVarsProvider } from '@mui/joy/styles'; import { AboutUs } from './AboutUs'; -import { App } from './App'; +import { IndexPage } from './IndexPage'; const VenusContainer = () => { return ( @@ -30,7 +30,7 @@ export function VenusRoutes() { }> } /> - } /> + } /> ); diff --git a/libs/components/account/src/login/Firebase.tsx b/libs/components/account/src/login/Firebase.tsx index f976ef8a84..8bf8ca5630 100644 --- a/libs/components/account/src/login/Firebase.tsx +++ b/libs/components/account/src/login/Firebase.tsx @@ -25,9 +25,9 @@ const GoogleIcon = () => (