Loading...
Loading...
Compare original and translation side by side
grid-rowsautogrid-rows-[0fr]overflow-hiddengrid-rows-[1fr]grid-rowsautogrid-rows-[0fr]overflow-hiddengrid-rows-[1fr]"use client";
import { useState } from "react";
import { ChevronDown } from "lucide-react";
function ExpandableCard() {
const [expanded, setExpanded] = useState(true);
return (
<div className="rounded-xl border overflow-hidden transition-all duration-300">
{/* Header - clickable toggle */}
<div
className="flex items-center justify-between px-4 py-3 cursor-pointer hover:bg-zinc-50 transition-colors"
onClick={() => setExpanded(!expanded)}
>
<span className="font-medium">Card Title</span>
<ChevronDown
className={`w-5 h-5 transition-transform duration-200 ${
expanded ? "rotate-180" : ""
}`}
/>
</div>
{/* Content - animated container */}
<div
className={`grid transition-all duration-300 ease-in-out ${
expanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
}`}
>
<div className="overflow-hidden">
<div className="px-4 py-4 border-t">
{/* Your content here */}
<p>Expandable content goes here.</p>
</div>
</div>
</div>
</div>
);
}"use client";
import { useState } from "react";
import { ChevronDown } from "lucide-react";
function ExpandableCard() {
const [expanded, setExpanded] = useState(true);
return (
<div className="rounded-xl border overflow-hidden transition-all duration-300">
{/* 头部 - 可点击的切换区域 */}
<div
className="flex items-center justify-between px-4 py-3 cursor-pointer hover:bg-zinc-50 transition-colors"
onClick={() => setExpanded(!expanded)}
>
<span className="font-medium">卡片标题</span>
<ChevronDown
className={`w-5 h-5 transition-transform duration-200 ${
expanded ? "rotate-180" : ""
}`}
/>
</div>
{/* 内容 - 动画容器 */}
<div
className={`grid transition-all duration-300 ease-in-out ${
expanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
}`}
>
<div className="overflow-hidden">
<div className="px-4 py-4 border-t">
{/* 在此处添加你的内容 */}
<p>可展开内容放置于此。</p>
</div>
</div>
</div>
</div>
);
}const [expanded, setExpanded] = useState(true); // Start expanded
// or
const [expanded, setExpanded] = useState(false); // Start collapsedconst [expanded, setExpanded] = useState(true); // 默认展开
// 或者
const [expanded, setExpanded] = useState(false); // 默认折叠<div
className="cursor-pointer hover:bg-zinc-50 transition-colors"
onClick={() => setExpanded(!expanded)}
><div
className="cursor-pointer hover:bg-zinc-50 transition-colors"
onClick={() => setExpanded(!expanded)}
><ChevronDown
className={`transition-transform duration-200 ${
expanded ? "rotate-180" : ""
}`}
/><ChevronDown
className={`transition-transform duration-200 ${
expanded ? "rotate-180" : ""
}`}
/><div
className={`grid transition-all duration-300 ease-in-out ${
expanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
}`}
>
<div className="overflow-hidden">
{/* Content wrapper - REQUIRED for animation */}
</div>
</div><div
className={`grid transition-all duration-300 ease-in-out ${
expanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
}`}
>
<div className="overflow-hidden">
{/* 内容包裹层 - 动画必需 */}
</div>
</div>| Duration | Use Case |
|---|---|
| Small cards, quick feedback |
| Chevron rotation |
| Content expansion (recommended) |
| Large content areas |
| 时长值 | 使用场景 |
|---|---|
| 小型卡片,快速反馈 |
| Chevron图标旋转 |
| 内容展开(推荐值) |
| 大型内容区域 |
<div
className={`rounded-xl border overflow-hidden transition-all duration-300 ${
expanded ? "shadow-lg" : "shadow-sm hover:shadow-md"
}`}
><div
className={`rounded-xl border overflow-hidden transition-all duration-300 ${
expanded ? "shadow-lg" : "shadow-sm hover:shadow-md"
}`}
><div
role="button"
tabIndex={0}
aria-expanded={expanded}
onClick={() => setExpanded(!expanded)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
setExpanded(!expanded);
}
}}
><div
role="button"
tabIndex={0}
aria-expanded={expanded}
onClick={() => setExpanded(!expanded)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
setExpanded(!expanded);
}
}}
>const [expandedId, setExpandedId] = useState<string | null>("first");
// Toggle logic
onClick={() => setExpandedId(expandedId === id ? null : id)}const [expandedId, setExpandedId] = useState<string | null>("first");
// 切换逻辑
onClick={() => setExpandedId(expandedId === id ? null : id)}<a
href="..."
onClick={(e) => e.stopPropagation()}
>stopPropagation<a>// Full example with multiple interactive elements
<div className="overflow-hidden">
<div className="px-4 py-4 border-t">
<a
href="https://example.com"
onClick={(e) => e.stopPropagation()}
className="text-blue-500 hover:underline"
>
External link
</a>
<button
onClick={(e) => {
e.stopPropagation();
// Handle button action
}}
>
Action Button
</button>
</div>
</div><a
href="..."
onClick={(e) => e.stopPropagation()}
>stopPropagation<a>// 包含多个交互元素的完整示例
<div className="overflow-hidden">
<div className="px-4 py-4 border-t">
<a
href="https://example.com"
onClick={(e) => e.stopPropagation()}
className="text-blue-500 hover:underline"
>
外部链接
</a>
<button
onClick={(e) => {
e.stopPropagation();
// 处理按钮操作
}}
>
操作按钮
</button>
</div>
</div>overflow-hiddentransition-alltransition-transformcursor-pointeroverflow-hiddentransition-alltransition-transformcursor-pointer