Skip to content

fix: playlist loaders, audio player a11y#155

Merged
WINOFFRG merged 8 commits into
mainfrom
fix/1506
Jun 14, 2026
Merged

fix: playlist loaders, audio player a11y#155
WINOFFRG merged 8 commits into
mainfrom
fix/1506

Conversation

@WINOFFRG

@WINOFFRG WINOFFRG commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Review in cubic

Summary by CodeRabbit

Release Notes

  • New Features

    • Added an animated orb visualization to the audio player hover that responds to playback state.
    • Enabled Apple Music charts pagination so additional items load as you progress through the charts playlist.
  • Improvements

    • Redesigned the audio playlist dropdown with “Now playing” and “Next From,” updated artwork/controls, and refined dropdown positioning to reduce collisions.
    • Enhanced layout flexibility with Root Container support for asChild and configurable aspect ratios.
    • Updated toggle and toggle-group components for improved UI consistency.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@rohangupta-zomato, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 46 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c12b1cec-ba5d-4079-a84b-d99aecf7d91c

📥 Commits

Reviewing files that changed from the base of the PR and between f7ec6f6 and 8295ce4.

📒 Files selected for processing (4)
  • apps/www/components/mdx-components.tsx
  • apps/www/components/ui/toggle.tsx
  • apps/www/registry/default/blocks/audio-player/components/action-controls.tsx
  • apps/www/registry/default/blocks/audio-player/components/playlist.tsx
📝 Walkthrough

Walkthrough

This PR adds a new Three.js-based Orb component integrated into the audio hover player with playback-driven state, introduces paginated Apple Music chart fetching wired into stream-panel sync, redesigns the audio playlist UI with "Now playing"/"Next From" sections, refactors AudioPlayer to forwardRef using RootContainer, extends DropdownMenuContent with collision props and RootContainerProps with aspectRatio, migrates toggle primitives from Radix to Base UI, updates registry dependencies, refactors playback control animations, and tweaks preview-pane toggle logic.

Changes

Audio Player Enhancements

