Yacine Jernite
commited on
Commit
Β·
72be969
1
Parent(s):
803ec5a
v08
Browse files- index.html +214 -22
- js/bootstrap.js +1 -11
- js/cards/ArtifactSummaryCard.js +10 -6
- js/components/Card.js +13 -13
- js/main.js +15 -2
- js/utils/search.js +9 -14
- js/utils/tags.js +0 -1
index.html
CHANGED
|
@@ -3,7 +3,33 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>Machine Learning and Society at
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
<!-- Import map for lit-html -->
|
| 9 |
<script type="importmap">
|
|
@@ -20,7 +46,6 @@
|
|
| 20 |
window.navigationAreas = getNavigationData();
|
| 21 |
window.homeBackgroundImage = homeBackgroundImage;
|
| 22 |
window.overallBackgroundImage = overallBackgroundImage;
|
| 23 |
-
console.log('β Areas loaded in head:', Object.keys(areasData).length);
|
| 24 |
</script>
|
| 25 |
<!-- Alpine.js can now safely use window.navigationAreas -->
|
| 26 |
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
|
|
@@ -39,11 +64,72 @@
|
|
| 39 |
/* Apply fonts to base elements */
|
| 40 |
body {
|
| 41 |
font-family: 'Source Sans Pro', sans-serif;
|
| 42 |
-
--header-height: 100px; /* Two-line navigation menu */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
}
|
| 44 |
|
| 45 |
h1, h2, h3, h4, h5, h6 {
|
| 46 |
font-family: 'Montserrat', sans-serif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
}
|
| 48 |
|
| 49 |
/* Ensure all major containers respect viewport width */
|
|
@@ -59,6 +145,23 @@
|
|
| 59 |
}
|
| 60 |
}
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
/* Navigation overflow handling */
|
| 63 |
@media (min-width: 769px) {
|
| 64 |
.nav-line-scroll {
|
|
@@ -119,6 +222,62 @@
|
|
| 119 |
display: none;
|
| 120 |
}
|
| 121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
/* Custom scrollbar for research area card descriptions */
|
| 123 |
.overflow-y-auto::-webkit-scrollbar {
|
| 124 |
width: 4px;
|
|
@@ -198,16 +357,21 @@
|
|
| 198 |
<body class="bg-gray-50 text-gray-800">
|
| 199 |
<!-- Overall Background Image - Only for header and sidebars -->
|
| 200 |
<div id="overall-background" class="fixed opacity-100 z-40 pointer-events-none" style="top: 0; left: 0; right: 0; height: var(--header-height);">
|
| 201 |
-
<img src="/images/background_ai.png" alt="" class="w-full h-full object-cover object-left-top">
|
| 202 |
</div>
|
| 203 |
|
| 204 |
<!-- Right Sidebar Background (when open) -->
|
| 205 |
<div id="right-sidebar-background" class="fixed opacity-60 z-0 pointer-events-none hidden" style="top: var(--header-height); right: 0; width: 320px; bottom: 0;">
|
| 206 |
-
<img src="/images/background_ai.png" alt="" class="w-full h-full object-cover object-right">
|
| 207 |
</div>
|
| 208 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
<!-- Top Navigation -->
|
| 210 |
-
<header class="bg-white/60 shadow-sm border-b border-gray-200 fixed top-0 left-0 right-0 z-50" style="height: var(--header-height);" x-data="{
|
| 211 |
mobileMenuOpen: false,
|
| 212 |
areas: window.navigationAreas || [],
|
| 213 |
currentArea: null,
|
|
@@ -234,8 +398,12 @@
|
|
| 234 |
</a>
|
| 235 |
|
| 236 |
<!-- Mobile menu button -->
|
| 237 |
-
<button @click="mobileMenuOpen = !mobileMenuOpen"
|
| 238 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
<path x-show="!mobileMenuOpen" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
| 240 |
<path x-show="mobileMenuOpen" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
| 241 |
</svg>
|
|
@@ -270,8 +438,11 @@
|
|
| 270 |
<a href="/about"
|
| 271 |
class="flex items-center justify-center px-8 py-2 text-lg font-medium text-gray-700 hover:text-blue-600 hover:bg-blue-50/50 transition-colors border-b border-gray-200 flex-1">Press</a>
|
| 272 |
|
| 273 |
-
<button id="search-toggle"
|
| 274 |
-
|
|
|
|
|
|
|
|
|
|
| 275 |
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
|
| 276 |
</svg>
|
| 277 |
</button>
|
|
@@ -280,11 +451,13 @@
|
|
| 280 |
</div>
|
| 281 |
|
| 282 |
<!-- Mobile Menu (Dropdown) -->
|
| 283 |
-
<
|
| 284 |
x-transition
|
| 285 |
@click.away="mobileMenuOpen = false"
|
| 286 |
class="xl:hidden absolute top-full left-0 right-0 bg-white shadow-lg border-b border-gray-200 z-40"
|
| 287 |
-
x-data="mobileTopicNav()"
|
|
|
|
|
|
|
| 288 |
<div class="px-4 py-3 space-y-2 max-h-[70vh] overflow-y-auto">
|
| 289 |
<!-- Areas with Topics -->
|
| 290 |
<div>
|
|
@@ -318,7 +491,7 @@
|
|
| 318 |
<!-- Main Layout -->
|
| 319 |
<div id="main-layout" class="flex" style="padding-top: var(--header-height);">
|
| 320 |
<!-- Main Content -->
|
| 321 |
-
<main class="flex-1 transition-all duration-300 overflow-x-hidden" id="main-content">
|
| 322 |
<div class="w-full py-8">
|
| 323 |
<!-- Content will be loaded dynamically by the SPA router -->
|
| 324 |
<div class="bg-white rounded-lg shadow-sm p-8 mx-4 sm:mx-6 lg:mx-8" style="max-width: min(90%, 1400px); margin-left: auto; margin-right: auto;">
|
|
@@ -331,10 +504,18 @@
|
|
| 331 |
</main>
|
| 332 |
|
| 333 |
<!-- Right Sidebar - Search (Collapsible) -->
|
| 334 |
-
<aside id="search-sidebar"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 335 |
<h3 class="text-lg font-semibold text-gray-900">Search</h3>
|
| 336 |
-
<button id="search-close"
|
| 337 |
-
|
|
|
|
|
|
|
| 338 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
| 339 |
</svg>
|
| 340 |
</button>
|
|
@@ -342,21 +523,28 @@
|
|
| 342 |
|
| 343 |
<!-- Search Description -->
|
| 344 |
<div class="mb-4">
|
| 345 |
-
|
| 346 |
</div>
|
| 347 |
|
| 348 |
<!-- Search Input -->
|
| 349 |
<div class="mb-4">
|
|
|
|
| 350 |
<input
|
| 351 |
-
type="
|
| 352 |
id="search-input"
|
| 353 |
placeholder="Search works by the ML & Society team"
|
| 354 |
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
|
|
| 355 |
>
|
| 356 |
</div>
|
| 357 |
|
| 358 |
<!-- Search Results - Fixed height with proper scrolling -->
|
| 359 |
-
<div id="search-results"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 360 |
<div class="text-gray-500 text-center py-8">
|
| 361 |
<p>Enter a search term to find related works by the ML & Society team.</p>
|
| 362 |
</div>
|
|
@@ -365,11 +553,15 @@
|
|
| 365 |
</aside>
|
| 366 |
</div>
|
| 367 |
|
| 368 |
-
<!-- Overlay for mobile -->
|
| 369 |
-
<div id="sidebar-overlay"
|
|
|
|
|
|
|
| 370 |
|
| 371 |
<!-- Scroll to Top Button -->
|
| 372 |
-
<button id="scroll-to-top"
|
|
|
|
|
|
|
| 373 |
<svg class="w-5 h-5 transform group-hover:scale-110 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 374 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path>
|
| 375 |
</svg>
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Machine Learning and Society at Hugging Face</title>
|
| 7 |
+
|
| 8 |
+
<!-- SEO Meta Tags -->
|
| 9 |
+
<meta name="description" content="The Machine Learning and Society team at Hugging Face works on the sustainability, agency, and ecosystems of AI systems through open research and collaborative development.">
|
| 10 |
+
<meta name="keywords" content="machine learning, AI ethics, AI sustainability, AI agency, AI ecosystems, open source AI, Hugging Face">
|
| 11 |
+
<meta name="author" content="Hugging Face - Machine Learning and Society Team">
|
| 12 |
+
|
| 13 |
+
<!-- Open Graph / Facebook -->
|
| 14 |
+
<meta property="og:type" content="website">
|
| 15 |
+
<meta property="og:url" content="https://huggingface.co/">
|
| 16 |
+
<meta property="og:title" content="Machine Learning and Society at Hugging Face">
|
| 17 |
+
<meta property="og:description" content="Research on the sustainability, agency, and ecosystems of AI systems through open and collaborative development.">
|
| 18 |
+
<meta property="og:image" content="/images/background_ai.png">
|
| 19 |
+
|
| 20 |
+
<!-- Twitter -->
|
| 21 |
+
<meta property="twitter:card" content="summary_large_image">
|
| 22 |
+
<meta property="twitter:url" content="https://huggingface.co/">
|
| 23 |
+
<meta property="twitter:title" content="Machine Learning and Society at Hugging Face">
|
| 24 |
+
<meta property="twitter:description" content="Research on the sustainability, agency, and ecosystems of AI systems through open and collaborative development.">
|
| 25 |
+
<meta property="twitter:image" content="/images/background_ai.png">
|
| 26 |
+
|
| 27 |
+
<!-- Performance: Preconnect to CDN origins -->
|
| 28 |
+
<link rel="preconnect" href="https://cdn.tailwindcss.com">
|
| 29 |
+
<link rel="preconnect" href="https://cdn.jsdelivr.net">
|
| 30 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 31 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 32 |
+
|
| 33 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 34 |
<!-- Import map for lit-html -->
|
| 35 |
<script type="importmap">
|
|
|
|
| 46 |
window.navigationAreas = getNavigationData();
|
| 47 |
window.homeBackgroundImage = homeBackgroundImage;
|
| 48 |
window.overallBackgroundImage = overallBackgroundImage;
|
|
|
|
| 49 |
</script>
|
| 50 |
<!-- Alpine.js can now safely use window.navigationAreas -->
|
| 51 |
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
|
|
|
|
| 64 |
/* Apply fonts to base elements */
|
| 65 |
body {
|
| 66 |
font-family: 'Source Sans Pro', sans-serif;
|
| 67 |
+
--header-height: 100px; /* Two-line navigation menu - desktop */
|
| 68 |
+
|
| 69 |
+
/* Typography scale - consistent font sizes */
|
| 70 |
+
--text-xs: 0.75rem; /* 12px */
|
| 71 |
+
--text-sm: 0.875rem; /* 14px */
|
| 72 |
+
--text-base: 1rem; /* 16px */
|
| 73 |
+
--text-lg: 1.125rem; /* 18px */
|
| 74 |
+
--text-xl: 1.25rem; /* 20px */
|
| 75 |
+
--text-2xl: 1.5rem; /* 24px */
|
| 76 |
+
--text-3xl: 1.875rem; /* 30px */
|
| 77 |
+
--text-4xl: 2.25rem; /* 36px */
|
| 78 |
+
|
| 79 |
+
/* Line heights for readability */
|
| 80 |
+
--leading-tight: 1.25;
|
| 81 |
+
--leading-normal: 1.5;
|
| 82 |
+
--leading-relaxed: 1.625;
|
| 83 |
+
--leading-loose: 1.75;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
/* Ensure minimum readable font size on mobile */
|
| 87 |
+
@media (max-width: 767px) {
|
| 88 |
+
body {
|
| 89 |
+
font-size: 14px; /* Minimum 14px on mobile */
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
/* Adjust heading sizes for mobile */
|
| 93 |
+
h1 {
|
| 94 |
+
font-size: var(--text-2xl);
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
h2 {
|
| 98 |
+
font-size: var(--text-xl);
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
h3 {
|
| 102 |
+
font-size: var(--text-lg);
|
| 103 |
+
}
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
/* Responsive header height */
|
| 107 |
+
@media (max-width: 1023px) {
|
| 108 |
+
body {
|
| 109 |
+
--header-height: 80px; /* Tablet */
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
@media (max-width: 767px) {
|
| 114 |
+
body {
|
| 115 |
+
--header-height: 70px; /* Mobile */
|
| 116 |
+
}
|
| 117 |
}
|
| 118 |
|
| 119 |
h1, h2, h3, h4, h5, h6 {
|
| 120 |
font-family: 'Montserrat', sans-serif;
|
| 121 |
+
line-height: var(--leading-tight);
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
/* Body text readability */
|
| 125 |
+
p {
|
| 126 |
+
line-height: var(--leading-relaxed);
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
/* Improve readability of long-form content */
|
| 130 |
+
.prose p {
|
| 131 |
+
line-height: var(--leading-loose);
|
| 132 |
+
margin-bottom: 1em;
|
| 133 |
}
|
| 134 |
|
| 135 |
/* Ensure all major containers respect viewport width */
|
|
|
|
| 145 |
}
|
| 146 |
}
|
| 147 |
|
| 148 |
+
/* Mobile search sidebar - full screen on mobile */
|
| 149 |
+
@media (max-width: 767px) {
|
| 150 |
+
#search-sidebar {
|
| 151 |
+
width: 100vw !important;
|
| 152 |
+
right: 0;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
#search-sidebar > div {
|
| 156 |
+
padding: 1rem;
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
/* Adjust search results height for mobile */
|
| 160 |
+
#search-results {
|
| 161 |
+
height: calc(100vh - 180px) !important;
|
| 162 |
+
}
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
/* Navigation overflow handling */
|
| 166 |
@media (min-width: 769px) {
|
| 167 |
.nav-line-scroll {
|
|
|
|
| 222 |
display: none;
|
| 223 |
}
|
| 224 |
|
| 225 |
+
/* Screen reader only utility */
|
| 226 |
+
.sr-only {
|
| 227 |
+
position: absolute;
|
| 228 |
+
width: 1px;
|
| 229 |
+
height: 1px;
|
| 230 |
+
padding: 0;
|
| 231 |
+
margin: -1px;
|
| 232 |
+
overflow: hidden;
|
| 233 |
+
clip: rect(0, 0, 0, 0);
|
| 234 |
+
white-space: nowrap;
|
| 235 |
+
border-width: 0;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
.sr-only:focus {
|
| 239 |
+
position: static;
|
| 240 |
+
width: auto;
|
| 241 |
+
height: auto;
|
| 242 |
+
padding: inherit;
|
| 243 |
+
margin: inherit;
|
| 244 |
+
overflow: visible;
|
| 245 |
+
clip: auto;
|
| 246 |
+
white-space: normal;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
/* Mobile carousel improvements */
|
| 250 |
+
@media (max-width: 767px) {
|
| 251 |
+
/* Hide carousel navigation arrows on mobile */
|
| 252 |
+
.carousel-arrow {
|
| 253 |
+
display: none;
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
/* Smooth touch scrolling for carousels */
|
| 257 |
+
.carousel-scroll {
|
| 258 |
+
-webkit-overflow-scrolling: touch;
|
| 259 |
+
scroll-behavior: smooth;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
/* Add padding to carousel for better touch targets */
|
| 263 |
+
.carousel-scroll > * {
|
| 264 |
+
scroll-snap-align: start;
|
| 265 |
+
}
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
/* Carousel arrow styling */
|
| 269 |
+
.carousel-arrow {
|
| 270 |
+
transition: opacity 0.2s, transform 0.2s;
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
.carousel-arrow:hover {
|
| 274 |
+
transform: scale(1.1);
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
.carousel-arrow:active {
|
| 278 |
+
transform: scale(0.95);
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
/* Custom scrollbar for research area card descriptions */
|
| 282 |
.overflow-y-auto::-webkit-scrollbar {
|
| 283 |
width: 4px;
|
|
|
|
| 357 |
<body class="bg-gray-50 text-gray-800">
|
| 358 |
<!-- Overall Background Image - Only for header and sidebars -->
|
| 359 |
<div id="overall-background" class="fixed opacity-100 z-40 pointer-events-none" style="top: 0; left: 0; right: 0; height: var(--header-height);">
|
| 360 |
+
<img src="/images/background_ai.png" alt="" class="w-full h-full object-cover object-left-top" loading="eager">
|
| 361 |
</div>
|
| 362 |
|
| 363 |
<!-- Right Sidebar Background (when open) -->
|
| 364 |
<div id="right-sidebar-background" class="fixed opacity-60 z-0 pointer-events-none hidden" style="top: var(--header-height); right: 0; width: 320px; bottom: 0;">
|
| 365 |
+
<img src="/images/background_ai.png" alt="" class="w-full h-full object-cover object-right" loading="lazy">
|
| 366 |
</div>
|
| 367 |
|
| 368 |
+
<!-- Skip to main content link for accessibility -->
|
| 369 |
+
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-2 focus:left-2 focus:z-50 focus:px-4 focus:py-2 focus:bg-blue-600 focus:text-white focus:rounded">
|
| 370 |
+
Skip to main content
|
| 371 |
+
</a>
|
| 372 |
+
|
| 373 |
<!-- Top Navigation -->
|
| 374 |
+
<header role="banner" aria-label="Main navigation" class="bg-white/60 shadow-sm border-b border-gray-200 fixed top-0 left-0 right-0 z-50" style="height: var(--header-height);" x-data="{
|
| 375 |
mobileMenuOpen: false,
|
| 376 |
areas: window.navigationAreas || [],
|
| 377 |
currentArea: null,
|
|
|
|
| 398 |
</a>
|
| 399 |
|
| 400 |
<!-- Mobile menu button -->
|
| 401 |
+
<button @click="mobileMenuOpen = !mobileMenuOpen"
|
| 402 |
+
class="xl:hidden p-2 text-gray-600"
|
| 403 |
+
aria-label="Toggle mobile menu"
|
| 404 |
+
aria-expanded="false"
|
| 405 |
+
:aria-expanded="mobileMenuOpen.toString()">
|
| 406 |
+
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
| 407 |
<path x-show="!mobileMenuOpen" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
| 408 |
<path x-show="mobileMenuOpen" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
| 409 |
</svg>
|
|
|
|
| 438 |
<a href="/about"
|
| 439 |
class="flex items-center justify-center px-8 py-2 text-lg font-medium text-gray-700 hover:text-blue-600 hover:bg-blue-50/50 transition-colors border-b border-gray-200 flex-1">Press</a>
|
| 440 |
|
| 441 |
+
<button id="search-toggle"
|
| 442 |
+
class="flex items-center justify-center px-8 py-2 text-gray-700 hover:text-blue-600 hover:bg-blue-50/50 transition-colors flex-1"
|
| 443 |
+
aria-label="Open search"
|
| 444 |
+
aria-controls="search-sidebar">
|
| 445 |
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" aria-hidden="true">
|
| 446 |
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
|
| 447 |
</svg>
|
| 448 |
</button>
|
|
|
|
| 451 |
</div>
|
| 452 |
|
| 453 |
<!-- Mobile Menu (Dropdown) -->
|
| 454 |
+
<nav x-show="mobileMenuOpen"
|
| 455 |
x-transition
|
| 456 |
@click.away="mobileMenuOpen = false"
|
| 457 |
class="xl:hidden absolute top-full left-0 right-0 bg-white shadow-lg border-b border-gray-200 z-40"
|
| 458 |
+
x-data="mobileTopicNav()"
|
| 459 |
+
role="navigation"
|
| 460 |
+
aria-label="Mobile navigation menu">
|
| 461 |
<div class="px-4 py-3 space-y-2 max-h-[70vh] overflow-y-auto">
|
| 462 |
<!-- Areas with Topics -->
|
| 463 |
<div>
|
|
|
|
| 491 |
<!-- Main Layout -->
|
| 492 |
<div id="main-layout" class="flex" style="padding-top: var(--header-height);">
|
| 493 |
<!-- Main Content -->
|
| 494 |
+
<main role="main" class="flex-1 transition-all duration-300 overflow-x-hidden" id="main-content">
|
| 495 |
<div class="w-full py-8">
|
| 496 |
<!-- Content will be loaded dynamically by the SPA router -->
|
| 497 |
<div class="bg-white rounded-lg shadow-sm p-8 mx-4 sm:mx-6 lg:mx-8" style="max-width: min(90%, 1400px); margin-left: auto; margin-right: auto;">
|
|
|
|
| 504 |
</main>
|
| 505 |
|
| 506 |
<!-- Right Sidebar - Search (Collapsible) -->
|
| 507 |
+
<aside id="search-sidebar"
|
| 508 |
+
role="search"
|
| 509 |
+
aria-label="Search sidebar"
|
| 510 |
+
class="fixed right-0 h-full w-80 bg-white/85 backdrop-blur-sm shadow-sm border-l border-gray-200 transform translate-x-full z-40 transition-transform duration-300"
|
| 511 |
+
style="top: var(--header-height);">
|
| 512 |
+
<div class="p-6">
|
| 513 |
+
<div class="flex items-center justify-between mb-4">
|
| 514 |
<h3 class="text-lg font-semibold text-gray-900">Search</h3>
|
| 515 |
+
<button id="search-close"
|
| 516 |
+
class="p-1 rounded-md text-gray-400 hover:text-gray-500 transition-colors"
|
| 517 |
+
aria-label="Close search">
|
| 518 |
+
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
| 519 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
| 520 |
</svg>
|
| 521 |
</button>
|
|
|
|
| 523 |
|
| 524 |
<!-- Search Description -->
|
| 525 |
<div class="mb-4">
|
| 526 |
+
<p class="text-sm text-gray-600" style="line-height: var(--leading-relaxed);">We have produced or collaborated on a fair amount of papers, writings, and technical artifacts over the years. Use the search functionality here to navigate those!</p>
|
| 527 |
</div>
|
| 528 |
|
| 529 |
<!-- Search Input -->
|
| 530 |
<div class="mb-4">
|
| 531 |
+
<label for="search-input" class="sr-only">Search works by the ML & Society team</label>
|
| 532 |
<input
|
| 533 |
+
type="search"
|
| 534 |
id="search-input"
|
| 535 |
placeholder="Search works by the ML & Society team"
|
| 536 |
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
| 537 |
+
aria-describedby="search-description"
|
| 538 |
>
|
| 539 |
</div>
|
| 540 |
|
| 541 |
<!-- Search Results - Fixed height with proper scrolling -->
|
| 542 |
+
<div id="search-results"
|
| 543 |
+
class="overflow-y-auto"
|
| 544 |
+
style="height: calc(100vh - 193px);"
|
| 545 |
+
role="region"
|
| 546 |
+
aria-live="polite"
|
| 547 |
+
aria-label="Search results">
|
| 548 |
<div class="text-gray-500 text-center py-8">
|
| 549 |
<p>Enter a search term to find related works by the ML & Society team.</p>
|
| 550 |
</div>
|
|
|
|
| 553 |
</aside>
|
| 554 |
</div>
|
| 555 |
|
| 556 |
+
<!-- Overlay for mobile (darker on mobile for better visibility) -->
|
| 557 |
+
<div id="sidebar-overlay"
|
| 558 |
+
class="fixed inset-0 bg-black bg-opacity-30 md:bg-opacity-30 z-30 hidden"
|
| 559 |
+
aria-hidden="true"></div>
|
| 560 |
|
| 561 |
<!-- Scroll to Top Button -->
|
| 562 |
+
<button id="scroll-to-top"
|
| 563 |
+
class="fixed bottom-6 right-6 w-12 h-12 bg-blue-600 hover:bg-blue-700 text-white rounded-full shadow-lg hover:shadow-xl transition-all duration-300 opacity-0 invisible z-50 flex items-center justify-center group"
|
| 564 |
+
aria-label="Scroll to top">
|
| 565 |
<svg class="w-5 h-5 transform group-hover:scale-110 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 566 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path>
|
| 567 |
</svg>
|
js/bootstrap.js
CHANGED
|
@@ -3,30 +3,20 @@
|
|
| 3 |
// All initialization happens here in a well-defined sequence
|
| 4 |
|
| 5 |
async function bootstrap() {
|
| 6 |
-
console.log('=== Bootstrap Started ===');
|
| 7 |
-
|
| 8 |
try {
|
| 9 |
// Step 1: Load artifacts (areas already loaded in <head>)
|
| 10 |
-
console.log('Loading artifacts...');
|
| 11 |
const { loadArtifacts } = await import('./init.js');
|
| 12 |
await loadArtifacts();
|
| 13 |
-
console.log('β Artifacts loaded:', window.allArtifacts?.length || 0);
|
| 14 |
|
| 15 |
// Step 2: Initialize router (will render initial page)
|
| 16 |
-
console.log('Initializing router...');
|
| 17 |
const { router } = await import('./utils/router.js');
|
| 18 |
// Router auto-initializes in constructor, no need to call init()
|
| 19 |
-
console.log('β Router initialized');
|
| 20 |
|
| 21 |
// Step 3: Initialize UI components (search, scroll-to-top, etc.)
|
| 22 |
-
console.log('Initializing UI...');
|
| 23 |
const { initializeUI } = await import('./main.js');
|
| 24 |
await initializeUI();
|
| 25 |
-
console.log('β UI initialized');
|
| 26 |
-
|
| 27 |
-
console.log('=== Bootstrap Complete ===');
|
| 28 |
} catch (error) {
|
| 29 |
-
console.error('
|
| 30 |
// Show user-friendly error
|
| 31 |
const mainContent = document.getElementById('main-content');
|
| 32 |
if (mainContent) {
|
|
|
|
| 3 |
// All initialization happens here in a well-defined sequence
|
| 4 |
|
| 5 |
async function bootstrap() {
|
|
|
|
|
|
|
| 6 |
try {
|
| 7 |
// Step 1: Load artifacts (areas already loaded in <head>)
|
|
|
|
| 8 |
const { loadArtifacts } = await import('./init.js');
|
| 9 |
await loadArtifacts();
|
|
|
|
| 10 |
|
| 11 |
// Step 2: Initialize router (will render initial page)
|
|
|
|
| 12 |
const { router } = await import('./utils/router.js');
|
| 13 |
// Router auto-initializes in constructor, no need to call init()
|
|
|
|
| 14 |
|
| 15 |
// Step 3: Initialize UI components (search, scroll-to-top, etc.)
|
|
|
|
| 16 |
const { initializeUI } = await import('./main.js');
|
| 17 |
await initializeUI();
|
|
|
|
|
|
|
|
|
|
| 18 |
} catch (error) {
|
| 19 |
+
console.error('Bootstrap failed:', error);
|
| 20 |
// Show user-friendly error
|
| 21 |
const mainContent = document.getElementById('main-content');
|
| 22 |
if (mainContent) {
|
js/cards/ArtifactSummaryCard.js
CHANGED
|
@@ -15,18 +15,22 @@ export function createArtifactCarousel(artifacts, containerId) {
|
|
| 15 |
container.innerHTML = `
|
| 16 |
<div class="relative">
|
| 17 |
<!-- Carousel container -->
|
| 18 |
-
<div class="flex overflow-x-auto scrollbar-hide space-x-4 pb-4" id="${containerId}-scroll">
|
| 19 |
${cardsHtml}
|
| 20 |
</div>
|
| 21 |
|
| 22 |
-
<!-- Navigation arrows -->
|
| 23 |
-
<button class="absolute left-0 top-1/2 transform -translate-y-1/2 bg-white shadow-lg rounded-full p-2 hover:bg-gray-50 transition-colors z-10"
|
| 24 |
-
|
|
|
|
|
|
|
| 25 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
| 26 |
</svg>
|
| 27 |
</button>
|
| 28 |
-
<button class="absolute right-0 top-1/2 transform -translate-y-1/2 bg-white shadow-lg rounded-full p-2 hover:bg-gray-50 transition-colors z-10"
|
| 29 |
-
|
|
|
|
|
|
|
| 30 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
| 31 |
</svg>
|
| 32 |
</button>
|
|
|
|
| 15 |
container.innerHTML = `
|
| 16 |
<div class="relative">
|
| 17 |
<!-- Carousel container -->
|
| 18 |
+
<div class="flex overflow-x-auto scrollbar-hide carousel-scroll space-x-4 pb-4" id="${containerId}-scroll">
|
| 19 |
${cardsHtml}
|
| 20 |
</div>
|
| 21 |
|
| 22 |
+
<!-- Navigation arrows (hidden on mobile) -->
|
| 23 |
+
<button class="carousel-arrow absolute left-0 top-1/2 transform -translate-y-1/2 bg-white shadow-lg rounded-full p-2 hover:bg-gray-50 transition-colors z-10"
|
| 24 |
+
onclick="scrollCarousel('${containerId}-scroll', -320)"
|
| 25 |
+
aria-label="Scroll carousel left">
|
| 26 |
+
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
| 27 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
| 28 |
</svg>
|
| 29 |
</button>
|
| 30 |
+
<button class="carousel-arrow absolute right-0 top-1/2 transform -translate-y-1/2 bg-white shadow-lg rounded-full p-2 hover:bg-gray-50 transition-colors z-10"
|
| 31 |
+
onclick="scrollCarousel('${containerId}-scroll', 320)"
|
| 32 |
+
aria-label="Scroll carousel right">
|
| 33 |
+
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
| 34 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
| 35 |
</svg>
|
| 36 |
</button>
|
js/components/Card.js
CHANGED
|
@@ -71,7 +71,7 @@ function renderArtifactCard(artifact, options = {}) {
|
|
| 71 |
<!-- Background image -->
|
| 72 |
${backgroundImage ? `
|
| 73 |
<div class="absolute inset-0 opacity-10">
|
| 74 |
-
<img src="/images/${backgroundImage}" alt="" class="w-full h-full object-cover">
|
| 75 |
</div>
|
| 76 |
` : ''}
|
| 77 |
|
|
@@ -95,14 +95,14 @@ function renderArtifactCard(artifact, options = {}) {
|
|
| 95 |
<div class="flex justify-between items-start mb-3 pr-8">
|
| 96 |
<div class="flex items-center space-x-2">
|
| 97 |
<span class="text-lg">${style.icon}</span>
|
| 98 |
-
<span class="text-xs font-
|
| 99 |
</div>
|
| 100 |
-
<span class="text-xs text-gray-
|
| 101 |
</div>
|
| 102 |
|
| 103 |
<!-- Title -->
|
| 104 |
<div class="mb-4 flex-grow min-h-0">
|
| 105 |
-
<h3 class="font-semibold text-gray-900 text-
|
| 106 |
</div>
|
| 107 |
|
| 108 |
<!-- Bottom section with tags and image -->
|
|
@@ -126,7 +126,7 @@ function renderArtifactCard(artifact, options = {}) {
|
|
| 126 |
${backgroundImage ? `
|
| 127 |
<div class="relative group/image">
|
| 128 |
<div class="w-12 h-12 rounded-lg overflow-hidden bg-gray-100 flex items-center justify-center cursor-help" title="${imageCredit}">
|
| 129 |
-
<img src="/images/${backgroundImage}" alt="${primaryAreaData.name}" class="w-full h-full object-cover opacity-80">
|
| 130 |
</div>
|
| 131 |
</div>
|
| 132 |
` : ''}
|
|
@@ -137,12 +137,12 @@ function renderArtifactCard(artifact, options = {}) {
|
|
| 137 |
<div class="description-view hidden h-full flex flex-col min-h-0">
|
| 138 |
<!-- Title (single line with overflow) -->
|
| 139 |
<div class="mb-3 flex-shrink-0">
|
| 140 |
-
<h3 class="font-semibold text-gray-900 text-
|
| 141 |
</div>
|
| 142 |
|
| 143 |
<!-- Description (scrollable, takes remaining space) -->
|
| 144 |
<div class="flex-grow overflow-y-auto min-h-0">
|
| 145 |
-
<p class="text-
|
| 146 |
</div>
|
| 147 |
</div>
|
| 148 |
|
|
@@ -201,7 +201,7 @@ function renderAreaCard(area, options = {}) {
|
|
| 201 |
<!-- Background image with low opacity -->
|
| 202 |
${area.image ? `
|
| 203 |
<div class="absolute inset-0 opacity-15 group-hover:opacity-30 transition-opacity">
|
| 204 |
-
<img src="/images/${area.image}" alt="" class="w-full h-full object-cover">
|
| 205 |
</div>
|
| 206 |
` : ''}
|
| 207 |
|
|
@@ -209,23 +209,23 @@ function renderAreaCard(area, options = {}) {
|
|
| 209 |
<div class="relative p-5 h-full flex flex-col">
|
| 210 |
<!-- Header -->
|
| 211 |
<div class="flex justify-between items-start mb-3 flex-shrink-0">
|
| 212 |
-
<h3 class="text-
|
| 213 |
<svg class="w-5 h-5 text-gray-400 group-hover:text-blue-600 transition-colors flex-shrink-0 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 214 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
| 215 |
</svg>
|
| 216 |
</div>
|
| 217 |
|
| 218 |
<!-- Description - scrollable -->
|
| 219 |
-
<div class="text-
|
| 220 |
-
<p
|
| 221 |
</div>
|
| 222 |
|
| 223 |
<!-- Topics with colors from subAreas -->
|
| 224 |
<div class="flex-shrink-0">
|
| 225 |
-
<p class="text-xs font-semibold text-gray-
|
| 226 |
<div class="flex flex-wrap gap-2">
|
| 227 |
${topics.map(topic => `
|
| 228 |
-
<span class="inline-block px-2 py-
|
| 229 |
${topic.name}
|
| 230 |
</span>
|
| 231 |
`).join('')}
|
|
|
|
| 71 |
<!-- Background image -->
|
| 72 |
${backgroundImage ? `
|
| 73 |
<div class="absolute inset-0 opacity-10">
|
| 74 |
+
<img src="/images/${backgroundImage}" alt="" class="w-full h-full object-cover" loading="lazy">
|
| 75 |
</div>
|
| 76 |
` : ''}
|
| 77 |
|
|
|
|
| 95 |
<div class="flex justify-between items-start mb-3 pr-8">
|
| 96 |
<div class="flex items-center space-x-2">
|
| 97 |
<span class="text-lg">${style.icon}</span>
|
| 98 |
+
<span class="text-xs font-bold uppercase tracking-wide">${type}</span>
|
| 99 |
</div>
|
| 100 |
+
<span class="text-xs text-gray-500">${date}</span>
|
| 101 |
</div>
|
| 102 |
|
| 103 |
<!-- Title -->
|
| 104 |
<div class="mb-4 flex-grow min-h-0">
|
| 105 |
+
<h3 class="font-semibold text-gray-900 text-base leading-snug line-clamp-3">${title}</h3>
|
| 106 |
</div>
|
| 107 |
|
| 108 |
<!-- Bottom section with tags and image -->
|
|
|
|
| 126 |
${backgroundImage ? `
|
| 127 |
<div class="relative group/image">
|
| 128 |
<div class="w-12 h-12 rounded-lg overflow-hidden bg-gray-100 flex items-center justify-center cursor-help" title="${imageCredit}">
|
| 129 |
+
<img src="/images/${backgroundImage}" alt="${primaryAreaData.name}" class="w-full h-full object-cover opacity-80" loading="lazy">
|
| 130 |
</div>
|
| 131 |
</div>
|
| 132 |
` : ''}
|
|
|
|
| 137 |
<div class="description-view hidden h-full flex flex-col min-h-0">
|
| 138 |
<!-- Title (single line with overflow) -->
|
| 139 |
<div class="mb-3 flex-shrink-0">
|
| 140 |
+
<h3 class="font-semibold text-gray-900 text-base leading-tight truncate" title="${title}">${title}</h3>
|
| 141 |
</div>
|
| 142 |
|
| 143 |
<!-- Description (scrollable, takes remaining space) -->
|
| 144 |
<div class="flex-grow overflow-y-auto min-h-0">
|
| 145 |
+
<p class="text-sm text-gray-700" style="line-height: 1.6;">${description}</p>
|
| 146 |
</div>
|
| 147 |
</div>
|
| 148 |
|
|
|
|
| 201 |
<!-- Background image with low opacity -->
|
| 202 |
${area.image ? `
|
| 203 |
<div class="absolute inset-0 opacity-15 group-hover:opacity-30 transition-opacity">
|
| 204 |
+
<img src="/images/${area.image}" alt="" class="w-full h-full object-cover" loading="lazy">
|
| 205 |
</div>
|
| 206 |
` : ''}
|
| 207 |
|
|
|
|
| 209 |
<div class="relative p-5 h-full flex flex-col">
|
| 210 |
<!-- Header -->
|
| 211 |
<div class="flex justify-between items-start mb-3 flex-shrink-0">
|
| 212 |
+
<h3 class="text-xl font-bold text-gray-900 leading-tight">${area.navTitle}</h3>
|
| 213 |
<svg class="w-5 h-5 text-gray-400 group-hover:text-blue-600 transition-colors flex-shrink-0 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 214 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
| 215 |
</svg>
|
| 216 |
</div>
|
| 217 |
|
| 218 |
<!-- Description - scrollable -->
|
| 219 |
+
<div class="text-base text-gray-700 mb-4 flex-grow overflow-y-auto pr-2">
|
| 220 |
+
<p style="line-height: 1.6;">${shortDesc}</p>
|
| 221 |
</div>
|
| 222 |
|
| 223 |
<!-- Topics with colors from subAreas -->
|
| 224 |
<div class="flex-shrink-0">
|
| 225 |
+
<p class="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-2">Topics:</p>
|
| 226 |
<div class="flex flex-wrap gap-2">
|
| 227 |
${topics.map(topic => `
|
| 228 |
+
<span class="inline-block px-2.5 py-1 text-sm ${topic.bgColor} ${topic.textColor} rounded">
|
| 229 |
${topic.name}
|
| 230 |
</span>
|
| 231 |
`).join('')}
|
js/main.js
CHANGED
|
@@ -43,6 +43,7 @@ export function createTeamMember(name, role, hfUsername, tags) {
|
|
| 43 |
src="/images/${hfUsername}.jpeg"
|
| 44 |
alt="${name}"
|
| 45 |
class="w-full h-full object-cover"
|
|
|
|
| 46 |
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
|
| 47 |
/>
|
| 48 |
<span class="text-white font-semibold text-base hidden w-full h-full items-center justify-center absolute">${initials}</span>
|
|
@@ -142,17 +143,29 @@ function initializeSearchToggle() {
|
|
| 142 |
function toggleSearch() {
|
| 143 |
const isOpen = !searchSidebar.classList.contains('translate-x-full');
|
| 144 |
const rightSidebarBg = document.getElementById('right-sidebar-background');
|
|
|
|
| 145 |
|
| 146 |
if (isOpen) {
|
| 147 |
searchSidebar.classList.add('translate-x-full');
|
| 148 |
rightSidebarBg.classList.add('hidden');
|
| 149 |
-
|
|
|
|
|
|
|
|
|
|
| 150 |
overlay.classList.add('hidden');
|
|
|
|
| 151 |
} else {
|
| 152 |
searchSidebar.classList.remove('translate-x-full');
|
| 153 |
rightSidebarBg.classList.remove('hidden');
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
| 155 |
overlay.classList.remove('hidden');
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
}
|
| 157 |
}
|
| 158 |
|
|
|
|
| 43 |
src="/images/${hfUsername}.jpeg"
|
| 44 |
alt="${name}"
|
| 45 |
class="w-full h-full object-cover"
|
| 46 |
+
loading="lazy"
|
| 47 |
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
|
| 48 |
/>
|
| 49 |
<span class="text-white font-semibold text-base hidden w-full h-full items-center justify-center absolute">${initials}</span>
|
|
|
|
| 143 |
function toggleSearch() {
|
| 144 |
const isOpen = !searchSidebar.classList.contains('translate-x-full');
|
| 145 |
const rightSidebarBg = document.getElementById('right-sidebar-background');
|
| 146 |
+
const isMobile = window.innerWidth < 768;
|
| 147 |
|
| 148 |
if (isOpen) {
|
| 149 |
searchSidebar.classList.add('translate-x-full');
|
| 150 |
rightSidebarBg.classList.add('hidden');
|
| 151 |
+
// Only adjust main content margin on desktop
|
| 152 |
+
if (!isMobile) {
|
| 153 |
+
mainContent.classList.remove('mr-80');
|
| 154 |
+
}
|
| 155 |
overlay.classList.add('hidden');
|
| 156 |
+
document.body.style.overflow = ''; // Re-enable scroll
|
| 157 |
} else {
|
| 158 |
searchSidebar.classList.remove('translate-x-full');
|
| 159 |
rightSidebarBg.classList.remove('hidden');
|
| 160 |
+
// Only adjust main content margin on desktop
|
| 161 |
+
if (!isMobile) {
|
| 162 |
+
mainContent.classList.add('mr-80');
|
| 163 |
+
}
|
| 164 |
overlay.classList.remove('hidden');
|
| 165 |
+
// Prevent body scroll on mobile when search is open
|
| 166 |
+
if (isMobile) {
|
| 167 |
+
document.body.style.overflow = 'hidden';
|
| 168 |
+
}
|
| 169 |
}
|
| 170 |
}
|
| 171 |
|
js/utils/search.js
CHANGED
|
@@ -19,10 +19,7 @@ function createMiniSearchIndex(data, storeFields) {
|
|
| 19 |
|
| 20 |
// Initialize search
|
| 21 |
export async function initializeSearch(artifactsData) {
|
| 22 |
-
// Assign the passed artifactsData to allArtifacts
|
| 23 |
allArtifacts = artifactsData;
|
| 24 |
-
|
| 25 |
-
// The fetch for artifacts.json is removed from here since it's now loaded in main.js
|
| 26 |
|
| 27 |
// Prepare data for MiniSearch
|
| 28 |
const searchData = allArtifacts.map((artifact, index) => ({
|
|
@@ -70,9 +67,7 @@ function getSubAreaDisplayName(areaId, subArea) {
|
|
| 70 |
|
| 71 |
// Search UI
|
| 72 |
export function initializeSearchUI(artifactsData) {
|
| 73 |
-
initializeSearch(artifactsData)
|
| 74 |
-
console.log('Search initialized');
|
| 75 |
-
});
|
| 76 |
|
| 77 |
const searchInput = document.getElementById('search-input');
|
| 78 |
const searchResults = document.getElementById('search-results');
|
|
@@ -149,23 +144,23 @@ export function displaySearchResults(results, query) {
|
|
| 149 |
const { areaLinksHtml: areaLinks, topicLinksHtml: subAreaLinks } = renderSearchTags(areas, topics);
|
| 150 |
|
| 151 |
html += `
|
| 152 |
-
<div class="p-3 bg-gray-50 rounded-lg border">
|
| 153 |
<div class="flex items-center justify-between mb-2">
|
| 154 |
-
<h5 class="font-medium text-sm text-gray-900">${result.title}</h5>
|
| 155 |
-
<div class="flex items-center gap-2">
|
| 156 |
<span class="text-xs text-gray-500">${score}%</span>
|
| 157 |
-
<a href="${result.url}" target="_blank" class="text-gray-400 hover:text-gray-600 transition-colors">
|
| 158 |
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 159 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
|
| 160 |
</svg>
|
| 161 |
</a>
|
| 162 |
</div>
|
| 163 |
</div>
|
| 164 |
<div class="flex items-center gap-2 mb-2 text-xs text-gray-600">
|
| 165 |
-
<span class="px-2 py-
|
| 166 |
-
<span>${result.date}</span>
|
| 167 |
</div>
|
| 168 |
-
<div class="flex flex-wrap gap-1">
|
| 169 |
${areaLinks}
|
| 170 |
${subAreaLinks}
|
| 171 |
</div>
|
|
|
|
| 19 |
|
| 20 |
// Initialize search
|
| 21 |
export async function initializeSearch(artifactsData) {
|
|
|
|
| 22 |
allArtifacts = artifactsData;
|
|
|
|
|
|
|
| 23 |
|
| 24 |
// Prepare data for MiniSearch
|
| 25 |
const searchData = allArtifacts.map((artifact, index) => ({
|
|
|
|
| 67 |
|
| 68 |
// Search UI
|
| 69 |
export function initializeSearchUI(artifactsData) {
|
| 70 |
+
initializeSearch(artifactsData);
|
|
|
|
|
|
|
| 71 |
|
| 72 |
const searchInput = document.getElementById('search-input');
|
| 73 |
const searchResults = document.getElementById('search-results');
|
|
|
|
| 144 |
const { areaLinksHtml: areaLinks, topicLinksHtml: subAreaLinks } = renderSearchTags(areas, topics);
|
| 145 |
|
| 146 |
html += `
|
| 147 |
+
<div class="p-3 bg-gray-50 rounded-lg border border-gray-200">
|
| 148 |
<div class="flex items-center justify-between mb-2">
|
| 149 |
+
<h5 class="font-medium text-sm text-gray-900 leading-snug">${result.title}</h5>
|
| 150 |
+
<div class="flex items-center gap-2 flex-shrink-0 ml-2">
|
| 151 |
<span class="text-xs text-gray-500">${score}%</span>
|
| 152 |
+
<a href="${result.url}" target="_blank" class="text-gray-400 hover:text-gray-600 transition-colors" aria-label="Open ${result.title}">
|
| 153 |
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
| 154 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
|
| 155 |
</svg>
|
| 156 |
</a>
|
| 157 |
</div>
|
| 158 |
</div>
|
| 159 |
<div class="flex items-center gap-2 mb-2 text-xs text-gray-600">
|
| 160 |
+
<span class="px-2 py-0.5 bg-gray-200 text-gray-700 rounded font-medium">${result.type}</span>
|
| 161 |
+
<span class="text-gray-500">${result.date}</span>
|
| 162 |
</div>
|
| 163 |
+
<div class="flex flex-wrap gap-1.5">
|
| 164 |
${areaLinks}
|
| 165 |
${subAreaLinks}
|
| 166 |
</div>
|
js/utils/tags.js
CHANGED
|
@@ -34,7 +34,6 @@ export function renderTopicTag(areaId, topicId) {
|
|
| 34 |
}
|
| 35 |
|
| 36 |
const topicName = typeof topic === 'string' ? topic : (topic.name || topic.navName || topicId);
|
| 37 |
-
console.log(`renderTopicTag: areaId="${areaId}", topicId="${topicId}", topicName="${topicName}"`, topic);
|
| 38 |
let bgColor = 'bg-gray-200';
|
| 39 |
let textColor = 'text-gray-700';
|
| 40 |
|
|
|
|
| 34 |
}
|
| 35 |
|
| 36 |
const topicName = typeof topic === 'string' ? topic : (topic.name || topic.navName || topicId);
|
|
|
|
| 37 |
let bgColor = 'bg-gray-200';
|
| 38 |
let textColor = 'text-gray-700';
|
| 39 |
|