Skip to content

Commit 7d4c133

Browse files
committed
ui(site): frontend-design スキルで装飾・表現を磨き込み
Editorial × Developer 言語で公開サイトを再構成。ミニマリズムを保ったまま 「ソフトウェア開発サークルらしい」装飾レイヤーを追加。 - Hero: 座標スタンプ・コーナーティック・プライマリ下線ハイライト・build stamp - StatsSection / ActivitiesSection: 01/04 インデックス、ホバー下辺ライン、見出し二段組 - ProjectsSection / ArticlesSection: float カード、ホバーで矢印フェードイン - JoinCTA: ドットグリッド + 二重 radial glow、[01]/[02] 番号付き CTA - SponsorsSection: コーナーティック付きフレーム - AboutSection: 二段組 + sticky 見出し、ナンバー付き datasheet - about / faq / activities / join / donation: フルブリードヒーロー、章番号、 タイムライン、bank-info datasheet 等のページ固有装飾 - Articles 一覧/詳細: /// eyebrow、entry counter、editorial レイアウト - Projects 一覧/詳細: <projects /> eyebrow、filter pills、status badge 強化 - Members 一覧/詳細: @handle 表示、大型 avatar + halo ring、social pill 化 - Search: ~/search プロンプト、$ シェル風入力、blink caret 空状態 - Markdown: h3 § マーク、code chip、pre dark panel、blockquote primary bar - Pagination: mono arrows、current page lift、page X / N カウンタ すべての装飾は prefers-reduced-motion 尊重、focus ring / aria / alt は維持、 touch target ≥ 44px、新規依存ゼロ。bun tidy / build クリーン通過。
1 parent 507aa53 commit 7d4c133

24 files changed

Lines changed: 2298 additions & 1018 deletions

src/lib/components/ImageSection.svelte

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@
1212
const { title, image, imageAlt = "", alignImage, children }: Props = $props();
1313
</script>
1414

15+
<!--
16+
image-section --- alternating image-and-text block.
17+
Image gets subtle scale-on-hover. Title has a primary tick prefix.
18+
-->
1519
<section class="mt-16 lg:grid lg:items-center">
1620
<div style:grid-area="1 / 1">
1721
<div
18-
class="isolate h-[300px] overflow-clip md:h-[400px] lg:h-[500px] lg:w-1/2 xl:h-[600px] {alignImage ===
22+
class="group isolate h-[300px] overflow-clip md:h-[400px] lg:h-[500px] lg:w-1/2 xl:h-[600px] {alignImage ===
1923
'left'
2024
? 'lg:rounded-r-2xl'
2125
: 'lg:ml-auto lg:rounded-l-2xl'}"
@@ -25,14 +29,20 @@
2529
alt={imageAlt}
2630
loading="lazy"
2731
decoding="async"
28-
class="h-full w-full object-cover"
32+
class="h-full w-full object-cover transition-transform duration-700 group-hover:scale-[1.03]"
2933
/>
3034
</div>
3135
</div>
3236
<div style:grid-area="1 / 1" class="container mx-auto lg:max-w-screen-lg">
3337
<div class="p-8 lg:w-1/2 {alignImage === 'left' ? 'lg:ml-auto' : ''}">
34-
<h2 class="text-3xl font-bold text-zinc-900 lg:text-4xl">{title}</h2>
35-
<div class="mt-4 space-y-4 text-zinc-600">
38+
<div class="mb-3 flex items-center gap-2 font-mono text-[11px] tracking-widest text-primary uppercase">
39+
<span class="inline-block h-px w-5 bg-primary"></span>
40+
<span>topic</span>
41+
</div>
42+
<h2 class="text-3xl leading-tight font-bold tracking-tight text-zinc-900 lg:text-4xl">
43+
{title}
44+
</h2>
45+
<div class="mt-5 space-y-4 leading-relaxed text-zinc-600">
3646
{@render children()}
3747
</div>
3848
</div>

src/lib/components/Markdown.svelte

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,47 @@
1414
});
1515
</script>
1616

