feat: responsive ui above 640px (#1741)

This commit is contained in:
Peng Xiao
2023-03-30 20:12:18 -05:00
committed by GitHub
parent bdb1264f09
commit c55d61a641
22 changed files with 443 additions and 190 deletions
@@ -5,7 +5,7 @@ export const StyledSettingContainer = styled('div')(() => {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
padding: '48px 0 0 48px', padding: '48px 0 0 48px',
height: 'calc(100vh - 60px)', height: 'calc(100vh - 48px)',
}; };
}); });
@@ -18,7 +18,7 @@ export const PageListEmpty = (props: { listType?: string }) => {
}; };
return ( return (
<div style={{ height: 'calc(100% - 60px)' }}> <div style={{ height: 'calc(100% - 48px)' }}>
<Empty description={getEmptyDescription()} /> <Empty description={getEmptyDescription()} />
</div> </div>
); );
@@ -16,11 +16,7 @@ import {
PageIcon, PageIcon,
} from '@blocksuite/icons'; } from '@blocksuite/icons';
import type { PageMeta } from '@blocksuite/store'; import type { PageMeta } from '@blocksuite/store';
import { import { useMediaQuery, useTheme } from '@mui/material';
useMediaQuery,
useTheme as useMuiTheme,
useTheme,
} from '@mui/material';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import type React from 'react'; import type React from 'react';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
@@ -106,7 +102,7 @@ export const PageList: React.FC<PageListProps> = ({
const pageList = usePageMeta(blockSuiteWorkspace); const pageList = usePageMeta(blockSuiteWorkspace);
const helper = usePageMetaHelper(blockSuiteWorkspace); const helper = usePageMetaHelper(blockSuiteWorkspace);
const { t } = useTranslation(); const { t } = useTranslation();
const theme = useMuiTheme(); const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.up('sm')); const matches = useMediaQuery(theme.breakpoints.up('sm'));
const isTrash = listType === 'trash'; const isTrash = listType === 'trash';
const record = useAtomValue(workspacePreferredModeAtom); const record = useAtomValue(workspacePreferredModeAtom);
@@ -3,7 +3,7 @@ import { TableRow } from '@affine/component';
export const StyledTableContainer = styled('div')(({ theme }) => { export const StyledTableContainer = styled('div')(({ theme }) => {
return { return {
height: 'calc(100vh - 60px)', height: 'calc(100vh - 48px)',
padding: '78px 72px', padding: '78px 72px',
overflowY: 'auto', overflowY: 'auto',
[theme.breakpoints.down('sm')]: { [theme.breakpoints.down('sm')]: {
@@ -6,16 +6,22 @@ import {
} from '@affine/component'; } from '@affine/component';
export const StyledHeaderContainer = styled('div')<{ hasWarning: boolean }>( export const StyledHeaderContainer = styled('div')<{ hasWarning: boolean }>(
({ hasWarning }) => { ({ theme, hasWarning }) => {
return { return {
height: hasWarning ? '96px' : '48px', height: hasWarning ? '96px' : '48px',
flexShrink: 0,
position: 'sticky',
top: 0,
background: theme.colors.pageBackground,
zIndex: 1,
}; };
} }
); );
export const StyledHeader = styled('div')<{ hasWarning: boolean }>( export const StyledHeader = styled('div')<{ hasWarning: boolean }>(
({ theme }) => { ({ theme }) => {
return { return {
height: '60px', flexShrink: 0,
height: '48px',
width: '100%', width: '100%',
padding: '0 20px', padding: '0 20px',
...displayFlex('space-between', 'center'), ...displayFlex('space-between', 'center'),
@@ -28,7 +34,7 @@ export const StyledHeader = styled('div')<{ hasWarning: boolean }>(
); );
export const StyledTitleContainer = styled('div')(({ theme }) => ({ export const StyledTitleContainer = styled('div')(({ theme }) => ({
width: '720px', width: '100%',
height: '100%', height: '100%',
margin: 'auto', margin: 'auto',
@@ -37,15 +43,24 @@ export const StyledTitleContainer = styled('div')(({ theme }) => ({
fontSize: theme.font.base, fontSize: theme.font.base,
})); }));
export const StyledTitle = styled('div')(() => { export const StyledTitle = styled('div')(({ theme }) => {
return { return {
maxWidth: '620px', maxWidth: '620px',
[theme.breakpoints.down('lg')]: {
maxWidth: '480px',
},
[theme.breakpoints.down('md')]: {
maxWidth: '240px',
},
[theme.breakpoints.down('sm')]: {
maxWidth: '180px',
},
transition: 'max-width .15s',
...textEllipsis(1), ...textEllipsis(1),
}; };
}); });
export const StyledTitleWrapper = styled('div')({ export const StyledTitleWrapper = styled('div')({
maxWidth: '720px',
height: '100%', height: '100%',
position: 'relative', position: 'relative',
...displayFlex('center', 'center'), ...displayFlex('center', 'center'),
@@ -132,7 +147,7 @@ export const StyledQuickSearchTipButton = styled('div')(({ theme }) => {
...displayFlex('center', 'center'), ...displayFlex('center', 'center'),
marginTop: '12px', marginTop: '12px',
color: '#FFFFFF', color: '#FFFFFF',
width: '60px', width: '48px',
height: ' 26px', height: ' 26px',
fontSize: theme.font.sm, fontSize: theme.font.sm,
lineHeight: '22px', lineHeight: '22px',
@@ -68,7 +68,7 @@ export const PageDetailEditor: React.FC<PageDetailEditorProps> = ({
</BlockSuiteEditorHeader> </BlockSuiteEditorHeader>
<Editor <Editor
style={{ style={{
height: 'calc(100% - 60px)', height: 'calc(100% - 48px)',
}} }}
key={pageId} key={pageId}
blockSuiteWorkspace={blockSuiteWorkspace} blockSuiteWorkspace={blockSuiteWorkspace}
@@ -2,7 +2,6 @@ import { displayFlex, textEllipsis } from '@affine/component';
import { styled } from '@affine/component'; import { styled } from '@affine/component';
export const StyledSelectorContainer = styled('div')(({ theme }) => { export const StyledSelectorContainer = styled('div')(({ theme }) => {
return { return {
marginTop: '4px',
height: '58px', height: '58px',
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
@@ -10,7 +9,6 @@ export const StyledSelectorContainer = styled('div')(({ theme }) => {
marginBottom: '16px', marginBottom: '16px',
borderRadius: '8px', borderRadius: '8px',
color: theme.colors.textColor, color: theme.colors.textColor,
position: 'relative',
':hover': { ':hover': {
cursor: 'pointer', cursor: 'pointer',
background: theme.colors.hoverBackground, background: theme.colors.hoverBackground,
@@ -8,10 +8,15 @@ import {
SettingsIcon, SettingsIcon,
} from '@blocksuite/icons'; } from '@blocksuite/icons';
import type { Page, PageMeta } from '@blocksuite/store'; import type { Page, PageMeta } from '@blocksuite/store';
import { useMediaQuery, useTheme } from '@mui/material';
import type React from 'react'; import type React from 'react';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useSidebarStatus } from '../../../hooks/affine/use-sidebar-status'; import {
useSidebarResizing,
useSidebarStatus,
useSidebarWidth,
} from '../../../hooks/affine/use-sidebar-status';
import { usePageMeta } from '../../../hooks/use-page-meta'; import { usePageMeta } from '../../../hooks/use-page-meta';
import type { AllWorkspace } from '../../../shared'; import type { AllWorkspace } from '../../../shared';
import { SidebarSwitch } from '../../affine/sidebar-switch'; import { SidebarSwitch } from '../../affine/sidebar-switch';
@@ -23,8 +28,12 @@ import {
StyledLink, StyledLink,
StyledNewPageButton, StyledNewPageButton,
StyledSidebarSwitchWrapper, StyledSidebarSwitchWrapper,
StyledSlidebarWrapper,
StyledSliderBar, StyledSliderBar,
StyledSliderBarInnerWrapper,
StyledSliderBarWrapper,
StyledSliderModalBackground,
StyledSliderResizer,
StyledSliderResizerInner,
} from './style'; } from './style';
import { WorkspaceSelector } from './WorkspaceSelector'; import { WorkspaceSelector } from './WorkspaceSelector';
@@ -65,114 +74,171 @@ export const WorkSpaceSliderBar: React.FC<WorkSpaceSliderBarProps> = ({
}) => { }) => {
const currentWorkspaceId = currentWorkspace?.id || null; const currentWorkspaceId = currentWorkspace?.id || null;
const { t } = useTranslation(); const { t } = useTranslation();
const [sidebarOpen] = useSidebarStatus(); const [sidebarOpen, setSidebarOpen] = useSidebarStatus();
const pageMeta = usePageMeta(currentWorkspace?.blockSuiteWorkspace ?? null); const pageMeta = usePageMeta(currentWorkspace?.blockSuiteWorkspace ?? null);
const onClickNewPage = useCallback(async () => { const onClickNewPage = useCallback(async () => {
const page = await createPage(); const page = await createPage();
openPage(page.id); openPage(page.id);
}, [createPage, openPage]); }, [createPage, openPage]);
const theme = useTheme();
const floatingSlider = useMediaQuery(theme.breakpoints.down('md'));
const [sliderWidth, setSliderWidth] = useSidebarWidth();
const [isResizing, setIsResizing] = useSidebarResizing();
const show = isPublicWorkspace ? false : sidebarOpen;
const actualWidth = show
? floatingSlider
? 'calc(10vw + 400px)'
: sliderWidth
: 0;
const onResizeStart = useCallback(() => {
let resized = false;
function onMouseMove(e: MouseEvent) {
const newWidth = Math.min(480, Math.max(e.clientX, 256));
setSliderWidth(newWidth);
setIsResizing(true);
resized = true;
}
document.addEventListener('mousemove', onMouseMove);
document.addEventListener(
'mouseup',
() => {
// if not resized, toggle sidebar
if (!resized) {
setSidebarOpen(o => !o);
}
setIsResizing(false);
document.removeEventListener('mousemove', onMouseMove);
},
{ once: true }
);
}, [setIsResizing, setSidebarOpen, setSliderWidth]);
return ( return (
<> <>
<StyledSliderBar show={isPublicWorkspace ? false : sidebarOpen}> <StyledSliderBarWrapper data-testid="sliderBar-root">
<StyledSidebarSwitchWrapper> <StyledSliderBar
<SidebarSwitch resizing={isResizing}
visible={sidebarOpen} floating={floatingSlider}
tooltipContent={t('Collapse sidebar')} style={{ width: actualWidth }}
testid="sliderBar-arrowButton-collapse" show={show}
/>
</StyledSidebarSwitchWrapper>
<StyledSlidebarWrapper data-testid="sliderBar">
<WorkspaceSelector
currentWorkspace={currentWorkspace}
onClick={onOpenWorkspaceListModal}
/>
<ChangeLog />
<StyledListItem
data-testid="slider-bar-quick-search-button"
onClick={useCallback(() => {
onOpenQuickSearchModal();
}, [onOpenQuickSearchModal])}
>
<SearchIcon />
{t('Quick search')}
</StyledListItem>
<StyledListItem
active={
currentPath ===
(currentWorkspaceId && paths.setting(currentWorkspaceId))
}
data-testid="slider-bar-workspace-setting-button"
style={{
marginBottom: '16px',
}}
>
<StyledLink
href={{
pathname:
currentWorkspaceId && paths.setting(currentWorkspaceId),
}}
>
<SettingsIcon />
{t('Workspace Settings')}
</StyledLink>
</StyledListItem>
<StyledListItem
active={
currentPath ===
(currentWorkspaceId && paths.all(currentWorkspaceId))
}
>
<StyledLink
href={{
pathname: currentWorkspaceId && paths.all(currentWorkspaceId),
}}
>
<FolderIcon />
<span data-testid="all-pages">{t('All pages')}</span>
</StyledLink>
</StyledListItem>
<Favorite
currentPath={currentPath}
paths={paths}
currentPageId={currentPageId}
openPage={openPage}
currentWorkspace={currentWorkspace}
/>
{config.enableSubpage && !!currentWorkspace && (
<Pivots
currentWorkspace={currentWorkspace}
openPage={openPage}
allMetas={pageMeta}
/>
)}
<StyledListItem
active={
currentPath ===
(currentWorkspaceId && paths.trash(currentWorkspaceId))
}
style={{
marginTop: '16px',
}}
>
<StyledLink
href={{
pathname: currentWorkspaceId && paths.trash(currentWorkspaceId),
}}
>
<DeleteTemporarilyIcon /> {t('Trash')}
</StyledLink>
</StyledListItem>
</StyledSlidebarWrapper>
<StyledNewPageButton
data-testid="new-page-button"
onClick={onClickNewPage}
> >
<PlusIcon /> {t('New Page')} <StyledSidebarSwitchWrapper>
</StyledNewPageButton> <SidebarSwitch
</StyledSliderBar> visible={sidebarOpen}
tooltipContent={t('Collapse sidebar')}
testid="sliderBar-arrowButton-collapse"
/>
</StyledSidebarSwitchWrapper>
<StyledSliderBarInnerWrapper data-testid="sliderBar-inner">
<WorkspaceSelector
currentWorkspace={currentWorkspace}
onClick={onOpenWorkspaceListModal}
/>
<ChangeLog />
<StyledListItem
data-testid="slider-bar-quick-search-button"
onClick={useCallback(() => {
onOpenQuickSearchModal();
}, [onOpenQuickSearchModal])}
>
<SearchIcon />
{t('Quick search')}
</StyledListItem>
<StyledListItem
active={
currentPath ===
(currentWorkspaceId && paths.setting(currentWorkspaceId))
}
data-testid="slider-bar-workspace-setting-button"
style={{
marginBottom: '16px',
}}
>
<StyledLink
href={{
pathname:
currentWorkspaceId && paths.setting(currentWorkspaceId),
}}
>
<SettingsIcon />
{t('Workspace Settings')}
</StyledLink>
</StyledListItem>
<StyledListItem
active={
currentPath ===
(currentWorkspaceId && paths.all(currentWorkspaceId))
}
>
<StyledLink
href={{
pathname: currentWorkspaceId && paths.all(currentWorkspaceId),
}}
>
<FolderIcon />
<span data-testid="all-pages">{t('All pages')}</span>
</StyledLink>
</StyledListItem>
<Favorite
currentPath={currentPath}
paths={paths}
currentPageId={currentPageId}
openPage={openPage}
currentWorkspace={currentWorkspace}
/>
{config.enableSubpage && !!currentWorkspace && (
<Pivots
currentWorkspace={currentWorkspace}
openPage={openPage}
allMetas={pageMeta}
/>
)}
<StyledListItem
active={
currentPath ===
(currentWorkspaceId && paths.trash(currentWorkspaceId))
}
style={{
marginTop: '16px',
}}
>
<StyledLink
href={{
pathname:
currentWorkspaceId && paths.trash(currentWorkspaceId),
}}
>
<DeleteTemporarilyIcon /> {t('Trash')}
</StyledLink>
</StyledListItem>
</StyledSliderBarInnerWrapper>
<StyledNewPageButton
data-testid="new-page-button"
onClick={onClickNewPage}
>
<PlusIcon /> {t('New Page')}
</StyledNewPageButton>
</StyledSliderBar>
{!floatingSlider && sidebarOpen && (
<StyledSliderResizer
data-testid="sliderBar-resizer"
isResizing={isResizing}
onMouseDown={onResizeStart}
>
<StyledSliderResizerInner isResizing={isResizing} />
</StyledSliderResizer>
)}
</StyledSliderBarWrapper>
<StyledSliderModalBackground
data-testid="sliderBar-modalBackground"
active={floatingSlider && sidebarOpen}
onClick={() => setSidebarOpen(false)}
/>
</> </>
); );
}; };
@@ -1,36 +1,45 @@
import { displayFlex, styled } from '@affine/component'; import { displayFlex, styled } from '@affine/component';
import Link from 'next/link'; import Link from 'next/link';
export const StyledSliderBar = styled('div')<{ show: boolean }>(
({ theme, show }) => { export const StyledSliderBarWrapper = styled('div')(() => {
return { return {
width: show ? '256px' : '0', height: '100%',
whiteSpace: 'nowrap', width: 'auto',
height: '100vh', position: 'relative',
minHeight: '450px', };
background: theme.colors.hubBackground, });
boxShadow: theme.shadow.popover,
transition: 'width .15s, padding .15s', export const StyledSliderBar = styled('div')<{
position: 'relative', resizing: boolean;
zIndex: theme.zIndex.modal, show: boolean;
padding: show ? '0 4px' : '0', floating: boolean;
flexShrink: 0, }>(({ theme, show, floating, resizing }) => {
display: 'flex', return {
flexDirection: 'column', whiteSpace: 'nowrap',
overflow: 'hidden', height: '100%',
[theme.breakpoints.down('sm')]: { background: theme.colors.hubBackground,
position: 'absolute', zIndex: theme.zIndex.modal,
}, transition: !resizing ? 'width .15s, padding .15s' : '',
}; padding: show ? '0 4px' : '0',
} flexShrink: 0,
); display: 'flex',
flexDirection: 'column',
overflow: 'hidden',
position: floating ? 'absolute' : 'relative',
maxWidth: floating ? undefined : 'calc(100vw - 698px)',
borderRight: '1px solid',
borderColor: theme.colors.borderColor,
};
});
export const StyledSidebarSwitchWrapper = styled('div')(() => { export const StyledSidebarSwitchWrapper = styled('div')(() => {
return { return {
height: '48px', height: '48px',
flexShrink: 0,
padding: '0 16px', padding: '0 16px',
...displayFlex('flex-start', 'center'), ...displayFlex('flex-start', 'center'),
}; };
}); });
export const StyledSlidebarWrapper = styled('div')(() => { export const StyledSliderBarInnerWrapper = styled('div')(() => {
return { return {
flexGrow: 1, flexGrow: 1,
overflowX: 'hidden', overflowX: 'hidden',
@@ -70,3 +79,52 @@ export const StyledNewPageButton = styled('button')(({ theme }) => {
}, },
}; };
}); });
export const StyledSliderModalBackground = styled('div')<{ active: boolean }>(
({ theme, active }) => {
return {
transition: 'opacity .15s',
pointerEvents: active ? 'auto' : 'none',
opacity: active ? 1 : 0,
display: active ? 'block' : 'none',
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: theme.zIndex.modal - 1,
background: theme.colors.modalBackground,
};
}
);
export const StyledSliderResizer = styled('div')<{ isResizing: boolean }>(
({ theme }) => {
return {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
width: '12px',
transform: 'translateX(50%)',
cursor: 'col-resize',
zIndex: theme.zIndex.modal + 1,
userSelect: 'none',
':hover > *': {
background: 'rgba(0, 0, 0, 0.1)',
},
};
}
);
export const StyledSliderResizerInner = styled('div')<{ isResizing: boolean }>(
({ isResizing }) => {
return {
transition: 'background .15s .1s',
position: 'absolute',
top: 0,
right: '50%',
bottom: 0,
transform: 'translateX(0.5px)',
width: '2px',
background: isResizing ? 'rgba(0, 0, 0, 0.1)' : 'transparent',
};
}
);
@@ -1,8 +1,18 @@
import { useAtom } from 'jotai'; import { atom, useAtom } from 'jotai';
import { atomWithStorage } from 'jotai/utils'; import { atomWithStorage } from 'jotai/utils';
const sideBarOpenAtom = atomWithStorage('sidebarOpen', true); const sideBarOpenAtom = atomWithStorage('sidebarOpen', true);
const sideBarWidthAtom = atomWithStorage('sidebarWidth', 256);
const sidebarResizingAtom = atom(false);
export function useSidebarStatus() { export function useSidebarStatus() {
return useAtom(sideBarOpenAtom); return useAtom(sideBarOpenAtom);
} }
export function useSidebarWidth() {
return useAtom(sideBarWidthAtom);
}
export function useSidebarResizing() {
return useAtom(sidebarResizingAtom);
}
+28 -19
View File
@@ -26,6 +26,7 @@ import { HelpIsland } from '../components/pure/help-island';
import { PageLoading } from '../components/pure/loading'; import { PageLoading } from '../components/pure/loading';
import WorkSpaceSliderBar from '../components/pure/workspace-slider-bar'; import WorkSpaceSliderBar from '../components/pure/workspace-slider-bar';
import { useAffineRefreshAuthToken } from '../hooks/affine/use-affine-refresh-auth-token'; import { useAffineRefreshAuthToken } from '../hooks/affine/use-affine-refresh-auth-token';
import { useSidebarResizing } from '../hooks/affine/use-sidebar-status';
import { useCurrentPageId } from '../hooks/current/use-current-page-id'; import { useCurrentPageId } from '../hooks/current/use-current-page-id';
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace'; import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
import { useBlockSuiteWorkspaceHelper } from '../hooks/use-blocksuite-workspace-helper'; import { useBlockSuiteWorkspaceHelper } from '../hooks/use-blocksuite-workspace-helper';
@@ -37,7 +38,12 @@ import { WorkspacePlugins } from '../plugins';
import { ModalProvider } from '../providers/ModalProvider'; import { ModalProvider } from '../providers/ModalProvider';
import type { AllWorkspace } from '../shared'; import type { AllWorkspace } from '../shared';
import { pathGenerator, publicPathGenerator } from '../shared'; import { pathGenerator, publicPathGenerator } from '../shared';
import { StyledPage, StyledToolWrapper, StyledWrapper } from './styles'; import {
MainContainer,
MainContainerWrapper,
StyledPage,
StyledToolWrapper,
} from './styles';
declare global { declare global {
// eslint-disable-next-line no-var // eslint-disable-next-line no-var
@@ -246,6 +252,7 @@ export const WorkspaceLayoutInner: React.FC<React.PropsWithChildren> = ({
const handleOpenQuickSearchModal = useCallback(() => { const handleOpenQuickSearchModal = useCallback(() => {
setOpenQuickSearchModalAtom(true); setOpenQuickSearchModalAtom(true);
}, [setOpenQuickSearchModalAtom]); }, [setOpenQuickSearchModalAtom]);
const [resizingSidebar] = useSidebarResizing();
const lock = useAtomValue(workspaceLockAtom); const lock = useAtomValue(workspaceLockAtom);
if (lock) { if (lock) {
return <PageLoading />; return <PageLoading />;
@@ -256,7 +263,7 @@ export const WorkspaceLayoutInner: React.FC<React.PropsWithChildren> = ({
<Head> <Head>
<title>{title}</title> <title>{title}</title>
</Head> </Head>
<StyledPage> <StyledPage resizing={resizingSidebar}>
<WorkSpaceSliderBar <WorkSpaceSliderBar
isPublicWorkspace={isPublicWorkspace} isPublicWorkspace={isPublicWorkspace}
onOpenQuickSearchModal={handleOpenQuickSearchModal} onOpenQuickSearchModal={handleOpenQuickSearchModal}
@@ -268,23 +275,25 @@ export const WorkspaceLayoutInner: React.FC<React.PropsWithChildren> = ({
currentPath={router.asPath.split('?')[0]} currentPath={router.asPath.split('?')[0]}
paths={isPublicWorkspace ? publicPathGenerator : pathGenerator} paths={isPublicWorkspace ? publicPathGenerator : pathGenerator}
/> />
<StyledWrapper className="main-container"> <MainContainerWrapper>
<AffineWorkspaceEffect /> <MainContainer className="main-container">
{children} <AffineWorkspaceEffect />
<StyledToolWrapper> {children}
{/* fixme(himself65): remove this */} <StyledToolWrapper>
<div id="toolWrapper" style={{ marginBottom: '12px' }}> {/* fixme(himself65): remove this */}
{/* Slot for block hub */} <div id="toolWrapper" style={{ marginBottom: '12px' }}>
</div> {/* Slot for block hub */}
{!isPublicWorkspace && ( </div>
<HelpIsland {!isPublicWorkspace && (
showList={ <HelpIsland
router.query.pageId ? undefined : ['whatNew', 'contact'] showList={
} router.query.pageId ? undefined : ['whatNew', 'contact']
/> }
)} />
</StyledToolWrapper> )}
</StyledWrapper> </StyledToolWrapper>
</MainContainer>
</MainContainerWrapper>
</StyledPage> </StyledPage>
<QuickSearch /> <QuickSearch />
</> </>
@@ -14,7 +14,7 @@ import {
} from '../atoms/public-workspace'; } from '../atoms/public-workspace';
import { StyledTableContainer } from '../components/blocksuite/block-suite-page-list/page-list/styles'; import { StyledTableContainer } from '../components/blocksuite/block-suite-page-list/page-list/styles';
import { useRouterTitle } from '../hooks/use-router-title'; import { useRouterTitle } from '../hooks/use-router-title';
import { StyledPage, StyledWrapper } from './styles'; import { MainContainer, StyledPage } from './styles';
const QuickSearchModal = dynamic( const QuickSearchModal = dynamic(
() => import('../components/pure/quick-search-modal') () => import('../components/pure/quick-search-modal')
@@ -46,9 +46,9 @@ const PublicWorkspaceLayoutInner: React.FC<React.PropsWithChildren> = props => {
<title>{title}</title> <title>{title}</title>
</Head> </Head>
<StyledPage> <StyledPage>
<StyledWrapper className="main-container"> <MainContainer className="main-container">
{props.children} {props.children}
</StyledWrapper> </MainContainer>
<Suspense fallback=""> <Suspense fallback="">
{/* `publicBlockSuiteAtom` is available only when `publicWorkspaceIdAtom` loaded */} {/* `publicBlockSuiteAtom` is available only when `publicWorkspaceIdAtom` loaded */}
{workspaceId && <PublicQuickSearch />} {workspaceId && <PublicQuickSearch />}
+40 -11
View File
@@ -1,15 +1,21 @@
import { styled } from '@affine/component'; import { styled } from '@affine/component';
export const StyledPage = styled('div')(({ theme }) => { export const StyledPage = styled('div')<{ resizing?: boolean }>(
return { ({ theme, resizing }) => {
height: '100vh', return {
minHeight: '450px', cursor: resizing ? 'col-resize' : 'default',
backgroundColor: theme.colors.pageBackground, height: '100vh',
transition: 'background-color .5s', backgroundColor: theme.colors.pageBackground,
display: 'flex', transition: 'background-color .5s',
flexGrow: '1', display: 'flex',
}; flexGrow: '1',
}); '--affine-editor-width': '686px',
[theme.breakpoints.down('sm')]: {
'--affine-editor-width': '550px',
},
};
}
);
export const StyledWrapper = styled('div')(() => { export const StyledWrapper = styled('div')(() => {
return { return {
@@ -19,11 +25,34 @@ export const StyledWrapper = styled('div')(() => {
}; };
}); });
export const MainContainerWrapper = styled('div')(({ theme }) => {
return {
display: 'flex',
flexGrow: 1,
position: 'relative',
maxWidth: '100vw',
overflow: 'auto',
};
});
export const MainContainer = styled('div')(({ theme }) => {
return {
position: 'relative',
flexGrow: 1,
[theme.breakpoints.up('md')]: {
minWidth: '686px',
},
};
});
export const StyledToolWrapper = styled('div')(({ theme }) => { export const StyledToolWrapper = styled('div')(({ theme }) => {
return { return {
position: 'fixed', position: 'fixed',
right: '30px', right: 'calc((100vw - 640px) * 3 / 19 + 5px)',
bottom: '30px', bottom: '30px',
zIndex: theme.zIndex.popover, zIndex: theme.zIndex.popover,
[theme.breakpoints.down('md')]: {
right: '30px',
},
}; };
}); });
@@ -24,7 +24,7 @@ import { initPage } from '../../../utils';
export const NavContainer = styled('div')(({ theme }) => { export const NavContainer = styled('div')(({ theme }) => {
return { return {
width: '100vw', width: '100vw',
height: '60px', height: '48px',
...displayFlex('space-between', 'center'), ...displayFlex('space-between', 'center'),
backgroundColor: theme.colors.pageBackground, backgroundColor: theme.colors.pageBackground,
}; };
+4 -1
View File
@@ -191,15 +191,18 @@ input[type='number']::-webkit-outer-spin-button {
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 0 2rem;
} }
.affine-default-page-block-title-container { .affine-default-page-block-title-container {
margin-top: 78px; margin-top: 78px;
margin-bottom: 40px; margin-bottom: 40px;
transition: margin-top 0.2s;
} }
.affine-default-page-block-container { .affine-default-page-block-container {
max-width: 686px; transition: max-width 0.2s;
min-width: 550px;
} }
affine-block-hub { affine-block-hub {
+2
View File
@@ -27,6 +27,7 @@ declare module '@mui/material/styles' {
tooltipBackground: string; tooltipBackground: string;
hoverBackground: string; hoverBackground: string;
innerHoverBackground: string; innerHoverBackground: string;
modalBackground: string;
// Use for the quick search tips background // Use for the quick search tips background
backgroundTertiaryColor: string; backgroundTertiaryColor: string;
codeBackground: string; codeBackground: string;
@@ -103,6 +104,7 @@ declare module '@mui/material/styles' {
tooltipBackground: string; tooltipBackground: string;
hoverBackground: string; hoverBackground: string;
innerHoverBackground: string; innerHoverBackground: string;
modalBackground: string;
// Use for the quick search tips background // Use for the quick search tips background
backgroundTertiaryColor: string; backgroundTertiaryColor: string;
codeBackground: string; codeBackground: string;
+11 -1
View File
@@ -29,6 +29,7 @@ export const getLightTheme = (
cardHoverBackground: '#f8f9ff', cardHoverBackground: '#f8f9ff',
warningBackground: '#FFF9C7', warningBackground: '#FFF9C7',
errorBackground: '#FFDED8', errorBackground: '#FFDED8',
modalBackground: 'rgba(0, 0, 0, 0.6)',
textColor: '#424149', textColor: '#424149',
secondaryTextColor: '#8E8D91', secondaryTextColor: '#8E8D91',
@@ -83,6 +84,15 @@ export const getLightTheme = (
radius: { radius: {
popover: '10px', popover: '10px',
}, },
breakpoints: {
values: {
xs: 0,
sm: 640,
md: 960,
lg: 1280,
xl: 1920,
},
},
}; };
}; };
@@ -113,6 +123,7 @@ export const getDarkTheme = (
cardHoverBackground: '#363636', cardHoverBackground: '#363636',
warningBackground: '#FFF9C7', warningBackground: '#FFF9C7',
errorBackground: '#FFDED8', errorBackground: '#FFDED8',
modalBackground: 'rgba(0, 0, 0, 0.8)',
textColor: '#fff', textColor: '#fff',
secondaryTextColor: '#8E8D91', secondaryTextColor: '#8E8D91',
@@ -207,7 +218,6 @@ export const globalThemeVariables: (
'--affine-paragraph-space': theme.space.paragraph, '--affine-paragraph-space': theme.space.paragraph,
'--affine-popover-radius': theme.radius.popover, '--affine-popover-radius': theme.radius.popover,
'--affine-editor-width': '720px',
'--affine-zoom': '1', '--affine-zoom': '1',
'--affine-scale': 'calc(1 / var(--affine-zoom))', '--affine-scale': 'calc(1 / var(--affine-zoom))',
}; };
+10 -1
View File
@@ -27,6 +27,7 @@ export interface AffineTheme {
tooltipBackground: string; tooltipBackground: string;
hoverBackground: string; hoverBackground: string;
innerHoverBackground: string; innerHoverBackground: string;
modalBackground: string;
// Use for the quick search tips background // Use for the quick search tips background
backgroundTertiaryColor: string; backgroundTertiaryColor: string;
codeBackground: string; codeBackground: string;
@@ -92,6 +93,15 @@ export interface AffineTheme {
radius: { radius: {
popover: string; popover: string;
}; };
breakpoints: {
values: {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
};
};
} }
export interface AffineThemeCSSVariables { export interface AffineThemeCSSVariables {
@@ -150,7 +160,6 @@ export interface AffineThemeCSSVariables {
'--affine-popover-radius': AffineTheme['radius']['popover']; '--affine-popover-radius': AffineTheme['radius']['popover'];
// use for blocksuite // use for blocksuite
'--affine-editor-width': CSSProperties['width'];
'--affine-zoom': CSSProperties['zoom']; '--affine-zoom': CSSProperties['zoom'];
'--affine-scale': string; '--affine-scale': string;
} }
+1 -4
View File
@@ -12,10 +12,7 @@ export const StyledBackdrop = styled('div')(({ theme }) => {
bottom: '0', bottom: '0',
top: '0', top: '0',
left: '0', left: '0',
backgroundColor: backgroundColor: theme.colors.modalBackground,
theme.palette.mode === 'light'
? 'rgba(58, 76, 92, 0.2)'
: 'rgba(34, 34, 34, 0.6)',
}; };
}); });
+53 -2
View File
@@ -9,7 +9,7 @@ test.describe('Layout ui', () => {
await openHomePage(page); await openHomePage(page);
await waitMarkdownImported(page); await waitMarkdownImported(page);
await page.getByTestId('sliderBar-arrowButton-collapse').click(); await page.getByTestId('sliderBar-arrowButton-collapse').click();
const sliderBarArea = page.getByTestId('sliderBar'); const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).not.toBeVisible(); await expect(sliderBarArea).not.toBeVisible();
}); });
@@ -17,10 +17,61 @@ test.describe('Layout ui', () => {
await openHomePage(page); await openHomePage(page);
await waitMarkdownImported(page); await waitMarkdownImported(page);
await page.getByTestId('sliderBar-arrowButton-collapse').click(); await page.getByTestId('sliderBar-arrowButton-collapse').click();
const sliderBarArea = page.getByTestId('sliderBar'); const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).not.toBeVisible(); await expect(sliderBarArea).not.toBeVisible();
await page.getByTestId('sliderBar-arrowButton-expand').click(); await page.getByTestId('sliderBar-arrowButton-expand').click();
await expect(sliderBarArea).toBeVisible(); await expect(sliderBarArea).toBeVisible();
}); });
test('Click resizer can close sidebar', async ({ page }) => {
await openHomePage(page);
await waitMarkdownImported(page);
const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).toBeVisible();
await page.getByTestId('sliderBar-resizer').click();
await expect(sliderBarArea).not.toBeVisible();
});
test('Drag resizer can resize sidebar', async ({ page }) => {
await openHomePage(page);
await waitMarkdownImported(page);
const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).toBeVisible();
const sliderResizer = page.getByTestId('sliderBar-resizer');
await sliderResizer.hover();
await page.mouse.down();
await page.mouse.move(400, 300, {
steps: 10,
});
await page.mouse.up();
const boundingBox = await page.getByTestId('sliderBar-root').boundingBox();
expect(boundingBox?.width).toBe(400);
});
test('Sidebar in between sm & md breakpoint', async ({ page }) => {
await openHomePage(page);
await waitMarkdownImported(page);
const sliderBarArea = page.getByTestId('sliderBar-inner');
const sliderBarModalBackground = page.getByTestId(
'sliderBar-modalBackground'
);
await expect(sliderBarArea).toBeVisible();
await expect(sliderBarModalBackground).not.toBeVisible();
await page.setViewportSize({
width: 768,
height: 1024,
});
await expect(sliderBarModalBackground).toBeVisible();
// click modal background can close sidebar
await sliderBarModalBackground.click({
force: true,
position: { x: 600, y: 150 },
});
await expect(sliderBarArea).not.toBeVisible();
});
}); });
+1 -1
View File
@@ -180,7 +180,7 @@ test.describe('Novice guidance for quick search', () => {
const quickSearchTips = page.locator('[data-testid=quick-search-tips]'); const quickSearchTips = page.locator('[data-testid=quick-search-tips]');
await expect(quickSearchTips).not.toBeVisible(); await expect(quickSearchTips).not.toBeVisible();
await page.getByTestId('sliderBar-arrowButton-collapse').click(); await page.getByTestId('sliderBar-arrowButton-collapse').click();
const sliderBarArea = page.getByTestId('sliderBar'); const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).not.toBeVisible(); await expect(sliderBarArea).not.toBeVisible();
await expect(quickSearchTips).toBeVisible(); await expect(quickSearchTips).toBeVisible();
await page.locator('[data-testid=quick-search-got-it]').click(); await page.locator('[data-testid=quick-search-got-it]').click();
+1 -1
View File
@@ -9,7 +9,7 @@ test.describe('subpage', () => {
await openHomePage(page); await openHomePage(page);
await waitMarkdownImported(page); await waitMarkdownImported(page);
await page.getByTestId('sliderBar-arrowButton-collapse').click(); await page.getByTestId('sliderBar-arrowButton-collapse').click();
const sliderBarArea = page.getByTestId('sliderBar'); const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).not.toBeVisible(); await expect(sliderBarArea).not.toBeVisible();
}); });
}); });