Skip to content

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

Open
kno-raziel wants to merge 1 commit into
RustForWeb:mainfrom
kno-raziel:fix/opposite-axis-placements-bare-sides
Open

fix(utils): don't duplicate base placements in get_opposite_axis_placements#340
kno-raziel wants to merge 1 commit into
RustForWeb:mainfrom
kno-raziel:fix/opposite-axis-placements-bare-sides

Conversation

@kno-raziel

Copy link
Copy Markdown

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!

…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>

@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
Comment on lines +715 to +717
// The flip-alignment duplication only applies to aligned placements. In the
// JS source this block is nested inside `if (alignment)`; without that guard,
// base placements (e.g. Top/Bottom/Left/Right) are returned duplicated.

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.

Suggested change
// The flip-alignment duplication only applies to aligned placements. In the
// JS source this block is nested inside `if (alignment)`; without that guard,
// base placements (e.g. Top/Bottom/Left/Right) are returned duplicated.

Comment thread packages/utils/src/lib.rs
Comment on lines +769 to +770
#[cfg(test)]
mod opposite_axis_placements_tests {

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.

Suggested change
#[cfg(test)]
mod opposite_axis_placements_tests {
#[cfg(test)]
mod tests {

Comment thread packages/utils/src/lib.rs
Comment on lines +771 to +772
// Ported from @floating-ui/utils
// packages/utils/test/getOppositeAxisPlacements.test.ts

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.

Suggested change
// Ported from @floating-ui/utils
// packages/utils/test/getOppositeAxisPlacements.test.ts

Comment thread packages/utils/src/lib.rs
get_opposite_axis_placements(placement, flip, Some(dir), Some(true))
}

// --- side ---

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.

Suggested change
// --- side ---

Comment thread packages/utils/src/lib.rs
assert_eq!(goap(Right, true, Alignment::End), vec![Bottom, Top]);
}

// --- start alignment ---

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.

Suggested change
// --- start alignment ---

Comment thread packages/utils/src/lib.rs
assert_eq!(goap(RightStart, true, Alignment::End), vec![BottomStart, TopStart, BottomEnd, TopEnd]);
}

// --- end alignment ---

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.

Suggested change
// --- end alignment ---

Comment thread packages/utils/src/lib.rs
Comment on lines +855 to +856
// NOTE: upstream JS test asserts left-end for the non-flip cases and
// (verbatim, an upstream copy-paste) left-start for the flip cases.

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.

Suggested change
// NOTE: upstream JS test asserts left-end for the non-flip cases and
// (verbatim, an upstream copy-paste) left-start for the flip cases.

Comment thread packages/utils/src/lib.rs
assert_eq!(goap(RightEnd, true, Alignment::End), vec![BottomEnd, TopEnd, BottomStart, TopStart]);
}

// --- rtl ---

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.

Suggested change
// --- rtl ---

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