Layer / File(s) Summary
Orb component: types, Canvas, Scene, shaders
apps/www/components/ui/orb.tsx
Adds the complete Orb component: "use client" directive, WebGL library imports, exported AgentState type and OrbProps with color/volume configuration, a Canvas-wrapping Orb function, helper functions for clamping and smoothing, an internal Scene managing GLSL shader uniforms with frame-based animation, dark-mode inversion via MutationObserver, WebGL context-loss recovery, a splitmix32 deterministic PRNG, vertex shader, and fragment shader producing perlin-noise-driven visuals.
Audio hover player Orb integration
apps/www/components/players/audio-player/hover-player.tsx
Adds AudioHoverOrbSync helper that synchronizes usePlaybackStore statuses to AgentState via useEffect, introduces orbAgentState local state and handleAgentStateChange callback in AudioPlayerHoverContent, replaces static voice icon with the configured Orb component, and mounts AudioHoverOrbSync.
Apple Music pagination: types, fetch, stream-panel sync
apps/www/components/stream-panel/content-catalog.ts, apps/www/components/stream-panel/use-stream-panel-sync.ts
Introduces AppleMusicChartPage interface and fetchAppleMusicChartAssetsPage(page, signal?) for paginated charts, refactors internal fetchAppleMusicChartPage with page-aware errors and validation, updates fetchPlaylistPresetAssets to use the new API. Adds appleMusicPaginationRef for state tracking, implements appendNextAppleMusicChartPage callback with deduplication and abort handling wired into assetchange, branches loadPlaylistPreset to fetch page 1 for Apple Music charts and trigger immediate pagination, and updates callback dependencies.
AudioPlayer forwardRef and RootContainer integration
apps/www/registry/default/blocks/audio-player/components/media-player.tsx
Refactors AudioPlayer from plain function to React.forwardRef component forwarding ref to RootContainer (replacing previous div), preserves internal provider composition and children rendering, and sets AudioPlayer.displayName.
RootContainer: aspectRatio prop, composition, and event handlers
apps/www/registry/default/ui/root-container.tsx
Adds aspectRatio?: false | number | string prop to RootContainerProps with resolveAspectRatio memoization handling falseundefined, number stringification, and :/ normalization. Conditionally applies aspect-(--aspect-ratio) CSS class, selects between Slot and div based on asChild, refactors event handlers via composeEventHandlers to preserve internal idle logic, spreads incoming style with CSS variables, and adds helper implementations.
Audio playlist UI redesign
apps/www/registry/default/blocks/audio-player/components/playlist.tsx
Reworks Playlist with dropdown open state, MenuOffsetData-based getPlaylistSideOffset computed from container height, "Now playing"/"Next From" section split, empty states, and playlist-naming helpers (firstNonEmpty, getAssetPlaylistName, getPlaylistName) with SectionHeading component. Updates TrackRow with showArtworkOverlay prop, LimeplayLogo fallback for poster-less assets, PlayIcon-only overlay logic, string data-active values, and revised "Preloaded" indicator.
DropdownMenu collision props and playlist positioning
apps/www/components/ui/dropdown-menu.tsx, apps/www/registry/default/blocks/video-player/components/playlist.tsx
Extends DropdownMenuContent with collisionAvoidance, collisionBoundary, and collisionPadding props forwarded to MenuPrimitive.Positioner. Video player Playlist reads containerRef from usePlayerStore and passes it as collisionBoundary with collisionPadding={20}.
Toggle primitives: Radix to Base UI migration
apps/www/components/ui/toggle.tsx, apps/www/components/ui/toggle-group.tsx
Migrates Toggle and ToggleGroup from Radix UI to Base UI primitives. Updates imports and prop types to reference Base UI components directly, adjusts rendered elements, variant class strings, and attribute wiring accordingly.
ToggleGroup integration: block-viewer, panel-popover, action-controls
apps/www/components/block-viewer.tsx, apps/www/components/stream-panel/panel-popover.tsx, apps/www/registry/default/blocks/audio-player/components/action-controls.tsx
Updates BlockViewerToolbar to use array-based ToggleGroup value ["100"] and extract from first element in handler. Updates PanelToggleRow to use array value ["on"]/["off"] with boolean conversion. Refactors ActionControls to pass ToggleGroup props inline with array-based onValueChange.
Registry updates and animation refactoring
apps/www/registry/collection/registry-blocks.ts, apps/www/registry/collection/registry-ui.ts, apps/www/registry/default/blocks/audio-player/components/playback-controls.tsx
Adds root-container to audio-player registryDependencies, adds Radix slot dependencies to limeplay-logo, extends root-container registryDependencies to include use-player. Updates AnimatedIcon to use explicit animate/exit/initial blur/opacity/scale transitions keyed by id.
Type updates: LucideIcon for toolbar items
apps/www/components/blocks/block-toolbar.tsx
Updates ToolbarItem.icon field type from React.ElementType to LucideIcon for compile-time type checking.
Preview pane toggle refactor
apps/www/components/blocks/preview-pane.tsx
Renames setExpanded callback parameter from currentExpanded to previousExpanded; toggle computation remains unchanged.

Sequence Diagrams

sequenceDiagram
    rect rgba(100, 150, 255, 0.5)
        Note over PlaybackStore,Orb: Audio Hover Player Orb Sync
    end
    participant PlaybackStore
    participant AudioHoverOrbSync
    participant AudioPlayerHoverContent
    participant Orb

    PlaybackStore-->>AudioHoverOrbSync: status = "playing"
    AudioHoverOrbSync->>AudioPlayerHoverContent: onAgentStateChange("talking")
    AudioPlayerHoverContent->>Orb: agentState="talking", manualInput/Output=0.8

    PlaybackStore-->>AudioHoverOrbSync: status = "buffering"
    AudioHoverOrbSync->>AudioPlayerHoverContent: onAgentStateChange("thinking")
    AudioPlayerHoverContent->>Orb: agentState="thinking", manualInput/Output=0
