Skip to content

feat(ui): revamp corporate supporters carousel (Infinite Marquee + Dark Mode fix)#3837

Merged
kasya merged 6 commits intoOWASP:mainfrom
CYBORG-YASHRAJ:fix/carousel-ui-revamp
Feb 7, 2026
Merged

feat(ui): revamp corporate supporters carousel (Infinite Marquee + Dark Mode fix)#3837
kasya merged 6 commits intoOWASP:mainfrom
CYBORG-YASHRAJ:fix/carousel-ui-revamp

Conversation

@CYBORG-YASHRAJ
Copy link
Contributor

Proposed change
Resolves #3800

This PR completely revamps the Corporate Supporters Carousel to address UI regressions in Dark Mode, normalize logo sizing, and implement a high-performance Infinite Scrolling Marquee as requested by @arkid15r.

🔧 Key Changes
🌙 Dark Mode & UI Visibility (LogoCarousel.tsx)

The Issue: Transparent PNG logos were invisible against the dark background in Dark Mode.

The Fix: Wrapped each logo in a standardized White Card container (bg-white rounded-lg shadow-md).

Optimization: Reduced internal padding from p-5 to px-3 py-1. This maximizes the render area, ensuring wider logos are displayed at a legible size without excessive whitespace.

🔄 Infinite Marquee Animation (tailwind.config.mjs)

Math Fix: Changed translateX(-500%) to translateX(-50%).

Reasoning: We render the logo list exactly twice. Translating by 50% of the total width moves the strip by exactly one full set length, creating a seamless mathematical loop.

UX Improvement: Added group-hover:paused so users can pause the scrolling to click a sponsor link.

Pacing: Adjusted animation duration multiplier (from 2s to 3s per item) for a smoother, less dizzying scroll speed.

📐 Layout & Normalization

Sizing: Switched from absolute positioning (layout="fill") to explicit dimensions (width={168} height={72}) with object-fit: contain. This prevents layout shifts and ensures consistent aspect ratios across all sponsors.

Container: Changed the scroll container from w-full to w-max. This allows the flex container to expand to its natural width (2x the logos), ensuring the animation logic holds true on all screen sizes.

🧪 Tests (LogoCarousel.test.tsx)

Updated all unit tests to match the new DOM structure (checking for .bg-white wrappers instead of relative divs).

Updated duration assertions to match the new 3s multiplier.

Screen.Recording.2026-02-07.232504.mp4

