Skip to content

Conversation

@SHASHI9705
Copy link

@SHASHI9705 SHASHI9705 commented Nov 4, 2025

Description

Added a dismissible "×" close button to the conference banner to improve user control.

Implementation

  • Used React useState for banner visibility.
  • Used localStorage to persist user’s choice.
  • The banner remains hidden after user closes it and reappears only after clearing localStorage.

Screenshot

Before vs After
Screenshot 2025-11-05 004421
Screenshot 2025-11-05 004410

Summary by CodeRabbit

  • New Features

    • Announcement banners now include a close button, allowing users to dismiss them easily.
    • Dismissed banners are remembered across browser sessions, preventing redundant notifications from reappearing.
  • Chores

    • Updated build configuration.

@netlify
Copy link

netlify bot commented Nov 4, 2025

Deploy Preview for asyncapi-website ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit d9f8cca
🔍 Latest deploy log https://app.netlify.com/projects/asyncapi-website/deploys/690cdce715acd1000766d32b
😎 Deploy Preview https://deploy-preview-4537--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Welcome to AsyncAPI. Thanks a lot for creating your first pull request. Please check out our contributors guide useful for opening a pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out this issue.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

The PR adds client-side banner dismissal functionality to the AnnouncementHero component with localStorage persistence. Banners can be individually closed via a close button and filtered from view. The component maintains carousel behavior while rendering only the active banner.

Changes

Cohort / File(s) Summary
Banner Dismissal & Persistence
components/campaigns/AnnouncementHero.tsx
Adds isBannerVisible state and dismissedBanners localStorage persistence. On mount, loads bannerClosed to control visibility. Computes visibleBanners via useMemo by filtering banners through shouldShowBanner and excluding dismissed items. Implements handleClose to mark active banner as dismissed, then recalculates remaining banners and updates activeIndex accordingly. Adds per-banner close button inside active banner card. Updates conditional rendering to depend on both isBannerVisible and numberOfVisibleBanners.
Build Configuration
.gitignore
Adds next-env.d.ts to ignore auto-generated Next.js TypeScript declarations.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Component
    participant LocalStorage
    participant UI

    User->>Component: Mount component
    Component->>LocalStorage: Load bannerClosed & dismissedBanners
    LocalStorage-->>Component: Return stored values
    Component->>Component: Compute visibleBanners (filter by shouldShowBanner & dismissedBanners)
    Component->>UI: Render active banner with close button

    User->>UI: Click close button
    UI->>Component: Trigger handleClose()
    Component->>LocalStorage: Persist current banner as dismissed
    LocalStorage-->>Component: Confirm save
    Component->>Component: Recompute visibleBanners (exclude dismissed)
    alt Banners remain
        Component->>Component: Update activeIndex to valid banner
        Component->>UI: Re-render with new active banner
    else No banners remain
        Component->>Component: Set isBannerVisible = false
        Component->>UI: Hide entire banner component
    end
    UI-->>User: Display updated state
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • components/campaigns/AnnouncementHero.tsx: Multiple interacting state and side-effect patterns (localStorage loading, memoized filtering, event handling, conditional rendering logic) require careful verification of persistence behavior, index recalculation when banners are dismissed, and edge cases when all banners are dismissed.
  • Verify useMemo dependency array completeness and whether dismissedBanners updates trigger appropriate re-computations.
  • Confirm localStorage key consistency and error handling for malformed stored data.

Possibly related issues

Possibly related PRs

Suggested reviewers

  • derberg
  • akshatnema
  • anshgoyalevil
  • sambhavgupta0705
  • vishvamsinh28
  • Mayaleeeee
  • devilkiller-ag

Poem

🐰 A banner dismissed with a click so small,
Stored in localStorage, remembered by all,
The carousel hops to the next with cheer,
While dismissed announcements fade from here. ✨
Close buttons bring joy, state persists so true—
This feature's as bouncy as fresh morning dew! 🌿

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a dismissible close button to the conference banner component with localStorage persistence.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8711488 and a9098b3.