Loading
sequenceDiagram
    rect rgba(100, 200, 150, 0.5)
        Note over useStreamPanelSync,PlaylistStore: Apple Music Chart Pagination
    end
    participant useStreamPanelSync
    participant fetchAppleMusicChartAssetsPage
    participant appendNextAppleMusicChartPage
    participant PlaylistStore

    useStreamPanelSync->>fetchAppleMusicChartAssetsPage: page=1, signal
    fetchAppleMusicChartAssetsPage-->>useStreamPanelSync: {assets, nextPage: 2}
    useStreamPanelSync->>PlaylistStore: initialize queue with page 1 assets
    useStreamPanelSync->>appendNextAppleMusicChartPage: trigger for current index

    Note over appendNextAppleMusicChartPage: index approaches end of page 1
    appendNextAppleMusicChartPage->>fetchAppleMusicChartAssetsPage: page=2, signal
    fetchAppleMusicChartAssetsPage-->>appendNextAppleMusicChartPage: {assets, nextPage: 3}
    appendNextAppleMusicChartPage->>PlaylistStore: append deduplicated assets
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • WINOFFRG/limeplay#151: Renames and rewires hover-player.tsx's audio hover component, which this PR further modifies to add the Orb integration with playback-status sync.
  • WINOFFRG/limeplay#153: Performs the core StreamPanel and useStreamPanelSync refactor that this PR's Apple Music pagination additions build upon.
  • WINOFFRG/limeplay#149: Touches BlockPreviewWithToolbar in preview-pane.tsx with toolbar and theme changes around the same expand/collapse logic this PR refactors.

Poem

🐰 Hoppity-hop through the shader code deep,
A glowing orb now pulses while melodies sweep.
Apple Music pages turn one by one,
The playlist redesigned — oh, the work that was done!
forwardRef passes the torch down the tree,
Base UI toggles hop by with bunny-eared glee! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: playlist loaders, audio player a11y' directly matches the main changes: playlist pagination fixes and audio player accessibility improvements (Orb component with agent state, RefForward ref support).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1506

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
apps/www/registry/default/ui/root-container.tsx (1)

11-27: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add asChild support to RootContainer (required in this UI path).

RootContainer in this path should support asChild via @radix-ui/react-slot, but it currently hardcodes a <div>.

As per coding guidelines, "apps/www/registry/default/ui/**/*.{ts,tsx}: Support asChild prop via @radix-ui/react-slot in components" and "apps/www/registry/default/ui/**: Always support asChild via @radix-ui/react-slot."

Also applies to: 60-114

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/www/registry/default/ui/root-container.tsx` around lines 11 - 27, The
RootContainer component needs to support the asChild prop as per the coding
guidelines for this UI path. Add the asChild prop to the RootContainerProps
interface, then update the RootContainer component implementation to use the
Slot component from `@radix-ui/react-slot` instead of hardcoding a div element.
When asChild is true, render the content through Slot; otherwise, render the div
as normal. This allows consumers to pass a custom element through the asChild
prop while maintaining the container's styling and functionality.

Source: Coding guidelines

🧹 Nitpick comments (1)
apps/www/components/ui/orb.tsx (1)

212-222: 💤 Low value

Frame-rate dependent smoothing factors.

The lerp/smoothing factors (0.2, 0.12, 0.08) are applied per-frame without incorporating delta, so animation speed varies with refresh rate (e.g., 60Hz vs 120Hz displays). For a visual effect this is cosmetic, but using 1 - Math.pow(1 - factor, delta * 60) would normalize behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/www/components/ui/orb.tsx` around lines 212 - 222, The smoothing factors
(0.2, 0.12, and 0.08) applied to curInRef.current, curOutRef.current,
animSpeedRef.current, and the lerp calls for uColor1 and uColor2 are frame-rate
dependent. Normalize these factors to be frame-rate independent by replacing
each hardcoded factor with the delta-normalized equivalent using the formula 1 -
Math.pow(1 - factor, delta * 60), where factor is the original smoothing value.
This applies to the multiplication factor used in the curInRef and curOutRef
updates (currently 0.2), the animSpeedRef update (currently 0.12), and the lerp
parameters for both color values (currently 0.08). This ensures animation speed
remains consistent across different refresh rates.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/www/components/blocks/preview-pane.tsx`:
- Around line 54-57: The handleExpandToggle function derives nextExpanded from
the closed-over expanded variable, which can cause rapid consecutive toggles to
be lost if the function fires multiple times before React commits a render.
Replace the setExpanded(nextExpanded) call with a functional updater pattern
setExpanded(prev => !prev) to ensure each state update operates on the latest
state value rather than a stale closure. Since the new expanded value is now
computed inside the setState call, compute the toggled value separately (e.g.,
at the time of the functional updater) and pass it to updateExpandedQuery to
keep the query in sync with the actual state update.

In `@apps/www/registry/default/blocks/audio-player/components/media-player.tsx`:
- Line 23: The audio-player component in media-player.tsx now imports
RootContainer from root-container, but the audio-player registry entry in
apps/www/registry/collection/registry-ui.ts does not declare this dependency in
its registryDependencies array. Locate the audio-player registry configuration
object in registry-ui.ts and add "root-container" to its registryDependencies
array to satisfy the registry contract and pass validation. This update is
needed at the audio-player entry to ensure all component imports are properly
declared as registry dependencies.

In `@apps/www/registry/default/blocks/audio-player/components/playlist.tsx`:
- Around line 366-380: The inline style prop with transform: scale(0.5) on the
PlayIcon component has higher CSS specificity than the Tailwind hover utility
group-hover/track:scale-100, preventing the scale animation from applying on
hover for non-active tracks. Replace the inline style={{ transform: isActive ?
undefined : "scale(0.5)" }} with Tailwind scale utilities (such as scale-50)
added conditionally to the className based on isActive, ensuring all styling
uses class-based utilities with consistent specificity so the hover state
animation works properly.

In `@apps/www/registry/default/ui/root-container.tsx`:
- Around line 38-46: The root-container.tsx component spreads the destructured
`...etc` directly, which allows consumer-provided event handlers (like
onPointerMove, onBlur) to override the internal event handlers defined in the
component rather than composing with them. To fix this, extract event handler
props from the `etc` object and compose them with the internal handlers. Instead
of spreading `...etc` directly on line 111, selectively apply non-handler props
from `etc` while creating composed event handler functions that call both the
internal handler and the consumer's handler (if provided) for events like
onPointerMove, onBlur, and others to ensure event handlers chain together and
event propagation is not blocked.

---

Outside diff comments:
In `@apps/www/registry/default/ui/root-container.tsx`:
- Around line 11-27: The RootContainer component needs to support the asChild
prop as per the coding guidelines for this UI path. Add the asChild prop to the
RootContainerProps interface, then update the RootContainer component
implementation to use the Slot component from `@radix-ui/react-slot` instead of
hardcoding a div element. When asChild is true, render the content through Slot;
otherwise, render the div as normal. This allows consumers to pass a custom
element through the asChild prop while maintaining the container's styling and
functionality.

---

Nitpick comments:
In `@apps/www/components/ui/orb.tsx`:
- Around line 212-222: The smoothing factors (0.2, 0.12, and 0.08) applied to
curInRef.current, curOutRef.current, animSpeedRef.current, and the lerp calls
for uColor1 and uColor2 are frame-rate dependent. Normalize these factors to be
frame-rate independent by replacing each hardcoded factor with the
delta-normalized equivalent using the formula 1 - Math.pow(1 - factor, delta *
60), where factor is the original smoothing value. This applies to the
multiplication factor used in the curInRef and curOutRef updates (currently
0.2), the animSpeedRef update (currently 0.12), and the lerp parameters for both
color values (currently 0.08). This ensures animation speed remains consistent
across different refresh rates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 78ded28f-e16d-42e4-8f65-d76e06251bcb

📥 Commits

Reviewing files that changed from the base of the PR and between 14b084b and dbb301d.

⛔ Files ignored due to path filters (6)
  • DEVELOPMENT.md is excluded by none and included by none
  • README.md is excluded by none and included by none
  • apps/www/package.json is excluded by none and included by none
  • apps/www/public/github_preview.png is excluded by !**/*.png and included by none
  • apps/www/vercel.json is excluded by none and included by none
  • bun.lock is excluded by !**/*.lock and included by none
📒 Files selected for processing (10)
  • apps/www/components/blocks/preview-pane.tsx
  • apps/www/components/players/audio-player/hover-player.tsx
  • apps/www/components/stream-panel/content-catalog.ts
  • apps/www/components/stream-panel/use-stream-panel-sync.ts
  • apps/www/components/ui/dropdown-menu.tsx
  • apps/www/components/ui/orb.tsx
  • apps/www/registry/default/blocks/audio-player/components/media-player.tsx
  • apps/www/registry/default/blocks/audio-player/components/playlist.tsx
  • apps/www/registry/default/blocks/video-player/components/playlist.tsx
  • apps/www/registry/default/ui/root-container.tsx

Comment thread apps/www/components/blocks/preview-pane.tsx Outdated
import { TimelineControl } from "@/registry/default/blocks/audio-player/components/fixed-timeline-control"
import { MediaProvider } from "@/registry/default/blocks/audio-player/lib/media-kit"
import { Media } from "@/registry/default/ui/media"
import { RootContainer } from "@/registry/default/ui/root-container"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Registry contract is broken for audio-player after adding root-container.

CI already fails registry validation because this component now imports root-container but audio-player registry metadata doesn’t declare it in registryDependencies.

Please update the audio-player entry in apps/www/registry/collection/registry-ui.ts to include "root-container" in registryDependencies so registry build/validation passes.

Also applies to: 70-87

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/www/registry/default/blocks/audio-player/components/media-player.tsx` at
line 23, The audio-player component in media-player.tsx now imports
RootContainer from root-container, but the audio-player registry entry in
apps/www/registry/collection/registry-ui.ts does not declare this dependency in
its registryDependencies array. Locate the audio-player registry configuration
object in registry-ui.ts and add "root-container" to its registryDependencies
array to satisfy the registry contract and pass validation. This update is
needed at the audio-player entry to ensure all component imports are properly
declared as registry dependencies.

Source: Pipeline failures

Comment thread apps/www/registry/default/ui/root-container.tsx

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

3 issues found across 16 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/www/registry/default/blocks/audio-player/components/playlist.tsx">

<violation number="1" location="apps/www/registry/default/blocks/audio-player/components/playlist.tsx:103">
P2: `Next From` ignores repeat-all wraparound and can incorrectly show an empty next queue at the end of the playlist. This misrepresents playback order when repeat mode is `all`.</violation>
</file>

<file name="apps/www/components/ui/orb.tsx">

<violation number="1" location="apps/www/components/ui/orb.tsx:313">
P2: Shader uses `smoothstep` with inverted edge order, which is undefined behavior. Compute the inverted ramp explicitly to keep rendering deterministic.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

vec2 p = polarUv - polarCenter;
float oval = (p.x * p.x) / (a * a) + (p.y * p.y) / (b * b);

float edge = smoothstep(1.0, 1.0 - softness, oval);

@cubic-dev-ai cubic-dev-ai Bot Jun 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Shader uses smoothstep with inverted edge order, which is undefined behavior. Compute the inverted ramp explicitly to keep rendering deterministic.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/www/components/ui/orb.tsx, line 313:

<comment>Shader uses `smoothstep` with inverted edge order, which is undefined behavior. Compute the inverted ramp explicitly to keep rendering deterministic.</comment>

