Skip to content

Conversation

@velrest
Copy link

@velrest velrest commented Oct 22, 2025

The ember-power-select documentation mentions, that the argument verticalPosition is by default auto and therefor the positioning will be automatically calcualted based on available space. This is correct for wormhole positioning but not if the argument renderInPlace={{true}} is used as this is not implemented here in ember-basic-dropdown.

I was not sure if this is a bug or rather a new feature in the scope of ember-basic-dropdown.

Reference

Reproduction: https://github.com/velrest/render_in_place_reproduction

https://ember-power-select.com/docs/api-reference
In case page is updated this was the content:
image

@velrest velrest marked this pull request as ready for review October 22, 2025 15:06
@velrest velrest force-pushed the fix_render_in_place_position_calucaltion branch from 28b4a45 to 095e8c9 Compare October 23, 2025 07:43
@mkszepp
Copy link
Collaborator

mkszepp commented Oct 23, 2025

@velrest Thanks for your PR!

According to the Ember Basic Dropdown documentation, you need to pass the @verticalPosition argument when @renderInPlace={{true}} is used:
👉 https://ember-basic-dropdown.com/docs/position

Please note that when rendering the content in place, the vertical position will not automatically detect the best position based on the space around the trigger. You have to explicitly pass verticalPosition="above" to render it over the trigger.

Adding this feature will require a major version (which is already planned), since it changes the current behavior.

Could you also add some tests to ensure that this change works correctly and does not introduce any regressions?

@velrest
Copy link
Author

velrest commented Oct 23, 2025

@mkszepp I will change the commit message and add some tests on monday. Thanks for the link!

@velrest velrest force-pushed the fix_render_in_place_position_calucaltion branch from 095e8c9 to f71c7bd Compare October 30, 2025 13:41
@velrest
Copy link
Author

velrest commented Oct 30, 2025

@mkszepp I'm actually not quite sure on how to write an integration test for this as it seems there is no test for auto or calculatePosition to learn from. I would have to limit the testing container window as the util directly accesses window and document and i assume mocking those would also break the test?. Do you have an idea for a clean test setup or an example?

@mkszepp
Copy link
Collaborator

mkszepp commented Nov 3, 2025

Oh, interesting that we have no tests right now for this... 🙉

I will take a look in next days, how we can add useful tests for calculatePosition

@velrest velrest changed the title fix(calculateInPlacePosition): implement verticalPosition "auto" feat(calculateInPlacePosition): implement verticalPosition "auto" Nov 17, 2025
@velrest
Copy link
Author

velrest commented Nov 17, 2025

@mkszepp I tried to create a setup for this in my test commit but it didn't work. It seems like, the whole position calculation is never called it that rendering test, as the initial calculation is done outside the run loop? Also tried to emit a scroll event to force recalculation but that also didn't work.

@mkszepp
Copy link
Collaborator

mkszepp commented Nov 30, 2025

@velrest sry for my delayed answer...

you can add into basic-dropdown-test.ts this two tests to ensure that your code is working (right now at least the first test should fail in current 8.x version. With your changes both tests should pass):

test<ExtendedTestContext>('It adds the proper class above to trigger and content when it receives `renderInPlace={{true}}` and @verticalPosition="auto"', async function (assert) {
    assert.expect(2);

    await render(hbs`
      <div style="position: absolute; bottom: 0">
        <BasicDropdown @renderInPlace={{true}} @verticalPosition="auto" as |dropdown|>
          <dropdown.Trigger>Press me</dropdown.Trigger>
          <dropdown.Content><h3>Content of the dropdown</h3></dropdown.Content>
        </BasicDropdown>
      </div>
    `);

    await click(
      getRootNode(this.element).querySelector(
        '.ember-basic-dropdown-trigger',
      ) as HTMLElement,
    );

    assert
      .dom('.ember-basic-dropdown-trigger', getRootNode(this.element))
      .hasClass(
        'ember-basic-dropdown-trigger--above',
        'The proper class has been added',
      );
    assert
      .dom('.ember-basic-dropdown-content', getRootNode(this.element))
      .hasClass(
        'ember-basic-dropdown-content--above',
        'The proper class has been added',
      );
  });

  test<ExtendedTestContext>('It adds the proper class below to trigger and content when it receives `renderInPlace={{true}}` and @verticalPosition="auto"', async function (assert) {
    assert.expect(2);

    await render(hbs`
      <div style="position: absolute; top: 0">
        <BasicDropdown @renderInPlace={{true}} @verticalPosition="auto" as |dropdown|>
          <dropdown.Trigger>Press me</dropdown.Trigger>
          <dropdown.Content><h3>Content of the dropdown</h3></dropdown.Content>
        </BasicDropdown>
      </div>
    `);

    await click(
      getRootNode(this.element).querySelector(
        '.ember-basic-dropdown-trigger',
      ) as HTMLElement,
    );
    assert
      .dom('.ember-basic-dropdown-trigger', getRootNode(this.element))
      .hasClass(
        'ember-basic-dropdown-trigger--below',
        'The proper class has been added',
      );
    assert
      .dom('.ember-basic-dropdown-content', getRootNode(this.element))
      .hasClass(
        'ember-basic-dropdown-content--below',
        'The proper class has been added',
      );
  });

Everything else, changed in test-app i think it's not needed and can be reverted

content: HTMLElement,
) => GetViewDataResult;

export const getViewData: GetViewData = (trigger, content) => {
Copy link
Collaborator

@mkszepp mkszepp Nov 30, 2025

Choose a reason for hiding this comment

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

i think we don't need to export this... when somebody wants to override our default functions they should make everything custom, not only a part

viewportBottom: number;
};

export type GetViewData = (
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
export type GetViewData = (
type GetViewData = (

options: CalculatePositionOptions,
) => CalculatePositionResult;

export type GetViewDataResult = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
export type GetViewDataResult = {
type GetViewDataResult = {


@action
reposition(): undefined | RepositionChanges {
debugger
Copy link
Collaborator

Choose a reason for hiding this comment

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

debugger should be removed

content.getBoundingClientRect();
const viewportWidth = document.body.clientWidth || window.innerWidth;
const viewportBottom = scroll.top + window.innerHeight;
debugger
Copy link
Collaborator

Choose a reason for hiding this comment

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

debugger should be removed here

@velrest velrest force-pushed the fix_render_in_place_position_calucaltion branch from 74b2836 to 9195fa9 Compare December 4, 2025 12:32
@velrest velrest force-pushed the fix_render_in_place_position_calucaltion branch from 9195fa9 to 1d4329f Compare December 4, 2025 12:34
@velrest
Copy link
Author

velrest commented Dec 4, 2025

@mkszepp I update the PR with your tests and Review suggestions. The test passes without my code changes and the code in the function caluculcateInPlacePosition is never called from any test. Maybe it's the same issue why my test didn't work.

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