diff --git a/static/script.js b/static/script.js index 9d96ab9..0c74532 100644 --- a/static/script.js +++ b/static/script.js @@ -645,11 +645,31 @@ if (clearFiltersBtn) { title.textContent = project.title; // Description (truncated for visual consistency) + // Description with Read More toggle var desc = document.createElement("p"); desc.className = "project-card-desc"; - // Cut description to 120 chars so all cards stay the same height - desc.textContent = truncate(project.description, 120); + var shortText = truncate(project.description, 120); + var fullText = project.description; + var isExpanded = false; + + desc.textContent = shortText; + + // Only add Read More button if description is actually truncated + if (fullText.length > 120) { + var readMoreBtn = document.createElement("button"); + readMoreBtn.className = "read-more-btn"; + readMoreBtn.textContent = "Read more"; + + readMoreBtn.addEventListener("click", function () { + isExpanded = !isExpanded; + desc.textContent = isExpanded ? fullText : shortText; + readMoreBtn.textContent = isExpanded ? "Read less" : "Read more"; + desc.appendChild(readMoreBtn); // re-append button since textContent clears it + }); + + desc.appendChild(readMoreBtn); + } // Tags row var tagsRow = document.createElement("div"); tagsRow.className = "project-card-tags"; diff --git a/static/style.css b/static/style.css index 13cd1c9..7b67de5 100644 --- a/static/style.css +++ b/static/style.css @@ -2845,4 +2845,20 @@ select:focus { flex: 1; white-space: pre; color: #e6edf3; +} + +.read-more-btn { + background: none; + border: none; + color: #6366f1; + font-size: 0.85rem; + font-weight: 600; + cursor: pointer; + padding: 0; + margin-left: 4px; + text-decoration: underline; +} + +.read-more-btn:hover { + color: #4f46e5; } \ No newline at end of file