Skip to content

Conversation

krrish-sehgal
Copy link
Contributor

@krrish-sehgal krrish-sehgal commented Aug 26, 2025

fixes #4508

Screenshot 2025-08-26 at 2 38 45 PM

Summary by CodeRabbit

  • New Features
    • Live search on blog posts with instant filtering and a clear “No matching posts found” message.
    • Smooth scroll to the comments section from in-page links.
    • Subtle hover lift on blog cards for improved interactivity.
  • Style
    • Updated “Read more” and in-article links to accessible blue with hover underline for better readability.
  • Refactor
    • Moved inline page scripts to an external file for more reliable, maintainable behavior and faster page rendering.

Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

Walkthrough

Introduces website/static/js/blog.js to handle blog search filtering, empty-state rendering, link styling within blog content, smooth scroll to comments, and card hover effects. Updates templates to load the new script. post_detail adds a blog-content class. post_list removes inline JS and updates “Read more” link styling.

Changes

Cohort / File(s) Summary
Client-side blog interactions
website/static/js/blog.js
Adds DOMContentLoaded handler implementing: search filter for .blog-card via #post-search; empty-state message creation/removal; link styling within .blog-content; smooth scroll for #comments links; hover scale for .blog-card. Includes existence guards.
Post list template updates
website/templates/blog/post_list.html
Removes inline search/empty-state JS; adds external script include for js/blog.js; updates “Read more” link classes to blue (text-blue-600 hover:text-blue-800).
Post detail template hookup
website/templates/blog/post_detail.html
Adds blog-content class to content container; includes js/blog.js at bottom.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant DOM as Document
    participant JS as blog.js
    participant Grid as Blog Grid
    participant Empty as Empty State

    User->>DOM: Load page
    DOM-->>JS: DOMContentLoaded
    JS->>DOM: Bind input on #post-search
    JS->>DOM: Enhance links in .blog-content
    JS->>DOM: Bind hover on .blog-card
    JS->>DOM: Bind click on [href="#comments"]

    User->>DOM: Type in #post-search
    DOM-->>JS: input event
    JS->>Grid: Show/Hide .blog-card based on match
    JS->>JS: checkEmptyState()
    alt No visible cards and non-empty query
        JS->>Empty: Create/Attach empty-state node
    else Results visible or empty query
        JS->>Empty: Remove empty-state node if present
    end

    User->>DOM: Click #comments link
    JS->>DOM: scrollIntoView(#comment_root, smooth)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Links in blog content are visibly highlighted (#4508)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Search-based filtering of blog cards (website/static/js/blog.js) Not related to link highlighting; introduces new UI behavior.
Dynamic empty-state creation/removal for search (website/static/js/blog.js) Separate UX feature unrelated to highlighting links.
Smooth scroll to comments on anchor click (website/static/js/blog.js) Navigation enhancement; not part of link highlighting bug.
Hover scale effect on blog cards (website/static/js/blog.js) Visual effect unrelated to the reported issue.
“Read more” link color change in list view (website/templates/blog/post_list.html) Adjusts card link styling; the issue pertains to in-article link visibility.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (7)
website/static/js/blog.js (6)

18-24: Avoid forcing display:block; toggle only 'hidden' to reduce layout side-effects

Cards already have their display semantics. Forcing block can conflict with grid/flex layouts. Toggle the visibility class only.

-                if (title.includes(searchTerm) || author.includes(searchTerm)) {
-                    card.classList.remove('hidden');
-                    card.classList.add('block');
-                } else {
-                    card.classList.remove('block');
-                    card.classList.add('hidden');
-                }
+                const matches = title.includes(searchTerm) || author.includes(searchTerm);
+                card.classList.toggle('hidden', !matches);

10-28: Optional: debounce input to avoid excessive DOM churn on fast typing

Debouncing improves input responsiveness on long lists. Keep delay small (100–150ms).

-        searchInput.addEventListener('input', function() {
-            const searchTerm = this.value.toLowerCase().trim();
+        const debounce = (fn, delay = 120) => {
+            let t;
+            return (...args) => { clearTimeout(t); t = setTimeout(() => fn.apply(null, args), delay); };
+        };
+        searchInput.addEventListener('input', debounce(() => {
+            const searchTerm = searchInput.value.toLowerCase().trim();
             ...
-            checkEmptyState();
-        });
+            checkEmptyState();
+        }));

31-50: Guard against missing grid on pages without a grid; align empty-state color with site brand

  • If .blog-grid isn’t present, appendChild will throw.
  • The rest of the UI uses brand red #e74c3c; consider aligning the empty state icon color.
     function checkEmptyState() {
         const visibleCards = document.querySelectorAll('.blog-card:not(.hidden)');
         const grid = document.querySelector('.blog-grid');
         const existingEmptyState = document.querySelector('.empty-state-message');
 
-        if (visibleCards.length === 0 && !existingEmptyState && searchInput.value.trim() !== '') {
+        if (!grid) { return; }
+        if (visibleCards.length === 0 && !existingEmptyState && searchInput.value.trim() !== '') {
             const emptyState = document.createElement('div');
             emptyState.className = 'empty-state-message col-span-full flex flex-col items-center justify-center py-16 text-center';
             emptyState.innerHTML = `
-                <svg class="w-16 h-16 text-red-500 opacity-50 mb-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+                <svg class="w-16 h-16 text-[#e74c3c] opacity-50 mb-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                     <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
                 </svg>
                 <h2 class="text-xl font-semibold text-gray-700 mb-2">No matching posts found</h2>
                 <p class="text-gray-500 max-w-md">Try adjusting your search criteria or browse all posts below.</p>
             `;
             grid.appendChild(emptyState);
         } else if ((visibleCards.length > 0 || searchInput.value.trim() === '') && existingEmptyState) {
             existingEmptyState.remove();
         }
     }

52-72: Prefer CSS classes over inline styles and JS hover for content links; add base underline and visited states

Inline styles and JS hover handlers fight theming, visited color, and accessibility. Tailwind classes (or a small CSS rule) are sufficient.

         const links = blogContent.querySelectorAll('a');
         links.forEach(link => {
             // Apply blue styling to all links in blog content
-            link.classList.add('text-blue-600', 'hover:text-blue-800', 'hover:underline');
-            link.style.color = '#2563eb'; // Ensures the color is applied even if CSS classes don't load
-            
-            // Add hover event listeners for better control
-            link.addEventListener('mouseenter', function() {
-                this.style.color = '#1d4ed8';
-                this.style.textDecoration = 'underline';
-            });
-            
-            link.addEventListener('mouseleave', function() {
-                this.style.color = '#2563eb';
-                this.style.textDecoration = 'none';
-            });
+            link.classList.add(
+                'text-blue-600',
+                'visited:text-purple-600',
+                'hover:text-blue-800',
+                'underline',
+                'underline-offset-2',
+                'focus:outline-none',
+                'focus-visible:ring-2',
+                'focus-visible:ring-blue-300',
+                'rounded-sm'
+            );
         });

Note: if Tailwind’s visited: or focus-visible: variants aren’t enabled, add a small CSS rule instead:

.blog-content a { color:#2563eb; text-decoration:underline; }
.blog-content a:hover { color:#1d4ed8; }
.blog-content a:visited { color:#7c3aed; }

75-87: Make “scroll to comments” resilient; prefer the href target and only fall back to comment_root

Current code prevents default and targets comment_root unconditionally. Use the link’s hash if present, else fall back.

-    const commentLinks = document.querySelectorAll('[href="#comments"]');
+    const commentLinks = document.querySelectorAll('a[href="#comments"]');
     commentLinks.forEach(link => {
         link.addEventListener('click', function(e) {
-            e.preventDefault();
-            const commentsSection = document.getElementById('comment_root');
-            if (commentsSection) {
-                commentsSection.scrollIntoView({
+            const targetSelector = this.getAttribute('href'); // "#comments"
+            const targetEl = document.querySelector(targetSelector) || document.getElementById('comment_root');
+            if (targetEl) {
+                e.preventDefault();
+                targetEl.scrollIntoView({
                     behavior: 'smooth',
                     block: 'start'
                 });
             }
         });
     });

90-99: Use CSS hover for card scale; drop JS listeners

This effect is declarative in CSS and avoids many listeners.

-    // Blog card hover effects
-    const cards = document.querySelectorAll('.blog-card');
-    cards.forEach(card => {
-        card.addEventListener('mouseenter', function() {
-            this.classList.add('transform', 'scale-105');
-        });
-        
-        card.addEventListener('mouseleave', function() {
-            this.classList.remove('transform', 'scale-105');
-        });
-    });
+    // Tip: Prefer CSS utility classes on the card element: hover:scale-105
+    // (See template change suggestion in post_list.html review.)

Additional template change (outside this file) to apply:

<div class="blog-card ... transform transition duration-300 hover:-translate-y-1 hover:scale-105 hover:shadow-xl">
website/templates/blog/post_list.html (1)

168-169: Load blog.js here (OK); add a semantic author hook to stabilize search

Including the external script is good. To make author filtering robust and decoupled from classes, add a data attribute on the author span; update blog.js to prefer [data-author].

Outside this hunk, adjust the author badge span:

<span class="text-white text-sm" data-author="{{ post.author }}">{{ post.author }}</span>

Then the selector in blog.js (already suggested) continues to work even if classes change.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge Base: Disabled due to Reviews > Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 8dd528a and e99aca2.

📒 Files selected for processing (3)
  • website/static/js/blog.js (1 hunks)
  • website/templates/blog/post_detail.html (2 hunks)
  • website/templates/blog/post_list.html (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run Tests
  • GitHub Check: docker-test
🔇 Additional comments (5)
website/static/js/blog.js (2)

4-4: Good initialization guard with DOMContentLoaded

Encapsulating all bindings under DOMContentLoaded avoids timing issues across templates. LGTM.


39-45: Empty-state copy is clear; good UX touch

Concise and helpful guidance when no matches are found. Nice.

website/templates/blog/post_detail.html (2)

25-25: Adding blog-content hook is the right approach

This enables targeted styling of in-article links without affecting the rest of the page. LGTM.


50-50: blog.js inclusion verified; comment_root present

  • blog.js is only included once in website/templates/blog/post_detail.html, so there’s no risk of double-bound listeners.
  • An element with id="comment_root" is confirmed in website/templates/comments2.html, ensuring the script’s anchor exists.

Optional nit: you may add defer to the script tag to prevent parser blocking, e.g.:

-    <script src="{% static 'js/blog.js' %}"></script>
+    <script defer src="{% static 'js/blog.js' %}"></script>
website/templates/blog/post_list.html (1)

120-120: Link styling matches the “highlight link” objective

Switching “Read more” to blue aligns with the new in-article link color, improving consistency. LGTM.

@DonnieBLT DonnieBLT enabled auto-merge August 27, 2025 01:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: Links in blogs are not getting highlighted
2 participants