Skip to content

Commit 21348f1

Browse files
authored
Merge pull request #13 from vivliostyle/feature/header-redesign
Update header navigation and font
2 parents 54bef2d + 07eb897 commit 21348f1

2 files changed

Lines changed: 260 additions & 21 deletions

File tree

public/styles/global.css

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
Web Fonts - Google Fonts読み込み
1010
========================================================================== */
1111

12-
/* Noto Sans JP: 丸付き数字(❶-❿)を確実にカバー */
13-
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700&display=swap');
12+
/* Google Sans Flex: メインフォント */
13+
@import url('https://fonts.googleapis.com/css2?family=Google+Sans+Flex:opsz,wght@8..144,400;8..144,500;8..144,700&display=swap');
14+
15+
/* Noto Sans JP は日本語ページのみで読み込み */
1416

1517
/* 丸付き数字専用のフォント指定 (U+2776-U+277F) */
1618
@font-face {
@@ -48,8 +50,8 @@
4850
--color-border-dark: #cccccc;
4951

5052
/* タイポグラフィ */
51-
/* Noto Sans JP を先頭に配置、次に丸付き数字専用フォント */
52-
--font-sans: "Noto Sans JP", "Circled Numbers", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
53+
/* Google Sans Flex を先頭、次に日本語フォールバック */
54+
--font-sans: "Google Sans Flex", "Noto Sans JP", "Circled Numbers", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
5355
--font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
5456

5557
--font-size-base: 16px;

src/layouts/DocsLayout.astro

Lines changed: 254 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,56 @@ interface Props {
1717
1818
const { title, description = '', lang = 'en', showBreadcrumb = true, availableLanguages = [] } = Astro.props;
1919
const currentPath = Astro.url.pathname;
20+
21+
const isJa = lang === 'ja';
22+
const navLabels = isJa
23+
? {
24+
product: 'プロダクト',
25+
tutorial: 'チュートリアル',
26+
reference: 'リファレンス',
27+
faq: 'FAQ',
28+
docs: 'ドキュメント',
29+
contribution: 'コントリビューションガイド',
30+
}
31+
: {
32+
product: 'Product',
33+
tutorial: 'Tutorials',
34+
reference: 'Reference',
35+
faq: 'FAQ',
36+
docs: 'Documentation',
37+
contribution: 'Contribution Guides',
38+
};
39+
40+
const navLinks = {
41+
products: [
42+
{ label: 'Vivliostyle Viewer', href: `/${lang}/viewer/` },
43+
{ label: 'Vivliostyle CLI', href: `/${lang}/cli/` },
44+
{ label: 'VFM', href: `/${lang}/vfm/` },
45+
{ label: 'Vivliostyle Themes', href: `/${lang}/themes/` },
46+
],
47+
tutorial: {
48+
label: navLabels.tutorial,
49+
href: isJa ? 'https://vivliostyle.org/ja/tutorials/' : 'https://vivliostyle.org/en/tutorials/',
50+
external: true,
51+
},
52+
reference: {
53+
docs: [
54+
{ label: isJa ? 'サポートする CSS 機能' : 'Supported CSS Features', href: `/${lang}/reference/supported-css-features/` },
55+
{ label: isJa ? 'Core API リファレンス' : 'Core API Reference', href: `/${lang}/reference/api/` },
56+
],
57+
contribution: [
58+
{ label: 'Vivliostyle.js', href: `/${lang}/reference/contribution-guide/` },
59+
{ label: 'Vivliostyle CLI', href: `/${lang}/reference/contributing-cli/` },
60+
{ label: 'VFM', href: `/${lang}/reference/contributing-vfm/` },
61+
{ label: 'Vivliostyle Themes', href: `/${lang}/reference/contributing-themes/` },
62+
],
63+
},
64+
faq: {
65+
label: navLabels.faq,
66+
href: isJa ? 'https://vivliostyle.org/ja/faq/' : 'https://vivliostyle.org/en/faq/',
67+
external: true,
68+
},
69+
};
2070
---
2171
<!DOCTYPE html>
2272
<html lang={lang}>
@@ -36,6 +86,12 @@ const currentPath = Astro.url.pathname;
3686
))}
3787
<link rel="sitemap" href="/sitemap-index.xml">
3888
<link rel="stylesheet" href="/styles/global.css">
89+
{isJa && (
90+
<link
91+
rel="stylesheet"
92+
href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700&display=swap"
93+
/>
94+
)}
3995
<!-- Prism.js syntax highlighting -->
4096
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css" media="(prefers-color-scheme: light)">
4197
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" media="(prefers-color-scheme: dark)">
@@ -79,20 +135,56 @@ const currentPath = Astro.url.pathname;
79135
<a href={`/${lang}/`} class="logo">
80136
<img src="/vivliostyle-docs.svg" alt="Vivliostyle Docs" class="logo-image" />
81137
</a>
82-
<nav class="header-nav">
83-
<a href={`/${lang}/viewer/`}>Viewer</a>
84-
<a href={`/${lang}/cli/`}>CLI</a>
85-
<a href={`/${lang}/vfm/`}>VFM</a>
86-
<a href={`/${lang}/themes/`}>Themes</a>
87-
<a href={`/${lang}/reference/`}>Reference</a>
88-
<a href="https://github.com/vivliostyle" class="github-link" aria-label="GitHub" target="_blank" rel="noopener noreferrer">
89-
<svg viewBox="0 0 16 16" width="24" height="24" fill="currentColor">
90-
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
91-
</svg>
138+
<nav class="header-nav" aria-label={isJa ? 'グローバルナビゲーション' : 'Global navigation'}>
139+
<details class="nav-accordion">
140+
<summary>{navLabels.product}</summary>
141+
<div class="nav-panel">
142+
{navLinks.products.map((item) => (
143+
<a href={item.href}>{item.label}</a>
144+
))}
145+
</div>
146+
</details>
147+
<a
148+
href={navLinks.tutorial.href}
149+
target={navLinks.tutorial.external ? '_blank' : undefined}
150+
rel={navLinks.tutorial.external ? 'noopener noreferrer' : undefined}
151+
>
152+
{navLinks.tutorial.label}
92153
</a>
93-
<a href={lang === 'ja' ? 'https://vivliostyle.org/ja/' : 'https://vivliostyle.org/'} class="vivliostyle-link" aria-label="Vivliostyle" target="_blank" rel="noopener noreferrer">
94-
<img src="/vivliostyle-logo72.png" alt="Vivliostyle" class="vivliostyle-icon" />
154+
<details class="nav-accordion">
155+
<summary>{navLabels.reference}</summary>
156+
<div class="nav-panel">
157+
<div class="nav-group">
158+
<h3 class="nav-group-title">{navLabels.docs}</h3>
159+
{navLinks.reference.docs.map((item) => (
160+
<a href={item.href}>{item.label}</a>
161+
))}
162+
</div>
163+
<div class="nav-group">
164+
<h3 class="nav-group-title">{navLabels.contribution}</h3>
165+
{navLinks.reference.contribution.map((item) => (
166+
<a href={item.href}>{item.label}</a>
167+
))}
168+
</div>
169+
</div>
170+
</details>
171+
<a
172+
href={navLinks.faq.href}
173+
target={navLinks.faq.external ? '_blank' : undefined}
174+
rel={navLinks.faq.external ? 'noopener noreferrer' : undefined}
175+
>
176+
{navLinks.faq.label}
95177
</a>
178+
<div class="nav-icon-links">
179+
<a href="https://github.com/vivliostyle" class="github-link" aria-label="GitHub" target="_blank" rel="noopener noreferrer">
180+
<svg viewBox="0 0 16 16" width="24" height="24" fill="currentColor">
181+
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
182+
</svg>
183+
</a>
184+
<a href={lang === 'ja' ? 'https://vivliostyle.org/ja/' : 'https://vivliostyle.org/'} class="vivliostyle-link" aria-label="Vivliostyle" target="_blank" rel="noopener noreferrer">
185+
<img src="/vivliostyle-logo72.png" alt="Vivliostyle" class="vivliostyle-icon" />
186+
</a>
187+
</div>
96188
</nav>
97189
<div class="header-actions">
98190
<SearchBox lang={lang as 'en' | 'ja'} />
@@ -192,20 +284,105 @@ const currentPath = Astro.url.pathname;
192284

