Skip to content

Commit

Permalink
feat(mobile): impl masonry docs with flex and predict card height (#8849
Browse files Browse the repository at this point in the history
)

previous `columns` implementation has some limitation:
- the card order is not as expected
- there may be strange shadow on top
  • Loading branch information
CatsJuice committed Nov 18, 2024
1 parent bf09371 commit bd7c422
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ import { forwardRef, type ReactNode, useMemo } from 'react';
import * as styles from './styles.css';
import { DocCardTags } from './tag';

const calcRowsById = (id: string) => {
const [MIN, MAX] = [2, 8];

export const calcRowsById = (id: string, min = 2, max = 8) => {
const code = id.charCodeAt(0);
return Math.floor((code % (MAX - MIN)) + MIN);
return Math.floor((code % (max - min)) + min);
};

export interface DocCardProps extends Omit<WorkbenchLinkProps, 'to'> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { style } from '@vanilla-extract/css';
export const paddingX = 16;
export const columnGap = 17;

export const masonry = style({
export const columns = style({
padding: `16px ${paddingX}px`,
columnGap: columnGap,
display: 'flex',
gap: columnGap,
});
export const masonryItem = style({
breakInside: 'avoid',
marginBottom: 10,

export const column = style({
display: 'flex',
flexDirection: 'column',
gap: 10,
width: 0,
flex: 1,
});
44 changes: 33 additions & 11 deletions packages/frontend/core/src/mobile/views/all-docs/doc/masonry.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useGlobalEvent } from '@affine/core/mobile/hooks/use-global-events';
import type { DocMeta } from '@blocksuite/affine/store';
import { useCallback, useState } from 'react';
import { useCallback, useMemo, useState } from 'react';

import { DocCard } from '../../../components';
import { calcRowsById, DocCard } from '../../../components';
import * as styles from './masonry.css';

const calcColumnCount = () => {
Expand All @@ -14,6 +14,20 @@ const calcColumnCount = () => {
return Math.max(newColumnCount, 2);
};

const calcColumns = (items: DocMeta[], length: number) => {
const columns = Array.from({ length }, () => [] as DocMeta[]);
const heights = Array.from({ length }, () => 0);

items.forEach(item => {
const itemHeight = calcRowsById(item.id);
const minHeightIndex = heights.indexOf(Math.min(...heights));
heights[minHeightIndex] += itemHeight;
columns[minHeightIndex].push(item);
});

return columns;
};

export const MasonryDocs = ({
items,
showTags,
Expand All @@ -28,16 +42,24 @@ export const MasonryDocs = ({
}, []);
useGlobalEvent('resize', updateColumnCount);

const columns = useMemo(
() => calcColumns(items, columnCount),
[items, columnCount]
);

return (
<div className={styles.masonry} style={{ columnCount }}>
{items.map(item => (
<DocCard
key={item.id}
className={styles.masonryItem}
showTags={showTags}
meta={item}
autoHeightById
/>
<div className={styles.columns}>
{columns.map((col, index) => (
<div key={`${columnCount}-${index}`} className={styles.column}>
{col.map(item => (
<DocCard
key={item.id}
showTags={showTags}
meta={item}
autoHeightById
/>
))}
</div>
))}
</div>
);
Expand Down

0 comments on commit bd7c422

Please sign in to comment.