mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-15 00:56:26 +08:00
Merge pull request #31 from toeverything/feat/layout
feat: modify theme mode switch style
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
"@emotion/styled": "^11.10.4",
|
||||
"@mui/base": "^5.0.0-alpha.87",
|
||||
"@mui/material": "^5.8.6",
|
||||
"@mui/icons-material": "^5.10.9",
|
||||
"css-spring": "^4.1.0",
|
||||
"lit": "^2.3.1",
|
||||
"next": "12.3.1",
|
||||
|
||||
@@ -145,7 +145,7 @@ button,
|
||||
select,
|
||||
keygen,
|
||||
legend {
|
||||
color: var(--page-text-color);
|
||||
color: var(--affine-text-color);
|
||||
outline: 0;
|
||||
font-size: 18px;
|
||||
line-height: 1.5;
|
||||
@@ -156,7 +156,7 @@ body {
|
||||
}
|
||||
a,
|
||||
a:hover {
|
||||
color: var(--page-text-color);
|
||||
color: var(--affine-link-color);
|
||||
}
|
||||
|
||||
input {
|
||||
@@ -181,3 +181,11 @@ input[type='number']::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none; /* IE 10+ */
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
display: none; /* Chrome Safari */
|
||||
}
|
||||
|
||||
@@ -22,46 +22,6 @@ export const LogoIcon = ({ style = {}, ...props }: IconProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const MoonIcon = ({ style = {}, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="currentColor"
|
||||
style={style}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M9.549 3.314a.775.775 0 0 1-.136-.855.801.801 0 0 1 .746-.46c3.287.078 6.352 2.081 7.577 5.292 1.608 4.215-.569 8.911-4.862 10.49a8.407 8.407 0 0 1-9.044-2.138.775.775 0 0 1-.137-.855.802.802 0 0 1 .747-.46c.832.02 1.684-.11 2.51-.414 3.465-1.275 5.222-5.066 3.924-8.469a6.6 6.6 0 0 0-1.325-2.13Z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const SunIcon = ({ style = {}, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="currentColor"
|
||||
style={style}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M10.8 2.5a.8.8 0 0 0-1.6 0v.834a.8.8 0 1 0 1.6 0V2.5ZM5.15 4.018a.8.8 0 1 0-1.132 1.131l.678.679a.8.8 0 1 0 1.132-1.132l-.679-.678Zm10.832 1.131a.8.8 0 0 0-1.13-1.131l-.68.678a.8.8 0 1 0 1.132 1.132l.678-.679ZM10 5.867a4.133 4.133 0 1 0 0 8.267 4.133 4.133 0 0 0 0-8.267ZM2.5 9.2a.8.8 0 1 0 0 1.6h.834a.8.8 0 0 0 0-1.6H2.5Zm14.167 0a.8.8 0 1 0 0 1.6h.833a.8.8 0 0 0 0-1.6h-.833ZM5.827 15.31a.8.8 0 0 0-1.13-1.134l-.678.675a.8.8 0 0 0 1.129 1.134l.678-.675Zm9.476-1.134a.8.8 0 1 0-1.129 1.134l.679.675a.8.8 0 1 0 1.128-1.134l-.678-.675ZM10.8 16.667a.8.8 0 1 0-1.6 0v.833a.8.8 0 0 0 1.6 0v-.833Z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const MoreIcon = ({ style = {}, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { LogoIcon, SunIcon, MoonIcon, MoreIcon, ExportIcon } from './icons';
|
||||
import { LogoIcon, MoreIcon, ExportIcon } from './icons';
|
||||
import {
|
||||
StyledHeader,
|
||||
StyledTitle,
|
||||
@@ -10,34 +10,11 @@ import {
|
||||
IconButton,
|
||||
} from './styles';
|
||||
import { Popover } from '@/components/popover';
|
||||
import { useTheme } from '@/styles';
|
||||
import { useEditor } from '@/components/editor-provider';
|
||||
import EditorModeSwitch from '@/components/editor-mode-switch';
|
||||
import { EdgelessIcon, PaperIcon } from '../editor-mode-switch/icons';
|
||||
|
||||
const DarkModeSwitch = () => {
|
||||
const { changeMode, mode } = useTheme();
|
||||
|
||||
return (
|
||||
<>
|
||||
{mode === 'dark' ? (
|
||||
<SunIcon
|
||||
style={{ cursor: 'pointer', color: '#9096A5' }}
|
||||
onClick={() => {
|
||||
changeMode('light');
|
||||
}}
|
||||
></SunIcon>
|
||||
) : (
|
||||
<MoonIcon
|
||||
style={{ cursor: 'pointer', color: '#9096A5' }}
|
||||
onClick={() => {
|
||||
changeMode('dark');
|
||||
}}
|
||||
></MoonIcon>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
import ThemeModeSwitch from '@/components/theme-mode-switch';
|
||||
import ContactModal from '@/components/contact-modal';
|
||||
|
||||
const PopoverContent = () => {
|
||||
const { editor, mode, setMode } = useEditor();
|
||||
@@ -74,6 +51,7 @@ const PopoverContent = () => {
|
||||
export const Header = () => {
|
||||
const [title, setTitle] = useState('');
|
||||
const [isHover, setIsHover] = useState(false);
|
||||
const [showContactModal, setShowContactModal] = useState(false);
|
||||
|
||||
const { editor } = useEditor();
|
||||
|
||||
@@ -87,38 +65,48 @@ export const Header = () => {
|
||||
}, [editor]);
|
||||
|
||||
return (
|
||||
<StyledHeader>
|
||||
<StyledLogo>
|
||||
<LogoIcon style={{ color: '#6880FF' }} onClick={() => {}} />
|
||||
</StyledLogo>
|
||||
<StyledTitle
|
||||
onMouseEnter={() => {
|
||||
setIsHover(true);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setIsHover(false);
|
||||
}}
|
||||
>
|
||||
<EditorModeSwitch
|
||||
isHover={isHover}
|
||||
style={{
|
||||
marginRight: '12px',
|
||||
<>
|
||||
<ContactModal
|
||||
open={showContactModal}
|
||||
onClose={() => setShowContactModal(false)}
|
||||
/>
|
||||
<StyledHeader>
|
||||
<StyledLogo>
|
||||
<LogoIcon
|
||||
onClick={() => {
|
||||
setShowContactModal(true);
|
||||
}}
|
||||
/>
|
||||
</StyledLogo>
|
||||
<StyledTitle
|
||||
onMouseEnter={() => {
|
||||
setIsHover(true);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setIsHover(false);
|
||||
}}
|
||||
/>
|
||||
<StyledTitleWrapper>{title}</StyledTitleWrapper>
|
||||
</StyledTitle>
|
||||
|
||||
<StyledHeaderRightSide>
|
||||
<DarkModeSwitch />
|
||||
<Popover
|
||||
popoverContent={<PopoverContent />}
|
||||
style={{ marginLeft: '20px' }}
|
||||
>
|
||||
<IconButton>
|
||||
<MoreIcon />
|
||||
</IconButton>
|
||||
</Popover>
|
||||
</StyledHeaderRightSide>
|
||||
</StyledHeader>
|
||||
<EditorModeSwitch
|
||||
isHover={isHover}
|
||||
style={{
|
||||
marginRight: '12px',
|
||||
}}
|
||||
/>
|
||||
<StyledTitleWrapper>{title}</StyledTitleWrapper>
|
||||
</StyledTitle>
|
||||
|
||||
<StyledHeaderRightSide>
|
||||
<ThemeModeSwitch />
|
||||
<Popover
|
||||
popoverContent={<PopoverContent />}
|
||||
style={{ marginLeft: '20px' }}
|
||||
>
|
||||
<IconButton>
|
||||
<MoreIcon />
|
||||
</IconButton>
|
||||
</Popover>
|
||||
</StyledHeaderRightSide>
|
||||
</StyledHeader>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -33,14 +33,10 @@ export const StyledTitleWrapper = styled('div')({
|
||||
position: 'relative',
|
||||
});
|
||||
|
||||
export const StyledLogo = styled('div')({});
|
||||
|
||||
export const StyledModeSwitch = styled('div')({
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginRight: '12px',
|
||||
});
|
||||
export const StyledLogo = styled('div')(({ theme }) => ({
|
||||
color: theme.colors.primaryColor,
|
||||
cursor: 'pointer',
|
||||
}));
|
||||
|
||||
export const StyledHeaderRightSide = styled('div')({
|
||||
height: '100%',
|
||||
@@ -48,27 +44,25 @@ export const StyledHeaderRightSide = styled('div')({
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
export const StyledMoreMenuItem = styled('div')({
|
||||
height: '32px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
borderRadius: '5px',
|
||||
fontSize: '14px',
|
||||
color: '#4C6275',
|
||||
padding: '0 14px',
|
||||
svg: {
|
||||
fill: '#4C6275',
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
marginRight: '14px',
|
||||
},
|
||||
':hover': {
|
||||
color: 'var(--affine-highlight-color)',
|
||||
background: '#F1F3FF',
|
||||
export const StyledMoreMenuItem = styled('div')(({ theme }) => {
|
||||
return {
|
||||
height: '32px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
borderRadius: '5px',
|
||||
fontSize: '14px',
|
||||
color: theme.colors.popoverColor,
|
||||
padding: '0 14px',
|
||||
svg: {
|
||||
fill: 'var(--affine-highlight-color)',
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
marginRight: '14px',
|
||||
},
|
||||
},
|
||||
':hover': {
|
||||
color: theme.colors.primaryColor,
|
||||
background: theme.colors.hoverBackground,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const IconButton = styled('div')(({ theme }) => {
|
||||
@@ -78,12 +72,11 @@ export const IconButton = styled('div')(({ theme }) => {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
color: theme.colors.disabled,
|
||||
background: 'transparent',
|
||||
color: theme.colors.iconColor,
|
||||
borderRadius: '5px',
|
||||
':hover': {
|
||||
color: theme.colors.highlight,
|
||||
background: '#F1F3FF',
|
||||
color: theme.colors.primaryColor,
|
||||
background: theme.colors.hoverBackground,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,55 @@
|
||||
// export const CloseIcon = () => {
|
||||
// return (
|
||||
// <svg
|
||||
// width="14"
|
||||
// height="14"
|
||||
// viewBox="0 0 14 14"
|
||||
// fill="currentColor"
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// >
|
||||
// <path d="M7.94 7.00014L13.4667 1.47348C13.5759 1.34594 13.633 1.18189 13.6265 1.01411C13.62 0.846324 13.5504 0.687165 13.4317 0.568435C13.313 0.449706 13.1538 0.38015 12.986 0.37367C12.8183 0.367189 12.6542 0.42426 12.5267 0.533477L7 6.06014L1.47334 0.526811C1.3478 0.401275 1.17754 0.33075 1 0.33075C0.822468 0.33075 0.652205 0.401275 0.526669 0.526811C0.401133 0.652346 0.330608 0.82261 0.330608 1.00014C0.330608 1.17768 0.401133 1.34794 0.526669 1.47348L6.06 7.00014L0.526669 12.5268C0.456881 12.5866 0.400201 12.6601 0.360186 12.7428C0.32017 12.8255 0.297683 12.9156 0.294137 13.0074C0.290591 13.0993 0.306061 13.1908 0.339577 13.2764C0.373094 13.3619 0.423932 13.4396 0.488902 13.5046C0.553872 13.5695 0.63157 13.6204 0.71712 13.6539C0.80267 13.6874 0.894225 13.7029 0.986038 13.6993C1.07785 13.6958 1.16794 13.6733 1.25065 13.6333C1.33336 13.5933 1.4069 13.5366 1.46667 13.4668L7 7.94014L12.5267 13.4668C12.6542 13.576 12.8183 13.6331 12.986 13.6266C13.1538 13.6201 13.313 13.5506 13.4317 13.4319C13.5504 13.3131 13.62 13.154 13.6265 12.9862C13.633 12.8184 13.5759 12.6543 13.4667 12.5268L7.94 7.00014Z" />
|
||||
// </svg>
|
||||
// );
|
||||
// };
|
||||
|
||||
export const LogoIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M10.552 2 4 21h3.838l4.168-13.14L16.176 21H20L13.447 2h-2.895Z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const DiscordIcon = (props: any) => {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
width="71"
|
||||
height="55"
|
||||
viewBox="0 0 71 55"
|
||||
fill="currentcolor"
|
||||
>
|
||||
<g clipPath="url(#clip0)">
|
||||
<path
|
||||
d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z"
|
||||
fill="currentcolor"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="71" height="55" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,141 @@
|
||||
import { createPortal } from 'react-dom';
|
||||
import Fade from '@mui/material/Fade';
|
||||
import GitHubIcon from '@mui/icons-material/GitHub';
|
||||
import RedditIcon from '@mui/icons-material/Reddit';
|
||||
import TelegramIcon from '@mui/icons-material/Telegram';
|
||||
import TwitterIcon from '@mui/icons-material/Twitter';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
|
||||
import { LogoIcon, DiscordIcon } from './icons';
|
||||
import logo from './affine-text-logo.png';
|
||||
import {
|
||||
StyledModalContainer,
|
||||
StyledModalWrapper,
|
||||
StyledYellowBall,
|
||||
StyledBlueBall,
|
||||
StyledBigLink,
|
||||
StyledSmallLink,
|
||||
StyledSubTitle,
|
||||
StyledLeftContainer,
|
||||
StyledRightContainer,
|
||||
StyledContent,
|
||||
StyledBackdrop,
|
||||
StyledLogo,
|
||||
StyledModalHeader,
|
||||
StyledModalHeaderLeft,
|
||||
CloseButton,
|
||||
StyledModalFooter,
|
||||
} from './style';
|
||||
|
||||
const linkList = [
|
||||
{
|
||||
icon: <GitHubIcon />,
|
||||
title: 'Github',
|
||||
link: 'https://github.com/toeverything/AFFiNE',
|
||||
},
|
||||
{
|
||||
icon: <RedditIcon />,
|
||||
title: 'Reddit',
|
||||
link: 'https://www.reddit.com/r/Affine/',
|
||||
},
|
||||
{
|
||||
icon: <TwitterIcon />,
|
||||
title: 'Twitter',
|
||||
link: 'https://twitter.com/AffineOfficial',
|
||||
},
|
||||
{
|
||||
icon: <TelegramIcon />,
|
||||
title: 'Telegram',
|
||||
link: 'https://t.me/affineworkos',
|
||||
},
|
||||
{
|
||||
icon: <DiscordIcon />,
|
||||
title: 'Discord',
|
||||
link: 'https://discord.gg/Arn7TqJBvG',
|
||||
},
|
||||
];
|
||||
const rightLinkList = [
|
||||
{
|
||||
icon: <LogoIcon />,
|
||||
title: 'Official Website AFFiNE.pro',
|
||||
link: 'https://affine.pro',
|
||||
},
|
||||
{
|
||||
icon: <GitHubIcon />,
|
||||
title: 'Check Our Docs Open Source',
|
||||
link: 'https://github.com/toeverything/AFFiNE',
|
||||
},
|
||||
];
|
||||
|
||||
type TransitionsModalProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
export const ContactModal = ({ open, onClose }: TransitionsModalProps) => {
|
||||
return createPortal(
|
||||
<Fade in={open}>
|
||||
<StyledModalContainer>
|
||||
<StyledBackdrop onClick={onClose} />
|
||||
<StyledModalWrapper>
|
||||
<StyledYellowBall />
|
||||
<StyledBlueBall />
|
||||
|
||||
<StyledModalHeader>
|
||||
<StyledModalHeaderLeft>
|
||||
<StyledLogo src={logo.src} alt="" />
|
||||
<span>2.0</span>
|
||||
<span>live demo</span>
|
||||
</StyledModalHeaderLeft>
|
||||
<CloseButton
|
||||
onClick={() => {
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</CloseButton>
|
||||
</StyledModalHeader>
|
||||
|
||||
<StyledContent>
|
||||
<StyledLeftContainer>
|
||||
{rightLinkList.map(({ icon, title, link }) => {
|
||||
return (
|
||||
<StyledBigLink key={title} href={link} target="_blank">
|
||||
{icon}
|
||||
{title}
|
||||
</StyledBigLink>
|
||||
);
|
||||
})}
|
||||
</StyledLeftContainer>
|
||||
<StyledRightContainer>
|
||||
<StyledSubTitle>
|
||||
Get in touch! <br />
|
||||
Join our community.
|
||||
</StyledSubTitle>
|
||||
{linkList.map(({ icon, title, link }) => {
|
||||
return (
|
||||
<StyledSmallLink key={title} href={link} target="_blank">
|
||||
{icon}
|
||||
{title}
|
||||
</StyledSmallLink>
|
||||
);
|
||||
})}
|
||||
</StyledRightContainer>
|
||||
</StyledContent>
|
||||
|
||||
<StyledModalFooter>
|
||||
<p>
|
||||
<a href="javascript:;">
|
||||
What is the different from the affine 1.0?
|
||||
</a>
|
||||
</p>
|
||||
<p>Copyright © 2022 Toeverything</p>
|
||||
</StyledModalFooter>
|
||||
</StyledModalWrapper>
|
||||
</StyledModalContainer>
|
||||
</Fade>,
|
||||
document.body
|
||||
);
|
||||
};
|
||||
|
||||
export default ContactModal;
|
||||
@@ -0,0 +1,216 @@
|
||||
import { styled } from '@/styles';
|
||||
|
||||
export const StyledModalContainer = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '100vw',
|
||||
height: '100vh',
|
||||
position: 'fixed',
|
||||
left: '0',
|
||||
top: '0',
|
||||
zIndex: theme.zIndex.modal,
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledModalWrapper = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '1000px',
|
||||
height: '626px',
|
||||
background: theme.colors.popoverBackground,
|
||||
padding: '0 48px',
|
||||
borderRadius: '20px',
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
margin: 'auto',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledYellowBall = styled('div')`
|
||||
position: absolute;
|
||||
top: 189px;
|
||||
left: 186px;
|
||||
display: block;
|
||||
width: 122px;
|
||||
height: 122px;
|
||||
background-color: #dda82a;
|
||||
opacity: 0.45;
|
||||
filter: blur(78px);
|
||||
`;
|
||||
export const StyledBlueBall = styled('div')`
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 332px;
|
||||
left: 296px;
|
||||
display: block;
|
||||
width: 122px;
|
||||
height: 122px;
|
||||
background-color: #4461f2;
|
||||
filter: blur(78px);
|
||||
`;
|
||||
|
||||
export const StyledBigLink = styled('a')(({ theme }) => {
|
||||
return {
|
||||
width: '335px',
|
||||
height: '110px',
|
||||
marginBottom: '52px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
fontSize: '24px',
|
||||
lineHeight: '36px',
|
||||
padding: '0 24px',
|
||||
fontWeight: '600',
|
||||
color: theme.colors.textColor,
|
||||
borderRadius: '10px',
|
||||
|
||||
':visited': {
|
||||
color: theme.colors.textColor,
|
||||
},
|
||||
':hover': {
|
||||
color: theme.colors.primaryColor,
|
||||
background: theme.colors.hoverBackground,
|
||||
},
|
||||
':last-of-type': {
|
||||
marginBottom: 0,
|
||||
},
|
||||
svg: {
|
||||
width: '50px',
|
||||
height: '50px',
|
||||
marginRight: '40px',
|
||||
color: theme.colors.primaryColor,
|
||||
},
|
||||
p: {
|
||||
width: '197px',
|
||||
height: '73px',
|
||||
},
|
||||
};
|
||||
});
|
||||
export const StyledSmallLink = styled('a')(({ theme }) => {
|
||||
return {
|
||||
width: '214px',
|
||||
height: '37px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
fontSize: '18px',
|
||||
fontWeight: '500',
|
||||
paddingLeft: '24px',
|
||||
borderRadius: '5px',
|
||||
color: theme.colors.textColor,
|
||||
':visited': {
|
||||
color: theme.colors.textColor,
|
||||
},
|
||||
':hover': {
|
||||
color: theme.colors.primaryColor,
|
||||
background: theme.colors.hoverBackground,
|
||||
},
|
||||
svg: {
|
||||
width: '22px',
|
||||
marginRight: '30px',
|
||||
color: theme.colors.primaryColor,
|
||||
},
|
||||
};
|
||||
});
|
||||
export const StyledSubTitle = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '189px',
|
||||
fontSize: '18px',
|
||||
fontWeight: '600',
|
||||
color: theme.colors.textColor,
|
||||
marginBottom: '24px',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledLeftContainer = styled('div')({
|
||||
// height: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
});
|
||||
export const StyledRightContainer = styled('div')({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'flex-end',
|
||||
});
|
||||
|
||||
export const StyledContent = styled('div')({
|
||||
height: '276px',
|
||||
width: '100%',
|
||||
padding: '0 160px',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
color: '#3A4C5C',
|
||||
marginTop: '100px',
|
||||
});
|
||||
|
||||
export const StyledBackdrop = styled('div')(({ theme }) => {
|
||||
return { width: '100%', height: '100%', background: 'rgba(58, 76, 92, 0.2)' };
|
||||
});
|
||||
export const StyledLogo = styled('img')({
|
||||
height: '22px',
|
||||
width: 'auto',
|
||||
});
|
||||
|
||||
export const StyledModalHeader = styled('div')(({ theme }) => {
|
||||
return {
|
||||
height: '30px',
|
||||
marginTop: '54px',
|
||||
padding: '0 48px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledModalHeaderLeft = styled('div')(({ theme }) => {
|
||||
return {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
color: theme.colors.primaryColor,
|
||||
|
||||
'span:first-of-type': {
|
||||
fontSize: '28px',
|
||||
lineHeight: 1,
|
||||
fontWeight: '600',
|
||||
margin: '0 12px',
|
||||
},
|
||||
'span:last-of-type': {
|
||||
height: '26px',
|
||||
border: `1px solid ${theme.colors.primaryColor}`,
|
||||
borderRadius: '10px',
|
||||
padding: '0 10px',
|
||||
lineHeight: '26px',
|
||||
fontSize: '16px',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const CloseButton = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
borderRadius: '5px',
|
||||
color: theme.colors.iconColor,
|
||||
cursor: 'pointer',
|
||||
':hover': {
|
||||
background: theme.colors.hoverBackground,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledModalFooter = styled('div')(({ theme }) => {
|
||||
return {
|
||||
fontSize: '14px',
|
||||
lineHeight: '20px',
|
||||
textAlign: 'center',
|
||||
color: theme.colors.textColor,
|
||||
|
||||
marginTop: '75px',
|
||||
'p:first-of-type': {
|
||||
color: theme.colors.primaryColor,
|
||||
marginBottom: '10px',
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useState, useEffect, cloneElement } from 'react';
|
||||
import {
|
||||
StyledAnimateRadioContainer,
|
||||
StyledRadioMiddle,
|
||||
StyledMiddleLine,
|
||||
StyledRadioItem,
|
||||
StyledLabel,
|
||||
@@ -19,21 +18,21 @@ import { useEditor } from '@/components/editor-provider';
|
||||
const PaperItem = ({ active }: { active?: boolean }) => {
|
||||
const {
|
||||
theme: {
|
||||
colors: { highlight, disabled },
|
||||
colors: { iconColor, primaryColor },
|
||||
},
|
||||
} = useTheme();
|
||||
|
||||
return <PaperIcon style={{ color: active ? highlight : disabled }} />;
|
||||
return <PaperIcon style={{ color: active ? primaryColor : iconColor }} />;
|
||||
};
|
||||
|
||||
const EdgelessItem = ({ active }: { active?: boolean }) => {
|
||||
const {
|
||||
theme: {
|
||||
colors: { highlight, disabled },
|
||||
colors: { iconColor, primaryColor },
|
||||
},
|
||||
} = useTheme();
|
||||
|
||||
return <EdgelessIcon style={{ color: active ? highlight : disabled }} />;
|
||||
return <EdgelessIcon style={{ color: active ? primaryColor : iconColor }} />;
|
||||
};
|
||||
|
||||
const AnimateRadioItem = ({
|
||||
@@ -57,24 +56,11 @@ const AnimateRadioItem = ({
|
||||
);
|
||||
};
|
||||
|
||||
const RadioMiddle = ({
|
||||
isHover,
|
||||
direction,
|
||||
}: {
|
||||
isHover: boolean;
|
||||
direction: 'left' | 'right' | 'middle';
|
||||
}) => {
|
||||
return (
|
||||
<StyledRadioMiddle hidden={!isHover}>
|
||||
<StyledMiddleLine hidden={false} />
|
||||
</StyledRadioMiddle>
|
||||
);
|
||||
};
|
||||
|
||||
export const EditorModeSwitch = ({
|
||||
isHover,
|
||||
style = {},
|
||||
}: AnimateRadioProps) => {
|
||||
const { mode: themeMode } = useTheme();
|
||||
const { mode, setMode } = useEditor();
|
||||
const modifyRadioItemStatus = (): RadioItemStatus => {
|
||||
return {
|
||||
@@ -124,7 +110,7 @@ export const EditorModeSwitch = ({
|
||||
setRadioItemStatus(modifyRadioItemStatus());
|
||||
}}
|
||||
/>
|
||||
<StyledMiddleLine hidden={!isHover} />
|
||||
<StyledMiddleLine hidden={!isHover} dark={themeMode === 'dark'} />
|
||||
<AnimateRadioItem
|
||||
isLeft={false}
|
||||
label="Edgeless"
|
||||
|
||||
@@ -3,10 +3,10 @@ import { keyframes, styled } from '@/styles';
|
||||
import spring, { toString } from 'css-spring';
|
||||
import type { ItemStatus } from './type';
|
||||
|
||||
const ANIMATE_DURATION = 300;
|
||||
const ANIMATE_DURATION = 400;
|
||||
|
||||
export const StyledAnimateRadioContainer = styled('div')<{ shrink: boolean }>(
|
||||
({ shrink }) => {
|
||||
({ shrink, theme }) => {
|
||||
const animateScaleStretch = keyframes`${toString(
|
||||
spring({ width: '36px' }, { width: '160px' }, { preset: 'gentle' })
|
||||
)}`;
|
||||
@@ -27,7 +27,7 @@ export const StyledAnimateRadioContainer = styled('div')<{ shrink: boolean }>(
|
||||
return {
|
||||
height: '36px',
|
||||
borderRadius: '18px',
|
||||
background: '#F1F3FF',
|
||||
background: theme.colors.hoverBackground,
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
transition: `background ${ANIMATE_DURATION}ms`,
|
||||
@@ -36,31 +36,21 @@ export const StyledAnimateRadioContainer = styled('div')<{ shrink: boolean }>(
|
||||
}
|
||||
);
|
||||
|
||||
export const StyledRadioMiddle = styled('div')<{
|
||||
export const StyledMiddleLine = styled('div')<{
|
||||
hidden: boolean;
|
||||
}>(({ hidden }) => {
|
||||
dark: boolean;
|
||||
}>(({ hidden, dark }) => {
|
||||
return {
|
||||
width: '1px',
|
||||
height: '100%',
|
||||
position: 'relative',
|
||||
height: '16px',
|
||||
background: dark ? '#4d4c53' : '#D0D7E3',
|
||||
top: '0',
|
||||
bottom: '0',
|
||||
margin: 'auto',
|
||||
opacity: hidden ? '0' : '1',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledMiddleLine = styled('div')<{ hidden: boolean }>(
|
||||
({ hidden }) => {
|
||||
return {
|
||||
width: '1px',
|
||||
height: '16px',
|
||||
background: '#D0D7E3',
|
||||
top: '0',
|
||||
bottom: '0',
|
||||
margin: 'auto',
|
||||
opacity: hidden ? '0' : '1',
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
export const StyledRadioItem = styled('div')<{
|
||||
status: ItemStatus;
|
||||
active: boolean;
|
||||
@@ -89,7 +79,7 @@ export const StyledRadioItem = styled('div')<{
|
||||
: {};
|
||||
|
||||
const {
|
||||
colors: { highlight, disabled },
|
||||
colors: { iconColor, primaryColor },
|
||||
} = theme;
|
||||
return {
|
||||
width: '0',
|
||||
@@ -97,7 +87,7 @@ export const StyledRadioItem = styled('div')<{
|
||||
display: 'flex',
|
||||
cursor: 'pointer',
|
||||
overflow: 'hidden',
|
||||
color: active ? highlight : disabled,
|
||||
color: active ? primaryColor : iconColor,
|
||||
...dynamicStyle,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -43,3 +43,17 @@ export const KeyboardIcon = () => {
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const CloseIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="12"
|
||||
height="12"
|
||||
viewBox="0 0 12 12"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M6.88173 5.9864L11.8557 1.0257C11.954 0.911231 12.0054 0.76398 11.9996 0.613378C11.9937 0.462776 11.9311 0.319916 11.8243 0.213345C11.7174 0.106774 11.5742 0.0443419 11.4232 0.0385248C11.2722 0.0327077 11.1245 0.0839342 11.0097 0.181967L6.03573 5.14266L1.06173 0.175983C0.948744 0.063303 0.795507 0 0.635726 0C0.475945 0 0.322708 0.063303 0.209726 0.175983C0.0967439 0.288663 0.0332711 0.44149 0.0332711 0.600844C0.0332711 0.760197 0.0967439 0.913024 0.209726 1.0257L5.18973 5.9864L0.209726 10.9471C0.146917 11.0007 0.0959048 11.0668 0.0598909 11.141C0.0238769 11.2152 0.00363881 11.2961 0.000447115 11.3785C-0.00274458 11.4609 0.0111787 11.5431 0.0413434 11.6199C0.0715082 11.6967 0.117263 11.7664 0.175736 11.8247C0.234209 11.8831 0.304137 11.9287 0.381132 11.9588C0.458127 11.9889 0.540527 12.0027 0.623158 11.9996C0.70579 11.9964 0.786869 11.9762 0.861308 11.9403C0.935747 11.9044 1.00194 11.8535 1.05573 11.7908L6.03573 6.83014L11.0097 11.7908C11.1245 11.8889 11.2722 11.9401 11.4232 11.9343C11.5742 11.9285 11.7174 11.866 11.8243 11.7595C11.9311 11.6529 11.9937 11.51 11.9996 11.3594C12.0054 11.2088 11.954 11.0616 11.8557 10.9471L6.88173 5.9864Z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
import React from 'react';
|
||||
import { StyledFAQ, StyledIconWrapper, StyledFAQWrapper } from './style';
|
||||
import { ContactIcon, HelpIcon, KeyboardIcon } from './icons';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
StyledFAQ,
|
||||
StyledIconWrapper,
|
||||
StyledFAQWrapper,
|
||||
StyledTransformIcon,
|
||||
} from './style';
|
||||
import { CloseIcon, ContactIcon, HelpIcon, KeyboardIcon } from './icons';
|
||||
import Grow from '@mui/material/Grow';
|
||||
import { Tooltip } from '../tooltip';
|
||||
import { Modal } from '@/components/modal';
|
||||
import ContactModal from '@/components/contact-modal';
|
||||
import ShortcutsModal from '@/components/shortcuts-modal';
|
||||
const Contact = () => {
|
||||
const [openModal, setOpenModal] = React.useState(false);
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
open={openModal}
|
||||
onClose={() => {
|
||||
setOpenModal(false);
|
||||
}}
|
||||
>
|
||||
<div>modal content</div>
|
||||
</Modal>
|
||||
<ContactModal open={openModal} onClose={() => setOpenModal(false)} />
|
||||
<Tooltip content="Contact with us" placement="left-end">
|
||||
<StyledIconWrapper
|
||||
onClick={() => {
|
||||
@@ -28,32 +27,59 @@ const Contact = () => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const FAQ = () => {
|
||||
const [showContent, setShowContent] = React.useState(false);
|
||||
return (
|
||||
<StyledFAQ
|
||||
className=""
|
||||
onMouseEnter={() => {
|
||||
setShowContent(true);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setShowContent(false);
|
||||
}}
|
||||
>
|
||||
<Grow in={showContent}>
|
||||
<StyledFAQWrapper>
|
||||
<Contact />
|
||||
<Tooltip content="Keyboard shorts" placement="left-end">
|
||||
<StyledIconWrapper>
|
||||
<KeyboardIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
</StyledFAQWrapper>
|
||||
</Grow>
|
||||
|
||||
<StyledIconWrapper style={{ margin: '0', cursor: 'inherit' }}>
|
||||
<HelpIcon />
|
||||
</StyledIconWrapper>
|
||||
</StyledFAQ>
|
||||
const Shortcuts = () => {
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<ShortcutsModal
|
||||
open={openModal}
|
||||
onClose={() => {
|
||||
setOpenModal(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Tooltip content="Keyboard shorts" placement="left-end">
|
||||
<StyledIconWrapper
|
||||
onClick={() => {
|
||||
setOpenModal(true);
|
||||
}}
|
||||
>
|
||||
<KeyboardIcon />
|
||||
</StyledIconWrapper>
|
||||
</Tooltip>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const FAQ = () => {
|
||||
const [showContent, setShowContent] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<StyledFAQ
|
||||
className=""
|
||||
onMouseEnter={() => {
|
||||
setShowContent(true);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setShowContent(false);
|
||||
}}
|
||||
>
|
||||
<Grow in={showContent}>
|
||||
<StyledFAQWrapper>
|
||||
<Contact />
|
||||
<Shortcuts />
|
||||
</StyledFAQWrapper>
|
||||
</Grow>
|
||||
|
||||
<div style={{ position: 'relative' }}>
|
||||
<StyledIconWrapper>
|
||||
<HelpIcon />
|
||||
</StyledIconWrapper>
|
||||
<StyledTransformIcon in={showContent}>
|
||||
<CloseIcon />
|
||||
</StyledTransformIcon>
|
||||
</div>
|
||||
</StyledFAQ>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,35 +4,55 @@ export const StyledFAQ = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '32px',
|
||||
height: '32px',
|
||||
backgroundColor: '#fff',
|
||||
color: theme.colors.disabled,
|
||||
color: theme.colors.iconColor,
|
||||
position: 'fixed',
|
||||
right: '30px',
|
||||
bottom: '30px',
|
||||
borderRadius: '50%',
|
||||
zIndex: 1000,
|
||||
zIndex: theme.zIndex.popover,
|
||||
':hover': {
|
||||
backgroundColor: '#F1F3FF',
|
||||
color: theme.colors.highlight,
|
||||
backgroundColor: theme.colors.popoverBackground,
|
||||
color: theme.colors.primaryColor,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledTransformIcon = styled.div<{ in: boolean }>(
|
||||
({ in: isIn, theme }) => ({
|
||||
height: '32px',
|
||||
width: '32px',
|
||||
borderRadius: '50%',
|
||||
position: 'absolute',
|
||||
left: '0',
|
||||
right: '0',
|
||||
bottom: '0',
|
||||
top: '0',
|
||||
margin: 'auto',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
opacity: isIn ? 1 : 0,
|
||||
backgroundColor: isIn
|
||||
? theme.colors.hoverBackground
|
||||
: theme.colors.pageBackground,
|
||||
})
|
||||
);
|
||||
export const StyledIconWrapper = styled('div')(({ theme }) => {
|
||||
return {
|
||||
color: theme.colors.disabled,
|
||||
color: theme.colors.iconColor,
|
||||
marginBottom: '24px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
backgroundColor: 'transparent',
|
||||
backgroundColor: theme.colors.pageBackground,
|
||||
borderRadius: '50%',
|
||||
width: '32px',
|
||||
height: '32px',
|
||||
transition: 'background-color 0.3s',
|
||||
position: 'relative',
|
||||
':hover': {
|
||||
color: theme.colors.highlight,
|
||||
backgroundColor: '#F1F3FF',
|
||||
color: theme.colors.primaryColor,
|
||||
backgroundColor: theme.colors.hoverBackground,
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -43,12 +63,9 @@ export const StyledFAQWrapper = styled('div')(({ theme }) => {
|
||||
bottom: '100%',
|
||||
left: '0',
|
||||
width: '100%',
|
||||
color: theme.colors.disabled,
|
||||
color: theme.colors.iconColor,
|
||||
':hover': {
|
||||
'> svg': {
|
||||
color: theme.colors.highlight,
|
||||
},
|
||||
color: theme.colors.highlight,
|
||||
color: theme.colors.popoverColor,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import ModalUnstyled from '@mui/base/ModalUnstyled';
|
||||
import { styled } from '@/styles';
|
||||
import Fade from '@mui/material/Fade';
|
||||
|
||||
import { ClickAwayListener } from '@mui/material';
|
||||
|
||||
const StyledModal = styled(ModalUnstyled)`
|
||||
position: fixed;
|
||||
z-index: 1300;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
type TransitionsModalProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
export const Modal = (props: TransitionsModalProps) => {
|
||||
return (
|
||||
<StyledModal
|
||||
aria-labelledby="transition-modal-title"
|
||||
aria-describedby="transition-modal-description"
|
||||
open={props.open}
|
||||
onClose={props.onClose}
|
||||
closeAfterTransition
|
||||
>
|
||||
<ClickAwayListener onClickAway={props.onClose}>
|
||||
<Fade in={props.open} timeout={300}>
|
||||
{props.children}
|
||||
</Fade>
|
||||
</ClickAwayListener>
|
||||
</StyledModal>
|
||||
);
|
||||
};
|
||||
@@ -21,12 +21,12 @@ const StyledPopoverWrapper = styled('div')({
|
||||
paddingTop: '46px',
|
||||
zIndex: 1000,
|
||||
});
|
||||
const StyledPopover = styled('div')(() => {
|
||||
const StyledPopover = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '248px',
|
||||
background: '#fff',
|
||||
boxShadow:
|
||||
'0px 1px 10px -6px rgba(24, 39, 75, 0.5), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)',
|
||||
background: theme.colors.popoverBackground,
|
||||
boxShadow: theme.shadow.popover,
|
||||
color: theme.colors.popoverColor,
|
||||
borderRadius: '10px 0px 10px 10px',
|
||||
padding: '8px 4px',
|
||||
position: 'absolute',
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
export const macKeyboardShortcuts = {
|
||||
Undo: 'cmd + Z',
|
||||
Redo: 'cmd + shift + Z',
|
||||
Bold: 'cmd + B',
|
||||
Italic: 'cmd + I',
|
||||
Underline: 'cmd + U',
|
||||
Strikethrough: 'cmd + Shit + S',
|
||||
'Inline code': ' cmd + E',
|
||||
Link: 'cmd + K',
|
||||
'Body text': 'cmd + Option + 0',
|
||||
'Heading 1': 'cmd + Option + 1',
|
||||
'Heading 2': 'cmd + Option + 2',
|
||||
'Heading 3': 'cmd + Option + 3',
|
||||
'Heading 4': 'cmd + Option + 4',
|
||||
'Heading 5': 'cmd + Option + 5',
|
||||
'Heading 6': 'cmd + Option + 6',
|
||||
'Increase indent': 'Tab',
|
||||
'Reduce indent': 'Shift + Tab',
|
||||
};
|
||||
|
||||
export const macMarkdownShortcuts = {
|
||||
Bold: '**Text**',
|
||||
Italic: '*Text*',
|
||||
Underline: '~Text~',
|
||||
Strikethrough: '~~Text~~',
|
||||
'Inline code': '`Code`',
|
||||
'Heading 1': '# + Space',
|
||||
'Heading 2': '## + Space',
|
||||
'Heading 3': '### + Space',
|
||||
'Heading 4': '#### + Space',
|
||||
'Heading 5': '##### + Space',
|
||||
'Heading 6': '###### + Space',
|
||||
};
|
||||
|
||||
export const windowsKeyboardShortcuts = {
|
||||
Undo: 'Ctrl + Z',
|
||||
Redo: 'Ctrl + Y',
|
||||
Bold: 'Ctrl + B',
|
||||
Italic: 'Ctrl + I',
|
||||
Underline: 'Ctrl + U',
|
||||
Strikethrough: 'Ctrl + Shit + S',
|
||||
'Inline code': ' Ctrl + E',
|
||||
Link: 'Ctrl + K',
|
||||
'Body text': 'Ctrl + Shift + 0',
|
||||
'Heading 1': 'Ctrl + Shift + 1',
|
||||
'Heading 2': 'Ctrl + Shift + 2',
|
||||
'Heading 3': 'Ctrl + Shift + 3',
|
||||
'Heading 4': 'Ctrl + Shift + 4',
|
||||
'Heading 5': 'Ctrl + Shift + 5',
|
||||
'Heading 6': 'Ctrl + Shift + 6',
|
||||
'Increase indent': 'Tab',
|
||||
'Reduce indent': 'Shift + Tab',
|
||||
};
|
||||
export const winMarkdownShortcuts = {
|
||||
Bold: '**Text** + Space',
|
||||
Italic: '*Text* + Space',
|
||||
Underline: '~Text~ + Space',
|
||||
Strikethrough: '~~Text~~ + Space',
|
||||
'Inline code': '`Code` + Space',
|
||||
'Heading 1': '# + Space',
|
||||
'Heading 2': '## + Space',
|
||||
'Heading 3': '### + Space',
|
||||
'Heading 4': '#### + Space',
|
||||
'Heading 5': '##### + Space',
|
||||
'Heading 6': '###### + Space',
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
export const CloseIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 14 14"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M7.94 7.00014L13.4667 1.47348C13.5759 1.34594 13.633 1.18189 13.6265 1.01411C13.62 0.846324 13.5504 0.687165 13.4317 0.568435C13.313 0.449706 13.1538 0.38015 12.986 0.37367C12.8183 0.367189 12.6542 0.42426 12.5267 0.533477L7 6.06014L1.47334 0.526811C1.3478 0.401275 1.17754 0.33075 1 0.33075C0.822468 0.33075 0.652205 0.401275 0.526669 0.526811C0.401133 0.652346 0.330608 0.82261 0.330608 1.00014C0.330608 1.17768 0.401133 1.34794 0.526669 1.47348L6.06 7.00014L0.526669 12.5268C0.456881 12.5866 0.400201 12.6601 0.360186 12.7428C0.32017 12.8255 0.297683 12.9156 0.294137 13.0074C0.290591 13.0993 0.306061 13.1908 0.339577 13.2764C0.373094 13.3619 0.423932 13.4396 0.488902 13.5046C0.553872 13.5695 0.63157 13.6204 0.71712 13.6539C0.80267 13.6874 0.894225 13.7029 0.986038 13.6993C1.07785 13.6958 1.16794 13.6733 1.25065 13.6333C1.33336 13.5933 1.4069 13.5366 1.46667 13.4668L7 7.94014L12.5267 13.4668C12.6542 13.576 12.8183 13.6331 12.986 13.6266C13.1538 13.6201 13.313 13.5506 13.4317 13.4319C13.5504 13.3131 13.62 13.154 13.6265 12.9862C13.633 12.8184 13.5759 12.6543 13.4667 12.5268L7.94 7.00014Z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const KeyboardIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="15"
|
||||
viewBox="0 0 20 15"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M17.745 0C18.3417 0 18.914 0.237053 19.336 0.65901C19.7579 1.08097 19.995 1.65326 19.995 2.25V11.755C19.995 12.3517 19.7579 12.924 19.336 13.346C18.914 13.7679 18.3417 14.005 17.745 14.005H2.25C1.95453 14.005 1.66194 13.9468 1.38896 13.8337C1.11598 13.7207 0.867941 13.5549 0.65901 13.346C0.450078 13.1371 0.284344 12.889 0.171271 12.616C0.058198 12.3431 0 12.0505 0 11.755V2.25C0 1.65326 0.237053 1.08097 0.65901 0.65901C1.08097 0.237053 1.65326 0 2.25 0H17.745ZM17.745 1.5H2.25C2.05109 1.5 1.86032 1.57902 1.71967 1.71967C1.57902 1.86032 1.5 2.05109 1.5 2.25V11.755C1.5 12.169 1.836 12.505 2.25 12.505H17.745C17.9439 12.505 18.1347 12.426 18.2753 12.2853C18.416 12.1447 18.495 11.9539 18.495 11.755V2.25C18.495 2.05109 18.416 1.86032 18.2753 1.71967C18.1347 1.57902 17.9439 1.5 17.745 1.5ZM4.75 9.5H15.25C15.44 9.50006 15.6229 9.57224 15.7618 9.70197C15.9006 9.8317 15.9851 10.0093 15.998 10.1989C16.011 10.3885 15.9515 10.5759 15.8316 10.7233C15.7117 10.8707 15.5402 10.9671 15.352 10.993L15.25 11H4.75C4.55998 10.9999 4.37706 10.9278 4.23821 10.798C4.09936 10.6683 4.01493 10.4907 4.00197 10.3011C3.98902 10.1115 4.04852 9.92411 4.16843 9.7767C4.28835 9.62929 4.45975 9.5329 4.648 9.507L4.75 9.5H15.25H4.75ZM14.5 6C14.7652 6 15.0196 6.10536 15.2071 6.29289C15.3946 6.48043 15.5 6.73478 15.5 7C15.5 7.26522 15.3946 7.51957 15.2071 7.70711C15.0196 7.89464 14.7652 8 14.5 8C14.2348 8 13.9804 7.89464 13.7929 7.70711C13.6054 7.51957 13.5 7.26522 13.5 7C13.5 6.73478 13.6054 6.48043 13.7929 6.29289C13.9804 6.10536 14.2348 6 14.5 6ZM8.505 6C8.77022 6 9.02457 6.10536 9.21211 6.29289C9.39964 6.48043 9.505 6.73478 9.505 7C9.505 7.26522 9.39964 7.51957 9.21211 7.70711C9.02457 7.89464 8.77022 8 8.505 8C8.23978 8 7.98543 7.89464 7.79789 7.70711C7.61036 7.51957 7.505 7.26522 7.505 7C7.505 6.73478 7.61036 6.48043 7.79789 6.29289C7.98543 6.10536 8.23978 6 8.505 6ZM5.505 6C5.77022 6 6.02457 6.10536 6.21211 6.29289C6.39964 6.48043 6.505 6.73478 6.505 7C6.505 7.26522 6.39964 7.51957 6.21211 7.70711C6.02457 7.89464 5.77022 8 5.505 8C5.23978 8 4.98543 7.89464 4.79789 7.70711C4.61036 7.51957 4.505 7.26522 4.505 7C4.505 6.73478 4.61036 6.48043 4.79789 6.29289C4.98543 6.10536 5.23978 6 5.505 6ZM11.505 6C11.7702 6 12.0246 6.10536 12.2121 6.29289C12.3996 6.48043 12.505 6.73478 12.505 7C12.505 7.26522 12.3996 7.51957 12.2121 7.70711C12.0246 7.89464 11.7702 8 11.505 8C11.2398 8 10.9854 7.89464 10.7979 7.70711C10.6104 7.51957 10.505 7.26522 10.505 7C10.505 6.73478 10.6104 6.48043 10.7979 6.29289C10.9854 6.10536 11.2398 6 11.505 6ZM4 3C4.26522 3 4.51957 3.10536 4.70711 3.29289C4.89464 3.48043 5 3.73478 5 4C5 4.26522 4.89464 4.51957 4.70711 4.70711C4.51957 4.89464 4.26522 5 4 5C3.73478 5 3.48043 4.89464 3.29289 4.70711C3.10536 4.51957 3 4.26522 3 4C3 3.73478 3.10536 3.48043 3.29289 3.29289C3.48043 3.10536 3.73478 3 4 3ZM6.995 3C7.26022 3 7.51457 3.10536 7.70211 3.29289C7.88964 3.48043 7.995 3.73478 7.995 4C7.995 4.26522 7.88964 4.51957 7.70211 4.70711C7.51457 4.89464 7.26022 5 6.995 5C6.72978 5 6.47543 4.89464 6.28789 4.70711C6.10036 4.51957 5.995 4.26522 5.995 4C5.995 3.73478 6.10036 3.48043 6.28789 3.29289C6.47543 3.10536 6.72978 3 6.995 3ZM9.995 3C10.2602 3 10.5146 3.10536 10.7021 3.29289C10.8896 3.48043 10.995 3.73478 10.995 4C10.995 4.26522 10.8896 4.51957 10.7021 4.70711C10.5146 4.89464 10.2602 5 9.995 5C9.72978 5 9.47543 4.89464 9.28789 4.70711C9.10036 4.51957 8.995 4.26522 8.995 4C8.995 3.73478 9.10036 3.48043 9.28789 3.29289C9.47543 3.10536 9.72978 3 9.995 3ZM12.995 3C13.2602 3 13.5146 3.10536 13.7021 3.29289C13.8896 3.48043 13.995 3.73478 13.995 4C13.995 4.26522 13.8896 4.51957 13.7021 4.70711C13.5146 4.89464 13.2602 5 12.995 5C12.7298 5 12.4754 4.89464 12.2879 4.70711C12.1004 4.51957 11.995 4.26522 11.995 4C11.995 3.73478 12.1004 3.48043 12.2879 3.29289C12.4754 3.10536 12.7298 3 12.995 3ZM15.995 3C16.2602 3 16.5146 3.10536 16.7021 3.29289C16.8896 3.48043 16.995 3.73478 16.995 4C16.995 4.26522 16.8896 4.51957 16.7021 4.70711C16.5146 4.89464 16.2602 5 15.995 5C15.7298 5 15.4754 4.89464 15.2879 4.70711C15.1004 4.51957 14.995 4.26522 14.995 4C14.995 3.73478 15.1004 3.48043 15.2879 3.29289C15.4754 3.10536 15.7298 3 15.995 3Z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,78 @@
|
||||
import { createPortal } from 'react-dom';
|
||||
import { KeyboardIcon } from './icons';
|
||||
import {
|
||||
StyledListItem,
|
||||
StyledModalHeader,
|
||||
StyledShortcutsModal,
|
||||
StyledSubTitle,
|
||||
StyledTitle,
|
||||
CloseButton,
|
||||
} from './style';
|
||||
import {
|
||||
macKeyboardShortcuts,
|
||||
macMarkdownShortcuts,
|
||||
windowsKeyboardShortcuts,
|
||||
winMarkdownShortcuts,
|
||||
} from '@/components/shortcuts-modal/config';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import Slide from '@mui/material/Slide';
|
||||
type ModalProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const isMac = () => {
|
||||
return /macintosh|mac os x/i.test(navigator.userAgent);
|
||||
};
|
||||
|
||||
export const ShortcutsModal = ({ open, onClose }: ModalProps) => {
|
||||
const markdownShortcuts = isMac()
|
||||
? macMarkdownShortcuts
|
||||
: winMarkdownShortcuts;
|
||||
const keyboardShortcuts = isMac()
|
||||
? macKeyboardShortcuts
|
||||
: windowsKeyboardShortcuts;
|
||||
return createPortal(
|
||||
<Slide direction="left" in={open} mountOnEnter unmountOnExit>
|
||||
<StyledShortcutsModal>
|
||||
<>
|
||||
<StyledModalHeader>
|
||||
<StyledTitle>
|
||||
<KeyboardIcon />
|
||||
Shortcuts
|
||||
</StyledTitle>
|
||||
|
||||
<CloseButton
|
||||
onClick={() => {
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</CloseButton>
|
||||
</StyledModalHeader>
|
||||
<StyledSubTitle>Keyboard shortcuts</StyledSubTitle>
|
||||
{Object.entries(keyboardShortcuts).map(([title, shortcuts]) => {
|
||||
return (
|
||||
<StyledListItem key={title}>
|
||||
<span>{title}</span>
|
||||
<span>{shortcuts}</span>
|
||||
</StyledListItem>
|
||||
);
|
||||
})}
|
||||
<StyledSubTitle>Markdown shortcuts</StyledSubTitle>
|
||||
{Object.entries(markdownShortcuts).map(([title, shortcuts]) => {
|
||||
return (
|
||||
<StyledListItem key={title}>
|
||||
<span>{title}</span>
|
||||
<span>{shortcuts}</span>
|
||||
</StyledListItem>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
</StyledShortcutsModal>
|
||||
</Slide>,
|
||||
document.body
|
||||
);
|
||||
};
|
||||
|
||||
export default ShortcutsModal;
|
||||
@@ -0,0 +1,65 @@
|
||||
import { styled } from '@/styles';
|
||||
|
||||
export const StyledShortcutsModal = styled.div(({ theme }) => ({
|
||||
width: '268px',
|
||||
height: '66vh',
|
||||
backgroundColor: theme.colors.popoverBackground,
|
||||
boxShadow: theme.shadow.popover,
|
||||
color: theme.colors.popoverColor,
|
||||
padding: '8px 16px',
|
||||
overflow: 'auto',
|
||||
boxRadius: '10px',
|
||||
position: 'fixed',
|
||||
right: '12px',
|
||||
top: '0',
|
||||
bottom: '0',
|
||||
margin: 'auto',
|
||||
zIndex: theme.zIndex.modal,
|
||||
}));
|
||||
export const StyledTitle = styled.div(({ theme }) => ({
|
||||
color: theme.colors.textColor,
|
||||
fontWeight: '600',
|
||||
fontSize: theme.font.sm,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
svg: {
|
||||
width: '20px',
|
||||
marginRight: '14px',
|
||||
color: theme.colors.primaryColor,
|
||||
},
|
||||
}));
|
||||
export const StyledSubTitle = styled.div(({ theme }) => ({
|
||||
color: theme.colors.textColor,
|
||||
fontWeight: '500',
|
||||
fontSize: '12px',
|
||||
height: '36px',
|
||||
lineHeight: '36px',
|
||||
}));
|
||||
export const StyledModalHeader = styled.div(({ theme }) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
height: '36px',
|
||||
}));
|
||||
|
||||
export const StyledListItem = styled.div(({ theme }) => ({
|
||||
height: '32px',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
fontSize: theme.font.xs,
|
||||
}));
|
||||
|
||||
export const CloseButton = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
borderRadius: '5px',
|
||||
color: theme.colors.iconColor,
|
||||
cursor: 'pointer',
|
||||
':hover': {
|
||||
background: theme.colors.hoverBackground,
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -27,7 +27,7 @@ export class Counter extends LitElement {
|
||||
static styles = css`
|
||||
.counter-container {
|
||||
display: flex;
|
||||
color: var(--color-primary);
|
||||
color: var(--affine-text-color);
|
||||
}
|
||||
button {
|
||||
margin: 0 5px;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { DOMAttributes, CSSProperties } from 'react';
|
||||
type IconProps = {
|
||||
style?: CSSProperties;
|
||||
} & DOMAttributes<SVGElement>;
|
||||
|
||||
export const MoonIcon = ({ style = {}, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style={style}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M9.54893 3.31407C9.33328 3.08158 9.27962 2.74521 9.41255 2.45912C9.54547 2.17302 9.83936 1.99233 10.1595 1.99986C13.4456 2.07712 16.5114 4.08044 17.7359 7.29071C19.3437 11.5057 17.1672 16.2024 12.8744 17.781C9.60251 18.9843 6.04745 18.0285 3.82974 15.6428C3.61375 15.4104 3.55978 15.0739 3.69257 14.7876C3.82537 14.5014 4.11931 14.3205 4.43962 14.3279C5.27228 14.3474 6.12412 14.2171 6.94979 13.9135C10.415 12.6391 12.172 8.84782 10.8741 5.44537C10.5657 4.63692 10.1061 3.91474 9.54893 3.31407Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const SunIcon = ({ style = {}, ...props }: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
style={style}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M10.8002 2.5002C10.8002 2.05837 10.442 1.7002 10.0002 1.7002C9.55837 1.7002 9.2002 2.05837 9.2002 2.5002V3.33353C9.2002 3.77536 9.55837 4.13353 10.0002 4.13353C10.442 4.13353 10.8002 3.77536 10.8002 3.33353V2.5002ZM5.14921 4.01784C4.83679 3.70542 4.33026 3.70542 4.01784 4.01784C3.70542 4.33026 3.70542 4.83679 4.01784 5.14921L4.69627 5.82764C5.00869 6.14006 5.51522 6.14006 5.82764 5.82764C6.14006 5.51522 6.14006 5.00869 5.82764 4.69627L5.14921 4.01784ZM15.9825 5.1492C16.2949 4.83678 16.2949 4.33025 15.9825 4.01783C15.6701 3.70542 15.1636 3.70543 14.8511 4.01785L14.1727 4.69628C13.8603 5.00871 13.8603 5.51524 14.1728 5.82765C14.4852 6.14007 14.9917 6.14006 15.3041 5.82763L15.9825 5.1492ZM10.0002 5.86686C7.71742 5.86686 5.86686 7.71742 5.86686 10.0002C5.86686 12.283 7.71742 14.1335 10.0002 14.1335C12.283 14.1335 14.1335 12.283 14.1335 10.0002C14.1335 7.71742 12.283 5.86686 10.0002 5.86686ZM2.5002 9.2002C2.05837 9.2002 1.7002 9.55837 1.7002 10.0002C1.7002 10.442 2.05837 10.8002 2.5002 10.8002H3.33353C3.77536 10.8002 4.13353 10.442 4.13353 10.0002C4.13353 9.55837 3.77536 9.2002 3.33353 9.2002H2.5002ZM16.6669 9.2002C16.225 9.2002 15.8669 9.55837 15.8669 10.0002C15.8669 10.442 16.225 10.8002 16.6669 10.8002H17.5002C17.942 10.8002 18.3002 10.442 18.3002 10.0002C18.3002 9.55837 17.942 9.2002 17.5002 9.2002H16.6669ZM5.82623 15.309C6.13943 14.9973 6.14069 14.4908 5.82906 14.1776C5.51742 13.8644 5.01089 13.8631 4.69769 14.1748L4.01926 14.8498C3.70606 15.1615 3.70479 15.668 4.01643 15.9812C4.32807 16.2944 4.8346 16.2956 5.1478 15.984L5.82623 15.309ZM15.3027 14.1748C14.9895 13.8631 14.483 13.8644 14.1713 14.1776C13.8597 14.4908 13.861 14.9973 14.1742 15.3089L14.8526 15.984C15.1658 16.2956 15.6723 16.2944 15.9839 15.9812C16.2956 15.668 16.2943 15.1615 15.9811 14.8498L15.3027 14.1748ZM10.8002 16.6669C10.8002 16.225 10.442 15.8669 10.0002 15.8669C9.55837 15.8669 9.2002 16.225 9.2002 16.6669V17.5002C9.2002 17.942 9.55837 18.3002 10.0002 18.3002C10.442 18.3002 10.8002 17.942 10.8002 17.5002V16.6669Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import { useState } from 'react';
|
||||
import { useTheme } from '@/styles';
|
||||
import { MoonIcon, SunIcon } from './icons';
|
||||
import { StyledThemeModeSwitch, StyledSwitchItem } from './style';
|
||||
|
||||
export const ThemeModeSwitch = () => {
|
||||
const { mode, changeMode } = useTheme();
|
||||
const [isHover, setIsHover] = useState(false);
|
||||
const [firstTrigger, setFirstTrigger] = useState(false);
|
||||
return (
|
||||
<StyledThemeModeSwitch
|
||||
onMouseEnter={() => {
|
||||
setIsHover(true);
|
||||
if (!firstTrigger) {
|
||||
setFirstTrigger(true);
|
||||
}
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setIsHover(false);
|
||||
}}
|
||||
>
|
||||
<StyledSwitchItem
|
||||
active={mode === 'light'}
|
||||
isHover={isHover}
|
||||
firstTrigger={firstTrigger}
|
||||
onClick={() => {
|
||||
changeMode('light');
|
||||
}}
|
||||
>
|
||||
<SunIcon />
|
||||
</StyledSwitchItem>
|
||||
<StyledSwitchItem
|
||||
active={mode === 'dark'}
|
||||
isHover={isHover}
|
||||
firstTrigger={firstTrigger}
|
||||
onClick={() => {
|
||||
changeMode('dark');
|
||||
}}
|
||||
>
|
||||
<MoonIcon />
|
||||
</StyledSwitchItem>
|
||||
</StyledThemeModeSwitch>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThemeModeSwitch;
|
||||
@@ -0,0 +1,67 @@
|
||||
import { keyframes, styled } from '@/styles';
|
||||
import { CSSProperties } from 'react';
|
||||
// @ts-ignore
|
||||
import spring, { toString } from 'css-spring';
|
||||
|
||||
const ANIMATE_DURATION = 400;
|
||||
|
||||
export const StyledThemeModeSwitch = styled('div')({
|
||||
width: '32px',
|
||||
height: '32px',
|
||||
borderRadius: '5px',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: 'transparent',
|
||||
position: 'relative',
|
||||
});
|
||||
export const StyledSwitchItem = styled('div')<{
|
||||
active: boolean;
|
||||
isHover: boolean;
|
||||
firstTrigger: boolean;
|
||||
}>(({ active, isHover, firstTrigger, theme }) => {
|
||||
const activeRaiseAnimate = keyframes`${toString(
|
||||
spring({ top: '0' }, { top: '-100%' }, { preset: 'gentle' })
|
||||
)}`;
|
||||
const raiseAnimate = keyframes`${toString(
|
||||
spring({ top: '100%' }, { top: '0' }, { preset: 'gentle' })
|
||||
)}`;
|
||||
const activeDeclineAnimate = keyframes`${toString(
|
||||
spring({ top: '-100%' }, { top: '0' }, { preset: 'gentle' })
|
||||
)}`;
|
||||
const declineAnimate = keyframes`${toString(
|
||||
spring({ top: '0' }, { top: '100%' }, { preset: 'gentle' })
|
||||
)}`;
|
||||
const activeStyle = active
|
||||
? {
|
||||
color: theme.colors.iconColor,
|
||||
top: '0',
|
||||
animation: firstTrigger
|
||||
? `${
|
||||
isHover ? activeRaiseAnimate : activeDeclineAnimate
|
||||
} ${ANIMATE_DURATION}ms forwards`
|
||||
: 'unset',
|
||||
animationDirection: isHover ? 'normal' : 'alternate',
|
||||
}
|
||||
: ({
|
||||
top: '100%',
|
||||
color: theme.colors.primaryColor,
|
||||
backgroundColor: theme.colors.hoverBackground,
|
||||
animation: firstTrigger
|
||||
? `${
|
||||
isHover ? raiseAnimate : declineAnimate
|
||||
} ${ANIMATE_DURATION}ms forwards`
|
||||
: 'unset',
|
||||
animationDirection: isHover ? 'normal' : 'alternate',
|
||||
} as CSSProperties);
|
||||
|
||||
return {
|
||||
width: '32px',
|
||||
height: '32px',
|
||||
display: 'flex',
|
||||
position: 'absolute',
|
||||
left: '0',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
...activeStyle,
|
||||
};
|
||||
});
|
||||
@@ -30,7 +30,7 @@ const useTooltipStyle = (): CSSProperties => {
|
||||
return {
|
||||
boxShadow: '1px 1px 4px rgba(0, 0, 0, 0.14)',
|
||||
padding: '4px 12px',
|
||||
backgroundColor: theme.colors.highlight,
|
||||
backgroundColor: theme.colors.primaryColor,
|
||||
color: '#fff',
|
||||
fontSize: theme.font.xs,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
import { styled } from '@/styles';
|
||||
import { ThemeModeSwitch } from '@/components/theme-mode-switch';
|
||||
|
||||
export const StyledHeader = styled('div')({
|
||||
height: '60px',
|
||||
width: '100vw',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
padding: '0 22px',
|
||||
borderBottom: '1px solid #e5e5e5',
|
||||
});
|
||||
|
||||
const Affine = () => {
|
||||
return <div>affine page</div>;
|
||||
return (
|
||||
<StyledHeader>
|
||||
<ThemeModeSwitch></ThemeModeSwitch>
|
||||
</StyledHeader>
|
||||
);
|
||||
};
|
||||
|
||||
export default Affine;
|
||||
|
||||
@@ -12,12 +12,14 @@ const StyledEditorContainer = styled('div')(({ theme }) => {
|
||||
};
|
||||
});
|
||||
|
||||
const StyledPage = styled('div')({
|
||||
height: '100vh',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: 'var(--page-background-color)',
|
||||
transition: 'background-color .5s',
|
||||
const StyledPage = styled('div')(({ theme }) => {
|
||||
return {
|
||||
height: '100vh',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: theme.colors.pageBackground,
|
||||
transition: 'background-color .5s',
|
||||
};
|
||||
});
|
||||
|
||||
const DynamicEditor = dynamic(() => import('../components/editor'), {
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
debug-menu {
|
||||
display: none !important;
|
||||
}
|
||||
.affine-editor-container {
|
||||
height: 100%;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.affine-default-page-block-container {
|
||||
width: 720px;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
/*.affine-editor-container {*/
|
||||
/* height: 100%;*/
|
||||
/* padding: 0 !important;*/
|
||||
/*}*/
|
||||
/*.affine-default-page-block-container {*/
|
||||
/* width: 720px;*/
|
||||
/* height: 100%;*/
|
||||
/* margin: 0 auto;*/
|
||||
/*}*/
|
||||
|
||||
u {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid #4c6275 !important;
|
||||
}
|
||||
u::after {
|
||||
display: none;
|
||||
}
|
||||
/*u {*/
|
||||
/* text-decoration: none;*/
|
||||
/* border-bottom: 1px solid #4c6275 !important;*/
|
||||
/*}*/
|
||||
/*u::after {*/
|
||||
/* display: none;*/
|
||||
/*}*/
|
||||
|
||||
.affine-paragraph-block-container.text {
|
||||
margin-top: 18px !important;
|
||||
}
|
||||
/*.affine-paragraph-block-container.text {*/
|
||||
/* margin-top: 18px !important;*/
|
||||
/*}*/
|
||||
|
||||
.affine-default-page-block-title {
|
||||
width: 100%;
|
||||
}
|
||||
s {
|
||||
text-decoration: line-through !important;
|
||||
}
|
||||
/*.affine-default-page-block-title {*/
|
||||
/* width: 100%;*/
|
||||
/*}*/
|
||||
/*s {*/
|
||||
/* text-decoration: line-through !important;*/
|
||||
/*}*/
|
||||
|
||||
.affine-edgeless-page-block-container {
|
||||
height: 100% !important;
|
||||
}
|
||||
.affine-block-children-container.edgeless {
|
||||
height: 100% !important;
|
||||
}
|
||||
.affine-list-rich-text-wrapper > div {
|
||||
box-sizing: content-box;
|
||||
color: var(--affine-highlight-color);
|
||||
min-width: unset !important;
|
||||
max-width: 26px;
|
||||
}
|
||||
/*.affine-edgeless-page-block-container {*/
|
||||
/* height: 100% !important;*/
|
||||
/*}*/
|
||||
/*.affine-block-children-container.edgeless {*/
|
||||
/* height: 100% !important;*/
|
||||
/*}*/
|
||||
/*.affine-list-rich-text-wrapper > div {*/
|
||||
/* box-sizing: content-box;*/
|
||||
/* color: var(--affine-highlight-color);*/
|
||||
/* min-width: unset !important;*/
|
||||
/* max-width: 26px;*/
|
||||
/*}*/
|
||||
|
||||
@@ -1,47 +1,109 @@
|
||||
import '@emotion/react';
|
||||
import { AffineTheme, ThemeMode } from './types';
|
||||
import { AffineTheme, AffineThemeCSSVariables, ThemeMode } from './types';
|
||||
|
||||
const basicFontFamily =
|
||||
'apple-system, BlinkMacSystemFont,Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei, Arial,Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji,Segoe UI Symbol, Noto Color Emoji';
|
||||
|
||||
export const lightTheme: AffineTheme = {
|
||||
colors: {
|
||||
primary: '#3A4C5C',
|
||||
highlight: '#7389FD',
|
||||
disabled: '#9096A5',
|
||||
background: '#fff',
|
||||
primaryColor: '#6880FF',
|
||||
|
||||
pageBackground: '#fff',
|
||||
hoverBackground: '#F1F3FF',
|
||||
popoverBackground: '#fff',
|
||||
codeBackground: '#f2f5f9',
|
||||
|
||||
textColor: '#3A4C5C',
|
||||
iconColor: '#9096A5',
|
||||
linkColor: '#6880FF',
|
||||
linkColor2: '#6880FF',
|
||||
linkVisitedColor: '#ABB8FE',
|
||||
popoverColor: '#4C6275',
|
||||
codeColor: '#517ea6',
|
||||
quoteColor: '#4C6275',
|
||||
placeHolderColor: '#C7C7C7',
|
||||
selectedColor: 'rgba(104, 128, 255, 0.1)',
|
||||
},
|
||||
font: {
|
||||
xs: '12px',
|
||||
sm: '16px',
|
||||
base: '18px',
|
||||
family: `Avenir Next, ${basicFontFamily}`,
|
||||
family2: `Roboto Mono, ${basicFontFamily}`,
|
||||
},
|
||||
zIndex: {
|
||||
modal: 1000,
|
||||
popover: 100,
|
||||
},
|
||||
shadow: {
|
||||
popover:
|
||||
'4px 4px 7px rgba(58, 76, 92, 0.04), -4px -4px 13px rgba(58, 76, 92, 0.02), 6px 6px 36px rgba(58, 76, 92, 0.06);',
|
||||
modal:
|
||||
'4px 4px 7px rgba(58, 76, 92, 0.04), -4px -4px 13px rgba(58, 76, 92, 0.02), 6px 6px 36px rgba(58, 76, 92, 0.06);',
|
||||
},
|
||||
};
|
||||
|
||||
export const darkTheme: AffineTheme = {
|
||||
...lightTheme,
|
||||
colors: {
|
||||
primary: '#fff',
|
||||
highlight: '#7389FD',
|
||||
disabled: '#9096A5',
|
||||
background: '#3d3c3f',
|
||||
primaryColor: '#6880FF',
|
||||
|
||||
pageBackground: '#2c2c2c',
|
||||
hoverBackground: '#3C3C42',
|
||||
popoverBackground: '#1F2021',
|
||||
codeBackground: '#505662',
|
||||
|
||||
textColor: '#fff',
|
||||
iconColor: '#9096A5',
|
||||
linkColor: '#6880FF',
|
||||
linkColor2: '#7D91FF',
|
||||
linkVisitedColor: '#505FAB',
|
||||
popoverColor: '#A9B1C6',
|
||||
codeColor: '#BDDBFD',
|
||||
quoteColor: '#A9B1C6',
|
||||
placeHolderColor: '#C7C7C7',
|
||||
selectedColor: 'rgba(240, 242, 255, 0.8)',
|
||||
},
|
||||
shadow: {
|
||||
popover:
|
||||
'0px 1px 10px -6px rgba(24, 39, 75, 0.08), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)',
|
||||
modal:
|
||||
'0px 1px 10px -6px rgba(24, 39, 75, 0.08), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)',
|
||||
},
|
||||
};
|
||||
|
||||
export const globalThemeConstant = (mode: ThemeMode, theme: AffineTheme) => {
|
||||
const isDark = mode === 'dark';
|
||||
export const globalThemeVariables: (
|
||||
mode: ThemeMode,
|
||||
theme: AffineTheme
|
||||
) => AffineThemeCSSVariables = (mode, theme) => {
|
||||
return {
|
||||
'--page-background-color': theme.colors.background,
|
||||
'--page-text-color': theme.colors.primary,
|
||||
'--affine-primary-color': theme.colors.primaryColor,
|
||||
|
||||
// editor style variables
|
||||
'--affine-primary-color': theme.colors.primary,
|
||||
'--affine-muted-color': '#a6abb7',
|
||||
'--affine-highlight-color': '#6880ff',
|
||||
'--affine-placeholder-color': '#c7c7c7',
|
||||
'--affine-selected-color': 'rgba(104, 128, 255, 0.1)',
|
||||
'--affine-page-background': theme.colors.pageBackground,
|
||||
'--affine-popover-background': theme.colors.popoverBackground,
|
||||
'--affine-hover-background': theme.colors.hoverBackground,
|
||||
'--affine-code-background': theme.colors.codeBackground,
|
||||
|
||||
'--affine-font-family':
|
||||
'Avenir Next, apple-system, BlinkMacSystemFont,Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei, Arial,Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji,Segoe UI Symbol, Noto Color Emoji',
|
||||
'--affine-text-color': theme.colors.textColor,
|
||||
'--affine-link-color': theme.colors.linkColor,
|
||||
// In dark mode, normal text`s (not bold) color
|
||||
'--affine-link-color2': theme.colors.linkColor2,
|
||||
'--affine-link-visited-color': theme.colors.linkVisitedColor,
|
||||
'--affine-icon-color': theme.colors.iconColor,
|
||||
'--affine-popover-color': theme.colors.popoverColor,
|
||||
'--affine-code-color': theme.colors.codeColor,
|
||||
'--affine-quote-color': theme.colors.quoteColor,
|
||||
'--affine-selected-color': theme.colors.selectedColor,
|
||||
'--affine-placeholder-color': theme.colors.placeHolderColor,
|
||||
|
||||
'--affine-font-family2':
|
||||
'Roboto Mono, apple-system, BlinkMacSystemFont,Helvetica Neue, Tahoma, PingFang SC, Microsoft Yahei, Arial,Hiragino Sans GB, sans-serif, Apple Color Emoji, Segoe UI Emoji,Segoe UI Symbol, Noto Color Emoji',
|
||||
'--affine-modal-shadow': theme.shadow.modal,
|
||||
'--affine-popover-shadow': theme.shadow.popover,
|
||||
|
||||
'--affine-font-xs': theme.font.xs, // tiny
|
||||
'--affine-font-sm': theme.font.sm, // small
|
||||
'--affine-font-base': theme.font.base,
|
||||
|
||||
'--affine-font-family': theme.font.family,
|
||||
'--affine-font-family2': theme.font.family2,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
ThemeProviderProps,
|
||||
ThemeProviderValue,
|
||||
} from './types';
|
||||
import { lightTheme, darkTheme, globalThemeConstant } from './theme';
|
||||
import { lightTheme, darkTheme, globalThemeVariables } from './theme';
|
||||
import { SystemThemeHelper, localStorageThemeHelper } from './utils';
|
||||
|
||||
export const ThemeContext = createContext<ThemeProviderValue>({
|
||||
@@ -67,7 +67,7 @@ export const ThemeProvider = ({
|
||||
<Global
|
||||
styles={css`
|
||||
:root {
|
||||
${globalThemeConstant(mode, themeStyle)}
|
||||
${globalThemeVariables(mode, themeStyle) as {}}
|
||||
}
|
||||
`}
|
||||
/>
|
||||
|
||||
@@ -13,16 +13,71 @@ export type ThemeProviderValue = {
|
||||
|
||||
export interface AffineTheme {
|
||||
colors: {
|
||||
primary: string;
|
||||
highlight: string;
|
||||
disabled: string;
|
||||
background: string;
|
||||
primaryColor: string;
|
||||
|
||||
pageBackground: string;
|
||||
popoverBackground: string;
|
||||
hoverBackground: string;
|
||||
codeBackground: string;
|
||||
|
||||
textColor: string;
|
||||
linkColor: string;
|
||||
// In dark mode, normal text`s (not bold) color
|
||||
linkColor2: string;
|
||||
linkVisitedColor: string;
|
||||
iconColor: string;
|
||||
popoverColor: string;
|
||||
codeColor: string;
|
||||
quoteColor: string;
|
||||
placeHolderColor: string;
|
||||
selectedColor: string;
|
||||
};
|
||||
font: {
|
||||
xs: string; // tiny
|
||||
sm: string; // small
|
||||
base: string;
|
||||
|
||||
family: string;
|
||||
family2: string;
|
||||
};
|
||||
zIndex: {
|
||||
modal: number;
|
||||
popover: number;
|
||||
};
|
||||
shadow: {
|
||||
modal: string;
|
||||
popover: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AffineThemeCSSVariables {
|
||||
'--affine-primary-color': AffineTheme['colors']['primaryColor'];
|
||||
'--affine-page-background': AffineTheme['colors']['pageBackground'];
|
||||
'--affine-popover-background': AffineTheme['colors']['popoverBackground'];
|
||||
'--affine-hover-background': AffineTheme['colors']['hoverBackground'];
|
||||
'--affine-code-background': AffineTheme['colors']['codeBackground'];
|
||||
|
||||
'--affine-text-color': AffineTheme['colors']['textColor'];
|
||||
'--affine-link-color': AffineTheme['colors']['linkColor'];
|
||||
// In dark mode, normal text`s (not bold) color
|
||||
'--affine-link-color2': AffineTheme['colors']['linkColor2'];
|
||||
'--affine-link-visited-color': AffineTheme['colors']['linkVisitedColor'];
|
||||
'--affine-icon-color': AffineTheme['colors']['iconColor'];
|
||||
'--affine-popover-color': AffineTheme['colors']['popoverColor'];
|
||||
'--affine-code-color': AffineTheme['colors']['codeColor'];
|
||||
'--affine-quote-color': AffineTheme['colors']['quoteColor'];
|
||||
'--affine-placeholder-color': AffineTheme['colors']['placeHolderColor'];
|
||||
'--affine-selected-color': AffineTheme['colors']['selectedColor'];
|
||||
|
||||
'--affine-modal-shadow': AffineTheme['shadow']['popover'];
|
||||
'--affine-popover-shadow': AffineTheme['shadow']['modal'];
|
||||
|
||||
'--affine-font-xs': AffineTheme['font']['xs']; // tiny
|
||||
'--affine-font-sm': AffineTheme['font']['sm']; // small
|
||||
'--affine-font-base': AffineTheme['font']['base'];
|
||||
|
||||
'--affine-font-family': AffineTheme['font']['family'];
|
||||
'--affine-font-family2': AffineTheme['font']['family2'];
|
||||
}
|
||||
|
||||
declare module '@emotion/react' {
|
||||
|
||||
Generated
+21
-2
@@ -26,6 +26,7 @@ importers:
|
||||
'@emotion/server': ^11.10.0
|
||||
'@emotion/styled': ^11.10.4
|
||||
'@mui/base': ^5.0.0-alpha.87
|
||||
'@mui/icons-material': ^5.10.9
|
||||
'@mui/material': ^5.8.6
|
||||
'@types/node': 18.7.18
|
||||
'@types/react': 18.0.20
|
||||
@@ -52,6 +53,7 @@ importers:
|
||||
'@emotion/server': 11.10.0_@emotion+css@11.10.0
|
||||
'@emotion/styled': 11.10.4_yiaqs725o7pcd7rteavrnhgj4y
|
||||
'@mui/base': 5.0.0-alpha.101_7ey2zzynotv32rpkwno45fsx4e
|
||||
'@mui/icons-material': 5.10.9_5fncb4nagb4cvvcnwamw2rozfa
|
||||
'@mui/material': 5.10.9_af5ln35zuaotaffazii6n6bke4
|
||||
css-spring: 4.1.0
|
||||
lit: 2.4.0
|
||||
@@ -407,6 +409,23 @@ packages:
|
||||
resolution: {integrity: sha512-rqoFu4qww6KJBbXYhyRd9YXjwBHa3ylnBPSWbGf1bdfG0AYMKmVzg8zxkWvxAWOp97kvx3M2kNPb0xMIDZiogQ==}
|
||||
dev: false
|
||||
|
||||
/@mui/icons-material/5.10.9_5fncb4nagb4cvvcnwamw2rozfa:
|
||||
resolution: {integrity: sha512-sqClXdEM39WKQJOQ0ZCPTptaZgqwibhj2EFV9N0v7BU1PO8y4OcX/a2wIQHn4fNuDjIZktJIBrmU23h7aqlGgg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@mui/material': ^5.0.0
|
||||
'@types/react': ^17.0.0 || ^18.0.0
|
||||
react: ^17.0.0 || ^18.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.19.0
|
||||
'@mui/material': 5.10.9_af5ln35zuaotaffazii6n6bke4
|
||||
'@types/react': 18.0.20
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@mui/material/5.10.9_af5ln35zuaotaffazii6n6bke4:
|
||||
resolution: {integrity: sha512-sdOzlgpCmyw48je+E7o9UGGJpgBaF+60FlTRpVpcd/z+LUhnuzzuis891yPI5dPPXLBDL/bO4SsGg51lgNeLBw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@@ -1370,7 +1389,7 @@ packages:
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.38.0_eslint@8.22.0
|
||||
'@typescript-eslint/parser': 5.38.0_76twfck5d7crjqrmw4yltga7zm
|
||||
debug: 3.2.7
|
||||
eslint: 8.22.0
|
||||
eslint-import-resolver-node: 0.3.6
|
||||
@@ -1389,7 +1408,7 @@ packages:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.38.0_eslint@8.22.0
|
||||
'@typescript-eslint/parser': 5.38.0_76twfck5d7crjqrmw4yltga7zm
|
||||
array-includes: 3.1.5
|
||||
array.prototype.flat: 1.3.0
|
||||
debug: 2.6.9
|
||||
|
||||
Reference in New Issue
Block a user