193285
.header-nav {
194286
display: flex;
195-
gap: 1.5rem;
287+
gap: 1rem;
196288
flex: 1;
197289
align-items: center;
290+
min-width: 0;
198291
}
199-
292+
200293
.header-nav a {
201294
color: var(--color-text);
202295
text-decoration: none;
203296
font-weight: 500;
297+
font-size: 0.95rem;
204298
}
205-
206-
.header-nav a:hover {
299+
300+
.header-nav summary {
301+
list-style: none;
302+
cursor: pointer;
303+
display: flex;
304+
align-items: center;
305+
gap: 0.35rem;
306+
font-size: 1.1rem;
307+
}
308+
309+
.header-nav summary::-webkit-details-marker {
310+
display: none;
311+
}
312+
313+
.header-nav summary::after {
314+
content: '';
315+
width: 0;
316+
height: 0;
317+
border-left: 4px solid transparent;
318+
border-right: 4px solid transparent;
319+
border-top: 5px solid currentColor;
320+
opacity: 0.6;
321+
transition: transform 0.2s ease;
322+
}
323+
324+
.header-nav a:hover,
325+
.header-nav summary:hover {
326+
color: var(--color-primary);
327+
}
328+
329+
.nav-accordion {
330+
position: relative;
331+
}
332+
333+
.nav-accordion[open] summary::after {
334+
transform: rotate(180deg);
335+
}
336+
337+
.nav-panel {
338+
position: absolute;
339+
top: calc(100% + 0.5rem);
340+
left: 0;
341+
background: var(--color-bg);
342+
border: 1px solid var(--color-border);
343+
border-radius: 8px;
344+
padding: 0.75rem;
345+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
346+
display: none;
347+
min-width: 240px;
348+
z-index: 1200;
349+
}
350+
351+
.nav-accordion[open] .nav-panel {
352+
display: grid;
353+
gap: 0.75rem;
354+
}
355+
356+
.nav-group {
357+
display: grid;
358+
gap: 0.4rem;
359+
}
360+
361+
.nav-group-title {
362+
font-size: 1rem;
363+
font-weight: 600;
364+
color: var(--color-text-muted);
365+
letter-spacing: 0.02em;
366+
margin: 0;
367+
}
368+
369+
.nav-panel a {
370+
font-weight: 500;
371+
font-size: 0.9rem;
372+
color: var(--color-text);
373+
padding-left: 1rem;
374+
}
375+
376+
.nav-panel a:hover {
207377
color: var(--color-primary);
208378
}
379+
380+
.nav-icon-links {
381+
margin-left: auto;
382+
display: flex;
383+
align-items: center;
384+
gap: 0.5rem;
385+
}
209386

210387
.header-nav .github-link,
211388
.header-nav .vivliostyle-link {
@@ -484,6 +661,17 @@ const currentPath = Astro.url.pathname;
484661

485662
.header-nav {
486663
gap: 0.5rem;
664+
}
665+
666+
.header-nav a {
667+
font-size: 0.9rem;
668+
}
669+
670+
.header-nav summary {
671+
font-size: 1rem;
672+
}
673+
674+
.nav-panel a {
487675
font-size: 0.85rem;
488676
}
489677

@@ -682,11 +870,60 @@ const currentPath = Astro.url.pathname;
682870
}, 250);
683871
});
684872
};
873+
874+
// ヘッダーナビのアコーディオン制御
875+
const initNavAccordions = () => {
876+
const accordions = Array.from(document.querySelectorAll('.nav-accordion')) as HTMLDetailsElement[];
877+
if (!accordions.length) {
878+
return;
879+
}
880+
881+
const closeAll = () => {
882+
accordions.forEach((accordion) => {
883+
if (accordion.open) {
884+
accordion.removeAttribute('open');
885+
}
886+
});
887+
};
888+
889+
accordions.forEach((accordion) => {
890+
accordion.addEventListener('toggle', () => {
891+
if (!accordion.open) {
892+
return;
893+
}
894+
accordions.forEach((other) => {
895+
if (other !== accordion) {
896+
other.removeAttribute('open');
897+
}
898+
});
899+
});
900+
});
901+
902+
document.addEventListener('click', (event) => {
903+
const target = event.target;
904+
if (!(target instanceof Node)) {
905+
return;
906+
}
907+
if (!target.closest('.nav-accordion')) {
908+
closeAll();
909+
}
910+
});
911+
912+
document.addEventListener('keydown', (event) => {
913+
if (event.key === 'Escape') {
914+
closeAll();
915+
}
916+
});
917+
};
685918

686919
// DOMContentLoaded時に初期化
687920
if (document.readyState === 'loading') {
688-
document.addEventListener('DOMContentLoaded', initMobileMenu);
921+
document.addEventListener('DOMContentLoaded', () => {
922+
initMobileMenu();
923+
initNavAccordions();
924+
});
689925
} else {
690926
initMobileMenu();
927+
initNavAccordions();
691928
}
692929
</script>

0 commit comments

Comments
 (0)