ブログ/

著者別ブログセクション

Preview

著者ごとに記事をグルーピングして表示するブログセクション。アバターと役職付きの著者情報で信頼性を演出

Source Code
tsx
158 lines
1export function BlogAuthors001() {
2 const authors = [
3 {
4 name: "佐藤 美咲",
5 role: "デザインリード",
6 initial: "S",
7 posts: [
8 {
9 title: "余白が語るデザインの意図",
10 excerpt:
11 "ホワイトスペースは単なる空白ではなく、情報の優先度と視覚的リズムを制御する重要な設計要素です。",
12 date: "2024.03.12",
13 readTime: "6 min",
14 },
15 {
16 title: "色彩設計とアクセシビリティの両立",
17 excerpt:
18 "美しさとコントラスト比を同時に満たすカラーパレットの構築手法。",
19 date: "2024.02.28",
20 readTime: "5 min",
21 },
22 ],
23 },
24 {
25 name: "田中 健一",
26 role: "エンジニアリングマネージャー",
27 initial: "T",
28 posts: [
29 {
30 title: "コンポーネント設計の原則と実践",
31 excerpt:
32 "再利用性と保守性を両立するコンポーネントアーキテクチャの構築について。",
33 date: "2024.03.05",
34 readTime: "8 min",
35 },
36 {
37 title: "ビルドパフォーマンスの改善記録",
38 excerpt:
39 "開発体験を向上させるために実施したビルド最適化の具体的な施策と結果。",
40 date: "2024.02.15",
41 readTime: "7 min",
42 },
43 ],
44 },
45 ];
46
47 return (
48 <section className="bg-background py-28 border-t border-border">
49 <div className="mx-auto max-w-5xl px-4 sm:px-6 lg:px-8">
50 {/* ヘッダー */}
51 <div className="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
52 <div>
53 <p className="text-[10px] uppercase tracking-[0.3em] text-muted-foreground">
54 From Our Team
55 </p>
56 <h2 className="mt-3 text-2xl font-medium tracking-wide text-foreground sm:text-3xl">
57 著者別の記事
58 </h2>
59 </div>
60 <a
61 href="#"
62 className="inline-flex items-center gap-2 text-xs uppercase tracking-[0.2em] text-muted-foreground transition-colors duration-200 hover:text-foreground"
63 >
64 すべての記事
65 <svg
66 className="h-3.5 w-3.5"
67 fill="none"
68 stroke="currentColor"
69 viewBox="0 0 24 24"
70 >
71 <path
72 strokeLinecap="round"
73 strokeLinejoin="round"
74 strokeWidth={1.5}
75 d="M17 8l4 4m0 0l-4 4m4-4H3"
76 />
77 </svg>
78 </a>
79 </div>
80
81 <div className="mt-4 h-px bg-border/40" />
82
83 {/* 著者セクション */}
84 <div className="mt-16 space-y-20">
85 {authors.map((author) => (
86 <div key={author.name}>
87 {/* 著者情報 */}
88 <div className="flex items-center gap-4">
89 <div className="flex h-10 w-10 items-center justify-center rounded-full border border-border bg-muted">
90 <span className="text-xs font-medium tracking-wide text-foreground">
91 {author.initial}
92 </span>
93 </div>
94 <div>
95 <p className="text-sm font-medium tracking-wide text-foreground">
96 {author.name}
97 </p>
98 <p className="mt-0.5 text-[10px] uppercase tracking-[0.2em] text-muted-foreground/60">
99 {author.role}
100 </p>
101 </div>
102 </div>
103
104 {/* 記事リスト */}
105 <div className="mt-6 divide-y divide-border/40">
106 {author.posts.map((post) => (
107 <a
108 key={post.title}
109 href="#"
110 className="group block py-6 first:pt-0"
111 >
112 <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between sm:gap-12">
113 <div className="flex-1">
114 <h3 className="text-base font-medium tracking-wide text-foreground transition-colors duration-200 group-hover:text-muted-foreground">
115 {post.title}
116 </h3>
117 <p className="mt-2 text-sm font-light leading-relaxed text-muted-foreground">
118 {post.excerpt}
119 </p>
120 </div>
121 <div className="flex shrink-0 items-center gap-3 text-[10px] tracking-[0.15em] text-muted-foreground/50 sm:flex-col sm:items-end sm:gap-1.5">
122 <span>{post.date}</span>
123 <div className="h-3 w-px bg-border/40 sm:hidden" />
124 <div className="flex items-center gap-1.5">
125 <svg
126 className="h-3 w-3"
127 fill="none"
128 stroke="currentColor"
129 viewBox="0 0 24 24"
130 >
131 <path
132 strokeLinecap="round"
133 strokeLinejoin="round"
134 strokeWidth={1.5}
135 d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z"
136 />
137 </svg>
138 {post.readTime}
139 </div>
140 </div>
141 </div>
142 </a>
143 ))}
144 </div>
145 </div>
146 ))}
147 </div>
148
149 {/* フッター装飾 */}
150 <div className="mt-20 flex items-center justify-center gap-4">
151 <div className="h-px w-8 bg-border/40" />
152 <div className="h-1.5 w-1.5 rounded-full bg-foreground/20" />
153 <div className="h-px w-8 bg-border/40" />
154 </div>
155 </div>
156 </section>
157 );
158}