テスティモニアル/

マーキースクロール・テスティモニアル

Preview

カード型の顧客の声が上下2段で水平に自動スクロールするテスティモニアルセクション。無限ループアニメーションで動きのあるレイアウト

Source Code
tsx
174 lines
1const testimonials = [
2 {
3 content:
4 "導入から3ヶ月で開発サイクルが40%短縮されました。チーム全体の生産性が目に見えて向上しています。",
5 author: "田中 美咲",
6 role: "CTO",
7 company: "Apex Technologies",
8 },
9 {
10 content:
11 "直感的なインターフェースと堅牢なAPI。私たちが求めていたものがすべて揃っていました。",
12 author: "鈴木 健太",
13 role: "Lead Engineer",
14 company: "Nova Digital",
15 },
16 {
17 content:
18 "サポートチームの対応が素晴らしい。技術的な質問にも的確に答えてくれます。",
19 author: "山田 優子",
20 role: "Product Manager",
21 company: "Bloom Studio",
22 },
23 {
24 content:
25 "スケーラビリティに優れ、急成長するサービスにも安心して使えるプラットフォームです。",
26 author: "佐藤 亮",
27 role: "Founder",
28 company: "Drift Labs",
29 },
30 {
31 content:
32 "デザインシステムとの統合が非常にスムーズ。開発者体験を最優先に考えられた設計です。",
33 author: "伊藤 真理",
34 role: "Design Director",
35 company: "Echo Creative",
36 },
37 {
38 content:
39 "コスト効率と信頼性のバランスが絶妙。他のソリューションに戻ることは考えられません。",
40 author: "高橋 翔",
41 role: "VP of Engineering",
42 company: "Forge Systems",
43 },
44];
45
46function TestimonialCard({
47 content,
48 author,
49 role,
50 company,
51}: {
52 content: string;
53 author: string;
54 role: string;
55 company: string;
56}) {
57 return (
58 <div className="relative flex w-[340px] shrink-0 flex-col justify-between border border-border/40 px-8 py-8 sm:w-[400px]">
59 <div className="absolute left-3 top-3 h-1 w-1 rounded-full bg-foreground/20" />
60 <div className="absolute right-3 top-3 h-1 w-1 rounded-full bg-foreground/20" />
61
62 <p className="text-sm font-light leading-relaxed text-foreground/80">
63 &ldquo;{content}&rdquo;
64 </p>
65
66 <div className="mt-8">
67 <div className="h-px w-8 bg-border/60" />
68 <div className="mt-4 flex items-center gap-3">
69 <div className="flex h-8 w-8 items-center justify-center rounded-full bg-muted text-xs font-medium text-muted-foreground">
70 {author.charAt(0)}
71 </div>
72 <div>
73 <p className="text-xs font-medium tracking-wide text-foreground">
74 {author}
75 </p>
76 <p className="mt-0.5 text-[10px] tracking-[0.15em] text-muted-foreground">
77 {role}{company}
78 </p>
79 </div>
80 </div>
81 </div>
82 </div>
83 );
84}
85
86export function TestimonialMarquee001() {
87 return (
88 <section className="bg-background py-28">
89 <div className="mx-auto max-w-5xl px-4 sm:px-6 lg:px-8">
90 {/* ヘッダー */}
91 <div className="mb-16 text-center">
92 <div className="mx-auto flex items-center justify-center gap-4">
93 <div className="h-px w-8 bg-border/40" />
94 <div className="h-1.5 w-1.5 rounded-full bg-foreground/20" />
95 <div className="h-px w-8 bg-border/40" />
96 </div>
97 <p className="mt-8 text-[10px] uppercase tracking-[0.3em] text-muted-foreground">
98 Testimonials
99 </p>
100 <h2 className="mt-3 text-2xl font-medium tracking-wide text-foreground sm:text-3xl">
101 お客様の声
102 </h2>
103 <p className="mx-auto mt-4 max-w-md text-sm font-light leading-relaxed text-muted-foreground">
104 多くのチームに信頼され、日々のワークフローを支えています。
105 </p>
106 </div>
107 </div>
108
109 {/* マーキースクロール */}
110 <div className="overflow-hidden">
111 {/* 上段:左へスクロール */}
112 <div className="relative">
113 <div className="pointer-events-none absolute left-0 top-0 z-10 h-full w-16 bg-gradient-to-r from-background to-transparent sm:w-24" />
114 <div className="pointer-events-none absolute right-0 top-0 z-10 h-full w-16 bg-gradient-to-l from-background to-transparent sm:w-24" />
115
116 <div className="flex animate-[testimonial-scroll_45s_linear_infinite] gap-6 py-3">
117 {testimonials.map((t) => (
118 <TestimonialCard key={`a-${t.author}`} {...t} />
119 ))}
120 {testimonials.map((t) => (
121 <TestimonialCard key={`b-${t.author}`} {...t} />
122 ))}
123 </div>
124 </div>
125
126 {/* 区切り */}
127 <div className="mx-auto h-px max-w-5xl bg-border/20" />
128
129 {/* 下段:右へスクロール */}
130 <div className="relative">
131 <div className="pointer-events-none absolute left-0 top-0 z-10 h-full w-16 bg-gradient-to-r from-background to-transparent sm:w-24" />
132 <div className="pointer-events-none absolute right-0 top-0 z-10 h-full w-16 bg-gradient-to-l from-background to-transparent sm:w-24" />
133
134 <div className="flex animate-[testimonial-scroll-reverse_50s_linear_infinite] gap-6 py-3">
135 {[...testimonials].reverse().map((t) => (
136 <TestimonialCard key={`c-${t.author}`} {...t} />
137 ))}
138 {[...testimonials].reverse().map((t) => (
139 <TestimonialCard key={`d-${t.author}`} {...t} />
140 ))}
141 </div>
142 </div>
143 </div>
144
145 {/* フッター */}
146 <div className="mx-auto mt-16 max-w-5xl px-4 sm:px-6 lg:px-8">
147 <div className="flex items-center justify-center gap-6">
148 <p className="text-[10px] tracking-[0.15em] text-muted-foreground/50">
149 500社以上の導入実績
150 </p>
151 <div className="h-3 w-px bg-border/40" />
152 <p className="text-[10px] tracking-[0.15em] text-muted-foreground/50">
153 顧客満足度 98.5%
154 </p>
155 </div>
156 </div>
157
158 <style
159 dangerouslySetInnerHTML={{
160 __html: `
161 @keyframes testimonial-scroll {
162 0% { transform: translateX(0); }
163 100% { transform: translateX(-50%); }
164 }
165 @keyframes testimonial-scroll-reverse {
166 0% { transform: translateX(-50%); }
167 100% { transform: translateX(0); }
168 }
169 `,
170 }}
171 />
172 </section>
173 );
174}