📒 Files selected for processing (2)
  • .gitignore (1 hunks)
  • components/campaigns/AnnouncementHero.tsx (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-10-11T10:46:58.882Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3262
File: components/Avatar.tsx:35-44
Timestamp: 2024-10-11T10:46:58.882Z
Learning: In Next.js, when avoiding nested `<a>` tags due to hydration issues, use accessible non-link elements like `<button>` or `<span>` with appropriate roles, `tabIndex`, and event handlers to maintain accessibility and SEO.

Applied to files:

  • components/campaigns/AnnouncementHero.tsx
🧬 Code graph analysis (1)
components/campaigns/AnnouncementHero.tsx (2)
components/campaigns/banners.ts (2)
  • banners (18-46)
  • shouldShowBanner (6-16)
components/campaigns/AnnouncementBanner.tsx (1)
  • Banner (37-69)
🪛 GitHub Actions: PR testing - if Node project
components/campaigns/AnnouncementHero.tsx

[error] 27-27: Unexpected negated condition. (no-negated-condition)


[error] 61-61: Expected blank line after variable declarations. (newline-after-var)


[error] 62-62: Expected blank line before this statement. (padding-line-between-statements)


[error] 65-65: Replace ⏎ (b) => !dismissedBanners.includes(b.eventName) ⏎ with (b) => !dismissedBanners.includes(b.eventName) (prettier/prettier)


[error] 77-77: Expected blank line after variable declarations. (newline-after-var)


[error] 77-77: Replace () => setActiveIndex((index) => (index + 1) % numberOfVisibleBanners), 10000 with () => setActiveIndex((index) => (index + 1) % numberOfVisibleBanners), 10000 (prettier/prettier)


[error] 81-81: Expected blank line before this statement. (padding-line-between-statements)


[error] 89-89: Replace "section" padding="" className="text-center" with 'section' padding='' className='text-center' (prettier/prettier)


[error] 89-89: Unexpected usage of doublequote. (jsx-quotes)


[error] 89-89: Unexpected usage of doublequote. (jsx-quotes)


[error] 89-89: Unexpected usage of doublequote. (jsx-quotes)


[error] 90-90: Replace "relative flex flex-row items-center justify-center overflow-x-hidden md:gap-4" with 'relative flex flex-row items-center justify-center overflow-x-hidden md:gap-4' (prettier/prettier)


[error] 90-90: Unexpected usage of doublequote. (jsx-quotes)


[error] 97-97: Replace "text-white" with 'text-white' (prettier/prettier)


[error] 97-97: Unexpected usage of doublequote. (jsx-quotes)


[error] 101-101: Replace "relative flex w-4/5 md:w-5/6 flex-col items-center justify-center gap-2" with 'relative flex w-4/5 md:w-5/6 flex-col items-center justify-center gap-2' (prettier/prettier)


[error] 101-101: Unexpected usage of doublequote. (jsx-quotes)


[error] 102-102: Replace "relative min-h-72 w-full justify-center overflow-hidden lg:h-[17rem] lg:w-[38rem]" with 'relative min-h-72 w-full justify-center overflow-hidden lg:h-[17rem] lg:w-[38rem]' (prettier/prettier)


[error] 102-102: Unexpected usage of doublequote. (jsx-quotes)


[error] 107-107: Replace "relative w-full flex justify-center" with 'relative w-full flex justify-center' (prettier/prettier)


[error] 107-107: Unexpected usage of doublequote. (jsx-quotes)


[error] 111-111: Replace "Close announcement banner" with 'Close announcement banner' (prettier/prettier)


[error] 111-111: Unexpected usage of doublequote. (jsx-quotes)


[error] 112-112: This line has a length of 199. Maximum allowed is 120. (max-len)


[error] 112-112: Replace "absolute top-[1.7rem] right-4 z-20 flex h-6 w-6 items-center justify-center rounded border border-gray-400 bg-white text-gray-600 hover:bg-gray-100 hover:text-gray-800" with 'absolute top-[1.7rem] right-4 z-20 flex h-6 w-6 items-center justify-center rounded border border-gray-400 bg-white text-gray-600 hover:bg-gray-100 hover:text-gray-800' (prettier/prettier)


[error] 112-112: Unexpected usage of doublequote. (jsx-quotes)


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

Comment @coderabbitai help to get the list of available commands and usage tips.

@asyncapi-bot
Copy link
Contributor

asyncapi-bot commented Nov 4, 2025

⚡️ Lighthouse report for the changes in this PR:

Category Score
🔴 Performance 42
🟢 Accessibility 98
🟢 Best practices 92
🟢 SEO 100
🔴 PWA 33

Lighthouse ran on https://deploy-preview-4537--asyncapi-website.netlify.app/

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: 5

🧹 Nitpick comments (1)
components/campaigns/AnnouncementHero.tsx (1)

81-87: Close button implementation looks good with minor suggestions.

The close button has proper accessibility (aria-label) and styling. Consider these optional enhancements:

  1. Add keyboard support for Escape key to close banner
  2. Consider using an icon component instead of the × character for consistency
  3. Add focus styles for better keyboard navigation visibility

Example keyboard support:

useEffect(() => {
  const handleEscape = (e: KeyboardEvent) => {
    if (e.key === 'Escape' && isBannerVisible) {
      handleClose();
    }
  };
  
  document.addEventListener('keydown', handleEscape);
  return () => document.removeEventListener('keydown', handleEscape);
}, [isBannerVisible]);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4bdd8b and 8711488.

📒 Files selected for processing (2)
  • components/campaigns/AnnouncementHero.tsx (4 hunks)
  • next-env.d.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is enforced by the project's configuration which uses `moduleResolution: "bundler"` in tsconfig.json and TypeScript-aware ESLint plugins. The .ts extensions are required even though the files are imported using CommonJS require statements.

Applied to files:

  • next-env.d.ts
📚 Learning: 2025-04-20T16:05:16.482Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3950
File: scripts/utils/check-locales.ts:122-129
Timestamp: 2025-04-20T16:05:16.482Z
Learning: In the AsyncAPI website project, Next.js throws errors at runtime when locale files are missing, making additional validation for missing files unnecessary in the check-locales script.

Applied to files:

  • next-env.d.ts
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is a project-specific requirement enforced by the linting rules and build setup, even though it differs from typical Node.js behavior.

Applied to files:

  • next-env.d.ts
🧬 Code graph analysis (1)
components/campaigns/AnnouncementHero.tsx (1)
components/campaigns/AnnouncementBanner.tsx (1)
  • Banner (37-69)
🪛 GitHub Actions: PR testing - if Node project
components/campaigns/AnnouncementHero.tsx

[error] 27-27: eslint: Expected blank line after variable declarations. newline-after-var


[error] 28-28: eslint: Expected blank line before this statement. padding-line-between-statements


[warning] 31-31: React Hook useMemo has an unnecessary dependency: 'banners'.


[error] 52-52: eslint: Expected blank line after variable declarations. newline-after-var


[warning] 53-53: eslint: Expected blank line before this statement. padding-line-between-statements

⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Lighthouse CI
🔇 Additional comments (1)
components/campaigns/AnnouncementHero.tsx (1)

51-54: Fix required: Missing blank lines causing lint failures.

Pipeline is failing due to missing blank lines around the interval cleanup.

Apply this diff:

   useEffect(() => {
     const interval = setInterval(() => setActiveIndex((index) => (index + 1) % numberOfVisibleBanners), 10000);
+
     return () => clearInterval(interval);
   }, [numberOfVisibleBanners]);

Likely an incorrect or invalid review comment.

Comment on lines 46 to 49
const handleClose = () => {
setIsBannerVisible(false);
localStorage.setItem('bannerClosed', 'true');
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Consider banner-specific dismissal instead of global dismissal.

The current implementation dismisses ALL banners permanently when the close button is clicked, even if the user only intended to dismiss the currently visible banner. Once closed, the banner(s) remain hidden indefinitely until localStorage is manually cleared, which prevents users from seeing new conference announcements.

Consider implementing one of these approaches:

  1. Store dismissal state per banner (e.g., using banner ID/title as key)
  2. Add a time-based reset (e.g., show again after 7 days)
  3. Store the specific conference that was dismissed

Example implementation for banner-specific dismissal:

const handleClose = () => {
  const currentBanner = visibleBanners[activeIndex];
  const dismissedBanners = JSON.parse(localStorage.getItem('dismissedBanners') || '[]');
  dismissedBanners.push(currentBanner.eventName);
  localStorage.setItem('dismissedBanners', JSON.stringify(dismissedBanners));
  
  // Filter out dismissed banners
  const remainingBanners = visibleBanners.filter(
    b => !dismissedBanners.includes(b.eventName)
  );
  
  if (remainingBanners.length === 0) {
    setIsBannerVisible(false);
  } else {
    // Move to next banner or wrap around
    setActiveIndex(prev => prev % remainingBanners.length);
  }
};

Then update the initial load effect to filter dismissed banners from visibleBanners.

🤖 Prompt for AI Agents
In components/campaigns/AnnouncementHero.tsx around lines 46-49, the close
handler currently sets a global 'bannerClosed' flag which hides all banners
permanently; change it to store dismissal per banner (e.g., by eventName or id)
in localStorage (use a JSON array like 'dismissedBanners'), update handleClose
to add the current banner's identifier to that array and then filter
visibleBanners to remove dismissed ones (and adjust activeIndex safely or hide
the banner container if none remain), and modify the component's initial
load/effect to read and filter visibleBanners by that dismissed list (optionally
include a timestamp per entry if you prefer time-based reset).

Comment on lines 1 to 6
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference path="./.next/types/routes.d.ts" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify if this auto-generated file should be version controlled.

This file is auto-generated by Next.js and typically should not be manually edited or committed to version control (usually listed in .gitignore). However, some projects do commit it for consistency.

Run this script to check if next-env.d.ts is already in .gitignore:


🏁 Script executed:

#!/bin/bash
# Check if next-env.d.ts should be in .gitignore
grep -n "next-env.d.ts" .gitignore || echo "next-env.d.ts not found in .gitignore"

Length of output: 37


🏁 Script executed:

#!/bin/bash
# Check if next-env.d.ts exists and is tracked
echo "=== Checking if next-env.d.ts exists ==="
ls -la next-env.d.ts 2>/dev/null || echo "File does not exist"

echo ""
echo "=== Checking git status of next-env.d.ts ==="
git ls-files --cached next-env.d.ts 2>/dev/null && echo "File is tracked in git" || echo "File is not tracked"

echo ""
echo "=== Checking .gitignore content for auto-generated patterns ==="
cat .gitignore | head -50

Length of output: 234


🏁 Script executed:

#!/bin/bash
# Check git diff for changes to next-env.d.ts
echo "=== Git diff for next-env.d.ts ==="
git diff HEAD -- next-env.d.ts 2>/dev/null | head -50 || echo "No diff found"

echo ""
echo "=== Check if file is added (untracked) ==="
git status --short 2>/dev/null | grep -i "next-env" || echo "No untracked next-env files"

echo ""
echo "=== Check if this is a Next.js project ==="
test -f package.json && echo "package.json exists" || echo "No package.json"
test -f next.config.js && echo "next.config.js exists" || echo "No next.config.js"
test -f tsconfig.json && echo "tsconfig.json exists" || echo "No tsconfig.json"

echo ""
echo "=== List TypeScript declaration files ==="
find . -maxdepth 2 -name "*.d.ts" 2>/dev/null | head -10

Length of output: 268


Add next-env.d.ts to .gitignore.

This auto-generated file should not be committed to version control. Add next-env.d.ts to .gitignore so it's regenerated locally during builds instead of being versioned.

🤖 Prompt for AI Agents
In next-env.d.ts around lines 1 to 6, the auto-generated Next.js type file is
currently tracked in git; update the repository's .gitignore to include
"next-env.d.ts" so this file is not committed. Edit the .gitignore at the repo
root and add a line with next-env.d.ts, then remove the tracked file from the
index with git rm --cached next-env.d.ts (or equivalent) so it will be
regenerated locally during builds.

@Sourya07
Copy link
Contributor

Sourya07 commented Nov 4, 2025

Hi @SHASHI9705,
Please fix the CodeRabbitAI issues flagged in your PR when you get a chance. It’ll make the review process smoother. 👍

@SHASHI9705
Copy link
Author

Hi @SHASHI9705, Please fix the CodeRabbitAI issues flagged in your PR when you get a chance. It’ll make the review process smoother. 👍

Ok sir, i'll do it asap.

@SHASHI9705
Copy link
Author

Hi @SHASHI9705, Please fix the CodeRabbitAI issues flagged in your PR when you get a chance. It’ll make the review process smoother. 👍

Done sir.

@SHASHI9705 SHASHI9705 closed this Nov 4, 2025
@SHASHI9705 SHASHI9705 reopened this Nov 4, 2025
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.

3 participants