Site Components
Components are organized by feature in subdirectories under src/components/. This page covers non-MDX components used by pages and layouts.
Layout Components
Directory: src/components/layout/
Header
Sticky navigation bar with mobile menu and full-site search.
No external props — navigation links are hardcoded in the component.
Alpine.js features:
- Search — Pagefind integration with 150ms debounce, keyboard navigation (arrows, Enter, Escape), and
Cmd/Ctrl+Kglobal hotkey - Mobile menu — Slide-out overlay with staggered link animations
- Scroll behavior — Hides on scroll down, shows on scroll up
Footer
Site-wide footer with navigation columns, social links, and legal info.
No external props — loads content from multiple page-text entries:
social— Social media icons with custom hover colorscontact-details— Email + multilineaddressfield, shared with the Contact page so both surfaces stay in syncnav-columns— Navigation columnsnav-links/footer-bottom— Copyright and legal links
BackToTopButton
Floating button that appears after scrolling 300px. Uses Alpine.js for scroll detection and smooth scroll back to top.
Post Catalog Components
Directory: src/components/posts-catalog/
These components work together with the Alpine.js grid filtering pattern in events.astro and projects.astro.
PostShowcase
| Prop | Type | Default | Description |
|---|---|---|---|
coverImage |
ImageMetadata |
— | Card background image |
imageAlt |
string |
— | Alt text |
date |
string |
— | Formatted date string |
title |
string |
— | Card title |
description |
string |
— | Card description |
href |
string? |
— | Link URL (renders <a> if set) |
isCompleted |
boolean? |
— | Show “Completed” badge |
isUpcoming |
boolean? |
— | Show “Upcoming” badge |
category |
string? |
— | Category label badge |
Fixed height card (320px) with image zoom on hover, glass-morphism badges, and accent glow border effect on desktop hover.
FilterMenu
| Prop | Type | Description |
|---|---|---|
filterGroups |
FilterGroup[] |
Array of { label, stateVariable, categories, categoryLabels } |
Dropdown panel with filter groups. Shows active filter count badge. Provides clearFilters() method.
SortMenu
| Prop | Type | Default | Description |
|---|---|---|---|
stateVariable |
string? |
'sortOrder' |
Alpine state variable to bind to |
Dropdown toggle between “Newest first” and “Oldest first” with animated direction icon.
CategoryFilter
| Prop | Type | Default | Description |
|---|---|---|---|
categories |
string[] |
— | Category values |
categoryLabels |
Record<string, string> |
— | Display labels |
stateVariable |
string? |
'activeCategory' |
Alpine state array to toggle |
Row of filter chip buttons that call toggleFilter() on the Alpine state.
Reusable Components
Directory: src/components/reusable/
PageHeroImage
| Prop | Type | Default | Description |
|---|---|---|---|
image |
ImageMetadata |
— | Background image |
alt |
string |
— | Alt text |
title |
string |
— | Title (bottom-left) |
subtitle |
string? |
— | Subtitle |
variant |
'dark' | 'light' |
'dark' |
Gradient color |
loading |
'eager' | 'lazy' |
'eager' |
Loading strategy |
Full viewport hero section (h-[50vh] lg:h-[60vh]) with gradient overlays for text readability. Title takes half width on desktop.
ImageGrid
| Prop | Type | Default | Description |
|---|---|---|---|
images |
ImageWithAlt[] |
— | Images with alt text + optional description (rendered as a gradient overlay) |
cols |
2-6 |
4 |
Grid columns |
gap |
'sm' | 'md' | 'lg' |
'md' |
Item spacing |
enableClickToEnlarge |
boolean |
true |
Click-to-enlarge modal |
aspectRatio |
'square' | 'native' |
'square' |
Layout mode |
Two modes: square uses CSS Grid with 1:1 aspect ratio, native uses CSS Columns for masonry layout. Mobile always shows 2 columns. First cols * 2 images use eager loading.
CollapsibleImageGrid
| Prop | Type | Default | Description |
|---|---|---|---|
images |
ImageWithAlt[] |
— | Images with alt text + optional description (rendered as a gradient overlay) |
cols |
2-6 |
4 |
Grid columns |
gap |
'sm' | 'md' | 'lg' |
'md' |
Item spacing |
previewRows |
number |
1 |
Visible rows when collapsed |
Wraps ImageGrid with a gradient overlay and expand/collapse button. Uses Alpine.js for height animation with scrollHeight measurement.
MediaAccordion
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
— | Section title |
images |
ImageMetadata[] |
— | Images to display |
cols |
2-6 |
4 |
Grid columns |
gap |
'sm' | 'md' | 'lg' |
'md' |
Item spacing |
Smart wrapper: if all images fit in one row, renders a static header. Otherwise renders a clickable header with CollapsibleImageGrid.
CarouselArrow
| Prop | Type | Default | Description |
|---|---|---|---|
direction |
'prev' | 'next' | 'down' |
— | Arrow direction |
onClick |
string |
— | Alpine click handler |
variant |
'flex' | 'absolute' |
'flex' |
Positioning mode |
position |
'left' | 'right' |
'left' |
Position for absolute variant |
inverted |
boolean |
false |
White border for dark backgrounds |
Responsive SVG arrow button (w-10 h-10 sm:w-12 sm:h-12). Standard variant uses red accent; inverted uses white border with mix-blend-difference.
GradientDivider
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
'dark' | 'light' |
'dark' |
Color scheme |
Thin gradient line used as a visual separator.
CrosslinkBanner
| Prop | Type | Description |
|---|---|---|
text |
string |
Prompt text |
linkText |
string |
Link label |
href |
string |
Destination URL |
Subtle banner with text and arrow link, used below pagination to cross-link between events and projects pages.
Landing Components
Directory: src/components/landing/
SponsorTier
| Prop | Type | Description |
|---|---|---|
sponsors |
SponsorData[] |
Array of sponsor objects |
tier |
SponsorTier |
Tier key for size styling |
Each sponsor object: { name, logo (ImageMetadata), url?, tier, slug, bgColor? }.
Renders sponsor logos in a flex-wrap row with tier-proportional sizing. Each logo sits inside a white card container with soft shadow, rounded corners, and padding that scales with the tier (larger cards for higher tiers). The card background color defaults to #ffffff but can be overridden per sponsor via the bgColor frontmatter field to meet corporate identity requirements.
Used by both BecomeSponsor (landing page) and SponsorShowcase (dedicated sponsors page).
SponsorShowcase
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string? |
— | Section heading |
subtitle |
string? |
— | Accent label above heading |
description |
string? |
— | Intro paragraph |
tiers |
TierGroup[] |
— | Tier groups with sponsors |
Light-background section with accordion-style tier groups (all open by default). Each tier header is a clickable button with height animation. Uses SponsorTier internally for logo display.
LandingHero
| Prop | Type | Default | Description |
|---|---|---|---|
autoScroll |
boolean? |
— | Auto-advance slides |
autoScrollInterval |
number? |
8000 |
Interval (ms) |
showArrows |
boolean? |
true |
Show navigation arrows |
showDots |
boolean? |
false |
Show dot indicators |
ctas |
HeroCTAItem[]? |
— | 1–3 CTA buttons |
tagline |
string? |
— | Text below BEARS logo |
Full viewport hero with video/image carousel background. Loads media from src/assets/hero/landingpage/. Videos autoplay muted. Touch swipe support for mobile.
The CTA grid (HeroCTA.astro) uses CSS-only hover effects — no client-side JS required.
Docs Components
Directory: src/components/docs/
DocsSidebar
Navigation sidebar for documentation pages. No external props — fetches docs via getDocsBySection().
- Collapsible sections (Guides, Dev Docs) and groups within sections
- localStorage persistence for expansion state
- Active page highlighting
- Desktop: sticky sidebar; Mobile: slide-out overlay
DocsToc
| Prop | Type | Description |
|---|---|---|
headings |
Array<{depth, slug, text}> |
Page heading hierarchy |
Table of contents sidebar (right column, XL+ screens only). Filters to depth 2–3 headings. Only renders if 2+ headings exist.