Skip to content

Commit b70531c

Browse files
authored
Merge pull request #322 from raifdmueller/feat/giscus
feat: sticky feedback bar with CTA in anchor modal
2 parents fe4ffdd + a4c5ae2 commit b70531c

4 files changed

Lines changed: 67 additions & 42 deletions

File tree

website/src/components/anchor-modal.js

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ export function createModal() {
5252
<div class="text-[var(--color-text-secondary)]">Loading...</div>
5353
</div>
5454
</div>
55+
<div id="modal-feedback-bar" class="modal-feedback-bar hidden">
56+
<span class="modal-feedback-cta">${i18n.t('feedback.cta')}</span>
57+
<div class="feedback-actions">
58+
<a id="modal-vote-btn" href="#" target="_blank" rel="noopener noreferrer" class="feedback-btn feedback-btn-vote">
59+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
60+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5"></path>
61+
</svg>
62+
<span>${i18n.t('feedback.vote')}</span>
63+
</a>
64+
<a id="modal-discuss-btn" href="#" target="_blank" rel="noopener noreferrer" class="feedback-btn feedback-btn-discuss">
65+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
66+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"></path>
67+
</svg>
68+
<span>${i18n.t('feedback.discuss')}</span>
69+
</a>
70+
</div>
71+
</div>
5572
</div>
5673
`
5774

@@ -276,49 +293,45 @@ export async function loadAnchorContent(anchorId) {
276293
/^https:\/\/github\.com\/LLM-Coding\/Semantic-Anchors\/discussions\/\d+$/.test(fb.url)
277294
? fb.url
278295
: null
296+
// Update sticky feedback bar
297+
const feedbackBar = document.getElementById('modal-feedback-bar')
298+
const voteBtn = document.getElementById('modal-vote-btn')
299+
const discussBtn = document.getElementById('modal-discuss-btn')
300+
279301
if (safeFeedbackUrl) {
280-
const commentsHtml =
281-
fb.recentComments && fb.recentComments.length > 0
282-
? `
283-
<div class="feedback-comments">
284-
${fb.recentComments
285-
.map(
286-
(c) => `
287-
<div class="feedback-comment">
288-
<img src="${escapeHtml(c.avatar)}" alt="${escapeHtml(c.author)}" class="feedback-avatar" width="24" height="24" />
289-
<div class="feedback-comment-body">
290-
<span class="feedback-author">${escapeHtml(c.author)}</span>
291-
<p class="feedback-text">${escapeHtml(c.body)}</p>
302+
voteBtn.href = safeFeedbackUrl
303+
voteBtn.querySelector('span').textContent =
304+
`${i18n.t('feedback.vote')}${fb.upvotes > 1 ? ` (${fb.upvotes})` : ''}`
305+
discussBtn.href = safeFeedbackUrl
306+
discussBtn.querySelector('span').textContent =
307+
`${i18n.t('feedback.discuss')}${fb.comments > 0 ? ` (${fb.comments})` : ''}`
308+
feedbackBar.classList.remove('hidden')
309+
310+
// Show recent comments in content area
311+
if (fb.recentComments && fb.recentComments.length > 0) {
312+
const commentsHtml = `
313+
<div class="feedback-section">
314+
<div class="feedback-comments">
315+
${fb.recentComments
316+
.map(
317+
(c) => `
318+
<div class="feedback-comment">
319+
<img src="${escapeHtml(c.avatar)}" alt="${escapeHtml(c.author)}" class="feedback-avatar" width="24" height="24" />
320+
<div class="feedback-comment-body">
321+
<span class="feedback-author">${escapeHtml(c.author)}</span>
322+
<p class="feedback-text">${escapeHtml(c.body)}</p>
323+
</div>
292324
</div>
293-
</div>
294-
`
295-
)
296-
.join('')}
325+
`
326+
)
327+
.join('')}
328+
</div>
297329
</div>
298330
`
299-
: ''
300-
301-
const feedbackHtml = `
302-
<div class="feedback-section">
303-
${commentsHtml}
304-
<div class="feedback-actions">
305-
<a href="${escapeHtml(safeFeedbackUrl)}" target="_blank" rel="noopener noreferrer" class="feedback-btn feedback-btn-vote">
306-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
307-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5"></path>
308-
</svg>
309-
<span>${i18n.t('feedback.vote')}${fb.upvotes > 1 ? ` (${fb.upvotes})` : ''}</span>
310-
</a>
311-
<a href="${escapeHtml(safeFeedbackUrl)}" target="_blank" rel="noopener noreferrer" class="feedback-btn feedback-btn-discuss">
312-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
313-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"></path>
314-
</svg>
315-
<span>${i18n.t('feedback.discuss')}${fb.comments > 0 ? ` (${fb.comments})` : ''}</span>
316-
</a>
317-
</div>
318-
<p class="feedback-hint">${i18n.t('feedback.requiresLogin')}</p>
319-
</div>
320-
`
321-
contentEl.insertAdjacentHTML('beforeend', feedbackHtml)
331+
contentEl.insertAdjacentHTML('beforeend', commentsHtml)
332+
}
333+
} else {
334+
feedbackBar.classList.add('hidden')
322335
}
323336
} catch (error) {
324337
console.error('Error loading anchor content:', error)

website/src/styles/main.css

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,24 @@ body {
171171
@apply hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors;
172172
}
173173

174-
/* Feedback section in anchor modal */
174+
/* Sticky feedback bar in anchor modal */
175+
.modal-feedback-bar {
176+
@apply flex items-center justify-between gap-4 px-6 py-3;
177+
@apply border-t border-[var(--color-border)];
178+
@apply bg-[var(--color-bg)];
179+
}
180+
181+
.modal-feedback-cta {
182+
@apply text-sm text-[var(--color-text-secondary)] hidden sm:block;
183+
}
184+
185+
/* Feedback section in anchor modal (comments area) */
175186
.feedback-section {
176187
@apply mt-8 pt-6 border-t border-gray-200 dark:border-gray-700;
177-
@apply text-center;
178188
}
179189

180190
.feedback-actions {
181-
@apply flex justify-center gap-3;
191+
@apply flex gap-3;
182192
}
183193

184194
.feedback-btn {

website/src/translations/de.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,6 @@
6060
"umbrella.notAnAnchor": "(kein semantischer Anker)",
6161
"feedback.vote": "Abstimmen",
6262
"feedback.discuss": "Diskutieren",
63+
"feedback.cta": "Ist dieser Anker hilfreich?",
6364
"feedback.requiresLogin": "Erfordert GitHub-Login"
6465
}

website/src/translations/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,6 @@
6060
"umbrella.notAnAnchor": "(not a semantic anchor)",
6161
"feedback.vote": "Vote",
6262
"feedback.discuss": "Discuss",
63+
"feedback.cta": "Is this anchor useful?",
6364
"feedback.requiresLogin": "Requires GitHub login"
6465
}

0 commit comments

Comments
 (0)