chore: enable compact mode for list view

This commit is contained in:
Steven 2026-01-22 22:52:14 +08:00
parent 6c9ea31de0
commit c0d6224155
8 changed files with 33 additions and 28 deletions

View File

@ -10,10 +10,10 @@ const MasonryView = ({ memoList, renderer, prefixElement, listMode = false }: Ma
const { columns, distribution, handleHeightChange } = useMasonryLayout(memoList, listMode, containerRef, prefixElementRef);
// Create render context: automatically enable compact mode when multiple columns
// Create render context: always enable compact mode for list views
const renderContext: MemoRenderContext = useMemo(
() => ({
compact: columns > 1,
compact: true,
columns,
}),
[columns],

View File

@ -1,6 +1,12 @@
import { defaultSchema } from "rehype-sanitize";
export const MAX_DISPLAY_HEIGHT = 256;
// Compact mode display settings
export const COMPACT_MODE_CONFIG = {
maxHeightVh: 60, // 60% of viewport height
gradientHeight: "h-24", // Tailwind class for gradient overlay
} as const;
export const getMaxDisplayHeight = () => window.innerHeight * (COMPACT_MODE_CONFIG.maxHeightVh / 100);
export const COMPACT_STATES: Record<"ALL" | "SNIPPET", { textKey: string; next: "ALL" | "SNIPPET" }> = {
ALL: { textKey: "memo.show-more", next: "SNIPPET" },

View File

@ -1,5 +1,5 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { COMPACT_STATES, MAX_DISPLAY_HEIGHT } from "./constants";
import { COMPACT_STATES, getMaxDisplayHeight } from "./constants";
import type { ContentCompactView } from "./types";
export const useCompactMode = (enabled: boolean) => {
@ -8,7 +8,8 @@ export const useCompactMode = (enabled: boolean) => {
useEffect(() => {
if (!enabled || !containerRef.current) return;
if (containerRef.current.getBoundingClientRect().height > MAX_DISPLAY_HEIGHT) {
const maxHeight = getMaxDisplayHeight();
if (containerRef.current.getBoundingClientRect().height > maxHeight) {
setMode("ALL");
}
}, [enabled]);

View File

@ -1,4 +1,5 @@
import type { Element } from "hast";
import { ChevronDown, ChevronUp } from "lucide-react";
import { memo } from "react";
import ReactMarkdown from "react-markdown";
import rehypeKatex from "rehype-katex";
@ -14,7 +15,7 @@ import { remarkPreserveType } from "@/utils/remark-plugins/remark-preserve-type"
import { remarkTag } from "@/utils/remark-plugins/remark-tag";
import { CodeBlock } from "./CodeBlock";
import { isTagNode, isTaskListItemNode } from "./ConditionalComponent";
import { SANITIZE_SCHEMA } from "./constants";
import { COMPACT_MODE_CONFIG, SANITIZE_SCHEMA } from "./constants";
import { useCompactLabel, useCompactMode } from "./hooks";
import { Tag } from "./Tag";
import { TaskListItem } from "./TaskListItem";
@ -37,7 +38,7 @@ const MemoContent = (props: MemoContentProps) => {
ref={memoContentContainerRef}
className={cn(
"markdown-content relative w-full max-w-full wrap-break-word text-base leading-6",
showCompactMode === "ALL" && "line-clamp-6 max-h-60",
showCompactMode === "ALL" && `max-h-[${COMPACT_MODE_CONFIG.maxHeightVh}vh] overflow-hidden`,
contentClassName,
)}
onMouseUp={onClick}
@ -71,18 +72,25 @@ const MemoContent = (props: MemoContentProps) => {
>
{content}
</ReactMarkdown>
{showCompactMode === "ALL" && (
<div
className={cn(
"absolute inset-x-0 bottom-0 pointer-events-none",
COMPACT_MODE_CONFIG.gradientHeight,
"bg-linear-to-t from-background from-0% via-background/60 via-40% to-transparent to-100%",
)}
/>
)}
</div>
{showCompactMode === "ALL" && (
<div className="absolute bottom-0 left-0 w-full h-12 bg-linear-to-b from-transparent to-background pointer-events-none"></div>
)}
{showCompactMode !== undefined && (
<div className="w-full mt-1">
<div className="relative w-full mt-2">
<button
type="button"
className="w-auto flex flex-row justify-start items-center cursor-pointer text-sm text-primary hover:opacity-80 text-left"
className="group inline-flex items-center gap-1 px-2 py-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
onClick={toggleCompactMode}
>
{compactLabel}
<span>{compactLabel}</span>
{showCompactMode === "ALL" ? <ChevronDown className="w-3 h-3" /> : <ChevronUp className="w-3 h-3" />}
</button>
</div>
)}

View File

@ -1,4 +1,3 @@
import { MemoRenderContext } from "@/components/MasonryView";
import MemoView from "@/components/MemoView";
import PagedMemoList from "@/components/PagedMemoList";
import { useMemoFilters, useMemoSorting } from "@/hooks";
@ -24,9 +23,7 @@ const Archived = () => {
return (
<PagedMemoList
renderer={(memo: Memo, context?: MemoRenderContext) => (
<MemoView key={`${memo.name}-${memo.updateTime}`} memo={memo} showVisibility compact={context?.compact} />
)}
renderer={(memo: Memo) => <MemoView key={`${memo.name}-${memo.updateTime}`} memo={memo} showVisibility compact />}
listSort={listSort}
state={State.ARCHIVED}
orderBy={orderBy}

View File

@ -1,4 +1,3 @@
import { MemoRenderContext } from "@/components/MasonryView";
import MemoView from "@/components/MemoView";
import PagedMemoList from "@/components/PagedMemoList";
import { useMemoFilters, useMemoSorting } from "@/hooks";
@ -30,9 +29,7 @@ const Explore = () => {
return (
<PagedMemoList
renderer={(memo: Memo, context?: MemoRenderContext) => (
<MemoView key={`${memo.name}-${memo.updateTime}`} memo={memo} showCreator showVisibility compact={context?.compact} />
)}
renderer={(memo: Memo) => <MemoView key={`${memo.name}-${memo.updateTime}`} memo={memo} showCreator showVisibility compact />}
listSort={listSort}
orderBy={orderBy}
filter={memoFilter}

View File

@ -1,4 +1,3 @@
import { MemoRenderContext } from "@/components/MasonryView";
import MemoView from "@/components/MemoView";
import PagedMemoList from "@/components/PagedMemoList";
import { useInstance } from "@/contexts/InstanceContext";
@ -25,9 +24,7 @@ const Home = () => {
return (
<div className="w-full min-h-full bg-background text-foreground">
<PagedMemoList
renderer={(memo: Memo, context?: MemoRenderContext) => (
<MemoView key={`${memo.name}-${memo.displayTime}`} memo={memo} showVisibility showPinned compact={context?.compact} />
)}
renderer={(memo: Memo) => <MemoView key={`${memo.name}-${memo.displayTime}`} memo={memo} showVisibility showPinned compact />}
listSort={listSort}
orderBy={orderBy}
filter={memoFilter}

View File

@ -2,7 +2,6 @@ import copy from "copy-to-clipboard";
import { ExternalLinkIcon, LayoutListIcon, type LucideIcon, MapIcon } from "lucide-react";
import { toast } from "react-hot-toast";
import { useParams, useSearchParams } from "react-router-dom";
import { MemoRenderContext } from "@/components/MasonryView";
import MemoView from "@/components/MemoView";
import PagedMemoList from "@/components/PagedMemoList";
import UserAvatar from "@/components/UserAvatar";
@ -130,8 +129,8 @@ const UserProfile = () => {
<div className="mx-auto w-full max-w-2xl">
{activeTab === "memos" ? (
<PagedMemoList
renderer={(memo: Memo, context?: MemoRenderContext) => (
<MemoView key={`${memo.name}-${memo.displayTime}`} memo={memo} showVisibility showPinned compact={context?.compact} />
renderer={(memo: Memo) => (
<MemoView key={`${memo.name}-${memo.displayTime}`} memo={memo} showVisibility showPinned compact />
)}
listSort={listSort}
orderBy={orderBy}