Yacine Jernite
commited on
Commit
·
5daef86
1
Parent(s):
186bc23
visuals
Browse files- index.html +2 -2
- js/components/Card.js +6 -6
- js/components/ContentSection.js +2 -2
- js/components/PageNavigation.js +3 -3
- js/main.js +1 -1
- js/pages/AreaPage.js +23 -11
- js/pages/HomePage.js +17 -3
- js/utils/router.js +1 -1
- js/utils/search.js +8 -8
- js/utils/tags.js +4 -4
- styles.css +6 -5
index.html
CHANGED
|
@@ -74,7 +74,7 @@
|
|
| 74 |
</a>
|
| 75 |
|
| 76 |
<!-- Top Navigation -->
|
| 77 |
-
<header role="banner" aria-label="Main navigation" class="bg-white/
|
| 78 |
mobileMenuOpen: false,
|
| 79 |
areas: window.navigationAreas || [],
|
| 80 |
currentArea: null,
|
|
@@ -164,7 +164,7 @@
|
|
| 164 |
<div class="px-4 py-3 space-y-2 max-h-[70vh] overflow-y-auto">
|
| 165 |
<!-- Areas with Topics -->
|
| 166 |
<div>
|
| 167 |
-
<p class="px-3 text-
|
| 168 |
|
| 169 |
<template x-for="area in areas" :key="area.id">
|
| 170 |
<div class="mb-2">
|
|
|
|
| 74 |
</a>
|
| 75 |
|
| 76 |
<!-- Top Navigation -->
|
| 77 |
+
<header role="banner" aria-label="Main navigation" class="bg-white/80 shadow-md border-b border-gray-300 fixed top-0 left-0 right-0 z-50" style="height: var(--header-height);" x-data="{
|
| 78 |
mobileMenuOpen: false,
|
| 79 |
areas: window.navigationAreas || [],
|
| 80 |
currentArea: null,
|
|
|
|
| 164 |
<div class="px-4 py-3 space-y-2 max-h-[70vh] overflow-y-auto">
|
| 165 |
<!-- Areas with Topics -->
|
| 166 |
<div>
|
| 167 |
+
<p class="px-3 text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2">Research Areas</p>
|
| 168 |
|
| 169 |
<template x-for="area in areas" :key="area.id">
|
| 170 |
<div class="mb-2">
|
js/components/Card.js
CHANGED
|
@@ -67,7 +67,7 @@ function renderArtifactCard(artifact, options = {}) {
|
|
| 67 |
const cardId = `artifact-card-${index}`;
|
| 68 |
|
| 69 |
return `
|
| 70 |
-
<div class="flex-none w-80 h-60 border border-gray-
|
| 71 |
<!-- Background image -->
|
| 72 |
${backgroundImage ? `
|
| 73 |
<div class="absolute inset-0 opacity-10">
|
|
@@ -95,9 +95,9 @@ 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-
|
| 99 |
</div>
|
| 100 |
-
<span class="text-
|
| 101 |
</div>
|
| 102 |
|
| 103 |
<!-- Title -->
|
|
@@ -196,7 +196,7 @@ function renderAreaCard(area, options = {}) {
|
|
| 196 |
|
| 197 |
return `
|
| 198 |
<a href="/${area.id}"
|
| 199 |
-
class="group relative block border border-gray-
|
| 200 |
|
| 201 |
<!-- Background image with low opacity -->
|
| 202 |
${area.image ? `
|
|
@@ -222,10 +222,10 @@ function renderAreaCard(area, options = {}) {
|
|
| 222 |
|
| 223 |
<!-- Topics with colors from subAreas -->
|
| 224 |
<div class="flex-shrink-0">
|
| 225 |
-
<p class="text-
|
| 226 |
<div class="flex flex-wrap gap-2">
|
| 227 |
${topics.map(topic => `
|
| 228 |
-
<span class="inline-block px-
|
| 229 |
${topic.name}
|
| 230 |
</span>
|
| 231 |
`).join('')}
|
|
|
|
| 67 |
const cardId = `artifact-card-${index}`;
|
| 68 |
|
| 69 |
return `
|
| 70 |
+
<div class="flex-none w-80 h-60 border border-gray-300 rounded-lg overflow-hidden bg-white/95 shadow-sm relative group hover:shadow-lg transition-shadow duration-200">
|
| 71 |
<!-- Background image -->
|
| 72 |
${backgroundImage ? `
|
| 73 |
<div class="absolute inset-0 opacity-10">
|
|
|
|
| 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-sm font-bold uppercase tracking-wide">${type}</span>
|
| 99 |
</div>
|
| 100 |
+
<span class="text-sm text-gray-500">${date}</span>
|
| 101 |
</div>
|
| 102 |
|
| 103 |
<!-- Title -->
|
|
|
|
| 196 |
|
| 197 |
return `
|
| 198 |
<a href="/${area.id}"
|
| 199 |
+
class="group relative block border border-gray-300 rounded-lg overflow-hidden bg-white/95 shadow-sm hover:shadow-lg transition-all duration-200 h-64">
|
| 200 |
|
| 201 |
<!-- Background image with low opacity -->
|
| 202 |
${area.image ? `
|
|
|
|
| 222 |
|
| 223 |
<!-- Topics with colors from subAreas -->
|
| 224 |
<div class="flex-shrink-0">
|
| 225 |
+
<p class="text-sm 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-3 py-1.5 text-sm ${topic.bgColor} ${topic.textColor} rounded">
|
| 229 |
${topic.name}
|
| 230 |
</span>
|
| 231 |
`).join('')}
|
js/components/ContentSection.js
CHANGED
|
@@ -11,14 +11,14 @@
|
|
| 11 |
export function renderContentSection(id, content, options = {}) {
|
| 12 |
const {
|
| 13 |
className = 'mb-16',
|
| 14 |
-
opacity = '
|
| 15 |
blur = 'sm', // sm, md, lg
|
| 16 |
padding = 'p-6 md:p-10'
|
| 17 |
} = options;
|
| 18 |
|
| 19 |
return `
|
| 20 |
<section id="${id}" class="${className} relative z-20 px-4 sm:px-6 lg:px-8">
|
| 21 |
-
<div class="bg-white/${opacity} backdrop-blur-${blur} shadow-
|
| 22 |
${content}
|
| 23 |
</div>
|
| 24 |
</section>
|
|
|
|
| 11 |
export function renderContentSection(id, content, options = {}) {
|
| 12 |
const {
|
| 13 |
className = 'mb-16',
|
| 14 |
+
opacity = '90', // Increased from 40% to 90% for better readability
|
| 15 |
blur = 'sm', // sm, md, lg
|
| 16 |
padding = 'p-6 md:p-10'
|
| 17 |
} = options;
|
| 18 |
|
| 19 |
return `
|
| 20 |
<section id="${id}" class="${className} relative z-20 px-4 sm:px-6 lg:px-8">
|
| 21 |
+
<div class="bg-white/${opacity} backdrop-blur-${blur} shadow-md rounded-lg ${padding} w-full border border-gray-200" style="max-width: min(90%, 1400px); margin: 0 auto;">
|
| 22 |
${content}
|
| 23 |
</div>
|
| 24 |
</section>
|
js/components/PageNavigation.js
CHANGED
|
@@ -14,9 +14,9 @@ export function renderPageNavigation(label, items) {
|
|
| 14 |
|
| 15 |
return `
|
| 16 |
<section class="mb-8 relative z-20 px-4 sm:px-6 lg:px-8">
|
| 17 |
-
<div class="bg-white/
|
| 18 |
<div class="flex items-center gap-3 overflow-x-auto">
|
| 19 |
-
<span class="text-gray-600 font-semibold whitespace-nowrap">${label}</span>
|
| 20 |
${items.map((item, index) => {
|
| 21 |
const activeClasses = item.active
|
| 22 |
? 'text-blue-600 font-semibold underline decoration-2 underline-offset-2'
|
|
@@ -24,7 +24,7 @@ export function renderPageNavigation(label, items) {
|
|
| 24 |
|
| 25 |
return `
|
| 26 |
${index > 0 ? '<span class="text-gray-300">•</span>' : ''}
|
| 27 |
-
<a href="${item.href}" class="px-
|
| 28 |
`;
|
| 29 |
}).join('')}
|
| 30 |
</div>
|
|
|
|
| 14 |
|
| 15 |
return `
|
| 16 |
<section class="mb-8 relative z-20 px-4 sm:px-6 lg:px-8">
|
| 17 |
+
<div class="bg-white/85 backdrop-blur-sm shadow-md rounded-lg px-6 py-4 w-full border border-gray-200" style="max-width: min(90%, 1400px); margin: 0 auto;">
|
| 18 |
<div class="flex items-center gap-3 overflow-x-auto">
|
| 19 |
+
<span class="text-gray-600 font-semibold whitespace-nowrap text-base">${label}</span>
|
| 20 |
${items.map((item, index) => {
|
| 21 |
const activeClasses = item.active
|
| 22 |
? 'text-blue-600 font-semibold underline decoration-2 underline-offset-2'
|
|
|
|
| 24 |
|
| 25 |
return `
|
| 26 |
${index > 0 ? '<span class="text-gray-300">•</span>' : ''}
|
| 27 |
+
<a href="${item.href}" class="px-4 py-2 text-base font-medium ${activeClasses} hover:bg-blue-50 rounded transition-colors whitespace-nowrap">${item.text}</a>
|
| 28 |
`;
|
| 29 |
}).join('')}
|
| 30 |
</div>
|
js/main.js
CHANGED
|
@@ -32,7 +32,7 @@ export function createTeamMember(name, role, hfUsername, tags) {
|
|
| 32 |
|
| 33 |
const tagElements = tags.map(tag => {
|
| 34 |
const tagInfo = teamTagData[tag];
|
| 35 |
-
return `<span class="inline-block px-2 py-
|
| 36 |
}).join('');
|
| 37 |
|
| 38 |
return `
|
|
|
|
| 32 |
|
| 33 |
const tagElements = tags.map(tag => {
|
| 34 |
const tagInfo = teamTagData[tag];
|
| 35 |
+
return `<span class="inline-block px-2.5 py-1 text-sm bg-gray-100 text-gray-700 rounded-full hover:bg-blue-100 hover:text-blue-800 cursor-pointer transition-colors whitespace-nowrap" onclick="window.scrollToSection('${tagInfo.id}')">${tagInfo.name}</span>`;
|
| 36 |
}).join('');
|
| 37 |
|
| 38 |
return `
|
js/pages/AreaPage.js
CHANGED
|
@@ -55,24 +55,36 @@ function renderAreaOverview(area, areaId) {
|
|
| 55 |
<!-- Area Description -->
|
| 56 |
<div class="mb-8">
|
| 57 |
${area.description.paragraphs ?
|
| 58 |
-
area.description.paragraphs.map(p => `<p class="text-gray-
|
| 59 |
-
: `<p class="text-gray-
|
| 60 |
}
|
| 61 |
</div>
|
| 62 |
|
| 63 |
<!-- Topics within this area -->
|
| 64 |
<div class="mb-8">
|
| 65 |
-
<p class="text-
|
| 66 |
<div class="flex flex-wrap gap-2">
|
| 67 |
${topics.map(topic => {
|
| 68 |
-
// Extract colors from topic.color
|
| 69 |
let bgColor = 'bg-gray-200';
|
| 70 |
-
let textColor = 'text-gray-
|
|
|
|
|
|
|
| 71 |
if (topic.color) {
|
| 72 |
const bgMatch = topic.color.match(/bg-(\w+)-(\d+)/);
|
| 73 |
const textMatch = topic.color.match(/text-(\w+)-(\d+)/);
|
| 74 |
-
if (bgMatch)
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
}
|
| 77 |
|
| 78 |
// Get short description for tooltip
|
|
@@ -80,7 +92,7 @@ function renderAreaOverview(area, areaId) {
|
|
| 80 |
const titleAttr = shortDesc ? ` title="${shortDesc}"` : '';
|
| 81 |
|
| 82 |
return `
|
| 83 |
-
<a href="/${areaId}/${topic.id}" class="inline-block px-3 py-1.5 text-sm ${bgColor} ${textColor} rounded hover:opacity-
|
| 84 |
${topic.navName}
|
| 85 |
</a>
|
| 86 |
`;
|
|
@@ -90,7 +102,7 @@ function renderAreaOverview(area, areaId) {
|
|
| 90 |
|
| 91 |
<!-- Research and Resources -->
|
| 92 |
<div>
|
| 93 |
-
<p class="text-
|
| 94 |
<div id="area-artifacts-carousel-${areaId}" class="overflow-x-auto -mx-2">
|
| 95 |
<!-- Carousel will be inserted here -->
|
| 96 |
</div>
|
|
@@ -109,7 +121,7 @@ function renderAreaOverview(area, areaId) {
|
|
| 109 |
function renderTopicView(area, areaId, topic, topicId) {
|
| 110 |
const topicName = topic.navName || topic.name;
|
| 111 |
const topicDescription = topic.description?.paragraphs
|
| 112 |
-
? topic.description.paragraphs.map(p => `<p class="text-gray-
|
| 113 |
: (topic.description?.short || topic.description || '');
|
| 114 |
|
| 115 |
// Get all topics for navigation
|
|
@@ -136,7 +148,7 @@ function renderTopicView(area, areaId, topic, topicId) {
|
|
| 136 |
|
| 137 |
<!-- Topic Description -->
|
| 138 |
${topicDescription ? `
|
| 139 |
-
<div class="mb-8">
|
| 140 |
${topicDescription}
|
| 141 |
</div>
|
| 142 |
` : ''}
|
|
|
|
| 55 |
<!-- Area Description -->
|
| 56 |
<div class="mb-8">
|
| 57 |
${area.description.paragraphs ?
|
| 58 |
+
area.description.paragraphs.map(p => `<p class="text-gray-900 leading-relaxed mb-4">${p}</p>`).join('')
|
| 59 |
+
: `<p class="text-gray-900 leading-relaxed">${area.description.short || area.description}</p>`
|
| 60 |
}
|
| 61 |
</div>
|
| 62 |
|
| 63 |
<!-- Topics within this area -->
|
| 64 |
<div class="mb-8">
|
| 65 |
+
<p class="text-sm font-semibold text-gray-600 uppercase tracking-wide mb-3">Topics in this area:</p>
|
| 66 |
<div class="flex flex-wrap gap-2">
|
| 67 |
${topics.map(topic => {
|
| 68 |
+
// Extract colors from topic.color and enhance them
|
| 69 |
let bgColor = 'bg-gray-200';
|
| 70 |
+
let textColor = 'text-gray-800';
|
| 71 |
+
let borderColor = 'border-gray-300';
|
| 72 |
+
|
| 73 |
if (topic.color) {
|
| 74 |
const bgMatch = topic.color.match(/bg-(\w+)-(\d+)/);
|
| 75 |
const textMatch = topic.color.match(/text-(\w+)-(\d+)/);
|
| 76 |
+
if (bgMatch) {
|
| 77 |
+
const colorName = bgMatch[1];
|
| 78 |
+
const shade = parseInt(bgMatch[2]);
|
| 79 |
+
// Increase saturation: 100 → 200, 200 → 300, etc.
|
| 80 |
+
const newShade = Math.min(shade + 100, 300);
|
| 81 |
+
bgColor = `bg-${colorName}-${newShade}`;
|
| 82 |
+
borderColor = `border-${colorName}-${Math.min(newShade + 100, 400)}`;
|
| 83 |
+
}
|
| 84 |
+
if (textMatch) {
|
| 85 |
+
const colorName = textMatch[1];
|
| 86 |
+
textColor = `text-${colorName}-900`;
|
| 87 |
+
}
|
| 88 |
}
|
| 89 |
|
| 90 |
// Get short description for tooltip
|
|
|
|
| 92 |
const titleAttr = shortDesc ? ` title="${shortDesc}"` : '';
|
| 93 |
|
| 94 |
return `
|
| 95 |
+
<a href="/${areaId}/${topic.id}" class="inline-block px-3 py-1.5 text-sm font-semibold ${bgColor} ${textColor} ${borderColor} border rounded hover:opacity-90 transition-opacity"${titleAttr}>
|
| 96 |
${topic.navName}
|
| 97 |
</a>
|
| 98 |
`;
|
|
|
|
| 102 |
|
| 103 |
<!-- Research and Resources -->
|
| 104 |
<div>
|
| 105 |
+
<p class="text-sm font-semibold text-gray-600 uppercase tracking-wide mb-3">Research and Resources:</p>
|
| 106 |
<div id="area-artifacts-carousel-${areaId}" class="overflow-x-auto -mx-2">
|
| 107 |
<!-- Carousel will be inserted here -->
|
| 108 |
</div>
|
|
|
|
| 121 |
function renderTopicView(area, areaId, topic, topicId) {
|
| 122 |
const topicName = topic.navName || topic.name;
|
| 123 |
const topicDescription = topic.description?.paragraphs
|
| 124 |
+
? topic.description.paragraphs.map(p => `<p class="text-gray-900 leading-relaxed mb-4">${p}</p>`).join('')
|
| 125 |
: (topic.description?.short || topic.description || '');
|
| 126 |
|
| 127 |
// Get all topics for navigation
|
|
|
|
| 148 |
|
| 149 |
<!-- Topic Description -->
|
| 150 |
${topicDescription ? `
|
| 151 |
+
<div class="mb-8 text-gray-900">
|
| 152 |
${topicDescription}
|
| 153 |
</div>
|
| 154 |
` : ''}
|
js/pages/HomePage.js
CHANGED
|
@@ -13,9 +13,23 @@ const homeBackgroundImage = window.homeBackgroundImage;
|
|
| 13 |
|
| 14 |
// Helper function to create inline styled links
|
| 15 |
function createInlineLink(text, href, colorClass = '', tooltip = '') {
|
| 16 |
-
const baseClass = 'inline-block px-2 py-
|
| 17 |
const titleAttr = tooltip ? ` title="${tooltip}"` : '';
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
}
|
| 20 |
|
| 21 |
export function renderHomePage() {
|
|
@@ -28,7 +42,7 @@ export function renderHomePage() {
|
|
| 28 |
${renderContentSection('about-and-works', `
|
| 29 |
<h3 id="about" class="text-xl md:text-2xl font-bold text-gray-900 mb-8 text-center">About</h3>
|
| 30 |
|
| 31 |
-
<div class="space-y-2 text-gray-
|
| 32 |
<p>
|
| 33 |
With the rapid evolution of Artificial Intelligence over the last five years – and particularly its shift from Machine Learning as a behind-the-scenes organizing principle of our digital infrastructure to the more visible "generative AI" systems sold as consumer products – the interaction modes between the technology and its social contexts have expanded drastically.
|
| 34 |
</p>
|
|
|
|
| 13 |
|
| 14 |
// Helper function to create inline styled links
|
| 15 |
function createInlineLink(text, href, colorClass = '', tooltip = '') {
|
| 16 |
+
const baseClass = 'inline-block px-2.5 py-1 mx-0.5 text-sm font-semibold rounded hover:opacity-90 transition-opacity no-underline border';
|
| 17 |
const titleAttr = tooltip ? ` title="${tooltip}"` : '';
|
| 18 |
+
|
| 19 |
+
// Map color classes to darker variants and add border colors
|
| 20 |
+
const enhancedColorClass = colorClass
|
| 21 |
+
.replace('bg-yellow-100', 'bg-yellow-200 border-yellow-300')
|
| 22 |
+
.replace('bg-blue-100', 'bg-blue-200 border-blue-300')
|
| 23 |
+
.replace('bg-green-100', 'bg-green-200 border-green-300')
|
| 24 |
+
.replace('bg-purple-100', 'bg-purple-200 border-purple-300')
|
| 25 |
+
.replace('bg-orange-100', 'bg-orange-200 border-orange-300')
|
| 26 |
+
.replace('text-yellow-800', 'text-yellow-900')
|
| 27 |
+
.replace('text-blue-800', 'text-blue-900')
|
| 28 |
+
.replace('text-green-800', 'text-green-900')
|
| 29 |
+
.replace('text-purple-800', 'text-purple-900')
|
| 30 |
+
.replace('text-orange-800', 'text-orange-900');
|
| 31 |
+
|
| 32 |
+
return `<a href="${href}" class="${baseClass} ${enhancedColorClass}"${titleAttr}>${text}</a>`;
|
| 33 |
}
|
| 34 |
|
| 35 |
export function renderHomePage() {
|
|
|
|
| 42 |
${renderContentSection('about-and-works', `
|
| 43 |
<h3 id="about" class="text-xl md:text-2xl font-bold text-gray-900 mb-8 text-center">About</h3>
|
| 44 |
|
| 45 |
+
<div class="space-y-2 text-gray-900 leading-relaxed mb-8">
|
| 46 |
<p>
|
| 47 |
With the rapid evolution of Artificial Intelligence over the last five years – and particularly its shift from Machine Learning as a behind-the-scenes organizing principle of our digital infrastructure to the more visible "generative AI" systems sold as consumer products – the interaction modes between the technology and its social contexts have expanded drastically.
|
| 48 |
</p>
|
js/utils/router.js
CHANGED
|
@@ -160,7 +160,7 @@ class Router {
|
|
| 160 |
// Create background element at document level
|
| 161 |
const backgroundDiv = document.createElement('div');
|
| 162 |
backgroundDiv.id = 'page-background';
|
| 163 |
-
backgroundDiv.className = 'fixed opacity-
|
| 164 |
|
| 165 |
// The positioning logic is now in updatePageBackgroundPosition, call it after adding to DOM
|
| 166 |
document.body.insertAdjacentElement('afterbegin', backgroundDiv);
|
|
|
|
| 160 |
// Create background element at document level
|
| 161 |
const backgroundDiv = document.createElement('div');
|
| 162 |
backgroundDiv.id = 'page-background';
|
| 163 |
+
backgroundDiv.className = 'fixed opacity-25 z-0';
|
| 164 |
|
| 165 |
// The positioning logic is now in updatePageBackgroundPosition, call it after adding to DOM
|
| 166 |
document.body.insertAdjacentElement('afterbegin', backgroundDiv);
|
js/utils/search.js
CHANGED
|
@@ -127,7 +127,7 @@ export function displaySearchResults(results, query) {
|
|
| 127 |
return;
|
| 128 |
}
|
| 129 |
|
| 130 |
-
let html = `<div class="text-
|
| 131 |
Found ${totalResults} result${totalResults === 1 ? '' : 's'}
|
| 132 |
</div>`;
|
| 133 |
|
|
@@ -144,23 +144,23 @@ export function displaySearchResults(results, query) {
|
|
| 144 |
const { areaLinksHtml: areaLinks, topicLinksHtml: subAreaLinks } = renderSearchTags(areas, topics);
|
| 145 |
|
| 146 |
html += `
|
| 147 |
-
<div class="p-
|
| 148 |
<div class="flex items-center justify-between mb-2">
|
| 149 |
-
<h5 class="font-medium text-
|
| 150 |
<div class="flex items-center gap-2 flex-shrink-0 ml-2">
|
| 151 |
-
<span class="text-
|
| 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-
|
| 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-
|
| 160 |
-
<span class="px-2 py-
|
| 161 |
<span class="text-gray-500">${result.date}</span>
|
| 162 |
</div>
|
| 163 |
-
<div class="flex flex-wrap gap-
|
| 164 |
${areaLinks}
|
| 165 |
${subAreaLinks}
|
| 166 |
</div>
|
|
|
|
| 127 |
return;
|
| 128 |
}
|
| 129 |
|
| 130 |
+
let html = `<div class="text-base text-gray-600 mb-4 font-medium">
|
| 131 |
Found ${totalResults} result${totalResults === 1 ? '' : 's'}
|
| 132 |
</div>`;
|
| 133 |
|
|
|
|
| 144 |
const { areaLinksHtml: areaLinks, topicLinksHtml: subAreaLinks } = renderSearchTags(areas, topics);
|
| 145 |
|
| 146 |
html += `
|
| 147 |
+
<div class="p-4 bg-white/95 rounded-lg border border-gray-300 shadow-sm hover:shadow-md transition-shadow">
|
| 148 |
<div class="flex items-center justify-between mb-2">
|
| 149 |
+
<h5 class="font-medium text-base 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-sm 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-5 h-5" 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-sm text-gray-600">
|
| 160 |
+
<span class="px-2.5 py-1 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-2">
|
| 164 |
${areaLinks}
|
| 165 |
${subAreaLinks}
|
| 166 |
</div>
|
js/utils/tags.js
CHANGED
|
@@ -10,7 +10,7 @@ export function renderAreaTag(areaId) {
|
|
| 10 |
const area = areasData[areaId];
|
| 11 |
if (!area) return '';
|
| 12 |
|
| 13 |
-
return `<span class="inline-block px-2 py-1 text-
|
| 14 |
}
|
| 15 |
|
| 16 |
/**
|
|
@@ -50,7 +50,7 @@ export function renderTopicTag(areaId, topicId) {
|
|
| 50 |
}
|
| 51 |
}
|
| 52 |
|
| 53 |
-
return `<span class="inline-block px-2 py-
|
| 54 |
}
|
| 55 |
|
| 56 |
/**
|
|
@@ -100,7 +100,7 @@ export function renderSearchTags(areas = [], topics = []) {
|
|
| 100 |
if (!area) return '';
|
| 101 |
|
| 102 |
const colorClass = area.color || 'bg-blue-100 text-blue-800';
|
| 103 |
-
return `<a href="/${areaId}#overview" class="text-
|
| 104 |
}).filter(link => link).join('');
|
| 105 |
|
| 106 |
const topicLinksHtml = topics.map(topicId => {
|
|
@@ -117,7 +117,7 @@ export function renderSearchTags(areas = [], topics = []) {
|
|
| 117 |
const topicName = typeof topic === 'string' ? topic : topic.name;
|
| 118 |
const colorClass = typeof topic === 'object' && topic.color ? topic.color : 'bg-gray-100 text-gray-800';
|
| 119 |
|
| 120 |
-
return `<a href="/${primaryArea}#${topicId}" class="text-
|
| 121 |
}).filter(link => link).join('');
|
| 122 |
|
| 123 |
return {
|
|
|
|
| 10 |
const area = areasData[areaId];
|
| 11 |
if (!area) return '';
|
| 12 |
|
| 13 |
+
return `<span class="inline-block px-2.5 py-1 text-sm rounded-full ${area.color}">${area.title}</span>`;
|
| 14 |
}
|
| 15 |
|
| 16 |
/**
|
|
|
|
| 50 |
}
|
| 51 |
}
|
| 52 |
|
| 53 |
+
return `<span class="inline-block px-2.5 py-1 text-sm ${bgColor} ${textColor} rounded">${topicName}</span>`;
|
| 54 |
}
|
| 55 |
|
| 56 |
/**
|
|
|
|
| 100 |
if (!area) return '';
|
| 101 |
|
| 102 |
const colorClass = area.color || 'bg-blue-100 text-blue-800';
|
| 103 |
+
return `<a href="/${areaId}#overview" class="text-sm px-2.5 py-1 ${colorClass} rounded hover:opacity-80 transition-opacity">${area.title}</a>`;
|
| 104 |
}).filter(link => link).join('');
|
| 105 |
|
| 106 |
const topicLinksHtml = topics.map(topicId => {
|
|
|
|
| 117 |
const topicName = typeof topic === 'string' ? topic : topic.name;
|
| 118 |
const colorClass = typeof topic === 'object' && topic.color ? topic.color : 'bg-gray-100 text-gray-800';
|
| 119 |
|
| 120 |
+
return `<a href="/${primaryArea}#${topicId}" class="text-sm px-2.5 py-1 ${colorClass} rounded hover:opacity-80 transition-opacity">${topicName}</a>`;
|
| 121 |
}).filter(link => link).join('');
|
| 122 |
|
| 123 |
return {
|
styles.css
CHANGED
|
@@ -46,6 +46,7 @@ body {
|
|
| 46 |
h1, h2, h3, h4, h5, h6 {
|
| 47 |
font-family: 'Montserrat', sans-serif;
|
| 48 |
line-height: var(--leading-tight);
|
|
|
|
| 49 |
}
|
| 50 |
|
| 51 |
/* Body text readability */
|
|
@@ -152,13 +153,13 @@ p {
|
|
| 152 |
|
| 153 |
/* Frosted glass effect */
|
| 154 |
.backdrop-blur-md {
|
| 155 |
-
backdrop-filter: blur(
|
| 156 |
-
-webkit-backdrop-filter: blur(
|
| 157 |
}
|
| 158 |
|
| 159 |
.backdrop-blur-sm {
|
| 160 |
-
backdrop-filter: blur(
|
| 161 |
-
-webkit-backdrop-filter: blur(
|
| 162 |
}
|
| 163 |
|
| 164 |
.drop-shadow-lg {
|
|
@@ -329,7 +330,7 @@ p {
|
|
| 329 |
|
| 330 |
/* Semi-transparent overlays for header and search sidebar */
|
| 331 |
header, #search-sidebar {
|
| 332 |
-
background: rgba(255, 255, 255, 0.
|
| 333 |
}
|
| 334 |
|
| 335 |
/* Ensure content is readable over background */
|
|
|
|
| 46 |
h1, h2, h3, h4, h5, h6 {
|
| 47 |
font-family: 'Montserrat', sans-serif;
|
| 48 |
line-height: var(--leading-tight);
|
| 49 |
+
text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
|
| 50 |
}
|
| 51 |
|
| 52 |
/* Body text readability */
|
|
|
|
| 153 |
|
| 154 |
/* Frosted glass effect */
|
| 155 |
.backdrop-blur-md {
|
| 156 |
+
backdrop-filter: blur(16px);
|
| 157 |
+
-webkit-backdrop-filter: blur(16px);
|
| 158 |
}
|
| 159 |
|
| 160 |
.backdrop-blur-sm {
|
| 161 |
+
backdrop-filter: blur(16px);
|
| 162 |
+
-webkit-backdrop-filter: blur(16px);
|
| 163 |
}
|
| 164 |
|
| 165 |
.drop-shadow-lg {
|
|
|
|
| 330 |
|
| 331 |
/* Semi-transparent overlays for header and search sidebar */
|
| 332 |
header, #search-sidebar {
|
| 333 |
+
background: rgba(255, 255, 255, 0.8);
|
| 334 |
}
|
| 335 |
|
| 336 |
/* Ensure content is readable over background */
|