Content stays in the Event Info Source. Native disclosures work without JavaScript;
search opens matching topics. Keep source provenance in docs/event-info-sources.md.
<section class="event-info">
<header class="info-search">
<label class="search-field">
<icp-search />
<input
type="search"
data-info-search
placeholder="Search event info"
aria-label="Search event information"
/>
</label>
</header>
<slot />
<p data-info-empty hidden>No matching information.</p>
</section>
.event-info {
max-width: 820px;
margin: 16px auto 0;
}
.info-search {
position: sticky;
top: 0;
z-index: 20;
background: var(--paper);
padding: 8px 0;
}
.info-search .search-field {
width: 100%;
margin: 0;
}
.info-search input {
font-size: 16px;
}
.event-info h1 {
font-size: 26px;
margin: 20px 0 6px;
}
.event-info .info-address {
font-size: 14px;
margin-bottom: 16px;
}
.event-info .info-actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 16px 0 24px;
}
.event-info .info-actions a {
text-decoration: none;
display: inline-flex;
gap: 8px;
align-items: center;
border: 1px solid var(--line);
border-radius: 7px;
min-height: 44px;
padding: 8px 12px;
font-size: 13px;
}
.event-info details {
border-top: 1px solid var(--line);
padding: 4px 0;
scroll-margin-top: 80px;
}
.event-info summary {
cursor: pointer;
padding: 16px 0;
font-size: 17px;
font-weight: 500;
}
.event-info details > :not(summary) {
margin: 0 0 16px;
font-size: 14px;
line-height: 1.65;
}
.event-info ul {
padding-left: 20px;
}
.event-info li {
margin: 8px 0;
}
.event-info a {
text-decoration: underline;
text-underline-offset: 3px;
}
.event-info img {
display: block;
width: 100%;
height: auto;
}
.event-info .info-updated {
margin-top: 22px;
font-size: 11px;
color: #61756a;
}
.event-info [hidden] {
display: none !important;
}
const input = el.querySelector("[data-info-search]")
const topics = [...el.querySelectorAll("details[data-info-topic]")]
let previous
function openLinkedTopic() {
const topic = topics.find(topic => "#" + topic.id === location.hash)
if (topic) {
topic.hidden = false
topic.open = true
requestAnimationFrame(() => topic.scrollIntoView({ block: "start" }))
}
}
openLinkedTopic()
on(window, "hashchange", openLinkedTopic)
on(input, "input", () => {
const query = input.value.trim().toLowerCase()
if (query && !previous) previous = topics.map((topic) => topic.open)
let matches = 0
topics.forEach((topic, index) => {
topic.hidden = !!query && !topic.textContent.toLowerCase().includes(query)
if (!topic.hidden) matches++
if (query) topic.open = !topic.hidden
else if (previous) topic.open = previous[index]
})
if (!query) previous = undefined
el.querySelector("[data-info-empty]").hidden = matches > 0
})