[x] Required: I followed the (https://github.com/OWASP/Nest/blob/main/CONTRIBUTING.md#contributing-workflow)

[x] Required: I verified that my code works as intended and resolves the issue as described

[x] Required: I ran make check-test locally: all warnings addressed, tests passed

[x] I used AI for code, documentation, tests, or communication related to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 7, 2026

Summary by CodeRabbit

  • Tests

    • Updated LogoCarousel component tests to align with recent animation and styling refinements.
  • Improvements

    • Optimized logo carousel animation timing for smoother scrolling performance.
    • Enhanced image fallback handling with visible text display for missing sponsor images.
    • Added pause-on-hover animation control for improved user interactivity.

Walkthrough

Reworks LogoCarousel rendering and animation timing, replaces Next/Image fill usage with explicit width/height and class-based styling, duplicates sponsor tracks with deterministic keys, updates Tailwind marquee keyframes/duration, and adjusts Jest Image mock and unit tests to match the new DOM and timing.

Changes

Cohort / File(s) Summary
Component Implementation
frontend/src/components/LogoCarousel.tsx
Replaced per-sponsor seconds math with a fixed string animationDuration; removed fixed min-width/old container structure; switched Next/Image from fill/style to explicit width/height + className (object-contain); visible fallback text for missing images; duplicated sponsor rendering into two tracks with deterministic logo-carousel-${keyBase}-${keySuffix} keys; added group wrapper and group-hover pause.
Tests & Mocks
frontend/__tests__/unit/components/LogoCarousel.test.tsx
Updated Jest mock for next/image signature from (style?, fill?) to (className?, width?, height?) rendering an img; adjusted animation-duration expectations (e.g., 6s→9s, 12s→18s, 200s→300s); switched DOM assertions from min-width-based containers to wrapper classes (bg-white rounded-lg shadow-md) and class-based image checks (h-full w-full object-contain); expect visible "No Image Sponsor" fallback when images absent.
Styling & Animation Config
frontend/tailwind.config.mjs
Changed marquee keyframes end translateX from -500% to -50% and increased animation timing (example: 0.5s → 30s), reducing travel distance and slowing the scroll animation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • arkid15r
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: revamping the corporate supporters carousel with an infinite marquee and dark mode fix.
Description check ✅ Passed The description provides detailed context for the changes, explains the motivations, and covers the key modifications across all affected files.
Linked Issues check ✅ Passed The PR directly addresses all coding requirements from issue #3800: dark mode visibility fixed via white card containers, logo sizing normalized through explicit dimensions, and spacing made consistent.
Out of Scope Changes check ✅ Passed All changes are scoped to the Corporate Supporters Carousel component, its configuration, and tests; no unrelated modifications present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
frontend/__tests__/unit/components/LogoCarousel.test.tsx (2)

269-275: Test name is misleading — the component no longer uses refs.

The test is titled "uses ref correctly for DOM manipulation" but it only asserts CSS classes on the scroller div. The component no longer manages a ref for DOM duplication; it renders two tracks declaratively. Consider renaming to something like "applies correct classes to scroll container".


349-355: Duplicate test — identical to "renders sponsor names correctly in alt attributes".

This test ("renders image alt text correctly") performs exactly the same assertions as the test on lines 341–347. Consider removing one of them.


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.

cubic-dev-ai[bot]
cubic-dev-ai bot previously approved these changes Feb 7, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

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

🤖 Fix all issues with AI agents
In `@frontend/src/components/LogoCarousel.tsx`:
- Around line 22-36: The sponsor card in LogoCarousel currently renders an empty
span when both sponsor.imageUrl and sponsor.name are falsy; update the render
logic in the LogoCarousel component (the block using Link, Image and the
fallback span) to detect when both are empty and either (a) render a generic
accessible placeholder label like "Sponsor" inside the span (e.g., fallback text
and an aria-label) or (b) skip rendering the card entirely for that sponsor;
ensure the chosen approach sets visible text or an aria-label so the card is not
blank and remains accessible.
🧹 Nitpick comments (2)
frontend/__tests__/unit/components/LogoCarousel.test.tsx (2)

126-132: Test name is misleading: "renders empty div" → actually renders a fallback text span.

The test body correctly asserts 0 images and 4 links, but the it(...) description says "renders empty div when imageUrl is not provided." The component actually renders <span className="text-sm text-gray-400">{sponsor.name}</span>. Consider updating the description to match:

-    it('renders empty div when imageUrl is not provided', () => {
+    it('renders fallback text when imageUrl is not provided', () => {

341-356: Duplicate tests: "renders sponsor names correctly in alt attributes" and "renders image alt text correctly" are identical.

Both tests render the same data and assert the exact same alt text values on the same elements. Consider removing one.

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 7, 2026
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 7, 2026

@codecov
Copy link

codecov bot commented Feb 7, 2026

Codecov Report

❌ Patch coverage is 75.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90.24%. Comparing base (2015442) to head (8f4320a).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
frontend/src/components/LogoCarousel.tsx 75.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #3837   +/-   ##
=======================================
  Coverage   90.24%   90.24%           
=======================================
  Files         463      463           
  Lines       14416    14416           
  Branches     1937     1937           
=======================================
  Hits        13009    13009           
  Misses        988      988           
  Partials      419      419           
Flag Coverage Δ
backend 90.97% <ø> (ø)
frontend 88.17% <75.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
frontend/src/components/LogoCarousel.tsx 85.71% <75.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2015442...8f4320a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

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

@CYBORG-YASHRAJ Thanks for working on this!

The change looks good 👍🏼 I was thinking bout making the dark theme background less contrasting, but some of the sponsor images have white background. So let's keep it this way 👌🏼

One note though, make sure you run make check-test before requesting a review, not just check that off in the PR template. The checks were failing in multiple places.

Image

I fixed those issues and pushed changes.

@CYBORG-YASHRAJ
Copy link
Contributor Author

@kasya Thanks for the review!
Yeah, I agree—keeping the dark theme as it is makes sense, especially with some sponsor images having white backgrounds.

My bad on the checks earlier—you’re right, I should’ve run make check-test locally before requesting the review instead of just ticking it off in the PR. I’ve fixed the issues and pushed the updated changes.

Thanks for pointing it out and for taking the time to review this 🙏

@kasya kasya added this pull request to the merge queue Feb 7, 2026
Merged via the queue into OWASP:main with commit 152206e Feb 7, 2026
55 of 58 checks passed
arkid15r added a commit that referenced this pull request Feb 10, 2026
* Run make update

* Clean up snapshot generated videos

* Update backend/data/nest.dump

* feat(ui): revamp corporate supporters carousel (Infinite Marquee + Dark Mode fix) (#3837)

* feat(ui): revamp corporate supporters carousel (Infinite Marquee + Dark Mode fix)

* fix: resolve failing test case

* fix: add fallback text for unnamed sponsors

* docs: add docstrings to satisfy coverage requirements

* Run make check and fix tests.

---------

Co-authored-by: Kate <kate@kgthreads.com>

* Fix/redundant typescript assertion (#3834)

* Fix Sonar S4325 by narrowing session user fields instead of casting

* Fix unused ExtendedSession in mentorship page

* fix: redundant-typescript-assertion

* Fix stale latest date displayed in Project Health Dashboard metrics (#3842)

* Fixed latest date in proejct health dashboard

* updated order

* Update code

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>

* feat: improve backend test coverage to 96% (#3840)

* feat: improve backend test coverage to 96%

* fix comments

* fix issues

* fix issue

* fix cubic-dev-ai comments

* Update code

* Fix tests

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>

* Fix: merge consecutive RUN instructions in frontend Dockerfile (#3644)

* Fix: merge consecutive RUN instructions in frontend Dockerfile

* fix: comment Dockerfile note to prevent syntax error

* Update code

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>

* Fix 'is_merged' not being available on the Issue (#3843)

* Fix 'is_merged' not being available on the Issue

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>

* CI:  Add ansible-lint workflow for Ansible playbooks (#3796)

* ci: add ansible-lint workflow

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

* Update .github/workflows/lint-ansible.yaml

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* ci: add ansible-lint make target and workflow

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

* ci: add ansible-lint pre-commit hook

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

* fix: whitespace & version

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

* Update Makefile

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* ci: enable ansible-lint scanning and add requirements.yml

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

* chore(ansible):align linting and module usage

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

* ci(ansible): install collections before deploy playbooks

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

* Update code

* Update code

* Update .github/workflows/run-ci-cd.yaml

---------

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>

* Fix ElevenLabs API error (#3861)

* use default liam voice

* bump speed by 0.10

---------

Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>

* Add Ime Iyonsi to MENTORS.md (#3866)

* Add mentor profile for Ime Iyonsi

Added Ime Iyonsi's mentor profile.

* Fix GitHub link for Ime Iyonsi

Corrected GitHub link for Ime Iyonsi.

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>

* Update MENTORS.md

* Enabled Strict Mode (#3776)

* Enabled Strict Mode

* fixed ai review

* fix

* fixed review

* fix

* update test

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>

* Resolve case-sensitivity in QueryParser to support Chapters/Members search (#3844)

* resolve query parser blocker

* use case_sensitive flag in QueryParser

* feat: add case_sensitive option to QueryParser and update tests

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>

* Update dependencies (#3874)

* Update dependencies

* Bump django-ninja version

* fix(proxy): pin nginx and certbot images (#3848)

* fix(proxy): pin nginx and certbot images

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

* fix stable verssions

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>

---------

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>

* Update docker-compose/proxy/compose.yaml

* Update backend/pyproject.toml

* Update ansible lint configuration (#3880)

* Update .github/ansible/.ansible-lint.yaml

* Improve frontend test coverage above 80% and add missing test files (#3864)

* Imrove test coverage to 80% and added test

* Fixed coderabbit review

* update code

* fixed coderabbit ai

* fixed soanrqube warning

* fixed review

* update

* fixed aloglia cache_key (#3825)

* fixed aloglia cache_key

* change separator val to be semicolon (;)

* Update code

* add tests + use json filters

* add trailing newline

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>

* fix: remove unused className prop from AnchorTitle component (#3822)

* fix: remove unused className prop from AnchorTitle component

Fixes #3805

The className prop was defined in AnchorTitleProps but never used
in the component implementation. Removing it resolves Sonar rule
typescript:S6767 and improves code maintainability.

* fix: use className prop instead of removing it

- Added className back to AnchorTitleProps interface
- Accept className parameter in component
- Apply className to root div element
- Resolves reviewer feedback on PR #3822

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>

---------

Signed-off-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>
Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Co-authored-by: Yashraj Pahuja <yashrajpahuja9999@gmail.com>
Co-authored-by: Kate <kate@kgthreads.com>
Co-authored-by: CodeAritraDhank <aritradhank21@gmail.com>
Co-authored-by: Anurag Yadav <143180737+anurag2787@users.noreply.github.com>
Co-authored-by: Harshit Verma <harshit1092004@gmail.com>
Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>
Co-authored-by: Shuban Mutagi <shubanmutagi55@gmail.com>
Co-authored-by: Muhammad Hassaan Saleem <iamhassaans@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: emaybu <152900874+emaybu@users.noreply.github.com>
Co-authored-by: sai chethana <saichethanavesireddy@gmail.com>
Co-authored-by: Rahul Paul <179798584+Mr-Rahul-Paul@users.noreply.github.com>
Co-authored-by: Lavanya <lavanyayadawad30@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UI/UX: Corporate Supporter Carousel - Dark Mode Visibility, Spacing, and Sizing Issues

2 participants