From c1e296c8601f7b029b2ce277f5ce11d137af85f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=84=AD=E6=B2=9B=E8=BB=92?= Date: Fri, 19 Sep 2025 23:09:45 +0800 Subject: [PATCH] =?UTF-8?q?ux:=20=E5=AF=A6=E7=8F=BE=E7=BF=BB=E5=8D=A1?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=8B=95=E6=85=8B=E9=AB=98=E5=BA=A6=E9=81=A9?= =?UTF-8?q?=E9=85=8D=E8=88=87=E7=89=88=E9=9D=A2=E5=84=AA=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增動態高度計算系統,解決翻轉時卡片大小變化問題 - 實現正面背面高度自動匹配,確保翻轉體驗一致 - 優化翻卡模式設計:移除CEFR標籤、簡化正面佈局 - 改善背面內容組織:灰底區分、左對齊文字、移除冗餘元素 - 修復背面底部空白問題,提升視覺整潔度 - 添加平滑高度過渡動畫,增強用戶體驗 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- frontend/app/learn/page.tsx | 192 ++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 83 deletions(-) diff --git a/frontend/app/learn/page.tsx b/frontend/app/learn/page.tsx index 98e28bb..b110d03 100644 --- a/frontend/app/learn/page.tsx +++ b/frontend/app/learn/page.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef, useLayoutEffect } from 'react' import { useRouter } from 'next/navigation' import { Navigation } from '@/components/Navigation' import AudioPlayer from '@/components/AudioPlayer' @@ -24,6 +24,12 @@ export default function LearnPage() { const [reportingCard, setReportingCard] = useState(null) const [showComplete, setShowComplete] = useState(false) const [quizOptions, setQuizOptions] = useState(['brought', 'determine', 'achieve', 'consider']) + const [cardHeight, setCardHeight] = useState(400) + + // Refs for measuring card content heights + const cardFrontRef = useRef(null) + const cardBackRef = useRef(null) + const cardContainerRef = useRef(null) // Mock data with real example images const cards = [ @@ -70,6 +76,37 @@ export default function LearnPage() { const currentCard = cards[currentCardIndex] + // Calculate optimal card height based on content (only when card changes) + const calculateCardHeight = () => { + if (!cardFrontRef.current || !cardBackRef.current) return 400; + + // Get the scroll heights to measure actual content + const frontHeight = cardFrontRef.current.scrollHeight; + const backHeight = cardBackRef.current.scrollHeight; + + console.log('Heights calculated:', { frontHeight, backHeight }); // Debug log + + // Use the maximum height with padding + const maxHeight = Math.max(frontHeight, backHeight); + const paddedHeight = maxHeight + 40; // Add padding for visual spacing + + // Ensure minimum height for visual consistency + return Math.max(paddedHeight, 450); + }; + + // Update card height only when card content changes (not on flip) + useLayoutEffect(() => { + if (mounted && cardFrontRef.current && cardBackRef.current) { + // Wait for DOM to be fully rendered + const timer = setTimeout(() => { + const newHeight = calculateCardHeight(); + setCardHeight(newHeight); + }, 50); + + return () => clearTimeout(timer); + } + }, [currentCardIndex, mounted]); + // Client-side mounting and quiz options generation useEffect(() => { setMounted(true) @@ -102,6 +139,7 @@ export default function LearnPage() { setShowResult(false) setFillAnswer('') setShowHint(false) + // Height will be recalculated in useLayoutEffect } else { setShowComplete(true) } @@ -115,6 +153,7 @@ export default function LearnPage() { setShowResult(false) setFillAnswer('') setShowHint(false) + // Height will be recalculated in useLayoutEffect } } @@ -305,95 +344,64 @@ export default function LearnPage() { -
+
{/* Front */}
-
-
- - {currentCard.difficulty} - -
-

+
+

{currentCard.word}

-

- {currentCard.partOfSpeech} {currentCard.pronunciation} -

- -

- 點擊查看翻譯 -

+
+ + {currentCard.pronunciation} + + +

{/* Back */}
-
-
- {/* Left Column - Text Content */} -
-
- - {currentCard.difficulty} - -
-

- {currentCard.word} -

-

- {currentCard.translation} -

-

- {currentCard.partOfSpeech} {currentCard.pronunciation} -

- -
- -
- -
-

定義

-

{currentCard.definition}

-
- -
-

例句

-

"{currentCard.example}"

-

"{currentCard.exampleTranslation}"

-
- -
-

同義詞

-
- {currentCard.synonyms.map((synonym, index) => ( - - {synonym} - - ))} -
-
+
+ {/* Content Sections */} +
+ {/* Definition */} +
+

定義

+

{currentCard.definition}

- {/* Right Column - Image */} -
-
- {`Example { - e.stopPropagation() - setModalImage(currentCard.exampleImage) - }} - /> -
- 點擊放大 -
+ {/* Example */} +
+

例句

+

"{currentCard.example}"

+

"{currentCard.exampleTranslation}"

+
+ + {/* Synonyms */} +
+

同義詞

+
+ {currentCard.synonyms.map((synonym, index) => ( + + {synonym} + + ))}
@@ -935,7 +943,9 @@ export default function LearnPage() {