feat: modify style

This commit is contained in:
QiShaoXuan 2022-10-18 00:28:39 +08:00
parent 249b5ab0f1
commit d7c6f7e8d5
20 changed files with 413 additions and 313 deletions

View File

@ -1,24 +1,17 @@
import type { DOMAttributes, CSSProperties } from 'react';
type IconProps = {
color?: string;
style?: CSSProperties;
} & DOMAttributes<SVGElement>;
export const LogoIcon = ({
color,
style: propsStyle = {},
...props
}: IconProps) => {
const style = { fill: color, ...propsStyle };
export const LogoIcon = ({ style = {}, ...props }: IconProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
{...props}
fill="currentColor"
style={style}
{...props}
>
<path
fillRule="evenodd"
@ -29,51 +22,16 @@ export const LogoIcon = ({
);
};
export const EdgelessIcon = ({
color,
style: propsStyle = {},
...props
}: IconProps) => {
const style = { fill: color, ...propsStyle };
export const MoonIcon = ({ style = {}, ...props }: IconProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
{...props}
fill="currentColor"
style={style}
>
<path
fillRule="evenodd"
d="M12 17.4a5.4 5.4 0 1 0 0-10.8 5.4 5.4 0 0 0 0 10.8Zm7-5.4a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z"
clipRule="evenodd"
/>
<path
fillRule="evenodd"
d="M18.565 8a.8.8 0 0 1 .8-.8c.797 0 1.511.07 2.07.24.5.15 1.172.477 1.334 1.202v.004c.089.405-.026.776-.186 1.065a3.165 3.165 0 0 1-.652.782c-.52.471-1.265.947-2.15 1.407-1.783.927-4.28 1.869-7.077 2.62-2.796.752-5.409 1.184-7.381 1.266-.98.04-1.848-.003-2.516-.162-.333-.079-.662-.196-.937-.38-.282-.19-.547-.48-.639-.892v-.002c-.138-.63.202-1.173.518-1.532.343-.39.836-.768 1.413-1.129a.8.8 0 0 1 .848 1.357c-.515.322-.862.605-1.06.83a1.524 1.524 0 0 0-.078.096c.07.03.169.064.304.095.461.11 1.163.158 2.08.12 1.822-.075 4.314-.481 7.033-1.212 2.718-.73 5.1-1.635 6.753-2.494.832-.433 1.441-.835 1.814-1.173.127-.115.213-.21.268-.284a1.67 1.67 0 0 0-.153-.053c-.342-.104-.878-.171-1.606-.171a.8.8 0 0 1-.8-.8Zm2.692 1.097-.004-.004a.026.026 0 0 1 .004.004Zm-18.46 5 .001-.002v.002Z"
clipRule="evenodd"
/>
</svg>
);
};
export const MoonIcon = ({
color,
style: propsStyle = {},
...props
}: IconProps) => {
const style = { fill: color, ...propsStyle };
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
{...props}
style={style}
>
<path
fillRule="evenodd"
@ -84,52 +42,17 @@ export const MoonIcon = ({
);
};
export const PaperIcon = ({
color,
style: propsStyle = {},
...props
}: IconProps) => {
const style = { fill: color, ...propsStyle };
export const SunIcon = ({ style = {}, ...props }: IconProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
{...props}
fill="currentColor"
style={style}
>
<path
fillRule="evenodd"
d="M17 9.8H7V8.2h10v1.6ZM12 12.8H7v-1.6h5v1.6Z"
clipRule="evenodd"
/>
<path d="m14 19 7-7h-5a2 2 0 0 0-2 2v5Z" />
<path
fillRule="evenodd"
d="M5 6.6h14c.22 0 .4.18.4.4v6.6L21 12V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h9l1.6-1.6H5a.4.4 0 0 1-.4-.4V7c0-.22.18-.4.4-.4Z"
clipRule="evenodd"
/>
</svg>
);
};
export const SunIcon = ({
color,
style: propsStyle = {},
...props
}: IconProps) => {
const style = { fill: color, ...propsStyle };
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
{...props}
style={style}
>
<path
fillRule="evenodd"
@ -140,21 +63,14 @@ export const SunIcon = ({
);
};
export const MoreIcon = ({
color,
style: propsStyle = {},
...props
}: IconProps) => {
const style = { fill: color, ...propsStyle, transform: 'rotate(90deg)' };
export const MoreIcon = ({ style = {}, ...props }: IconProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
{...props}
style={style}
fill="currentColor"
>
<circle cx="12" cy="5.5" r="1.5" />
<circle cx="12" cy="12" r="1.5" />
@ -162,26 +78,19 @@ export const MoreIcon = ({
</svg>
);
};
export const ExportIcon = ({
color,
style: propsStyle = {},
...props
}: IconProps) => {
const style = { fill: color, ...propsStyle };
export const ExportIcon = ({ style = {}, ...props }: IconProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
{...props}
style={style}
fill="currentColor"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M12 3.19995C12.2121 3.19995 12.4156 3.28424 12.5656 3.43427L16.5656 7.43427L15.4343 8.56564L12.8 5.93132V14H11.2V5.93132L8.56564 8.56564L7.43427 7.43427L11.4343 3.43427C11.5843 3.28424 11.7878 3.19995 12 3.19995ZM3.79995 12V16.7992C3.79995 17.3724 3.80057 17.7543 3.82454 18.0476C3.84775 18.3317 3.88879 18.4616 3.93074 18.544C4.04579 18.7698 4.22937 18.9533 4.45516 19.0684C4.5375 19.1103 4.66747 19.1514 4.9515 19.1746C5.24487 19.1985 5.6267 19.1992 6.19995 19.1992H17.8C18.3732 19.1992 18.755 19.1985 19.0484 19.1746C19.3324 19.1514 19.4624 19.1103 19.5447 19.0684C19.7705 18.9533 19.9541 18.7698 20.0692 18.544C20.1111 18.4616 20.1522 18.3317 20.1754 18.0476C20.1993 17.7543 20.2 17.3724 20.2 16.7992V12H21.8V16.8314C21.8 17.364 21.8 17.8116 21.77 18.1779C21.7388 18.5609 21.6708 18.9249 21.4948 19.2703C21.2263 19.7972 20.798 20.2255 20.2711 20.494C19.9256 20.67 19.5617 20.738 19.1787 20.7693C18.8124 20.7992 18.3648 20.7992 17.8322 20.7992H6.16775C5.63509 20.7992 5.18749 20.7992 4.82121 20.7693C4.43823 20.738 4.07426 20.67 3.72878 20.494C3.20193 20.2255 2.77358 19.7972 2.50513 19.2703C2.3291 18.9249 2.26115 18.5609 2.22986 18.1779C2.19993 17.8116 2.19994 17.364 2.19995 16.8313L2.19995 12H3.79995Z"
fill="#9096A5"
/>
</svg>
);

View File

@ -1,8 +1,6 @@
import React, { useEffect, useState } from 'react';
import {
LogoIcon,
PaperIcon,
EdgelessIcon,
SunIcon,
MoonIcon,
MoreIcon,
@ -13,56 +11,14 @@ import {
StyledTitle,
StyledTitleWrapper,
StyledLogo,
StyledModeSwitch,
StyledHeaderRightSide,
StyledMoreMenuItem,
IconButton,
} from './styles';
import { Popover } from '@/components/popover';
import { useTheme } from '@/styles';
import { useEditor } from '@/components/editor-provider';
import { AnimateRadio } from '@/components/animate-radio';
const PaperItem = ({ active }: { active?: boolean }) => {
const {
theme: {
colors: { highlight, disabled },
},
} = useTheme();
return <PaperIcon color={active ? highlight : disabled} />;
};
const EdgelessItem = ({ active }: { active?: boolean }) => {
const {
theme: {
colors: { highlight, disabled },
},
} = useTheme();
return <EdgelessIcon color={active ? highlight : disabled} />;
};
const EditorModeSwitch = ({ isHover }: { isHover: boolean }) => {
const handleModeSwitch = (mode: 'page' | 'edgeless') => {
const event = new CustomEvent('affine.switch-mode', { detail: mode });
window.dispatchEvent(event);
};
return (
<AnimateRadio
isHover={isHover}
labelLeft="Paper"
iconLeft={<PaperItem />}
labelRight="Edgeless"
iconRight={<EdgelessItem />}
style={{
marginRight: '12px',
}}
initialValue="left"
onChange={value => {
handleModeSwitch(value === 'left' ? 'page' : 'edgeless');
}}
/>
);
};
import EditorModeSwitch from '@/components/editor-mode-switch';
const DarkModeSwitch = () => {
const { changeMode, mode } = useTheme();
@ -71,16 +27,14 @@ const DarkModeSwitch = () => {
<>
{mode === 'dark' ? (
<SunIcon
color="#9096A5"
style={{ cursor: 'pointer' }}
style={{ cursor: 'pointer', color: '#9096A5' }}
onClick={() => {
changeMode('light');
}}
></SunIcon>
) : (
<MoonIcon
color="#9096A5"
style={{ cursor: 'pointer' }}
style={{ cursor: 'pointer', color: '#9096A5' }}
onClick={() => {
changeMode('dark');
}}
@ -130,26 +84,36 @@ export const Header = () => {
}, [editor]);
return (
<StyledHeader
onMouseEnter={() => {
setIsHover(true);
}}
onMouseLeave={() => {
setIsHover(false);
}}
>
<StyledHeader>
<StyledLogo>
<LogoIcon color={'#6880FF'} onClick={() => {}} />
<LogoIcon style={{ color: '#6880FF' }} onClick={() => {}} />
</StyledLogo>
<StyledTitle>
<EditorModeSwitch isHover={isHover} />
<StyledTitle
onMouseEnter={() => {
setIsHover(true);
}}
onMouseLeave={() => {
setIsHover(false);
}}
>
<EditorModeSwitch
isHover={isHover}
style={{
marginRight: '12px',
}}
/>
<StyledTitleWrapper>{title}</StyledTitleWrapper>
</StyledTitle>
<StyledHeaderRightSide>
<DarkModeSwitch />
<Popover popoverContent={<PopoverContent />}>
<MoreIcon color="#9096A5" style={{ marginLeft: '20px' }} />
<Popover
popoverContent={<PopoverContent />}
style={{ marginLeft: '20px' }}
>
<IconButton>
<MoreIcon />
</IconButton>
</Popover>
</StyledHeaderRightSide>
</StyledHeader>

View File

@ -71,3 +71,20 @@ export const StyledMoreMenuItem = styled('div')({
},
},
});
export const IconButton = styled('div')(({ theme }) => {
return {
width: '32px',
height: '32px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: theme.colors.disabled,
background: 'transparent',
borderRadius: '5px',
':hover': {
color: theme.colors.highlight,
background: '#F1F3FF',
},
};
});

View File

@ -1,38 +0,0 @@
import { CSSProperties, DOMAttributes } from 'react';
type IconProps = {
color?: string;
style?: CSSProperties;
} & DOMAttributes<SVGElement>;
export const ArrowIcon = ({
color,
style: propsStyle = {},
direction = 'right',
...props
}: IconProps & { direction?: 'left' | 'right' | 'middle' }) => {
const style = {
fill: color,
transform: `rotate(${direction === 'left' ? '0' : '180deg'})`,
opacity: direction === 'middle' ? 0 : 1,
...propsStyle,
};
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="6"
height="16"
viewBox="0 0 6 16"
fill="none"
{...props}
style={style}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0.602933 0.305738C0.986547 0.0865297 1.47523 0.219807 1.69444 0.603421L5.41093 7.10728C5.72715 7.66066 5.72715 8.34 5.41093 8.89338L1.69444 15.3972C1.47523 15.7809 0.986547 15.9141 0.602933 15.6949C0.219319 15.4757 0.0860414 14.987 0.305249 14.6034L4.02174 8.09956C4.05688 8.03807 4.05688 7.96259 4.02174 7.9011L0.305249 1.39724C0.0860414 1.01363 0.219319 0.524946 0.602933 0.305738Z"
fill="#6880FF"
/>
</svg>
);
};

View File

@ -0,0 +1,85 @@
import { CSSProperties, DOMAttributes } from 'react';
type IconProps = {
style?: CSSProperties;
} & DOMAttributes<SVGElement>;
export const ArrowIcon = ({
style: propsStyle = {},
direction = 'right',
...props
}: IconProps & { direction?: 'left' | 'right' | 'middle' }) => {
const style = {
transform: `rotate(${direction === 'left' ? '0' : '180deg'})`,
opacity: direction === 'middle' ? 0 : 1,
...propsStyle,
};
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="6"
height="16"
viewBox="0 0 6 16"
fill="currentColor"
{...props}
style={style}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0.602933 0.305738C0.986547 0.0865297 1.47523 0.219807 1.69444 0.603421L5.41093 7.10728C5.72715 7.66066 5.72715 8.34 5.41093 8.89338L1.69444 15.3972C1.47523 15.7809 0.986547 15.9141 0.602933 15.6949C0.219319 15.4757 0.0860414 14.987 0.305249 14.6034L4.02174 8.09956C4.05688 8.03807 4.05688 7.96259 4.02174 7.9011L0.305249 1.39724C0.0860414 1.01363 0.219319 0.524946 0.602933 0.305738Z"
/>
</svg>
);
};
export const PaperIcon = ({ 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="M17 9.8H7V8.2h10v1.6ZM12 12.8H7v-1.6h5v1.6Z"
clipRule="evenodd"
/>
<path d="m14 19 7-7h-5a2 2 0 0 0-2 2v5Z" />
<path
fillRule="evenodd"
d="M5 6.6h14c.22 0 .4.18.4.4v6.6L21 12V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h9l1.6-1.6H5a.4.4 0 0 1-.4-.4V7c0-.22.18-.4.4-.4Z"
clipRule="evenodd"
/>
</svg>
);
};
export const EdgelessIcon = ({ 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="M12 17.4a5.4 5.4 0 1 0 0-10.8 5.4 5.4 0 0 0 0 10.8Zm7-5.4a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z"
clipRule="evenodd"
/>
<path
fillRule="evenodd"
d="M18.565 8a.8.8 0 0 1 .8-.8c.797 0 1.511.07 2.07.24.5.15 1.172.477 1.334 1.202v.004c.089.405-.026.776-.186 1.065a3.165 3.165 0 0 1-.652.782c-.52.471-1.265.947-2.15 1.407-1.783.927-4.28 1.869-7.077 2.62-2.796.752-5.409 1.184-7.381 1.266-.98.04-1.848-.003-2.516-.162-.333-.079-.662-.196-.937-.38-.282-.19-.547-.48-.639-.892v-.002c-.138-.63.202-1.173.518-1.532.343-.39.836-.768 1.413-1.129a.8.8 0 0 1 .848 1.357c-.515.322-.862.605-1.06.83a1.524 1.524 0 0 0-.078.096c.07.03.169.064.304.095.461.11 1.163.158 2.08.12 1.822-.075 4.314-.481 7.033-1.212 2.718-.73 5.1-1.635 6.753-2.494.832-.433 1.441-.835 1.814-1.173.127-.115.213-.21.268-.284a1.67 1.67 0 0 0-.153-.053c-.342-.104-.878-.171-1.606-.171a.8.8 0 0 1-.8-.8Zm2.692 1.097-.004-.004a.026.026 0 0 1 .004.004Zm-18.46 5 .001-.002v.002Z"
clipRule="evenodd"
/>
</svg>
);
};

View File

@ -1,4 +1,4 @@
import { useState, useEffect, cloneElement } from 'react';
import React, { useState, useEffect, cloneElement } from 'react';
import {
StyledAnimateRadioContainer,
StyledRadioMiddle,
@ -7,12 +7,34 @@ import {
StyledLabel,
StyledIcon,
} from './style';
import { ArrowIcon } from './icons';
import type {
RadioItemStatus,
AnimateRadioProps,
AnimateRadioItemProps,
} from './type';
import { useTheme } from '@/styles';
import { EdgelessIcon, PaperIcon } from './icons';
import { useEditor } from '@/components/editor-provider';
const PaperItem = ({ active }: { active?: boolean }) => {
const {
theme: {
colors: { highlight, disabled },
},
} = useTheme();
return <PaperIcon style={{ color: active ? highlight : disabled }} />;
};
const EdgelessItem = ({ active }: { active?: boolean }) => {
const {
theme: {
colors: { highlight, disabled },
},
} = useTheme();
return <EdgelessIcon style={{ color: active ? highlight : disabled }} />;
};
const AnimateRadioItem = ({
active,
@ -24,7 +46,7 @@ const AnimateRadioItem = ({
}: AnimateRadioItemProps) => {
return (
<StyledRadioItem active={active} status={status} {...props}>
<StyledIcon shrink={status === 'stretch'} isLeft={isLeft}>
<StyledIcon shrink={status === 'shrink'} isLeft={isLeft}>
{cloneElement(icon, {
active,
})}
@ -44,37 +66,32 @@ const RadioMiddle = ({
}) => {
return (
<StyledRadioMiddle hidden={!isHover}>
<StyledMiddleLine hidden={direction !== 'middle'} />
<ArrowIcon
direction={direction}
style={{
position: 'absolute',
left: '0',
right: '0',
top: '0',
bottom: '0',
margin: 'auto',
}}
></ArrowIcon>
<StyledMiddleLine hidden={false} />
</StyledRadioMiddle>
);
};
export const AnimateRadio = ({
labelLeft,
labelRight,
iconLeft,
iconRight,
export const EditorModeSwitch = ({
isHover,
style = {},
onChange,
initialValue = 'left',
}: AnimateRadioProps) => {
const [active, setActive] = useState(initialValue);
const { mode, setMode } = useEditor();
const modifyRadioItemStatus = (): RadioItemStatus => {
return {
left: !isHover && active === 'right' ? 'shrink' : 'normal',
right: !isHover && active === 'left' ? 'shrink' : 'normal',
left: isHover
? mode === 'page'
? 'stretch'
: 'normal'
: mode === 'page'
? 'shrink'
: 'hidden',
right: isHover
? mode === 'edgeless'
? 'stretch'
: 'normal'
: mode === 'edgeless'
? 'shrink'
: 'hidden',
};
};
const [radioItemStatus, setRadioItemStatus] = useState<RadioItemStatus>(
@ -84,19 +101,18 @@ export const AnimateRadio = ({
useEffect(() => {
setRadioItemStatus(modifyRadioItemStatus());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isHover, active]);
}, [isHover, mode]);
return (
<StyledAnimateRadioContainer shrink={!isHover} style={style}>
<AnimateRadioItem
isLeft={true}
label={labelLeft}
icon={iconLeft}
active={active === 'left'}
label="Paper"
icon={<PaperItem />}
active={mode === 'page'}
status={radioItemStatus.left}
onClick={() => {
setActive('left');
onChange?.('left');
setMode('page');
}}
onMouseEnter={() => {
setRadioItemStatus({
@ -105,31 +121,18 @@ export const AnimateRadio = ({
});
}}
onMouseLeave={() => {
setRadioItemStatus({
...radioItemStatus,
left: 'normal',
});
setRadioItemStatus(modifyRadioItemStatus());
}}
/>
<RadioMiddle
isHover={isHover}
direction={
radioItemStatus.left === 'stretch'
? 'left'
: radioItemStatus.right === 'stretch'
? 'right'
: 'middle'
}
/>
<StyledMiddleLine hidden={!isHover} />
<AnimateRadioItem
isLeft={false}
label={labelRight}
icon={iconRight}
active={active === 'right'}
label="Edgeless"
icon={<EdgelessItem />}
active={mode === 'edgeless'}
status={radioItemStatus.right}
onClick={() => {
setActive('right');
onChange?.('right');
setMode('edgeless');
}}
onMouseEnter={() => {
setRadioItemStatus({
@ -138,14 +141,11 @@ export const AnimateRadio = ({
});
}}
onMouseLeave={() => {
setRadioItemStatus({
...radioItemStatus,
right: 'normal',
});
setRadioItemStatus(modifyRadioItemStatus());
}}
/>
</StyledAnimateRadioContainer>
);
};
export default AnimateRadio;
export default EditorModeSwitch;

View File

@ -8,11 +8,11 @@ const ANIMATE_DURATION = 300;
export const StyledAnimateRadioContainer = styled('div')<{ shrink: boolean }>(
({ shrink }) => {
const animateScaleStretch = keyframes`${toString(
spring({ width: '66px' }, { width: '132px' }, { preset: 'gentle' })
spring({ width: '36px' }, { width: '160px' }, { preset: 'gentle' })
)}`;
const animateScaleShrink = keyframes(
`${toString(
spring({ width: '132px' }, { width: '66px' }, { preset: 'gentle' })
spring({ width: '160px' }, { width: '36px' }, { preset: 'gentle' })
)}`
);
const shrinkStyle = shrink
@ -40,7 +40,7 @@ export const StyledRadioMiddle = styled('div')<{
hidden: boolean;
}>(({ hidden }) => {
return {
width: '6px',
width: '1px',
height: '100%',
position: 'relative',
opacity: hidden ? '0' : '1',
@ -53,9 +53,6 @@ export const StyledMiddleLine = styled('div')<{ hidden: boolean }>(
width: '1px',
height: '16px',
background: '#D0D7E3',
position: 'absolute',
left: '0',
right: '0',
top: '0',
bottom: '0',
margin: 'auto',
@ -69,13 +66,13 @@ export const StyledRadioItem = styled('div')<{
active: boolean;
}>(({ status, active, theme }) => {
const animateScaleStretch = keyframes`${toString(
spring({ width: '66px' }, { width: '116px' })
spring({ width: '44px' }, { width: '112px' })
)}`;
const animateScaleOrigin = keyframes(
`${toString(spring({ width: '116px' }, { width: '66px' }))}`
`${toString(spring({ width: '112px' }, { width: '44px' }))}`
);
const animateScaleShrink = keyframes(
`${toString(spring({ width: '66px' }, { width: '0px' }))}`
`${toString(spring({ width: '0px' }, { width: '36px' }))}`
);
const dynamicStyle =
status === 'stretch'
@ -86,14 +83,16 @@ export const StyledRadioItem = styled('div')<{
: status === 'shrink'
? {
animation: `${animateScaleShrink} ${ANIMATE_DURATION}ms forwards`,
opacity: '0',
}
: { animation: `${animateScaleOrigin} ${ANIMATE_DURATION}ms forwards` };
: status === 'normal'
? { animation: `${animateScaleOrigin} ${ANIMATE_DURATION}ms forwards` }
: {};
const {
colors: { highlight, disabled },
} = theme;
return {
width: '0',
height: '100%',
display: 'flex',
cursor: 'pointer',
@ -135,19 +134,14 @@ export const StyledIcon = styled('div')<{
shrink: boolean;
isLeft: boolean;
}>(({ shrink, isLeft }) => {
const shrinkStyle = shrink
? {
width: '24px',
margin: isLeft ? '0 12px' : '0 5px',
}
: {
width: '66px',
};
const dynamicStyle = shrink
? { width: '36px' }
: { width: isLeft ? '44px' : '34px' };
return {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexShrink: '0',
...shrinkStyle,
...dynamicStyle,
};
});

View File

@ -1,20 +1,14 @@
import { CSSProperties, DOMAttributes, ReactElement } from 'react';
export type ItemStatus = 'normal' | 'stretch' | 'shrink';
export type ItemStatus = 'normal' | 'stretch' | 'shrink' | 'hidden';
export type RadioItemStatus = {
left: ItemStatus;
right: ItemStatus;
};
export type AnimateRadioProps = {
labelLeft: string;
labelRight: string;
iconLeft: ReactElement;
iconRight: ReactElement;
isHover: boolean;
initialValue?: 'left' | 'right';
style?: CSSProperties;
onChange?: (value: 'left' | 'right') => void;
style: CSSProperties;
};
export type AnimateRadioItemProps = {
active: boolean;

View File

@ -5,13 +5,17 @@ import type { PropsWithChildren } from 'react';
type EditorContextValue = {
editor: EditorContainer | null;
mode: EditorContainer['mode'];
setEditor: (editor: EditorContainer) => void;
setMode: (mode: EditorContainer['mode']) => void;
};
type EditorContextProps = PropsWithChildren<{}>;
export const EditorContext = createContext<EditorContextValue>({
editor: null,
mode: 'page',
setEditor: () => {},
setMode: () => {},
});
export const useEditor = () => useContext(EditorContext);
@ -20,9 +24,15 @@ export const EditorProvider = ({
children,
}: PropsWithChildren<EditorContextProps>) => {
const [editor, setEditor] = useState<EditorContainer | null>(null);
const [mode, setMode] = useState<EditorContainer['mode']>('page');
useEffect(() => {
const event = new CustomEvent('affine.switch-mode', { detail: mode });
window.dispatchEvent(event);
}, [mode]);
return (
<EditorContext.Provider value={{ editor, setEditor }}>
<EditorContext.Provider value={{ editor, setEditor, mode, setMode }}>
{children}
</EditorContext.Provider>
);

View File

@ -0,0 +1,45 @@
export const HelpIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M12 3.8a8.2 8.2 0 1 0 0 16.4 8.2 8.2 0 0 0 0-16.4ZM2.2 12c0-5.412 4.388-9.8 9.8-9.8 5.412 0 9.8 4.388 9.8 9.8 0 5.412-4.388 9.8-9.8 9.8-5.412 0-9.8-4.388-9.8-9.8Zm9.978-3.18a1.448 1.448 0 0 0-1.61.948.8.8 0 1 1-1.51-.531 3.048 3.048 0 0 1 5.924 1.015c0 1.174-.87 1.945-1.48 2.351a6.082 6.082 0 0 1-1.275.642l-.027.01-.008.002-.003.001h-.002l-.254-.758.253.759a.8.8 0 0 1-.507-1.518h.001l.01-.004.055-.02a4.488 4.488 0 0 0 .869-.445c.513-.342.768-.696.768-1.02v-.002a1.449 1.449 0 0 0-1.204-1.43Zm-1.017 6.68a.8.8 0 0 1 .8-.8h.01a.8.8 0 1 1 0 1.6h-.01a.8.8 0 0 1-.8-.8Z"
clipRule="evenodd"
/>
</svg>
);
};
export const ContactIcon = () => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M3.8 11C3.8 6.47126 7.47126 2.8 12 2.8V1.2C6.58761 1.2 2.2 5.58761 2.2 11H3.8ZM12 2.8C16.5287 2.8 20.2 6.47126 20.2 11H21.8C21.8 5.58761 17.4124 1.2 12 1.2V2.8ZM3 11.8H5V10.2H3V11.8ZM6.2 13V15H7.8V13H6.2ZM5 16.2H4V17.8H5V16.2ZM4 16.2C3.88954 16.2 3.8 16.1105 3.8 16H2.2C2.2 16.9941 3.00589 17.8 4 17.8V16.2ZM6.2 15C6.2 15.6627 5.66274 16.2 5 16.2V17.8C6.5464 17.8 7.8 16.5464 7.8 15H6.2ZM5 11.8C5.66274 11.8 6.2 12.3373 6.2 13H7.8C7.8 11.4536 6.5464 10.2 5 10.2V11.8ZM21 10.2H19V11.8H21V10.2ZM16.2 13V15H17.8V13H16.2ZM19 17.8H20V16.2H19V17.8ZM20 17.8C20.9941 17.8 21.8 16.9941 21.8 16H20.2C20.2 16.1105 20.1105 16.2 20 16.2V17.8ZM16.2 15C16.2 16.5464 17.4536 17.8 19 17.8V16.2C18.3373 16.2 17.8 15.6627 17.8 15H16.2ZM19 10.2C17.4536 10.2 16.2 11.4536 16.2 13H17.8C17.8 12.3373 18.3373 11.8 19 11.8V10.2ZM4.2 17V18H5.8V17H4.2ZM7 20.8H9V19.2H7V20.8ZM4.2 18C4.2 19.5464 5.4536 20.8 7 20.8V19.2C6.33726 19.2 5.8 18.6627 5.8 18H4.2ZM10.5 19.3H11.5V17.7H10.5V19.3ZM11.5 20.7H10.5V22.3H11.5V20.7ZM10.5 20.7C10.1134 20.7 9.8 20.3866 9.8 20H8.2C8.2 21.2703 9.22974 22.3 10.5 22.3V20.7ZM12.2 20C12.2 20.3866 11.8866 20.7 11.5 20.7V22.3C12.7703 22.3 13.8 21.2703 13.8 20H12.2ZM11.5 19.3C11.8866 19.3 12.2 19.6134 12.2 20H13.8C13.8 18.7297 12.7703 17.7 11.5 17.7V19.3ZM10.5 17.7C9.22974 17.7 8.2 18.7297 8.2 20H9.8C9.8 19.6134 10.1134 19.3 10.5 19.3V17.7ZM2.2 11V16H3.8V11H2.2ZM20.2 11V16H21.8V11H20.2Z" />
</svg>
);
};
export const KeyboardIcon = () => {
return (
<svg
width="24"
height="25"
viewBox="0 0 24 25"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M19.745 5C20.3417 5 20.914 5.23705 21.336 5.65901C21.7579 6.08097 21.995 6.65326 21.995 7.25V16.755C21.995 17.3517 21.7579 17.924 21.336 18.346C20.914 18.7679 20.3417 19.005 19.745 19.005H4.25C3.95453 19.005 3.66194 18.9468 3.38896 18.8337C3.11598 18.7207 2.86794 18.5549 2.65901 18.346C2.45008 18.1371 2.28434 17.889 2.17127 17.616C2.0582 17.3431 2 17.0505 2 16.755V7.25C2 6.65326 2.23705 6.08097 2.65901 5.65901C3.08097 5.23705 3.65326 5 4.25 5H19.745ZM19.745 6.5H4.25C4.05109 6.5 3.86032 6.57902 3.71967 6.71967C3.57902 6.86032 3.5 7.05109 3.5 7.25V16.755C3.5 17.169 3.836 17.505 4.25 17.505H19.745C19.9439 17.505 20.1347 17.426 20.2753 17.2853C20.416 17.1447 20.495 16.9539 20.495 16.755V7.25C20.495 7.05109 20.416 6.86032 20.2753 6.71967C20.1347 6.57902 19.9439 6.5 19.745 6.5ZM6.75 14.5H17.25C17.44 14.5001 17.6229 14.5722 17.7618 14.702C17.9006 14.8317 17.9851 15.0093 17.998 15.1989C18.011 15.3885 17.9515 15.5759 17.8316 15.7233C17.7117 15.8707 17.5402 15.9671 17.352 15.993L17.25 16H6.75C6.55998 15.9999 6.37706 15.9278 6.23821 15.798C6.09936 15.6683 6.01493 15.4907 6.00197 15.3011C5.98902 15.1115 6.04852 14.9241 6.16843 14.7767C6.28835 14.6293 6.45975 14.5329 6.648 14.507L6.75 14.5H17.25H6.75ZM16.5 11C16.7652 11 17.0196 11.1054 17.2071 11.2929C17.3946 11.4804 17.5 11.7348 17.5 12C17.5 12.2652 17.3946 12.5196 17.2071 12.7071C17.0196 12.8946 16.7652 13 16.5 13C16.2348 13 15.9804 12.8946 15.7929 12.7071C15.6054 12.5196 15.5 12.2652 15.5 12C15.5 11.7348 15.6054 11.4804 15.7929 11.2929C15.9804 11.1054 16.2348 11 16.5 11ZM10.505 11C10.7702 11 11.0246 11.1054 11.2121 11.2929C11.3996 11.4804 11.505 11.7348 11.505 12C11.505 12.2652 11.3996 12.5196 11.2121 12.7071C11.0246 12.8946 10.7702 13 10.505 13C10.2398 13 9.98543 12.8946 9.79789 12.7071C9.61036 12.5196 9.505 12.2652 9.505 12C9.505 11.7348 9.61036 11.4804 9.79789 11.2929C9.98543 11.1054 10.2398 11 10.505 11ZM7.505 11C7.77022 11 8.02457 11.1054 8.21211 11.2929C8.39964 11.4804 8.505 11.7348 8.505 12C8.505 12.2652 8.39964 12.5196 8.21211 12.7071C8.02457 12.8946 7.77022 13 7.505 13C7.23978 13 6.98543 12.8946 6.79789 12.7071C6.61036 12.5196 6.505 12.2652 6.505 12C6.505 11.7348 6.61036 11.4804 6.79789 11.2929C6.98543 11.1054 7.23978 11 7.505 11ZM13.505 11C13.7702 11 14.0246 11.1054 14.2121 11.2929C14.3996 11.4804 14.505 11.7348 14.505 12C14.505 12.2652 14.3996 12.5196 14.2121 12.7071C14.0246 12.8946 13.7702 13 13.505 13C13.2398 13 12.9854 12.8946 12.7979 12.7071C12.6104 12.5196 12.505 12.2652 12.505 12C12.505 11.7348 12.6104 11.4804 12.7979 11.2929C12.9854 11.1054 13.2398 11 13.505 11ZM6 8C6.26522 8 6.51957 8.10536 6.70711 8.29289C6.89464 8.48043 7 8.73478 7 9C7 9.26522 6.89464 9.51957 6.70711 9.70711C6.51957 9.89464 6.26522 10 6 10C5.73478 10 5.48043 9.89464 5.29289 9.70711C5.10536 9.51957 5 9.26522 5 9C5 8.73478 5.10536 8.48043 5.29289 8.29289C5.48043 8.10536 5.73478 8 6 8ZM8.995 8C9.26022 8 9.51457 8.10536 9.70211 8.29289C9.88964 8.48043 9.995 8.73478 9.995 9C9.995 9.26522 9.88964 9.51957 9.70211 9.70711C9.51457 9.89464 9.26022 10 8.995 10C8.72978 10 8.47543 9.89464 8.28789 9.70711C8.10036 9.51957 7.995 9.26522 7.995 9C7.995 8.73478 8.10036 8.48043 8.28789 8.29289C8.47543 8.10536 8.72978 8 8.995 8ZM11.995 8C12.2602 8 12.5146 8.10536 12.7021 8.29289C12.8896 8.48043 12.995 8.73478 12.995 9C12.995 9.26522 12.8896 9.51957 12.7021 9.70711C12.5146 9.89464 12.2602 10 11.995 10C11.7298 10 11.4754 9.89464 11.2879 9.70711C11.1004 9.51957 10.995 9.26522 10.995 9C10.995 8.73478 11.1004 8.48043 11.2879 8.29289C11.4754 8.10536 11.7298 8 11.995 8ZM14.995 8C15.2602 8 15.5146 8.10536 15.7021 8.29289C15.8896 8.48043 15.995 8.73478 15.995 9C15.995 9.26522 15.8896 9.51957 15.7021 9.70711C15.5146 9.89464 15.2602 10 14.995 10C14.7298 10 14.4754 9.89464 14.2879 9.70711C14.1004 9.51957 13.995 9.26522 13.995 9C13.995 8.73478 14.1004 8.48043 14.2879 8.29289C14.4754 8.10536 14.7298 8 14.995 8ZM17.995 8C18.2602 8 18.5146 8.10536 18.7021 8.29289C18.8896 8.48043 18.995 8.73478 18.995 9C18.995 9.26522 18.8896 9.51957 18.7021 9.70711C18.5146 9.89464 18.2602 10 17.995 10C17.7298 10 17.4754 9.89464 17.2879 9.70711C17.1004 9.51957 16.995 9.26522 16.995 9C16.995 8.73478 17.1004 8.48043 17.2879 8.29289C17.4754 8.10536 17.7298 8 17.995 8Z" />
</svg>
);
};

View File

@ -0,0 +1,59 @@
import React from 'react';
import { StyledFAQ, StyledIconWrapper, StyledFAQWrapper } from './style';
import { ContactIcon, HelpIcon, KeyboardIcon } from './icons';
import Grow from '@mui/material/Grow';
import { Tooltip } from '../tooltip';
import { Modal } from '@/components/modal';
const Contact = () => {
const [openModal, setOpenModal] = React.useState(false);
return (
<>
<Modal
open={openModal}
onClose={() => {
setOpenModal(false);
}}
>
<div>modal content</div>
</Modal>
<Tooltip content="Contact with us" placement="left-end">
<StyledIconWrapper
onClick={() => {
setOpenModal(true);
}}
>
<ContactIcon />
</StyledIconWrapper>
</Tooltip>
</>
);
};
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>
);
};

View File

@ -0,0 +1,54 @@
import { styled } from '@/styles';
export const StyledFAQ = styled('div')(({ theme }) => {
return {
width: '32px',
height: '32px',
backgroundColor: '#fff',
color: theme.colors.disabled,
position: 'fixed',
right: '30px',
bottom: '30px',
borderRadius: '50%',
zIndex: 1000,
':hover': {
backgroundColor: '#F1F3FF',
color: theme.colors.highlight,
},
};
});
export const StyledIconWrapper = styled('div')(({ theme }) => {
return {
color: theme.colors.disabled,
marginBottom: '24px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
cursor: 'pointer',
backgroundColor: 'transparent',
borderRadius: '50%',
width: '32px',
height: '32px',
':hover': {
color: theme.colors.highlight,
backgroundColor: '#F1F3FF',
},
};
});
export const StyledFAQWrapper = styled('div')(({ theme }) => {
return {
position: 'absolute',
bottom: '100%',
left: '0',
width: '100%',
color: theme.colors.disabled,
':hover': {
'> svg': {
color: theme.colors.highlight,
},
color: theme.colors.highlight,
},
};
});

View File

@ -1,9 +1,10 @@
import { useState } from 'react';
import type { PropsWithChildren } from 'react';
import type { CSSProperties, PropsWithChildren } from 'react';
import { styled } from '@/styles';
type PopoverProps = {
popoverContent?: React.ReactNode;
style?: CSSProperties;
};
const StyledPopoverContainer = styled('div')({
@ -34,6 +35,7 @@ const StyledPopover = styled('div')<{ show: boolean }>(({ show }) => {
export const Popover = ({
children,
popoverContent,
style = {},
}: PropsWithChildren<PopoverProps>) => {
const [show, setShow] = useState(false);
return (
@ -47,6 +49,7 @@ export const Popover = ({
onMouseLeave={() => {
setShow(false);
}}
style={style}
>
{children}
<StyledPopoverWrapper>

View File

@ -95,7 +95,6 @@ export const Popper = ({
};
});
// @ts-ignore
// @ts-ignore
return (
<ClickAwayListener

View File

@ -19,18 +19,11 @@ const border_radius_map: Record<PopoverContainerProps['direction'], string> = {
export const PopoverContainer = styled('div')<
Pick<PopoverContainerProps, 'direction'>
>(({ theme, direction, style }) => {
return '';
// const shadow = theme.affine.shadows.shadow1;
// const white = theme.affine.palette.white;
//
// const borderRadius =
// border_radius_map[direction] || border_radius_map['left-top'];
// return {
// boxShadow: shadow,
// borderRadius: borderRadius,
// padding: '8px 4px',
// backgroundColor: white,
// ...style,
// };
>(({ direction, style }) => {
const borderRadius =
border_radius_map[direction] || border_radius_map['left-top'];
return {
borderRadius: borderRadius,
...style,
};
});

View File

@ -26,14 +26,14 @@ export const placementToContainerDirection: Record<
};
const useTooltipStyle = (): CSSProperties => {
const theme = useTheme();
return {};
// return {
// backgroundColor: theme.affine.palette.icons,
// color: theme.affine.palette.white,
// ...theme.affine.typography.tooltip,
// padding: '4px 8px',
// };
const { theme } = useTheme();
return {
boxShadow: '1px 1px 4px rgba(0, 0, 0, 0.14)',
padding: '4px 12px',
backgroundColor: theme.colors.highlight,
color: '#fff',
fontSize: theme.font.xs,
};
};
export const Tooltip = (

View File

@ -1,7 +1,7 @@
import type { ReactNode } from 'react';
import { useRef, useState, useEffect } from 'react';
import { styled } from '@/styles';
import { PaperIcon, EdgelessIcon } from '../components/Header/icons';
import { PaperIcon, EdgelessIcon } from '@/components/Header/icons';
export const StyledHeader = styled('div')({
height: '60px',
width: '100vw',

View File

@ -2,7 +2,7 @@ import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import { styled, useTheme } from '@/styles';
import { Header } from '@/components/Header';
import { FAQ } from '@/components/faq';
import '@/components/simple-counter';
const StyledEditorContainer = styled('div')(({ theme }) => {
@ -56,6 +56,7 @@ const Home: NextPage = () => {
{/*>*/}
{/* auto*/}
{/*</button>*/}
<FAQ />
</StyledPage>
);
};

View File

@ -8,9 +8,15 @@ export const lightTheme: AffineTheme = {
disabled: '#9096A5',
background: '#fff',
},
font: {
xs: '12px',
sm: '16px',
base: '18px',
},
};
export const darkTheme: AffineTheme = {
...lightTheme,
colors: {
primary: '#fff',
highlight: '#7389FD',

View File

@ -18,6 +18,11 @@ export interface AffineTheme {
disabled: string;
background: string;
};
font: {
xs: string; // tiny
sm: string; // small
base: string;
};
}
declare module '@emotion/react' {