カード
Flip Card
ホバーまたはクリックで表裏がフリップするカードコンポーネント。
インストール
npx shadcn add https://d-ui.daigo-suhara.com/registry/flip-card.jsonサンプル
使い方
import { FlipCard } from "@/components/ui/flip-card"
export default function Example() {
return (
<FlipCard
height="180px"
className="w-64"
front={
<div className="flex h-full items-center justify-center rounded-xl bg-primary text-primary-foreground text-lg font-bold">
表面
</div>
}
back={
<div className="flex h-full items-center justify-center rounded-xl bg-muted text-foreground text-sm p-4 text-center">
裏面のコンテンツがここに表示されます。
</div>
}
/>
)
}プロパティ
front必須ReactNode表面のコンテンツ
back必須ReactNode裏面のコンテンツ
trigger任意"hover" | "click"フリップのトリガー
デフォルト:
"hover"direction任意"horizontal" | "vertical"フリップの方向
デフォルト:
"horizontal"height任意stringカードの高さ
デフォルト:
"200px"className必須string追加のCSSクラス
| 名前 | 型 | デフォルト | 説明 | |
|---|---|---|---|---|
| 必須 | front | ReactNode | — | 表面のコンテンツ |
| 必須 | back | ReactNode | — | 裏面のコンテンツ |
| 任意 | trigger | "hover" | "click" | "hover" | フリップのトリガー |
| 任意 | direction | "horizontal" | "vertical" | "horizontal" | フリップの方向 |
| 任意 | height | string | "200px" | カードの高さ |
| 必須 | className | string | — | 追加のCSSクラス |
ソースコード
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
interface FlipCardProps {
front: React.ReactNode;
back: React.ReactNode;
trigger?: "hover" | "click";
direction?: "horizontal" | "vertical";
className?: string;
height?: string;
}
export function FlipCard({
front,
back,
trigger = "hover",
direction = "horizontal",
className,
height = "200px",
}: FlipCardProps) {
const [flipped, setFlipped] = React.useState(false);
const isHover = trigger === "hover";
const isVertical = direction === "vertical";
return (
<div
className={cn("relative cursor-pointer", className)}
style={{ height, perspective: "1000px" }}
onClick={!isHover ? () => setFlipped((f) => !f) : undefined}
onMouseEnter={isHover ? () => setFlipped(true) : undefined}
onMouseLeave={isHover ? () => setFlipped(false) : undefined}
>
<div
className="relative w-full h-full transition-transform duration-500"
style={{
transformStyle: "preserve-3d",
transform: flipped
? isVertical
? "rotateX(180deg)"
: "rotateY(180deg)"
: "rotateX(0deg) rotateY(0deg)",
}}
>
{/* Front */}
<div
className="absolute inset-0 rounded-xl overflow-hidden"
style={{ backfaceVisibility: "hidden" }}
>
{front}
</div>
{/* Back */}
<div
className="absolute inset-0 rounded-xl overflow-hidden"
style={{
backfaceVisibility: "hidden",
transform: isVertical ? "rotateX(180deg)" : "rotateY(180deg)",
}}
>
{back}
</div>
</div>
</div>
);
}