Skip to content

Commit

Permalink
feat(ui5-dynamic-page-title): add snapped title for mobile devices
Browse files Browse the repository at this point in the history
- Introduced `snappedTitleOnMobile` property to display a simplified
  title on mobile when the header is snapped.
- Added `snappedTitleOnMobileText` to define the text for the
  mobile-specific snapped title.
- This feature optimizes title display on small screens, improving
  mobile usability.
- Clicking the snapped title on mobile expands the header.
- On non-mobile devices, the standard title is displayed, ignoring the
  mobile-specific title.
  • Loading branch information
kgogov committed Sep 19, 2024
1 parent 0b5a320 commit 4c95948
Show file tree
Hide file tree
Showing 9 changed files with 808 additions and 400 deletions.
30 changes: 16 additions & 14 deletions packages/fiori/src/DynamicPage.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
{{> header-actions}}
{{/if}}
</header>

{{#if headerInContent}}
<slot tabindex="{{headerTabIndex}}" ?aria-hidden="{{headerAriaHidden}}" name="headerArea"></slot>
{{/if}}
Expand All @@ -42,17 +42,19 @@
</div>

{{#*inline "header-actions"}}
{{#if hasHeading}}
<ui5-dynamic-page-header-actions
?snapped="{{headerSnapped}}"
?pinned="{{headerPinned}}"
?hide-pin-button="{{hidePinButton}}"
.accessibilityAttributes="{{_accAttributesForHeaderActions}}"
@ui5-expand-button-click={{onExpandClick}}
@ui5-pin-button-click={{onPinClick}}
@ui5-expand-button-hover-in={{onExpandHoverIn}}
@ui5-expand-button-hover-out={{onExpandHoverOut}}
>
</ui5-dynamic-page-header-actions>
{{/if}}
{{#unless hasSnappedTitleOnMobile}}
{{#if hasHeading}}
<ui5-dynamic-page-header-actions
?snapped="{{headerSnapped}}"
?pinned="{{headerPinned}}"
?hide-pin-button="{{hidePinButton}}"
.accessibilityAttributes="{{_accAttributesForHeaderActions}}"
@ui5-expand-button-click={{onExpandClick}}
@ui5-pin-button-click={{onPinClick}}
@ui5-expand-button-hover-in={{onExpandHoverIn}}
@ui5-expand-button-hover-out={{onExpandHoverOut}}
>
</ui5-dynamic-page-header-actions>
{{/if}}
{{/unless}}
{{/inline}}
13 changes: 13 additions & 0 deletions packages/fiori/src/DynamicPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import announce from "@ui5/webcomponents-base/dist/util/InvisibleMessage.js";
import InvisibleMessageMode from "@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js";
import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";

import debounce from "@ui5/webcomponents-base/dist/util/debounce.js";

Expand Down Expand Up @@ -223,6 +224,7 @@ class DynamicPage extends UI5Element {
if (this.dynamicPageTitle) {
this.dynamicPageTitle.snapped = this._headerSnapped;
this.dynamicPageTitle.interactive = this.hasHeading;
this.dynamicPageTitle.showSnappedTitleOnMobile = this.hasSnappedTitleOnMobile;
}
}

Expand Down Expand Up @@ -278,6 +280,12 @@ class DynamicPage extends UI5Element {
return this._headerSnapped;
}

get hasSnappedTitleOnMobile() {
return !!(this.dynamicPageTitle?.snappedTitleOnMobile
&& this.headerSnapped
&& (this.mediaRange === "S" || (this.mediaRange === "M" && isPhone())));
}

/**
* Defines if the header is snapped.
*
Expand Down Expand Up @@ -327,6 +335,11 @@ class DynamicPage extends UI5Element {
this.fireEvent("title-toggle");
await renderFinished();
this.headerActions?.focusExpandButton();

if (this.hasSnappedTitleOnMobile) {
this.dynamicPageTitle?.focus();
}

announce(this._headerLabel, InvisibleMessageMode.Polite);
}

Expand Down
61 changes: 35 additions & 26 deletions packages/fiori/src/DynamicPageTitle.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,48 @@
aria-labelledby="{{_ariaLabelledBy}}"
aria-describedby="{{_id}}-toggle-description">
</span>
<div class="ui5-dynamic-page-title--top-area">
<slot name="breadcrumbs"></slot>

{{#if mobileNavigationActions}}
<slot name="navigationBar"></slot>
{{/if}}
</div>
{{#if showSnappedTitleOnMobile}}
<div id="{{_id}}-heading" class="ui5-dynamic-page--snapped-title-on-mobile">
<ui5-title size="H4">{{snappedTitleOnMobileText}}</ui5-title>
<ui5-icon name="slim-arrow-down" mode="Decorative"></ui5-icon>
</div>
{{else}}
<div class="ui5-dynamic-page-title--top-area">
<slot name="breadcrumbs"></slot>

<div class="ui5-dynamic-page-title--wrapper"
@ui5-_min-content-width-change={{onMinContentWidthChange}}>
<div id="{{_id}}-heading" class="ui5-dynamic-page-title--heading">
<slot name="{{headingSlotName}}"></slot>
{{#if mobileNavigationActions}}
<slot name="navigationBar"></slot>
{{/if}}
</div>

{{#if hasContent}}
<div class="ui5-dynamic-page-title--content"
style="{{styles.content}}">
<slot></slot>
<div class="ui5-dynamic-page-title--wrapper"
@ui5-_min-content-width-change={{onMinContentWidthChange}}>
<div id="{{_id}}-heading" class="ui5-dynamic-page-title--heading">
<slot name="{{headingSlotName}}"></slot>
</div>
{{/if}}

<div class="ui5-dynamic-page-title--actions"
style="{{styles.actions}}">
<slot name="actionsBar"></slot>
{{#unless mobileNavigationActions}}
{{#if _needsSeparator}}
<div class="ui5-dynamic-page-title--actions-separator"></div>
{{/if}}
<slot name="navigationBar"></slot>
{{/unless}}
{{#if hasContent}}
<div class="ui5-dynamic-page-title--content"
style="{{styles.content}}">
<slot></slot>
</div>
{{/if}}

<div class="ui5-dynamic-page-title--actions"
style="{{styles.actions}}">
<slot name="actionsBar"></slot>
{{#unless mobileNavigationActions}}
{{#if _needsSeparator}}
<div class="ui5-dynamic-page-title--actions-separator"></div>
{{/if}}
<slot name="navigationBar"></slot>
{{/unless}}
</div>
</div>
</div>

<slot name="{{subheadingSlotName}}"></slot>
<slot name="{{subheadingSlotName}}"></slot>
{{/if}}

<span id="{{_id}}-toggle-description" class="ui5-hidden-text">{{_ariaDescribedbyText}}</span>
</div>
38 changes: 38 additions & 0 deletions packages/fiori/src/DynamicPageTitle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import type Toolbar from "@ui5/webcomponents/dist/Toolbar.js";
import type { ToolbarMinWidthChangeEventDetail } from "@ui5/webcomponents/dist/Toolbar.js";
import ToolbarItemOverflowBehavior from "@ui5/webcomponents/dist/types/ToolbarItemOverflowBehavior.js";
import { isDesktop } from "@ui5/webcomponents-base/dist/Device.js";
import Icon from "@ui5/webcomponents/dist/Icon.js";
import Title from "@ui5/webcomponents/dist/Title.js";

// Template
import DynamicPageTitleTemplate from "./generated/templates/DynamicPageTitleTemplate.lit.js";
Expand Down Expand Up @@ -63,6 +65,7 @@ import {
renderer: litRender,
styles: DynamicPageTitleCss,
template: DynamicPageTitleTemplate,
dependencies: [Title, Icon],
})

/**
Expand All @@ -81,6 +84,41 @@ class DynamicPageTitle extends UI5Element {
@property({ type: Boolean })
snapped = false;

/**
* Defines if snapped title on mobile is enabled.
*
* Using this property enables you to provide a simple, single-line title that takes less space
* on the smaller phone screens when the DynamicPageHeader is in its collapsed (snapped) state.
*
* **Note:** The content set in `snappedTitleOnMobileText` overrides all other content set in the `DynamicPageTitle` slots
* and is only visible on phone screen sizes when the header is in snapped state.
*
* @public
*/
@property({ type: Boolean })
snappedTitleOnMobile = false;

/**
* Defines the text of the snapped title on mobile.
*
* The only content that is displayed in the DynamicPageTitle when it is viewed on a mobile device
* and the DynamicPageHeader is in collapsed (snapped) state.
*
* **Note:** This property takes effect if the `snappedTitleOnMobile` property is set to `true`.
*
* @public
*/
@property({ type: String })
snappedTitleOnMobileText = "";

/**
* Defines if snapped title on mobile is shown.
*
* @private
*/
@property({ type: Boolean, noAttribute: true })
showSnappedTitleOnMobile = false;

/**
* Defines if the mobileNavigationActions are shown.
*
Expand Down
7 changes: 7 additions & 0 deletions packages/fiori/src/themes/DynamicPage.css
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,11 @@

:host([media-range="XL"]) ::slotted([slot="headerArea"]) {
padding: var(--_ui5_dynamic_page_header_padding_XL);
}

/* snappedTitleOnMobile */
:host([_header-snapped]) ::slotted([slot="headerArea"]) {
height: 0;
padding: 0;
visibility: hidden;
}
14 changes: 14 additions & 0 deletions packages/fiori/src/themes/DynamicPageTitle.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
box-shadow: var(--sapContent_HeaderShadow);
}

:host([snapped][snapped-title-on-mobile]) {
min-height: var(--_ui5_dynamic_page_snapped_title_on_mobile_min_height);
}

/* breadcrumbs */
::slotted([ui5-breadcrumbs][slot="breadcrumbs"]) {
padding: var(--_ui5_dynamic_page_title_breadcrumbs_padding_top) 0
Expand Down Expand Up @@ -88,6 +92,16 @@
min-width: 1px;
}

.ui5-dynamic-page--snapped-title-on-mobile {
display: flex;
justify-content: space-between;
align-items: center;

[ui5-title] {
line-height: var(--_ui5_dynamic_page_snapped_title_on_mobile_line_height);
}
}

.ui5-dynamic-page-title--content {
padding: 0 0 0 1rem;
flex-shrink: 1.6;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@

--_ui5_dynamic_page_title_hover_background: var(--sapObjectHeader_Hover_Background);

--_ui5_dynamic_page_snapped_title_on_mobile_line_height: 2rem;
--_ui5_dynamic_page_snapped_title_on_mobile_min_height: 2rem;
}
Loading

0 comments on commit 4c95948

Please sign in to comment.