Skip to content

Conversation

@Yeom-JinHo
Copy link
Contributor

@Yeom-JinHo Yeom-JinHo commented Oct 23, 2025

Description

This PR fixes the Marquee animation that stopped working after migrating to Tailwind CSS v4.
The issue was caused by invalid arbitrary value syntax (gap-(--gap)) and missing animation keyframes that were no longer compatible with the new Tailwind v4 structure.
This update restores all marquee functionality — including forward, reverse, horizontal, and vertical animations — while maintaining hover-pause behavior and spacing consistency.

Changes

  • Animation Restoration (major fix):
    Reintroduced missing keyframes for both forward and reverse marquee directions (marquee, marquee-reverse, marquee-vertical, marquee-vertical-reverse).
  • Tailwind v4 Compatibility:
    Replaced invalid gap-(--gap) with valid gap-[var(--gap)] syntax to align with Tailwind v4’s arbitrary value parsing.
  • Reverse Animation Utilities:
    Added new animation variables --animate-marquee-reverse and --animate-marquee-vertical-reverse for bidirectional control.
  • Component Logic Update:
    Updated Marquee component conditions to correctly apply reverse and vertical animations based on props.
  • Hover-Pause Behavior:
    Retained group-hover:[animation-play-state:paused] behavior for consistent user experience across versions.

Motivation

After upgrading to Tailwind CSS v4, the marquee component lost its animation due to breaking changes in arbitrary value handling and missing keyframe utilities.
This fix fully restores the expected behavior — smooth, continuous marquee animation in both directions — ensuring visual consistency and motion integrity across all layouts.

Summary by CodeRabbit

  • New Features

    • Extended marquee animations with reverse direction support for both horizontal and vertical scrolling layouts.
  • Documentation

    • Updated component documentation with examples demonstrating new reverse animation capabilities.

@coderabbitai
Copy link

coderabbitai bot commented Oct 23, 2025

Walkthrough

This PR introduces reverse marquee animations by adding CSS keyframes and custom properties to support horizontal and vertical reverse transitions. The marquee component is refactored to conditionally apply animation classes based on vertical and reverse flags, replacing the [animation-direction:reverse] style. CSS variable syntax is standardized across files.

Changes

Cohort / File(s) Summary
CSS Animations & Properties
apps/ui-layout/app/globals.css
Added two new CSS custom properties (--animate-marquee-reverse, --animate-marquee-vertical-reverse) and two corresponding keyframe definitions (@keyframes marquee-reverse, @keyframes marquee-vertical-reverse) to enable reverse-direction marquee transitions.
Component Logic
apps/ui-layout/components/ui/marquee.tsx
Refactored marquee component to conditionally apply animation classes based on vertical and reverse props, introducing four animation variants. Standardized gap syntax from gap-(--gap) to gap-[var(--gap)]. Removed inline [animation-direction:reverse] style in favor of dedicated animation classes.
Documentation & Examples
apps/ui-layout/content/components/marquee.mdx
Updated marquee documentation examples to use new conditional animation classes and standardized gap syntax. Examples now demonstrate all combinations of vertical and reverse animations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Rationale: Changes span three related files with a consistent pattern (adding reverse animation variants), but require understanding the interaction between CSS keyframes, custom properties, and component conditional logic. The refactoring replaces animation-direction with explicit classes, which adds semantic clarity but demands careful verification across all use cases.

Poem

🐰 In reverse we leap and bound,
Marquees spin both up and round,
Horizontal swirls, vertical flight,
CSS properties shining bright—
Whoooosh! 💫 Animation done right!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 "fix: restore marquee animation after Tailwind v4 migration" is fully related to and clearly summarizes the main change in the pull request. The PR restores broken Marquee animation behavior following a Tailwind CSS v4 migration by reintroducing missing keyframes, fixing CSS variable syntax (gap-(--gap)gap-[var(--gap)]), and adding bidirectional animation support. The title is concise, specific, and uses standard git conventions, making it immediately clear to developers scanning history what the change addresses and why.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/ui-layout/content/components/marquee.mdx (1)

163-173: Fix typographical errors in section headings.

Several headings contain spelling mistakes:

  • Line 163: "Exammple" → "Example"
  • Line 165: "Varticle Maruqee" → "Vertical Marquee"
  • Line 169: "Logos Maruqee" → "Logos Marquee"
  • Line 173: "3D Maruqee" → "3D Marquee"

Apply this diff to correct the typos:

-## Exammple
+## Example

-### Varticle Maruqee
+### Vertical Marquee

-### Logos Maruqee
+### Logos Marquee

-### 3D Maruqee
+### 3D Marquee
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6d4fd5 and 15c8547.

📒 Files selected for processing (3)
  • apps/ui-layout/app/globals.css (2 hunks)
  • apps/ui-layout/components/ui/marquee.tsx (2 hunks)
  • apps/ui-layout/content/components/marquee.mdx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/ui-layout/components/ui/marquee.tsx (1)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
🪛 Biome (2.1.2)
apps/ui-layout/app/globals.css

