diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/Updates.astro | 80 |
1 files changed, 75 insertions, 5 deletions
diff --git a/src/components/Updates.astro b/src/components/Updates.astro index 8fbe795..eaf159a 100644 --- a/src/components/Updates.astro +++ b/src/components/Updates.astro @@ -1,13 +1,16 @@ --- import updates from "../data/updates.json"; -const limit = Number(Astro.props.limit ?? 5); -const items = (updates as { date: string; title: string; url: string; group: string }[]).slice(0, limit); +type Update = { date: string; title: string; url: string; group: string }; + +const initial = Number(Astro.props.limit ?? 5); +const step = Number(Astro.props.step ?? 10); +const items = updates as Update[]; --- -<ul class="updates"> - {items.map((u) => ( - <li> +<ul class="updates" data-updates data-step={step}> + {items.map((u, index) => ( + <li hidden={index >= initial}> <time datetime={u.date}>{u.date.replace(/-/g, ".")}</time> {u.group && <span class="updates-group">{u.group}</span>} <a href={u.url}>{u.title}</a> @@ -15,6 +18,52 @@ const items = (updates as { date: string; title: string; url: string; group: str ))} </ul> +{ + items.length > initial && ( + <div class="updates-footer"> + <button type="button" class="updates-more" data-updates-more> + 次へ(さらに{step}件) + </button> + </div> + ) +} + +<noscript> + <style> + .updates li[hidden] { + display: flex !important; + } + .updates-footer { + display: none; + } + </style> +</noscript> + +<script> + const list = document.querySelector<HTMLElement>("[data-updates]"); + const button = document.querySelector<HTMLButtonElement>("[data-updates-more]"); + + if (list && button) { + const step = Number(list.dataset.step ?? 10); + + const relabel = () => { + const remaining = list.querySelectorAll("li[hidden]").length; + if (remaining === 0) { + button.hidden = true; + return; + } + button.textContent = `次へ(さらに${Math.min(step, remaining)}件)`; + }; + + button.addEventListener("click", () => { + list.querySelectorAll<HTMLElement>("li[hidden]").forEach((li, index) => { + if (index < step) li.hidden = false; + }); + relabel(); + }); + } +</script> + <style> .updates { list-style: none; @@ -31,6 +80,10 @@ const items = (updates as { date: string; title: string; url: string; group: str padding: 0.5rem 0; border-bottom: 1px solid var(--sl-color-gray-5); } + /* hidden 属性の UA スタイル(display: none)は、上の .updates li に負けるため明示する */ + .updates li[hidden] { + display: none; + } .updates time { color: var(--sl-color-gray-3); font-variant-numeric: tabular-nums; @@ -50,4 +103,21 @@ const items = (updates as { date: string; title: string; url: string; group: str .updates a:hover { text-decoration: underline; } + .updates-footer { + margin-top: 0.75rem; + text-align: center; + } + .updates-more { + font: inherit; + font-size: 0.85rem; + color: inherit; + background: var(--sl-color-gray-6); + border: 1px solid var(--sl-color-gray-5); + border-radius: 999px; + padding: 0.3rem 1rem; + cursor: pointer; + } + .updates-more:hover { + background: var(--sl-color-gray-5); + } </style> |
