Skip to content

feat(ui5-shellbar): enhance responsive behaviour for custom branding - #14015

Open
NakataCode wants to merge 12 commits into
mainfrom
feat/shellbar-custom-branding-responsiveness
Open

NakataCode wants to merge 12 commits into
mainfrom
feat/shellbar-custom-branding-responsiveness

Conversation

@NakataCode

@NakataCode NakataCode commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

The ShellBar previously hid the product identifier as soon as space ran out, regardless of how much room was actually available. This PR replaces that approach with a fully space-aware overflow loop that keeps branding visible as long as possible, progressively hiding elements only when no other option remains.

Note

Full test coverage is not yet complete.

Overflow order

Elements hide in this sequence:

  1. Actions (rightmost first)
  2. Content items
  3. Search button
  4. Branding identifier
  5. Branding logo (always last)

What changed

Dynamic title wrapping

Before hiding the branding identifier, the overflow loop attempts to wrap the product title to two lines in place. A tryShrink callback sets a computed max-width on the title, forces a synchronous layout flush, then re-measures. The identifier is only moved to the overflow when two lines still do not fit. The wrap is entirely space-driven, with no fixed breakpoints.

Branding in the overflow popover

When the identifier or logo is hidden, a branding entry appears at the top of the overflow popover (always first, order: -1). The logo is a cloneNode of the actual slotted element, so <img>, <svg>, and ui5-avatar logos all work. Clicking the entry fires the branding click event and closes the popover. The aria-label follows the pattern "[ProductIdentifier] Home".

Overflow popover sizing

The popover no longer has a fixed max-width: 20rem. It sizes to its content: when the logo and title fit side by side, they sit on one line; when they do not, the title wraps below and the popover narrows. The floor is min-width: 100px. An oversized logo produces a horizontal scrollbar at the bottom of the popover.

Branding DOM position

The branding area <div> moved from outside overflow-container-inner to inside it as the first child. This means hiding it actually reduces the measured inner width. margin-inline-end: auto pushes actions to the right while keeping branding left-aligned as a natural flex child.

Render stability

  • getOverflowSignature() hashes the measurement inputs (available width, enabled features, search state, content items, branding title). updateOverflow skips re-measuring when the signature is unchanged, preventing a borderline wrap decision from oscillating between renders and spinning the render queue.
  • A requestAnimationFrame settle loop re-measures once if the row is still overflowing after the first pass, handling cases where action button widths are not ready on first mount.
  • Re-entry while the overflow popover is open is also guarded.

visibilityPolicy refactor

Replaced two overlapping booleans on ShellBarHidableItem with a "normal" | "keepHidden" | "neverHide" discriminated union. A neverHide item stays in the DOM but is still reported in hiddenItemsIds, so consumers can show a compact alternative by handling the hide event.

Content slot priority

Attribute Behavior
data-hide-order="N" Explicit numeric hide priority (lower hides first)
data-never-hide Item never leaves the DOM (still fires hide events)
No attribute Defaults to reverse insertion order (last added hides first)

Empty branding

An empty <ui5-shellbar-branding> (no logo, no title text) now renders nothing: it is removed from layout, tab order, and the accessibility tree, and falls back to the legacy primaryTitle/logo slots. Runtime content changes are detected automatically via invalidateOnChildChange.

Spec-conformance fixes

  • In-bar logo max-height restored to 1.875rem (30px); the 1.5625rem figure applies only to the overflow popover logo
  • In-bar branding right padding restored to 0.5rem
  • Title font updated to --sapFontHeader6Size (was --_ui5_shellbar_menu_button_title_font_size)
  • In-bar title now uses -webkit-line-clamp: 2 instead of white-space: nowrap + text-overflow: ellipsis

Removed

  • _isSBreakPoint property and its sync from ShellBar.onAfterRendering
  • In-bar branding stacking: the branding-stacked hidable item, BRANDING_STACKED priority, and _stacked host attribute with its CSS
  • Fixed max-width on the overflow popover

Testing

Cypress tests cover:

  • Empty branding (renders nothing, excluded from tab order and accessibility tree)
  • Logo-only branding
  • Runtime content changes
  • Branding entry in the overflow popover (two cases in ShellBar.cy.tsx)

Warning

Full Cypress coverage for all overflow scenarios is not yet complete.

@sap-ui5-webcomponents-release

Copy link
Copy Markdown

@PetyaMarkovaBogdanova PetyaMarkovaBogdanova left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Standards
Hard Violations (documented rules). 0

Smells (judgement calls)

Magic number — logoEl.offsetWidth * 2 has no named constant. STACKING_WIDTH_RATIO would reveal intent.
Primitive Obsession — keepHidden: boolean + neverHide?: boolean on ShellBarHidableItem encodes three modes with two booleans; an illegal combination (both true) is representable. A discriminated union visibilityPolicy: "normal" | "keepHidden" | "neverHide" would be cleaner.

Spec