17-
<div class="prose max-w-none prose-zinc prose-headings:text-zinc-900 prose-p:text-zinc-700 prose-a:text-primary hover:prose-a:underline">
17+
<!--
18+
Editorial prose for site content. Tuned for "developer-editorial" feel:
19+
- h2 has a thin bottom rule; h3 carries a primary section mark
20+
- inline code uses zinc-100 chip with mono; code blocks use zinc-900 panel
21+
- blockquote takes a primary left bar
22+
- links use offset underline with primary decoration on hover
23+
-->
24+
<div class="markdown-prose prose max-w-none prose-zinc
25+
prose-headings:text-zinc-900 prose-headings:font-semibold prose-headings:tracking-tight
26+
prose-h2:mt-12 prose-h2:mb-4 prose-h2:pb-2 prose-h2:text-2xl prose-h2:border-b prose-h2:border-zinc-200
27+
prose-h3:mt-8 prose-h3:mb-3 prose-h3:text-xl
28+
prose-p:text-zinc-700 prose-p:leading-relaxed
29+
prose-a:text-primary prose-a:no-underline hover:prose-a:underline hover:prose-a:underline-offset-4
30+
prose-strong:text-zinc-900
31+
prose-blockquote:border-l-2 prose-blockquote:border-primary prose-blockquote:bg-zinc-50/60 prose-blockquote:py-1 prose-blockquote:not-italic prose-blockquote:text-zinc-600
32+
prose-code:before:content-none prose-code:after:content-none prose-code:bg-zinc-100 prose-code:text-zinc-800 prose-code:rounded prose-code:px-1.5 prose-code:py-0.5 prose-code:text-[0.875em] prose-code:font-medium
33+
prose-pre:bg-zinc-900 prose-pre:text-zinc-100 prose-pre:rounded-xl prose-pre:shadow-inner prose-pre:border prose-pre:border-zinc-800
34+
prose-img:rounded-xl prose-img:border prose-img:border-zinc-200/60
35+
prose-hr:border-zinc-200
36+
prose-li:marker:text-primary/70">
1837
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
1938
{@html html}
2039
</div>
40+
41+
<style>
42+
/* H3 section mark — a subtle § that signals depth without shouting. */
43+
.markdown-prose :global(h3::before) {
44+
content: "§";
45+
color: oklch(76% 0.2 153);
46+
margin-right: 0.5rem;
47+
font-weight: 500;
48+
opacity: 0.7;
49+
}
50+
51+
/* Code blocks: nudge inline children back to inherit so the chip-style
52+
prose-code rule doesn't compete with the dark pre background. */
53+
.markdown-prose :global(pre code) {
54+
background-color: transparent;
55+
color: inherit;
56+
padding: 0;
57+
font-size: 0.875em;
58+
font-weight: 400;
59+
}
60+
</style>
Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
<!--
2+
Pagination
3+
- Visual rhythm: prev/next anchored by mono arrows; current page lifted with subtle ring + shadow
4+
- Page number cells are square-ish for typographic rhythm; mono numerals reinforce data feel
5+
- Touch targets ≥ 44px via min-h-11 on all interactive cells
6+
-->
17
<script lang="ts">
28
interface Props {
39
currentPage: number;
@@ -9,53 +15,73 @@
915
</script>
1016

1117
{#if totalPages > 1}
12-
<div class="mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row sm:gap-4">
18+
<nav
19+
aria-label="ページネーション"
20+
class="mt-12 flex flex-col items-center justify-center gap-3 sm:flex-row sm:gap-2"
21+
>
1322
{#if currentPage > 1}
1423
<a
1524
href={pageUrl(currentPage - 1)}
16-
class="w-full rounded-lg border border-zinc-200 bg-white px-4 py-2 text-center text-sm font-medium transition-colors hover:bg-primary/5 hover:border-primary/30 hover:text-primary focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 sm:w-auto"
25+
class="group inline-flex min-h-11 w-full items-center justify-center gap-2 rounded-lg border border-zinc-200 bg-white px-4 py-2 text-sm font-medium transition-all hover:bg-primary/5 hover:border-primary/30 hover:text-primary focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 sm:w-auto"
26+
rel="prev"
1727
>
28+
<span aria-hidden="true" class="font-[JetBrains_Mono,monospace] transition-transform group-hover:-translate-x-0.5">←</span>
1829
前へ
1930
</a>
2031
{:else}
2132
<span
22-
class="w-full cursor-not-allowed rounded-lg border border-zinc-200 bg-white px-4 py-2 text-center text-sm font-medium opacity-50 sm:w-auto"
33+
class="inline-flex min-h-11 w-full cursor-not-allowed items-center justify-center gap-2 rounded-lg border border-zinc-200 bg-white px-4 py-2 text-sm font-medium opacity-40 sm:w-auto"
34+
aria-hidden="true"
2335
>
36+
<span class="font-[JetBrains_Mono,monospace]">←</span>
2437
前へ
2538
</span>
2639
{/if}
2740

28-
<div class="flex flex-1 flex-wrap items-center justify-center gap-1 sm:flex-initial">
41+
<div class="flex flex-1 flex-wrap items-center justify-center gap-1 sm:mx-2 sm:flex-initial">
2942
{#each Array.from({ length: totalPages }, (_, i) => i + 1) as pageNum (pageNum)}
3043
{#if totalPages <= 7 || pageNum === 1 || pageNum === totalPages || Math.abs(pageNum - currentPage) <= 1}
3144
<a
3245
href={pageUrl(pageNum)}
33-
class="min-w-[2.5rem] rounded-lg border px-3 py-2 text-center text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 {currentPage ===
46+
aria-current={currentPage === pageNum ? "page" : undefined}
47+
aria-label="ページ {pageNum}"
48+
class="flex min-h-11 min-w-11 items-center justify-center rounded-lg border px-3 py-2 text-center font-[JetBrains_Mono,monospace] text-sm font-medium transition-all focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 {currentPage ===
3449
pageNum
35-
? 'border-primary bg-primary text-white'
36-
: 'border-zinc-200 bg-white hover:bg-primary/5 hover:border-primary/30 hover:text-primary'}"
50+
? 'border-primary bg-primary text-white shadow-md shadow-primary/20'
51+
: 'border-zinc-200 bg-white text-zinc-700 hover:bg-primary/5 hover:border-primary/30 hover:text-primary hover:-translate-y-px'}"
3752
>
3853
{pageNum}
3954
</a>
4055
{:else if pageNum === currentPage - 2 || pageNum === currentPage + 2}
41-
<span class="px-1 text-zinc-500">...</span>
56+
<span
57+
class="flex min-h-11 w-6 items-center justify-center font-[JetBrains_Mono,monospace] text-zinc-400"
58+
aria-hidden="true">···</span
59+
>
4260
{/if}
4361
{/each}
4462
</div>
4563

4664
{#if currentPage < totalPages}
4765
<a
4866
href={pageUrl(currentPage + 1)}
49-
class="w-full rounded-lg border border-zinc-200 bg-white px-4 py-2 text-center text-sm font-medium transition-colors hover:bg-primary/5 hover:border-primary/30 hover:text-primary focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 sm:w-auto"
67+
class="group inline-flex min-h-11 w-full items-center justify-center gap-2 rounded-lg border border-zinc-200 bg-white px-4 py-2 text-sm font-medium transition-all hover:bg-primary/5 hover:border-primary/30 hover:text-primary focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 sm:w-auto"
68+
rel="next"
5069
>
5170
次へ
71+
<span aria-hidden="true" class="font-[JetBrains_Mono,monospace] transition-transform group-hover:translate-x-0.5">→</span>
5272
</a>
5373
{:else}
5474
<span
55-
class="w-full cursor-not-allowed rounded-lg border border-zinc-200 bg-white px-4 py-2 text-center text-sm font-medium opacity-50 sm:w-auto"
75+
class="inline-flex min-h-11 w-full cursor-not-allowed items-center justify-center gap-2 rounded-lg border border-zinc-200 bg-white px-4 py-2 text-sm font-medium opacity-40 sm:w-auto"
76+
aria-hidden="true"
5677
>
5778
次へ
79+
<span class="font-[JetBrains_Mono,monospace]">→</span>
5880
</span>
5981
{/if}
60-
</div>
82+
</nav>
83+
84+
<p class="mt-3 text-center font-[JetBrains_Mono,monospace] text-[11px] text-zinc-400">
85+
page {currentPage} / {totalPages}
86+
</p>
6187
{/if}

src/lib/components/home/AboutSection.svelte

Lines changed: 86 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,47 +8,98 @@
88
const { members }: Props = $props();
99
1010
const currentYear = new Date().getFullYear();
11+
12+
type Row = { label: string; value: string };
13+
14+
const rows: Row[] = $derived([
15+
{ label: "団体名", value: "ut.code();" },
16+
{ label: "部員", value: `${members}名程度` },
17+
{ label: "所属", value: `東京大学工学部丁友会 (${currentYear}年度)` },
18+
{ label: "部室", value: "駒場キャンパス学生会館 313B 教室" },
19+
{ label: "活動場所", value: "オンライン, 部室, 本郷図書館プロジェクトボックス等" },
20+
]);
1121
</script>
1222

13-
<section class="bg-white py-24">
23+
<!--
24+
about --- "spec sheet" treatment. Two-column layout on desktop:
25+
left = heading + tagline, right = key/value rows like a tech datasheet.
26+
-->
27+
<section class="relative bg-white py-24">
1428
<div class="mx-auto max-w-6xl px-6">
15-
<div class="mb-16 text-center">
16-
<div class="mb-4 font-mono text-sm font-medium uppercase tracking-widest text-primary">ABOUT US</div>
17-
<h2 class="text-5xl font-bold text-zinc-900 lg:text-6xl">
18-
団体概要
19-
</h2>
20-
</div>
21-
<div class="mx-auto max-w-4xl">
22-
<div class="divide-y divide-zinc-100 rounded-2xl border border-zinc-200 bg-white">
23-
{#each [{ label: "団体名", value: "ut.code();" }, { label: "部員", value: `${members}名程度` }, { label: "所属", value: `東京大学工学部丁友会 (${currentYear}年度)` }, { label: "部室", value: "駒場キャンパス学生会館 313B 教室" }, { label: "活動場所", value: "オンライン, 部室, 本郷図書館プロジェクトボックス等" }] as item (item.label)}
24-
<div class="flex flex-col gap-2 px-6 py-5 sm:flex-row sm:gap-0 sm:px-8 sm:py-6">
25-
<span class="w-full shrink-0 font-mono text-sm font-medium text-primary sm:w-36">{item.label}</span>
26-
<span class="text-zinc-700">{item.value}</span>
27-
</div>
28-
{/each}
29-
<div class="flex flex-col gap-3 px-6 py-5 sm:flex-row sm:items-center sm:gap-0 sm:px-8 sm:py-6">
30-
<span class="w-full shrink-0 font-mono text-sm font-medium text-primary sm:w-36">SNS</span>
31-
<div class="flex flex-wrap gap-4">
32-
<a
33-
href="https://github.com/ut-code"
34-
target="_blank"
35-
rel="noopener noreferrer"
36-
class="group flex items-center gap-2 rounded-lg border border-zinc-200 bg-white px-4 py-2 text-zinc-700 transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
29+
<div class="grid gap-12 lg:grid-cols-[1fr_1.4fr] lg:gap-16">
30+
<!-- Left: heading -->
31+
<div class="lg:sticky lg:top-24 lg:self-start">
32+
<div
33+
class="mb-4 flex items-center gap-3 font-mono text-[11px] tracking-widest text-primary uppercase"
34+
>
35+
<span class="inline-block h-px w-6 bg-primary"></span>
36+
<span>// about us</span>
37+
</div>
38+
<h2 class="text-4xl leading-[1.1] font-bold tracking-tight text-zinc-900 sm:text-5xl">
39+
団体概要
40+
</h2>
41+
<p class="mt-5 max-w-md leading-relaxed text-zinc-600">
42+
ut.code(); の組織情報、活動場所、ソーシャル。基礎データをひと目で。
43+
</p>
44+
45+
<!-- decorative file-stamp -->
46+
<div
47+
class="mt-8 inline-block rounded-lg border border-zinc-200 bg-zinc-50 px-3 py-1.5 font-mono text-[11px] tracking-wider text-zinc-500"
48+
>
49+
<span class="text-primary">●</span>
50+
<span class="ml-2">fy{currentYear} / public</span>
51+
</div>
52+
</div>
53+
54+
<!-- Right: spec sheet -->
55+
<div>
56+
<dl
57+
class="divide-y divide-zinc-100 overflow-hidden rounded-2xl border border-zinc-200 bg-white"
58+
>
59+
{#each rows as item, i (item.label)}
60+
<div
61+
class="grid grid-cols-[auto_1fr] items-baseline gap-x-4 gap-y-1 px-6 py-5 transition-colors hover:bg-zinc-50/50 sm:grid-cols-[10rem_1fr] sm:gap-x-6 sm:px-8 sm:py-6"
3762
>
38-
<Github class="h-5 w-5" />
39-
<span>ut-code</span>
40-
</a>
41-
<a
42-
href="https://x.com/utokyo_code"
43-
target="_blank"
44-
rel="noopener noreferrer"
45-
class="group flex items-center gap-2 rounded-lg border border-zinc-200 bg-white px-4 py-2 text-zinc-700 transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
63+
<dt
64+
class="font-mono text-[11px] tracking-widest text-zinc-400 uppercase sm:text-xs"
65+
>
66+
<span class="text-primary">{String(i + 1).padStart(2, "0")}</span>
67+
<span class="ml-2 text-zinc-500">{item.label}</span>
68+
</dt>
69+
<dd class="text-zinc-800">{item.value}</dd>
70+
</div>
71+
{/each}
72+
<div
73+
class="grid grid-cols-[auto_1fr] items-baseline gap-x-4 gap-y-3 px-6 py-5 transition-colors hover:bg-zinc-50/50 sm:grid-cols-[10rem_1fr] sm:items-center sm:gap-x-6 sm:px-8 sm:py-6"
74+
>
75+
<dt
76+
class="font-mono text-[11px] tracking-widest text-zinc-400 uppercase sm:text-xs"
4677
>
47-
<Twitter class="h-5 w-5" />
48-
<span>@utokyo_code</span>
49-
</a>
78+
<span class="text-primary">{String(rows.length + 1).padStart(2, "0")}</span>
79+
<span class="ml-2 text-zinc-500">SNS</span>
80+
</dt>
81+
<dd class="flex flex-wrap gap-2">
82+
<a
83+
href="https://github.com/ut-code"
84+
target="_blank"
85+
rel="noopener noreferrer"
86+
class="group inline-flex min-h-11 items-center gap-2 rounded-lg border border-zinc-200 bg-white px-4 py-2 text-sm text-zinc-700 transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:outline-none"
87+
>
88+
<Github class="h-4 w-4" />
89+
<span class="font-mono">ut-code</span>
90+
</a>
91+
<a
92+
href="https://x.com/utokyo_code"
93+
target="_blank"
94+
rel="noopener noreferrer"
95+
class="group inline-flex min-h-11 items-center gap-2 rounded-lg border border-zinc-200 bg-white px-4 py-2 text-sm text-zinc-700 transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:outline-none"
96+
>
97+
<Twitter class="h-4 w-4" />
98+
<span class="font-mono">@utokyo_code</span>
99+
</a>
100+
</dd>
50101
</div>
51-
</div>
102+
</dl>
52103
</div>
53104
</div>
54105
</div>

0 commit comments

Comments
 (0)