feat(mobile): mobile index page UI (#7959)

This commit is contained in:
CatsJuice
2024-08-29 06:09:46 +00:00
parent f37051dc87
commit db76780bc9
47 changed files with 1404 additions and 84 deletions
@@ -0,0 +1,3 @@
# mobile views
Maintain complex views that used for `../pages`, view can contain mobile-components in `../components`
@@ -0,0 +1,51 @@
import { IconButton } from '@affine/component';
import { SettingsIcon } from '@blocksuite/icons/rc';
import clsx from 'clsx';
import { useCallback, useState } from 'react';
import { Link } from 'react-router-dom';
import { SearchButton, WorkspaceSelector } from '../../components';
import { useGlobalEvent } from '../../hooks/use-global-events';
import * as styles from './styles.css';
/**
* Contains `Setting`, `Workspace Selector`, `Search`
* When scrolled:
* - combine Setting and Workspace Selector
* - hide Search
*/
export const HomeHeader = () => {
const [dense, setDense] = useState(false);
useGlobalEvent(
'scroll',
useCallback(() => {
setDense(window.scrollY > 114);
}, [])
);
return (
<div className={clsx(styles.root, { dense })}>
<div className={styles.float}>
<div className={styles.headerAndWsSelector}>
<div className={styles.wsSelectorWrapper}>
<WorkspaceSelector />
</div>
<div className={styles.settingWrapper}>
<Link to="/settings">
<IconButton
size="24"
style={{ padding: 10 }}
icon={<SettingsIcon />}
/>
</Link>
</div>
</div>
<div className={styles.searchWrapper}>
<SearchButton />
</div>
</div>
<div className={styles.space} />
</div>
);
};
@@ -0,0 +1,83 @@
import { cssVarV2 } from '@toeverything/theme/v2';
import { createVar, style } from '@vanilla-extract/css';
const headerHeight = createVar('headerHeight');
const wsSelectorHeight = createVar('wsSelectorHeight');
const searchHeight = createVar('searchHeight');
const searchPadding = [10, 16, 15, 16];
export const root = style({
vars: {
[headerHeight]: '44px',
[wsSelectorHeight]: '48px',
[searchHeight]: '44px',
},
width: '100vw',
});
export const float = style({
// why not 'sticky'?
// when height change, will affect scroll behavior, causing shaking
position: 'fixed',
top: 0,
width: '100%',
background: cssVarV2('layer/background/secondary'),
paddingTop: 12,
zIndex: 1,
});
export const space = style({
height: `calc(${headerHeight} + ${wsSelectorHeight} + ${searchHeight} + ${searchPadding[0] + searchPadding[2]}px + 12px)`,
});
export const headerAndWsSelector = style({
display: 'flex',
gap: 10,
alignItems: 'end',
transition: 'height 0.2s',
height: `calc(${headerHeight} + ${wsSelectorHeight})`,
selectors: {
[`${root}.dense &`]: {
height: wsSelectorHeight,
},
},
});
export const wsSelectorWrapper = style({
width: 0,
flex: 1,
height: wsSelectorHeight,
padding: '0 10px 0 16px',
});
export const settingWrapper = style({
width: '44px',
height: headerHeight,
transition: 'height 0.2s',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'start',
selectors: {
[`${root}.dense &`]: {
height: wsSelectorHeight,
},
},
});
export const searchWrapper = style({
padding: searchPadding.map(v => `${v}px`).join(' '),
width: '100%',
height: 44 + searchPadding[0] + searchPadding[2],
transition: 'all 0.2s',
overflow: 'hidden',
selectors: {
[`${root}.dense &`]: {
height: 0,
paddingTop: 0,
paddingBottom: 0,
},
},
});
@@ -0,0 +1,2 @@
export * from './home-header';
export * from './recent-docs';
@@ -0,0 +1,36 @@
import { useBlockSuiteDocMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { CollapsibleSection } from '@affine/core/modules/explorer';
import { useService, WorkspaceService } from '@toeverything/infra';
import { useMemo } from 'react';
import { DocCard } from '../../components/doc-card';
import * as styles from './styles.css';
export const RecentDocs = ({ max = 5 }: { max?: number }) => {
const workspace = useService(WorkspaceService).workspace;
const allPageMetas = useBlockSuiteDocMeta(workspace.docCollection);
const cardMetas = useMemo(() => {
return [...allPageMetas]
.sort((a, b) => (b.updatedDate ?? 0) - (a.updatedDate ?? 0))
.slice(0, max);
}, [allPageMetas, max]);
return (
<CollapsibleSection
name="recent"
title="Recent"
headerClassName={styles.header}
>
<div className={styles.scroll}>
<ul className={styles.list}>
{cardMetas.map((doc, index) => (
<li key={index} className={styles.cardWrapper}>
<DocCard meta={doc} />
</li>
))}
</ul>
</div>
</CollapsibleSection>
);
};
@@ -0,0 +1,31 @@
import { globalStyle, style } from '@vanilla-extract/css';
export const scroll = style({
width: '100%',
paddingTop: 8,
paddingBottom: 32,
overflowX: 'auto',
});
export const list = style({
paddingLeft: 16,
paddingRight: 16,
display: 'flex',
gap: 10,
width: 'fit-content',
});
export const cardWrapper = style({
width: 172,
height: 210,
flexShrink: 0,
});
export const header = style({
margin: '0 8px',
});
globalStyle(`${cardWrapper} > *`, {
width: '100%',
height: '100%',
});