(a) Scope Creep (not in spec) (same as above)
Stacking measurement gate — The spec says the identifier wraps first, then stacks, then overflows. The brandingTitleWouldWrap heuristic (scrollWidth > logoWidth × 2) silently skips stacking for short titles and sends them straight to overflow. The spec shows no such conditional — stacking always precedes overflow.

(b) Implemented but Wrong
brandingOverflowLabel uses textContent instead of the product title.
Spec aria-label: "[ProductIdentifier] Home". The getter reads this.branding[0]?.textContent?.trim(), which returns all slotted text across the whole element (potentially including alt-text from the logo slot in some browsers). It should target only the title text node/slot.

(c) Logo source assumes only.
brandingOverflowLogoSrc does querySelector("[slot='logo']").src. The logo slot accepts SVG elements, which have no .src. An SVG logo produces a silent empty result in the overflow popover.

Also:

Image -> Padding left seems incorrect

Image -> Too long Primary title text wraps outside the overflow, maybe it should truncate?

@github-actions

Copy link
Copy Markdown

👋 Heads-up: dev close is in effect

Thanks for the contribution! This repository is currently in dev close ahead of release 2.28 (scheduled 2026-10-21, UTC). See the release schedule for the full timeline.

This PR appears to introduce public-API changes (detected by diffing the Custom Elements Manifest against the latest published version on npm):

@ui5/webcomponents-fiori

  • ➕ added element: ShellBar
  • ➕ added property: accessibilityAttributes
  • ➕ added method: closeOverflow
  • ➕ added property: disableSearchCollapse
  • ➕ added method: getSearchButtonDomRef
  • ➕ added property: hideSearchButton
  • ➕ added property: logoDomRef
  • ➕ added property: notificationsCount
  • ➕ added property: notificationsDomRef
  • ➕ added property: overflowDomRef
  • ➕ added property: primaryTitle
  • ➕ added property: productSwitchDomRef
  • ➕ added property: profileDomRef
  • ➕ added property: secondaryTitle
  • ➕ added property: showNotifications
  • ➕ added property: showProductSwitch
  • ➕ added property: showSearchField
  • ➕ added event: content-item-visibility-change
  • ➕ added event: logo-click
  • ➕ added event: menu-item-click
  • ➕ added event: notifications-click
  • ➕ added event: product-switch-click
  • ➕ added event: profile-click
  • ➕ added event: search-button-click
  • ➕ added event: search-field-clear
  • ➕ added event: search-field-toggle
  • ➕ added slot: assistant
  • ➕ added slot: branding
  • ➕ added slot: content
  • ➕ added slot: default
  • ➕ added slot: logo
  • ➕ added slot: menuItems
  • ➕ added slot: profile
  • ➕ added slot: searchField
  • ➕ added slot: startButton
  • ➕ added CSS part: root
  • ➕ added attribute: accessibility-attributes
  • ➕ added attribute: disable-search-collapse
  • ➕ added attribute: hide-search-button
  • ➕ added attribute: logo-dom-ref
  • ➕ added attribute: notifications-count
  • ➕ added attribute: notifications-dom-ref
  • ➕ added attribute: overflow-dom-ref
  • ➕ added attribute: primary-title
  • ➕ added attribute: product-switch-dom-ref
  • ➕ added attribute: profile-dom-ref
  • ➕ added attribute: secondary-title
  • ➕ added attribute: show-notifications
  • ➕ added attribute: show-product-switch
  • ➕ added attribute: show-search-field
  • ➕ added element: ShellBarBranding
  • ➕ added property: accessibleName
  • ➕ added property: href
  • ➕ added property: target
  • ➕ added event: click
  • ➕ added slot: default
  • ➕ added slot: logo
  • ➕ added attribute: accessible-name
  • ➕ added attribute: href
  • ➕ added attribute: target

Could you please hold off on merging into main until the release ships? Public-API changes are best landed in the next dev cycle so they don't slip into the release at the last minute. Once the release is out, this PR is good to go.

If this change must ship in the current release, please request a review from one or two members of @UI5/ui5-team-webc so the team can sign off explicitly.

💬 False positive? If you believe this PR doesn't actually change the public API (e.g. only internal refactoring, or an entry the detector mis-attributed), please reply on this thread — your feedback helps us improve the detection during this trial run.

Posted automatically by the Dev Close Notice workflow.

@plamenivanov91

Copy link
Copy Markdown
Contributor

Hello @NakataCode ,

Please fix this issue as part of the overall design:
#14148

Regards,
Plamen

@PetyaMarkovaBogdanova

Copy link
Copy Markdown
Contributor

Two possible concerns:

1. Logo-only branding aria-label — spec says aria-label="Home" for logo-only; implementation returns undefined (no label at all).
2. Identifier >2 lines goes to overflow — spec says it should reflow below the logo, not disappear to overflow.

This branch was previously deployed

1 inactive deployment
netlify-preview — 77d5186e Deployed Nov 4, 2026 by NakataCode via deploy-preview #3665
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.

3 participants