Skip to content

ObjectPage in IconTabBar mode: header collapses when re-selecting a non-first section via selectedSectionId #8582

@mbritof

Description

@mbritof

Description

When using ObjectPage in IconTabBar mode with controlled selectedSectionId, switching back to a non-first section causes a programmatic scroll that collapses the header — even though the user did not scroll.

Expected Behavior

Changing selectedSectionId to a previously-visited non-first section should render that section's content without scrolling or collapsing the header.

Actual Behavior

The header collapses because scrollToSectionById sets scrollTop to a non-zero value based on stale scroll state.

Root Cause

In ObjectPage/index.tsx, the useIsomorphicLayoutEffect on selectedSectionId change (in IconTabBar mode) does:

  1. setInternalSelectedSectionId(selectedSectionId) — synchronous state update
  2. setTimeout(fireSelectEvent) — deferred call to handleOnSectionSelected

Inside handleOnSectionSelected:

setInternalSelectedSectionId((prevSelectedSection) => {
  if (prevSelectedSection === newSelectionSectionId) {
    scrollToSection(newSelectionSectionId);
  }
  return newSelectionSectionId;
});

Since step 1 already set internalSelectedSectionId to the new value, prev === new is always true when fireSelectEvent runs. For non-first sections, scrollToSection calls scrollToSectionById, which calculates:

objectPageElement.scrollTop =
  sectionRect.top - objectPageRect.top + objectPageElement.scrollTop - scrollMargin;

This produces a non-zero scrollTop, which triggers header collapse.

For the first section this is harmless because scrollToSection does scrollTo({ top: 0 }) instead.

Reproduction

const [selectedSection, setSelectedSection] = useState("section-1");

<ObjectPage
  mode="IconTabBar"
  selectedSectionId={selectedSection}
  onSelectedSectionChange={(e) => setSelectedSection(e.detail.selectedSectionId)}
  headerArea={<ObjectPageHeader>Header content</ObjectPageHeader>}
  titleArea={<ObjectPageTitle header="Title" />}
>
  <ObjectPageSection id="section-1" titleText="First">Content 1</ObjectPageSection>
  <ObjectPageSection id="section-2" titleText="Second">Content 2</ObjectPageSection>
  <ObjectPageSection id="section-3" titleText="Third">Content 3</ObjectPageSection>
</ObjectPage>

Steps:

  1. Click "Second" tab → works fine (first visit, prev !== new)
  2. Click "First" tab → works fine
  3. Click "Second" tab again → header collapses (prev === new, triggers scroll)

Suggested Fix

In handleOnSectionSelected, skip scrollToSection when in IconTabBar mode and the selection is driven by a controlled selectedSectionId change (not a user tab click). Alternatively, reset scrollTop to 0 before calculating the target position in scrollToSectionById when switching sections in IconTabBar mode.

Environment

  • @ui5/webcomponents-react: 2.21.3 (also confirmed on main branch)
  • React 18
  • Browser: Chrome (reproducible across browsers)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions