Skip to content

fix(utils): don't duplicate base placements in get_opposite_axis_placements#340

Merged
DanielleHuisman merged 3 commits into
RustForWeb:mainfrom
kno-raziel:fix/opposite-axis-placements-bare-sides
Jun 28, 2026
Merged

fix(utils): don't duplicate base placements in get_opposite_axis_placements#340
DanielleHuisman merged 3 commits into
RustForWeb:mainfrom
kno-raziel:fix/opposite-axis-placements-bare-sides

Conversation

@kno-raziel

Copy link
Copy Markdown
Contributor

Problem

get_opposite_axis_placements applies the flip-alignment duplication unconditionally:

if flip_alignment {
    let mut opposite_list = list.clone().into_iter().map(get_opposite_alignment_placement).collect();
    list.append(&mut opposite_list);
}

In the JS source (@floating-ui/utils) this block is nested inside if (alignment), so base placements (no alignment) are never duplicated:

if (alignment) {
  list = list.map((side) => `${side}-${alignment}`);
  if (flipAlignment) {
    list = list.concat(list.map(getOppositeAlignmentPlacement));
  }
}

Without the guard, a base placement comes back duplicated:

get_opposite_axis_placements(Placement::Top, true, Some(Alignment::Start), None)
// returns [Left, Right, Left, Right]   (expected: [Left, Right])

Fix

Guard the flip-alignment block with alignment.is_some() to match the JS behaviour (the list.map(...) step is already a no-op for base placements via get_placement(side, None), so only the duplication needed guarding).

Tests

Adds a #[cfg(test)] module porting the JS suite packages/utils/test/getOppositeAxisPlacements.test.ts (16 cases: side / start-alignment / end-alignment / rtl). packages/utils had no tests previously; these fail before the fix on the base-placement cases and pass after.

cargo test -p floating-ui-utils   # 16 passed

Found while building a Leptos UI library on top of this crate — thanks for the Rust port!

@DanielleHuisman DanielleHuisman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for finding and reporting this issue. Please remove the unnecessary comments.

Comment thread packages/utils/src/lib.rs Outdated
Comment thread packages/utils/src/lib.rs Outdated
Comment thread packages/utils/src/lib.rs Outdated
Comment thread packages/utils/src/lib.rs Outdated
Comment thread packages/utils/src/lib.rs Outdated
Comment thread packages/utils/src/lib.rs Outdated
Comment thread packages/utils/src/lib.rs Outdated
Comment thread packages/utils/src/lib.rs Outdated
kno-raziel and others added 3 commits June 28, 2026 12:21
…ements

`get_opposite_axis_placements` applied the flip-alignment duplication
unconditionally. In the JS source (`@floating-ui/utils`) this block is nested
inside `if (alignment)`, so base placements (Top/Bottom/Left/Right) must not be
duplicated. Without the guard, e.g.

    get_opposite_axis_placements(Placement::Top, true, Some(Alignment::Start), None)

returned `[Left, Right, Left, Right]` instead of `[Left, Right]`.

Guard the block with `alignment.is_some()` to match the JS behaviour, and add a
`#[cfg(test)]` module porting `getOppositeAxisPlacements.test.ts` (16 cases);
`utils` previously had no tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Daniëlle Huisman <danielle@huisman.me>
@DanielleHuisman DanielleHuisman force-pushed the fix/opposite-axis-placements-bare-sides branch from 35eb379 to 8e9a448 Compare June 28, 2026 10:21
@DanielleHuisman DanielleHuisman enabled auto-merge (squash) June 28, 2026 10:22
@DanielleHuisman DanielleHuisman disabled auto-merge June 28, 2026 10:23
@DanielleHuisman DanielleHuisman merged commit da76f76 into RustForWeb:main Jun 28, 2026
7 of 8 checks passed
DanielleHuisman added a commit that referenced this pull request Jun 28, 2026
…ements (#340)

* fix(utils): don't duplicate base placements in get_opposite_axis_placements

`get_opposite_axis_placements` applied the flip-alignment duplication
unconditionally. In the JS source (`@floating-ui/utils`) this block is nested
inside `if (alignment)`, so base placements (Top/Bottom/Left/Right) must not be
duplicated. Without the guard, e.g.

    get_opposite_axis_placements(Placement::Top, true, Some(Alignment::Start), None)

returned `[Left, Right, Left, Right]` instead of `[Left, Right]`.

Guard the block with `alignment.is_some()` to match the JS behaviour, and add a
`#[cfg(test)]` module porting `getOppositeAxisPlacements.test.ts` (16 cases);
`utils` previously had no tests.

---------

* chore: remove unnecessary comments
* chore: format

Co-authored-by: Daniëlle Huisman <danielle@huisman.me>

---------

Co-authored-by: kno-raziel <8211946+kno-raziel@users.noreply.github.com>
Co-authored-by: Daniëlle Huisman <danielle@huisman.me>
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