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 type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions