mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-02 18:09:58 +08:00
feat: initial style of workspace slide bar
This commit is contained in:
@@ -81,9 +81,15 @@ const PopoverContent = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const BrowserWarning = ({ onClose }: { onClose: () => void }) => {
|
||||
const BrowserWarning = ({
|
||||
show,
|
||||
onClose,
|
||||
}: {
|
||||
show: boolean;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
return (
|
||||
<StyledBrowserWarning>
|
||||
<StyledBrowserWarning show={show}>
|
||||
{getWarningMessage()}
|
||||
<StyledCloseButton onClick={onClose}>
|
||||
<CloseIcon />
|
||||
@@ -101,8 +107,10 @@ export const Header = () => {
|
||||
const { editor } = useEditor();
|
||||
|
||||
useEffect(() => {
|
||||
if (editor) {
|
||||
setTitle(editor.model.title || '');
|
||||
console.log('header', editor);
|
||||
|
||||
if (editor?.model) {
|
||||
setTitle(editor.model.title ?? '');
|
||||
editor.model.propsUpdated.on(() => {
|
||||
setTitle(editor.model.title);
|
||||
});
|
||||
@@ -111,19 +119,19 @@ export const Header = () => {
|
||||
return (
|
||||
<StyledHeaderContainer hasWarning={showWarning}>
|
||||
<BrowserWarning
|
||||
show={showWarning}
|
||||
onClose={() => {
|
||||
setShowWarning(false);
|
||||
}}
|
||||
/>
|
||||
<StyledHeader hasWarning={showWarning}>
|
||||
<StyledLogo
|
||||
data-testid="left-top-corner-logo"
|
||||
onClick={() => {
|
||||
contactModalHandler(true);
|
||||
}}
|
||||
>
|
||||
<LogoIcon />
|
||||
</StyledLogo>
|
||||
{/*<StyledLogo*/}
|
||||
{/* onClick={() => {*/}
|
||||
{/* contactModalHandler(true);*/}
|
||||
{/* }}*/}
|
||||
{/*>*/}
|
||||
{/* <LogoIcon />*/}
|
||||
{/*</StyledLogo>*/}
|
||||
{title ? (
|
||||
<StyledTitle
|
||||
onMouseEnter={() => {
|
||||
|
||||
@@ -13,11 +13,11 @@ export const StyledHeader = styled.div<{ hasWarning: boolean }>(
|
||||
({ hasWarning, theme }) => {
|
||||
return {
|
||||
height: '60px',
|
||||
width: '100vw',
|
||||
...displayFlex('space-between', 'center'),
|
||||
width: '100%',
|
||||
...displayFlex('flex-end', 'center'),
|
||||
background: 'var(--affine-page-background)',
|
||||
transition: 'background-color 0.5s',
|
||||
position: 'fixed',
|
||||
position: 'absolute',
|
||||
left: '0',
|
||||
top: hasWarning ? '36px' : '0',
|
||||
padding: '0 22px',
|
||||
@@ -97,19 +97,23 @@ export const IconButton = styled('div')(({ theme }) => {
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledBrowserWarning = styled.div(({ theme }) => {
|
||||
return {
|
||||
backgroundColor: theme.colors.warningBackground,
|
||||
color: theme.colors.warningColor,
|
||||
height: '36px',
|
||||
width: '100vw',
|
||||
fontSize: theme.font.sm,
|
||||
position: 'fixed',
|
||||
left: '0',
|
||||
top: '0',
|
||||
...displayFlex('center', 'center'),
|
||||
};
|
||||
});
|
||||
export const StyledBrowserWarning = styled.div<{ show: boolean }>(
|
||||
({ theme, show }) => {
|
||||
return {
|
||||
backgroundColor: theme.colors.warningBackground,
|
||||
color: theme.colors.warningColor,
|
||||
height: '36px',
|
||||
width: '100vw',
|
||||
fontSize: theme.font.sm,
|
||||
position: 'fixed',
|
||||
left: '0',
|
||||
top: '0',
|
||||
display: show ? 'flex' : 'none',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
export const StyledCloseButton = styled.div(({ theme }) => {
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { EditorContainer } from '@blocksuite/editor';
|
||||
import { createContext, useContext, useEffect, useState } from 'react';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { createWebsocketDocProvider, Store } from '@blocksuite/store';
|
||||
import { BlockSchema, createEditor } from '@blocksuite/editor';
|
||||
import '@blocksuite/blocks';
|
||||
|
||||
const getEditorParams = () => {
|
||||
const providers = [];
|
||||
const params = new URLSearchParams(location.search);
|
||||
if (params.get('syncModes') === 'websocket') {
|
||||
const WebsocketDocProvider = createWebsocketDocProvider(
|
||||
'ws://127.0.0.1:3000/collaboration/AFFiNE'
|
||||
);
|
||||
providers.push(WebsocketDocProvider);
|
||||
}
|
||||
|
||||
return {
|
||||
providers,
|
||||
};
|
||||
};
|
||||
|
||||
export const InitialEditor = ({
|
||||
setEditor,
|
||||
}: {
|
||||
setEditor: (editor: EditorContainer) => void;
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
const store = new Store({
|
||||
// ...getEditorParams(),
|
||||
});
|
||||
const space = store.createSpace('page0').register(BlockSchema);
|
||||
const editor = createEditor(space);
|
||||
setEditor(editor);
|
||||
}, [setEditor]);
|
||||
return <div>111</div>;
|
||||
};
|
||||
|
||||
export default InitialEditor;
|
||||
@@ -2,10 +2,11 @@ import { useEditor } from '@/components/editor-provider';
|
||||
import '@blocksuite/blocks';
|
||||
import '@blocksuite/blocks/style';
|
||||
import type { EditorContainer } from '@blocksuite/editor';
|
||||
import { createEditor } from '@blocksuite/editor';
|
||||
import { BlockSchema, createEditor } from '@blocksuite/editor';
|
||||
import { forwardRef, Suspense, useEffect, useRef } from 'react';
|
||||
import pkg from '../../package.json';
|
||||
import exampleMarkdown from './example-markdown';
|
||||
import { Store } from '@blocksuite/store';
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
const BlockSuiteEditor = forwardRef<EditorContainer>(({}, ref) => {
|
||||
@@ -14,7 +15,13 @@ const BlockSuiteEditor = forwardRef<EditorContainer>(({}, ref) => {
|
||||
if (!containerElement.current) {
|
||||
return;
|
||||
}
|
||||
const editor = createEditor();
|
||||
|
||||
const store = new Store({
|
||||
// ...getEditorParams(),
|
||||
});
|
||||
const space = store.createSpace('page0').register(BlockSchema);
|
||||
const editor = createEditor(space);
|
||||
|
||||
containerElement.current.appendChild(editor);
|
||||
if (ref) {
|
||||
if ('current' in ref) {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
export const Arrow = () => {
|
||||
return (
|
||||
<svg
|
||||
width="6"
|
||||
height="10"
|
||||
viewBox="0 0 6 10"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M0.354 9.22997C0.201333 9.0773 0.125 8.91764 0.125 8.75097C0.125 8.5843 0.201333 8.42464 0.354 8.27197L3.625 5.00097L0.354 1.72997C0.201333 1.5773 0.125 1.41764 0.125 1.25097C0.125 1.0843 0.201333 0.924636 0.354 0.771969C0.506667 0.619302 0.666333 0.542969 0.833 0.542969C0.999667 0.542969 1.15933 0.619302 1.312 0.771969L4.979 4.43897C5.06233 4.52164 5.125 4.61164 5.167 4.70897C5.20833 4.8063 5.229 4.90364 5.229 5.00097C5.229 5.0983 5.20833 5.19564 5.167 5.29297C5.125 5.3903 5.06233 5.4803 4.979 5.56297L1.312 9.22997C1.15933 9.38264 0.999667 9.45897 0.833 9.45897C0.666333 9.45897 0.506667 9.38264 0.354 9.22997Z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
StyledArrowButton,
|
||||
StyledListItem,
|
||||
StyledSliderBar,
|
||||
StyledSubListItem,
|
||||
StyledWrapper,
|
||||
} from './style';
|
||||
import { Arrow } from './icons';
|
||||
|
||||
export const WorkSpaceSliderBar = () => {
|
||||
const [show, setShow] = useState(false);
|
||||
return (
|
||||
<>
|
||||
|
||||
<StyledSliderBar show={show}>
|
||||
|
||||
<StyledListItem>Quick search</StyledListItem>
|
||||
<StyledListItem>All pages</StyledListItem>
|
||||
<StyledListItem>Favourites</StyledListItem>
|
||||
<StyledSubListItem>
|
||||
document 1, this is a paper icondocument 1
|
||||
</StyledSubListItem>
|
||||
<StyledSubListItem>document 2</StyledSubListItem>
|
||||
<StyledSubListItem>document 4</StyledSubListItem>
|
||||
<StyledListItem>Import</StyledListItem>
|
||||
<StyledListItem>Bin</StyledListItem>
|
||||
</StyledSliderBar>
|
||||
<StyledArrowButton
|
||||
isShow={show}
|
||||
onClick={() => {
|
||||
setShow(!show);
|
||||
}}
|
||||
>
|
||||
<Arrow />
|
||||
</StyledArrowButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default WorkSpaceSliderBar;
|
||||
@@ -0,0 +1,83 @@
|
||||
import { displayFlex, styled, textEllipsis } from '@/styles';
|
||||
|
||||
export const StyledSliderBar = styled.div<{ show: boolean }>(
|
||||
({ theme, show }) => {
|
||||
return {
|
||||
width: show ? '320px' : '0',
|
||||
height: '100vh',
|
||||
background: '#FBFBFC',
|
||||
boxShadow: theme.shadow.modal,
|
||||
transition: 'width .15s',
|
||||
position: 'relative',
|
||||
zIndex: theme.zIndex.modal,
|
||||
padding: show ? '24px 12px' : '24px 0',
|
||||
overflowX: 'hidden',
|
||||
};
|
||||
}
|
||||
);
|
||||
export const StyledWrapper = styled.div(() => {
|
||||
return {
|
||||
// padding: '24px 12px',
|
||||
// height: '100%',
|
||||
// overflowY: 'auto',
|
||||
};
|
||||
});
|
||||
export const StyledArrowButton = styled.button<{ isShow: boolean }>(
|
||||
({ theme, isShow }) => {
|
||||
return {
|
||||
width: '32px',
|
||||
height: '32px',
|
||||
...displayFlex('center', 'center'),
|
||||
color: theme.colors.primaryColor,
|
||||
backgroundColor: theme.colors.hoverBackground,
|
||||
borderRadius: '50%',
|
||||
transition: 'all .15s',
|
||||
position: 'fixed',
|
||||
top: '34px',
|
||||
left: isShow ? '304px' : '-8px',
|
||||
zIndex: theme.zIndex.modal,
|
||||
svg: {
|
||||
transform: isShow ? 'rotate(180deg)' : 'unset',
|
||||
},
|
||||
':hover': {
|
||||
color: '#fff',
|
||||
backgroundColor: theme.colors.primaryColor,
|
||||
},
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
export const StyledListItem = styled.button(({ theme }) => {
|
||||
return {
|
||||
width: '296px',
|
||||
height: '32px',
|
||||
marginTop: '12px',
|
||||
fontSize: theme.font.sm,
|
||||
color: theme.colors.popoverColor,
|
||||
...displayFlex('flex-start', 'center'),
|
||||
':hover': {
|
||||
color: theme.colors.primaryColor,
|
||||
backgroundColor: theme.colors.hoverBackground,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledSubListItem = styled.button(({ theme }) => {
|
||||
return {
|
||||
width: '296px',
|
||||
height: '32px',
|
||||
marginTop: '4px',
|
||||
fontSize: theme.font.sm,
|
||||
fontWeight: 400,
|
||||
color: theme.colors.popoverColor,
|
||||
paddingLeft: '45px',
|
||||
lineHeight: '32px',
|
||||
textAlign: 'start',
|
||||
...textEllipsis(1),
|
||||
':hover': {
|
||||
color: theme.colors.primaryColor,
|
||||
backgroundColor: theme.colors.hoverBackground,
|
||||
fontWeight: 500,
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -6,26 +6,57 @@ import './temporary.css';
|
||||
import { EditorProvider } from '@/components/editor-provider';
|
||||
import { ModalProvider } from '@/components/global-modal-provider';
|
||||
import { Logger } from '@toeverything/pathfinder-logger';
|
||||
|
||||
import { WorkSpaceSliderBar } from '@/components/workspace-slider-bar';
|
||||
import '@fontsource/space-mono';
|
||||
import '@fontsource/poppins';
|
||||
import '../utils/print-build-info';
|
||||
import { styled } from '@/styles';
|
||||
import type { ReactNode, PropsWithChildren, FC } from 'react';
|
||||
import { cloneElement } from 'react';
|
||||
|
||||
const ThemeProvider = dynamic(() => import('@/styles/themeProvider'), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const StyledPage = styled('div')(({ theme }) => {
|
||||
return {
|
||||
height: '100vh',
|
||||
backgroundColor: theme.colors.pageBackground,
|
||||
transition: 'background-color .5s',
|
||||
display: 'flex',
|
||||
};
|
||||
});
|
||||
|
||||
const ProviderComposer: FC<
|
||||
PropsWithChildren<{
|
||||
contexts: any;
|
||||
}>
|
||||
> = ({ contexts, children }) =>
|
||||
contexts.reduceRight(
|
||||
(kids: ReactNode, parent: any) =>
|
||||
cloneElement(parent, {
|
||||
children: kids,
|
||||
}),
|
||||
children
|
||||
);
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<>
|
||||
<Logger />
|
||||
<EditorProvider>
|
||||
<ThemeProvider>
|
||||
<ModalProvider>
|
||||
<Component {...pageProps} />
|
||||
</ModalProvider>
|
||||
</ThemeProvider>
|
||||
</EditorProvider>
|
||||
<ProviderComposer
|
||||
contexts={[
|
||||
<EditorProvider key="EditorProvider" />,
|
||||
<ThemeProvider key="ThemeProvider" />,
|
||||
<ModalProvider key="ModalProvider" />,
|
||||
]}
|
||||
>
|
||||
<StyledPage>
|
||||
{/*<TestEditor />*/}
|
||||
<WorkSpaceSliderBar />
|
||||
<Component {...pageProps} />
|
||||
</StyledPage>
|
||||
</ProviderComposer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ const StyledEditorContainer = styled('div')(({ theme }) => {
|
||||
};
|
||||
});
|
||||
|
||||
const StyledPage = styled('div')(({ theme }) => {
|
||||
const StyledWrapper = styled('div')(({ theme }) => {
|
||||
return {
|
||||
height: '100vh',
|
||||
backgroundColor: theme.colors.pageBackground,
|
||||
transition: 'background-color .5s',
|
||||
flexGrow: 1,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -51,7 +52,7 @@ const DynamicEditor = dynamic(() => import('../components/editor'), {
|
||||
|
||||
const Home: NextPage = () => {
|
||||
return (
|
||||
<StyledPage>
|
||||
<StyledWrapper>
|
||||
<Header />
|
||||
<MobileModal />
|
||||
<StyledEditorContainer>
|
||||
@@ -59,7 +60,7 @@ const Home: NextPage = () => {
|
||||
</StyledEditorContainer>
|
||||
<FAQ />
|
||||
<EdgelessToolbar />
|
||||
</StyledPage>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -82,3 +82,21 @@ export const fixedCenter = ({
|
||||
})`,
|
||||
};
|
||||
};
|
||||
|
||||
export const textEllipsis = (lineNum: number = 1): CSSProperties => {
|
||||
if (lineNum > 1) {
|
||||
return {
|
||||
display: '-webkit-box',
|
||||
wordBreak: 'break-all',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
WebkitLineClamp: '$lineNum', //需要显示的行数
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
};
|
||||
}
|
||||
return {
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user