<file context>
@@ -0,0 +1,498 @@
+    vec2 p = polarUv - polarCenter;
+    float oval = (p.x * p.x) / (a * a) + (p.y * p.y) / (b * b);
+
+    float edge = smoothstep(1.0, 1.0 - softness, oval);
+
+    if (edge > 0.0) {
</file context>
Suggested change
float edge = smoothstep(1.0, 1.0 - softness, oval);
float edge = 1.0 - smoothstep(1.0 - softness, 1.0, oval);
Fix with cubic

Comment thread apps/www/registry/default/blocks/audio-player/components/playlist.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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/www/components/ui/toggle.tsx (1)

48-55: ⚠️ Potential issue | 🟠 Major

Update the pressed-state selectors for the Base UI primitive.

This wrapper now renders Base UI's Toggle, but toggleVariants still keys the active styles off data-[state=on]. Base UI marks the pressed state with data-pressed, so the selected styles stop applying after this swap.

Suggested fix
-    data-[state=on]:bg-accent data-[state=on]:text-accent-foreground
+    data-[pressed]:bg-accent data-[pressed]:text-accent-foreground
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/www/components/ui/toggle.tsx` around lines 48 - 55, The toggleVariants
styling configuration is using the outdated data-[state=on] selector which was
for the previous primitive, but Base UI's Toggle component uses data-[pressed]
to mark the active state. Update the toggleVariants function or constant to
replace all occurrences of data-[state=on] selectors with data-[pressed] so that
the pressed-state styles correctly apply to the Base UI Toggle primitive.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/www/components/ui/toggle-group.tsx`:
- Around line 28-33: The ToggleGroupPrimitive wrapper accepts a scalar value
interface that callers expect (with type="single", scalar value, and scalar
onValueChange callback) but Base UI's ToggleGroup always uses arrays regardless
of the multiple prop, causing runtime failures. Add adapter logic in the
toggle-group wrapper component to convert between the scalar interface that
callers use and the array-based interface that ToggleGroupPrimitive requires.
This means accepting scalar value and onValueChange parameters, then converting
them to/from arrays when passing to and receiving from ToggleGroupPrimitive, so
callers can continue using scalar operations like parseInt(value) and v === "on"
comparisons without breaking.

---

Outside diff comments:
In `@apps/www/components/ui/toggle.tsx`:
- Around line 48-55: The toggleVariants styling configuration is using the
outdated data-[state=on] selector which was for the previous primitive, but Base
UI's Toggle component uses data-[pressed] to mark the active state. Update the
toggleVariants function or constant to replace all occurrences of
data-[state=on] selectors with data-[pressed] so that the pressed-state styles
correctly apply to the Base UI Toggle primitive.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 71df524e-d77a-4204-81e9-7d46e076090f

📥 Commits

Reviewing files that changed from the base of the PR and between dbb301d and d14a89e.

📒 Files selected for processing (9)
  • apps/www/components/blocks/preview-pane.tsx
  • apps/www/components/ui/orb.tsx
  • apps/www/components/ui/toggle-group.tsx
  • apps/www/components/ui/toggle.tsx
  • apps/www/registry/collection/registry-blocks.ts
  • apps/www/registry/collection/registry-ui.ts
  • apps/www/registry/default/blocks/audio-player/components/playback-controls.tsx
  • apps/www/registry/default/blocks/audio-player/components/playlist.tsx
  • apps/www/registry/default/ui/root-container.tsx
✅ Files skipped from review due to trivial changes (3)
  • apps/www/registry/collection/registry-blocks.ts
  • apps/www/registry/default/blocks/audio-player/components/playback-controls.tsx
  • apps/www/components/blocks/preview-pane.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/www/components/ui/orb.tsx
  • apps/www/registry/default/blocks/audio-player/components/playlist.tsx

Comment thread apps/www/components/ui/toggle-group.tsx Outdated
Comment on lines +28 to +33
}: React.ComponentProps<typeof ToggleGroupPrimitive> &
VariantProps<typeof toggleVariants> & {
spacing?: number
}) {
return (
<ToggleGroupPrimitive.Root
<ToggleGroupPrimitive

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and examine the structure
cd /repo && git ls-files "**/toggle-group.tsx" | head -20

Repository: WINOFFRG/limeplay

Length of output: 117


🏁 Script executed:

# If file found, examine the implementation around lines 28-33
cat -n apps/www/components/ui/toggle-group.tsx | head -60

Repository: WINOFFRG/limeplay

Length of output: 1923


🏁 Script executed:

# Find all usages of ToggleGroup in the codebase
rg "ToggleGroup" --type tsx --type ts -B 2 -A 2 | head -100

Repository: WINOFFRG/limeplay

Length of output: 89


🏁 Script executed:

# Check Base UI documentation or package info for ToggleGroup API
fd "package.json" | xargs grep -l "`@base-ui`" 2>/dev/null | head -5

Repository: WINOFFRG/limeplay

Length of output: 83


🏁 Script executed:

# Search for actual callers of ToggleGroup component
rg "ToggleGroup" apps/www --type-add 'tsx:*.tsx' --type-add 'ts:*.ts' -A 3 -B 1 | head -150

Repository: WINOFFRG/limeplay

Length of output: 9949


🏁 Script executed:

# Check the package.json for Base UI version
cat apps/www/package.json | grep -A 2 -B 2 "base-ui"

Repository: WINOFFRG/limeplay

Length of output: 288


🏁 Script executed:

# Look for the specific caller files mentioned in the review
fd "panel-popover.tsx" apps/www
fd "block-viewer.tsx" apps/www  
fd "action-controls.tsx" apps/www

Repository: WINOFFRG/limeplay

Length of output: 226


🏁 Script executed:

# Examine one of the callers to see how they use ToggleGroup
cat apps/www/components/stream-panel/panel-popover.tsx | grep -n "ToggleGroup" -A 20 -B 2 | head -80

Repository: WINOFFRG/limeplay

Length of output: 1722


🏁 Script executed:

# Check if there are node_modules or type definitions for `@base-ui/react`
fd "`@base-ui`" apps/www/node_modules 2>/dev/null | head -20

Repository: WINOFFRG/limeplay

Length of output: 43


🏁 Script executed:

# Look for the actual error or type mismatch patterns - check block-viewer for onValueChange handler
cat apps/www/components/block-viewer.tsx | grep -n "ToggleGroup" -A 15 | head -50

Repository: WINOFFRG/limeplay

Length of output: 2024


🏁 Script executed:

# Get more context from panel-popover - check what the actual issue is at type check time
cat apps/www/components/stream-panel/panel-popover.tsx | sed -n '413,430p'

Repository: WINOFFRG/limeplay

Length of output: 507


🏁 Script executed:

# Search for any tsconfig or type checking to see what strict mode is enabled
cat apps/www/tsconfig.json 2>/dev/null | head -50

Repository: WINOFFRG/limeplay

Length of output: 1230


🌐 Web query:

Base UI React ToggleGroup API value type multiple boolean array documentation

💡 Result:

In the Base UI React ToggleGroup component, the value type for the value and defaultValue props is a string array (string[]) [1][2][3]. The ToggleGroup manages the pressed states of its child Toggle components [1][4]. Regardless of whether the multiple prop is enabled, the component tracks these states using an array of strings [1][3]. Key details regarding the API: - Value Type: The props value and defaultValue accept readonly string[] [2][5]. - Callback: The onValueChange callback provides the updated state as an array of strings: (groupValue: string[], eventDetails: ChangeEventDetails) => void [2][5]. - Multiple Selection: When the multiple prop is set to true, multiple toggle buttons can be active simultaneously, and their corresponding string values are collected into the array [5][4]. When multiple is false (the default), the array will contain at most one string value, representing the single active toggle [4]. Technical note: Recent updates (as of early 2026) tightened the type definition from any[] to string[] to ensure better type safety and consistency with the Toggle component, which only accepts string values [3].

Citations:


Base UI's ToggleGroup uses array-based values; callers pass scalar strings and type="single" (a Radix API).

Existing callers in panel-popover.tsx and block-viewer.tsx pass type="single" (not a Base UI prop) and treat value as a scalar string and onValueChange as receiving a scalar. Base UI always uses string[] for values regardless of the multiple prop, so callers expecting scalar behavior will break at runtime (e.g., parseInt(value) and v === "on" comparisons fail on arrays). Either add an adapter in this wrapper to convert between scalar and array interfaces, or update all callers to the Base UI contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/www/components/ui/toggle-group.tsx` around lines 28 - 33, The
ToggleGroupPrimitive wrapper accepts a scalar value interface that callers
expect (with type="single", scalar value, and scalar onValueChange callback) but
Base UI's ToggleGroup always uses arrays regardless of the multiple prop,
causing runtime failures. Add adapter logic in the toggle-group wrapper
component to convert between the scalar interface that callers use and the
array-based interface that ToggleGroupPrimitive requires. This means accepting
scalar value and onValueChange parameters, then converting them to/from arrays
when passing to and receiving from ToggleGroupPrimitive, so callers can continue
using scalar operations like parseInt(value) and v === "on" comparisons without
breaking.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

3 issues found across 9 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/www/components/ui/orb.tsx">

<violation number="1" location="apps/www/components/ui/orb.tsx:313">
P2: Shader uses `smoothstep` with inverted edge order, which is undefined behavior. Compute the inverted ramp explicitly to keep rendering deterministic.</violation>
</file>

<file name="apps/www/components/ui/toggle-group.tsx">

<violation number="1" location="apps/www/components/ui/toggle-group.tsx:28">
P1: The wrapper switched to Base UI prop types without adapting the existing Radix-style API (`type="single"`, scalar `value`). This causes toggle-group state callbacks and controlled values to be interpreted incorrectly.</violation>
</file>

<file name="apps/www/components/ui/toggle.tsx">

<violation number="1" location="apps/www/components/ui/toggle.tsx:3">
P2: State styling selector is incompatible with the new Toggle primitive. `data-[state=on]` should be updated to Base UI's `data-[pressed]` selector.</violation>
</file>

<file name="apps/www/components/blocks/preview-pane.tsx">

<violation number="1" location="apps/www/components/blocks/preview-pane.tsx:56">
P2: Side effect inside state updater; URL replace can run more than once for a single toggle. Move query-sync side effect outside the updater (e.g., effect driven by `expanded`).</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/www/components/ui/toggle-group.tsx Outdated
variant,
...props
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
}: React.ComponentProps<typeof ToggleGroupPrimitive> &

@cubic-dev-ai cubic-dev-ai Bot Jun 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: The wrapper switched to Base UI prop types without adapting the existing Radix-style API (type="single", scalar value). This causes toggle-group state callbacks and controlled values to be interpreted incorrectly.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/www/components/ui/toggle-group.tsx, line 28:

<comment>The wrapper switched to Base UI prop types without adapting the existing Radix-style API (`type="single"`, scalar `value`). This causes toggle-group state callbacks and controlled values to be interpreted incorrectly.</comment>

<file context>
@@ -24,12 +25,12 @@ function ToggleGroup({
   variant,
   ...props
-}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
+}: React.ComponentProps<typeof ToggleGroupPrimitive> &
   VariantProps<typeof toggleVariants> & {
     spacing?: number
</file context>
Fix with cubic

const nextExpanded = !currentExpanded
setExpanded((previousExpanded) => {
const nextExpanded = !previousExpanded
updateExpandedQuery(nextExpanded)

@cubic-dev-ai cubic-dev-ai Bot Jun 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Side effect inside state updater; URL replace can run more than once for a single toggle. Move query-sync side effect outside the updater (e.g., effect driven by expanded).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/www/components/blocks/preview-pane.tsx, line 56:

<comment>Side effect inside state updater; URL replace can run more than once for a single toggle. Move query-sync side effect outside the updater (e.g., effect driven by `expanded`).</comment>

<file context>
@@ -51,10 +51,12 @@ export function BlockPreviewWithToolbar({
-  }, [expanded, updateExpandedQuery])
+    setExpanded((previousExpanded) => {
+      const nextExpanded = !previousExpanded
+      updateExpandedQuery(nextExpanded)
+      return nextExpanded
+    })
</file context>
Fix with cubic

"use client"

import * as TogglePrimitive from "@radix-ui/react-toggle"
import { Toggle as TogglePrimitive } from "@base-ui/react/toggle"

@cubic-dev-ai cubic-dev-ai Bot Jun 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: State styling selector is incompatible with the new Toggle primitive. data-[state=on] should be updated to Base UI's data-[pressed] selector.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/www/components/ui/toggle.tsx, line 3:

<comment>State styling selector is incompatible with the new Toggle primitive. `data-[state=on]` should be updated to Base UI's `data-[pressed]` selector.</comment>

<file context>
@@ -1,6 +1,6 @@
 "use client"
 
-import * as TogglePrimitive from "@radix-ui/react-toggle"
+import { Toggle as TogglePrimitive } from "@base-ui/react/toggle"
 import { cva, type VariantProps } from "class-variance-authority"
 import * as React from "react"
</file context>
Fix with cubic

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/www/components/ui/toggle-group.tsx`:
- Around line 23-53: The orientation prop is destructured but not forwarded to
the ToggleGroupPrimitive component—only mirrored as a data-orientation attribute
for styling. This breaks keyboard navigation and ARIA semantics. Add
orientation={orientation} as a prop when rendering ToggleGroupPrimitive to
ensure the Base UI primitive receives the actual orientation value and can
properly handle keyboard navigation and accessibility features based on the
declared axis.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f490f1aa-0ffb-481c-a236-0d2067b44f79

📥 Commits

Reviewing files that changed from the base of the PR and between d14a89e and f7ec6f6.

⛔ Files ignored due to path filters (1)
  • apps/www/next-env.d.ts is excluded by none and included by none
📒 Files selected for processing (7)
  • apps/www/components/block-viewer.tsx
  • apps/www/components/blocks/block-toolbar.tsx
  • apps/www/components/stream-panel/panel-popover.tsx
  • apps/www/components/ui/toggle-group.tsx
  • apps/www/components/ui/toggle.tsx
  • apps/www/registry/default/blocks/audio-player/components/action-controls.tsx
  • apps/www/registry/default/blocks/audio-player/components/playlist.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/www/registry/default/blocks/audio-player/components/playlist.tsx

Comment thread apps/www/components/ui/toggle-group.tsx
@WINOFFRG WINOFFRG merged commit 8047d1c into main Jun 14, 2026
7 checks 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.

1 participant