feat: content-UX — header search, metadata de-noise, icon/microcopy coherence, article composition

This commit is contained in:
ctao
2026-07-25 07:32:11 +02:00
parent a8833ce736
commit 419e9a2dd1
12 changed files with 361 additions and 119 deletions
+62 -19
View File
@@ -11,12 +11,15 @@ const ogImage = new URL(image || '/brand/og-card.jpg', site);
const path = Astro.url.pathname;
const isActive = (href) => (href === '/' ? path === '/' : path.startsWith(href));
// Navigation = services from the Science Portal spec (REQUIREMENTS.md §2/§5).
// External systems built by other teams are links out, clearly marked.
// Order: serial-position effect (NN/g) — News (universal entry) first, Support
// (help convention) last; Data/Proposals by task frequency; Dashboard is the
// personal area, placed late next to the Sign-in cluster. External systems
// built by other teams are links out, clearly marked.
const links = [
{ href: '/news', label: 'News' },
{ href: 'https://padc-ctao-data-explorer.obspm.fr/', label: 'Data', ext: true },
{ href: '/proposals', label: 'Proposals' },
{ href: '/dashboard', label: 'Dashboard' },
{ href: 'https://padc-ctao-data-explorer.obspm.fr/', label: 'Data', ext: true },
{ href: '/support', label: 'Support' },
];
---
@@ -45,6 +48,15 @@ const links = [
</head>
<body class={ambient ? 'has-ambient' : undefined}>
<a class="skip" href="#main">Skip to content</a>
{/* Demo disclosure — GOV.UK phase-banner pattern: one slim, honest banner
instead of implementation talk scattered through the UI. Not sticky;
it scrolls away and the header sticks below it. */}
<div class="phase-banner">
<div class="container">
<strong class="phase-tag">Demo</strong>
<span>This is a demonstration of the CTAO Science Portal — content is sample data.</span>
</div>
</div>
<header class="site-header">
<div class="container nav">
<a class="brand" href="/" aria-label="CTAO Science Portal — home">
@@ -59,17 +71,37 @@ const links = [
))}
</nav>
<span class="spacer"></span>
<a class="navlink" href="/search">Search</a>
<a class="navlink navlink--edit" href="/admin" title="Content editor (demo CMS)">
<svg class="ico" aria-hidden="true" viewBox="0 0 24 24"><path d="M17 3l4 4L8 20l-5 1 1-5L17 3z" /></svg>
Editor
</a>
{/* Site search lives in the header (desktop: compact field; ≤1024px: the
magnifier <details> below). Plain GET form — works without JS; with JS
the shared suggest dropdown appears (search-client.js). */}
<form class="nav-search" role="search" aria-label="Site search" action="/search" method="get">
<label class="sr-only" for="hdr-q">Search news</label>
<svg class="ico search-ico" aria-hidden="true" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7" /><path d="m20 20-4.3-4.3" /></svg>
<input id="hdr-q" name="q" type="search" placeholder="Search…" autocomplete="off" />
<ul class="suggest" id="hdr-suggest"></ul>
<p class="sr-only" id="hdr-suggest-status" role="status" aria-live="polite"></p>
</form>
<a class="login-mock" href="/login">Sign in</a>
{/* ≤1024px: magnifier button reveals a full-width search row. name="header-panel"
pairs it with the menu as a native exclusive group — opening one closes
the other, no JS (exclusive-accordion behavior of <details name>). */}
<details class="search-pop" name="header-panel">
<summary aria-label="Search">
<svg class="ico" aria-hidden="true" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7" /><path d="m20 20-4.3-4.3" /></svg>
</summary>
<form role="search" aria-label="Site search" action="/search" method="get">
<label class="sr-only" for="pop-q">Search news</label>
<input id="pop-q" name="q" type="search" placeholder="Search news…" autocomplete="off" />
<button class="btn" type="submit">Search</button>
<ul class="suggest" id="pop-suggest"></ul>
<p class="sr-only" id="pop-suggest-status" role="status" aria-live="polite"></p>
</form>
</details>
{/* Mobile disclosure menu — native <details>/<summary>, no JS; desktop hides it via CSS */}
<details class="menu">
<summary>
<details class="menu" name="header-panel">
<summary aria-label="Menu">
<svg class="ico" aria-hidden="true" viewBox="0 0 24 24"><path class="i-menu" d="M3 6h18M3 12h18M3 18h18" /><path class="i-close" d="M5 5l14 14M19 5 5 19" /></svg>
Menu
<span class="menu-label">Menu</span>
</summary>
<nav aria-label="Main navigation">
{links.map((l) => l.ext ? (
@@ -77,12 +109,21 @@ const links = [
) : (
<a href={l.href} aria-current={isActive(l.href) ? 'page' : undefined}>{l.label}</a>
))}
<a href="/search">Search</a>
<a href="/admin">Editor</a>
</nav>
</details>
</div>
</header>
<script is:inline src="/search-client.js"></script>
<script is:inline>
// Header search suggestions (desktop field + mobile reveal); the forms are
// plain GET /search, so everything below is progressive enhancement.
newsSearch({ input: 'hdr-q', list: 'hdr-suggest', status: 'hdr-suggest-status', limit: 6, unit: 'suggestion' });
newsSearch({ input: 'pop-q', list: 'pop-suggest', status: 'pop-suggest-status', limit: 6, unit: 'suggestion' });
var pop = document.querySelector('.search-pop');
pop.addEventListener('toggle', function () {
if (pop.open) document.getElementById('pop-q').focus();
});
</script>
<main id="main">
<slot />
</main>
@@ -92,23 +133,25 @@ const links = [
<div class="container">
<div class="foot-top">
<img src="/brand/AAFF_CTAO_Logo_RGB_Monochrome-negative.svg" alt="CTAO" />
<p>Science Portal — news, observation proposals, data and user services of the
Cherenkov Telescope Array Observatory.</p>
<p>CTAO Science Portal — demo by Cyfronet (SUSS-PORT team).</p>
</div>
{/* Order: action/utility first, legal middle, meta last (GOV.UK/NN-g
footer anatomy). Spec §3.3.1 requires the five items, not an order. */}
<nav class="foot-links" aria-label="Footer">
<a href="/pages/contact">Contact</a>
<a href="/search">Search</a>
<a href="/pages/disclaimer">Disclaimer</a>
<a href="/pages/privacy">Privacy</a>
<a href="/pages/contact">Contact</a>
<a>Site settings</a>
<a href="/search">Search</a>
{/* Internal tooling stays out of the main nav (NN/g: navigation reflects
user tasks); the editor is a discreet utility link for the demo. */}
<a href="/admin">Content editor</a>
</nav>
<div class="foot-note">
{/* The real brand flash — path taken from the official logo SVG (BRAND D.4).
Sole decorative accent in this view; static by design. */}
<svg class="flash" viewBox="85.3 15 15 15" aria-hidden="true"><path fill="currentColor" d="M94.7,23.8c1-1.4,3.3-2.1,5.2-2.7c-2,0.1-4.4,0.3-5.8-0.6c-1.4-1-2.1-3.3-2.7-5.2c0.1,2,0.3,4.4-0.6,5.8c-1,1.4-3.3,2.1-5.2,2.7c2-0.1,4.4-0.3,5.8,0.6c1.4,1,2.1,3.3,2.7,5.2C93.9,27.6,93.7,25.2,94.7,23.8z"/></svg>
<span>Science Portal Core demo (Cyfronet / SUSS-PORT team). Sample content
imported from ctao.org; the Site settings link is a placeholder. Statically
generated from Markdown (git-based CMS).</span>
<span>© 2026 CTAO — demonstration, not an official service.</span>
</div>
</div>
</footer>