[error] 110-110: expected , but instead found --animate-marquee-reverse

Remove --animate-marquee-reverse

(parse)


[error] 110-110: expected , but instead found (

Remove (

(parse)


[error] 110-110: expected , but instead found --duration

Remove --duration

(parse)


[error] 110-110: expected , but instead found )

Remove )

(parse)


[error] 110-110: expected , but instead found linear

Remove linear

(parse)


[error] 110-110: expected , but instead found ;

Remove ;

(parse)


[error] 111-111: expected , but instead found --animate-marquee-vertical-reverse

Remove --animate-marquee-vertical-reverse

(parse)


[error] 111-111: expected , but instead found (

Remove (

(parse)


[error] 111-111: expected , but instead found --duration

Remove --duration

(parse)


[error] 111-111: expected , but instead found )

Remove )

(parse)


[error] 111-111: expected , but instead found linear

Remove linear

(parse)


[error] 111-111: expected , but instead found ;

Remove ;

(parse)


[error] 110-110: Unexpected unknown pseudo-class marquee-reverse

See MDN web docs for more details.

(lint/correctness/noUnknownPseudoClass)


[error] 110-110: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)


[error] 110-110: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)


[error] 111-111: Unexpected unknown pseudo-class marquee-vertical-reverse

See MDN web docs for more details.

(lint/correctness/noUnknownPseudoClass)


[error] 111-111: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)


[error] 111-111: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)

🔇 Additional comments (5)
apps/ui-layout/app/globals.css (2)

110-111: LGTM! Reverse animation variables follow the established pattern.

The new animation custom properties for reverse marquee directions are correctly defined and consistent with the existing --animate-marquee and --animate-marquee-vertical properties on lines 108-109.

Note: The static analysis errors from Biome are false positives. Biome doesn't recognize Tailwind v4's @theme directive syntax. These custom property definitions are valid CSS within the @theme block.


142-157: LGTM! Reverse keyframes correctly invert the animation direction.

The new marquee-reverse and marquee-vertical-reverse keyframes properly implement reverse scrolling by animating from the end position (negative offset) back to the origin. This approach is cleaner than using animation-direction: reverse and provides explicit control over the reverse behavior.

apps/ui-layout/components/ui/marquee.tsx (1)

39-44: LGTM! Animation class logic correctly handles all combinations.

The conditional animation classes properly cover all four marquee states (horizontal/vertical × forward/reverse) and align with the new keyframes defined in globals.css. This approach is cleaner than using animation-direction: reverse and provides explicit control over each animation variant.

apps/ui-layout/content/components/marquee.mdx (2)

134-134: Verify gap syntax aligns with Tailwind v4 conventions.

Same as in marquee.tsx, the documentation uses gap-[var(--gap)] instead of the Tailwind v4 idiomatic syntax gap-(--gap). Ensure this documentation example matches the final implementation in the component.

Also applies to: 147-147


148-151: LGTM! Documentation example correctly demonstrates the new animation approach.

The code example accurately shows the four animation class variants and aligns with the component implementation in marquee.tsx.

{...props}
className={cn(
'group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] gap-(--gap)',
'group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] gap-[var(--gap)]',
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify gap syntax aligns with Tailwind v4 conventions.

According to the Tailwind v4 documentation, CSS variable references should use parentheses without the var() function: gap-(--gap) rather than gap-[var(--gap)]. While gap-[var(--gap)] may work as an arbitrary value, the idiomatic v4 syntax is gap-(--gap) where Tailwind automatically wraps the variable in var().


🌐 Web query:

Does Tailwind CSS v4 support gap-[var(--gap)] syntax or should it be gap-(--gap)?

💡 Result:

Short answer: Use gap-(--gap). Tailwind v4 provides the shorthand gap-(--my-var) which expands to gap-[var(--my-var)] (the long arbitrary-value form also works, but the documented shorthand is gap-(--gap)). [1][2]

Sources:

  • Tailwind v4 docs (gap: shorthand for CSS custom properties). [1]
  • Community/local docs showing gap-(--my-gap) is shorthand for gap-[var(--my-gap)]. [2]

Update gap syntax to follow Tailwind v4 conventions.

Tailwind v4 provides the shorthand gap-(--gap) which expands to gap-[var(--gap)]. While the current gap-[var(--gap)] syntax works, the documented shorthand is gap-(--gap).

Change line 26:

  • From: gap-[var(--gap)]
  • To: gap-(--gap)
🤖 Prompt for AI Agents
In apps/ui-layout/components/ui/marquee.tsx around line 26, update the Tailwind
gap token syntax to follow Tailwind v4 shorthand: replace the class segment
gap-[var(--gap)] with gap-(--gap) so the class list becomes 'group flex
overflow-hidden p-2 [--duration:40s] [--gap:1rem] gap-(--gap)'; ensure no other
characters change and run the Tailwind build to verify the new utility is
recognized.

@naymurdev naymurdev merged commit 2f89595 into ui-layouts:main Oct 23, 2025
1 check passed
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.

2 participants