Skip to content

Commit

Permalink
fix(mobile): fixed all docs header, remove doc card tags layout strat…
Browse files Browse the repository at this point in the history
…egy (#8104)

close AF-1326
  • Loading branch information
CatsJuice committed Sep 5, 2024
1 parent 24acce2 commit 73dd1d3
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 139 deletions.
1 change: 1 addition & 0 deletions packages/frontend/mobile/src/components/app-tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const AppTabs = () => {
className={styles.tabItem}
role="tab"
aria-label={route.to.slice(1)}
replaceHistory
>
<li>
<route.Icon />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const appTabs = style({
backgroundColor: cssVarV2('layer/background/secondary'),
borderTop: `1px solid ${cssVarV2('layer/insideBorder/border')}`,

width: '100vw',
width: '100dvw',
height: globalVars.appTabHeight,
padding: 16,
gap: 15.5,
Expand Down
15 changes: 7 additions & 8 deletions packages/frontend/mobile/src/components/doc-card/tag.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,12 @@ export const tags = style({
width: '100%',
display: 'flex',
flexWrap: 'wrap',
alignItems: 'flex-start',
alignItems: 'center',
position: 'relative',

transition: 'height 0.23s',
overflow: 'hidden',
gap: 4,
});

export const tag = style({
visibility: 'hidden',
position: 'absolute',
// transition: 'all 0.23s',

padding: '0px 8px',
borderRadius: 10,
alignItems: 'center',
Expand All @@ -43,3 +37,8 @@ export const tag = style({
marginRight: 4,
},
});

export const more = style({
fontSize: 16,
color: cssVarV2('icon/primary'),
});
115 changes: 7 additions & 108 deletions packages/frontend/mobile/src/components/doc-card/tag.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { observeResize } from '@affine/component';
import type { Tag } from '@affine/core/modules/tag';
import { TagService } from '@affine/core/modules/tag';
import { MoreHorizontalIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import { useCallback, useEffect, useRef } from 'react';

import * as styles from './tag.css';

Expand All @@ -23,121 +22,21 @@ const DocCardTag = ({ tag }: { tag: Tag }) => {
);
};

const GAP = 4;
const MIN_WIDTH = 32;

const DocCardTagsRenderer = ({ tags, rows }: { tags: Tag[]; rows: number }) => {
const ulRef = useRef<HTMLUListElement>(null);

// A strategy to layout tags
const layoutTags = useCallback(
(entry: ResizeObserverEntry) => {
const availableWidth = entry.contentRect.width;
const lis = Array.from(ulRef.current?.querySelectorAll('li') ?? []);

const tagGrid: Array<{
x: number;
y: number;
w: number;
el: HTMLLIElement;
}> = [];

for (let i = 0; i < rows; i++) {
let width = 0;
let restSpace = availableWidth - width;
while (restSpace >= MIN_WIDTH) {
const li = lis.shift();
if (!li) break;
const liWidth = li.scrollWidth + 2; // 2 is for border
let liDisplayWidth = Math.min(liWidth, restSpace);

restSpace = restSpace - liDisplayWidth - GAP;
if (restSpace < MIN_WIDTH) {
liDisplayWidth += restSpace;
}

tagGrid.push({
x: width,
y: i * (22 + GAP),
w: liDisplayWidth,
el: li,
});

width += liDisplayWidth + GAP;
}
}

const lastItem = tagGrid[tagGrid.length - 1];

tagGrid.forEach(({ el, x, y, w }) => {
Object.assign(el.style, {
width: `${w}px`,
transform: `translate(${x}px, ${y}px)`,
visibility: 'visible',
});
});

// hide rest
lis.forEach(li =>
Object.assign(li.style, {
visibility: 'hidden',
width: '0px',
transform: `translate(0px, ${lastItem.y + 22 + GAP}px)`,
})
);

// update ul height
// to avoid trigger resize immediately
setTimeout(() => {
if (ulRef.current) {
ulRef.current.style.height = `${lastItem.y + 22}px`;
}
});
},
[rows]
);

const prevEntryRef = useRef<ResizeObserverEntry | null>(null);
useEffect(() => {
tags; // make sure tags is in deps
const ul = ulRef.current;
if (!ul) return;

const dispose = observeResize(ul, entry => {
if (entry.contentRect.width === prevEntryRef.current?.contentRect.width) {
return;
}

layoutTags(entry);
prevEntryRef.current = entry;
});
return () => {
dispose();
prevEntryRef.current = null;
};
}, [layoutTags, tags]);

const DocCardTagsRenderer = ({ tags }: { tags: Tag[] }) => {
return (
<ul className={styles.tags} ref={ulRef} style={{ gap: GAP }}>
{tags.map(tag => (
<ul className={styles.tags}>
{tags.slice(0, 2).map(tag => (
<DocCardTag key={tag.id} tag={tag} />
))}
{/* TODO(@CatsJuice): more icon */}
{/* <MoreHorizontalIcon /> */}
{tags.length > 2 ? <MoreHorizontalIcon className={styles.more} /> : null}
</ul>
);
};

export const DocCardTags = ({
docId,
rows = 2,
}: {
docId: string;
rows?: number;
}) => {
export const DocCardTags = ({ docId }: { docId: string; rows?: number }) => {
const tagService = useService(TagService);
const tags = useLiveData(tagService.tagList.tagsByPageId$(docId));

if (!tags.length) return null;
return <DocCardTagsRenderer tags={tags} rows={rows} />;
return <DocCardTagsRenderer tags={tags} />;
};
25 changes: 14 additions & 11 deletions packages/frontend/mobile/src/views/all-docs/header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IconButton, MobileMenu } from '@affine/component';
import { MoreHorizontalIcon } from '@blocksuite/icons/rc';

import { header } from './style.css';
import { header, headerSpace } from './style.css';
import { AllDocsTabs } from './tabs';

export interface AllDocsHeaderProps {
Expand All @@ -10,15 +10,18 @@ export interface AllDocsHeaderProps {

export const AllDocsHeader = ({ operations }: AllDocsHeaderProps) => {
return (
<header className={header}>
<AllDocsTabs />
<div>
{operations ? (
<MobileMenu items={operations}>
<IconButton icon={<MoreHorizontalIcon />} />
</MobileMenu>
) : null}
</div>
</header>
<>
<header className={header}>
<AllDocsTabs />
<div>
{operations ? (
<MobileMenu items={operations}>
<IconButton icon={<MoreHorizontalIcon />} />
</MobileMenu>
) : null}
</div>
</header>
<div className={headerSpace} />
</>
);
};
34 changes: 23 additions & 11 deletions packages/frontend/mobile/src/views/all-docs/style.css.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';

export const header = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 16,
padding: '16px 16px 0px 16px',
const headerContentHeight = 56;
const headerPaddingTop = 16;

position: 'sticky',
top: 0,
backgroundColor: cssVarV2('layer/background/secondary'),
zIndex: 1,
const basicHeader = style({
width: '100%',
height: headerContentHeight + headerPaddingTop,
});
export const header = style([
basicHeader,
{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 16,
padding: `${headerPaddingTop}px 16px 0px 16px`,

position: 'fixed',
top: 0,
backgroundColor: cssVarV2('layer/background/secondary'),
zIndex: 1,
},
]);
export const headerSpace = style([basicHeader]);

export const tabs = style({
height: 56,
height: headerContentHeight,
gap: 16,
display: 'flex',
alignItems: 'center',
Expand Down

0 comments on commit 73dd1d3

Please sign in to comment.