Skip to content

Commit 8fbc626

Browse files
committed
feat(ui5-dynamic-page-title): add snapped title for mobile devices
- 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.
1 parent 0b5a320 commit 8fbc626

10 files changed

+792
-402
lines changed

packages/fiori/src/DynamicPage.hbs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
{{> header-actions}}
1818
{{/if}}
1919
</header>
20-
20+
2121
{{#if headerInContent}}
2222
<slot tabindex="{{headerTabIndex}}" ?aria-hidden="{{headerAriaHidden}}" name="headerArea"></slot>
2323
{{/if}}
@@ -42,17 +42,19 @@
4242
</div>
4343

4444
{{#*inline "header-actions"}}
45-
{{#if hasHeading}}
46-
<ui5-dynamic-page-header-actions
47-
?snapped="{{headerSnapped}}"
48-
?pinned="{{headerPinned}}"
49-
?hide-pin-button="{{hidePinButton}}"
50-
.accessibilityAttributes="{{_accAttributesForHeaderActions}}"
51-
@ui5-expand-button-click={{onExpandClick}}
52-
@ui5-pin-button-click={{onPinClick}}
53-
@ui5-expand-button-hover-in={{onExpandHoverIn}}
54-
@ui5-expand-button-hover-out={{onExpandHoverOut}}
55-
>
56-
</ui5-dynamic-page-header-actions>
57-
{{/if}}
45+
{{#unless hasSnappedTitleOnMobile}}
46+
{{#if hasHeading}}
47+
<ui5-dynamic-page-header-actions
48+
?snapped="{{headerSnapped}}"
49+
?pinned="{{headerPinned}}"
50+
?hide-pin-button="{{hidePinButton}}"
51+
.accessibilityAttributes="{{_accAttributesForHeaderActions}}"
52+
@ui5-expand-button-click={{onExpandClick}}
53+
@ui5-pin-button-click={{onPinClick}}
54+
@ui5-expand-button-hover-in={{onExpandHoverIn}}
55+
@ui5-expand-button-hover-out={{onExpandHoverOut}}
56+
>
57+
</ui5-dynamic-page-header-actions>
58+
{{/if}}
59+
{{/unless}}
5860
{{/inline}}

packages/fiori/src/DynamicPage.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import announce from "@ui5/webcomponents-base/dist/util/InvisibleMessage.js";
1313
import InvisibleMessageMode from "@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js";
1414
import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
1515
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
16+
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
1617

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

@@ -278,6 +279,12 @@ class DynamicPage extends UI5Element {
278279
return this._headerSnapped;
279280
}
280281

282+
get hasSnappedTitleOnMobile() {
283+
return this.headerSnapped
284+
&& (this.dynamicPageTitle?.snappedTitleOnMobile ?? false)
285+
&& isPhone();
286+
}
287+
281288
/**
282289
* Defines if the header is snapped.
283290
*
@@ -327,6 +334,11 @@ class DynamicPage extends UI5Element {
327334
this.fireEvent("title-toggle");
328335
await renderFinished();
329336
this.headerActions?.focusExpandButton();
337+
338+
if (this.hasSnappedTitleOnMobile) {
339+
this.dynamicPageTitle?.focus();
340+
}
341+
330342
announce(this._headerLabel, InvisibleMessageMode.Polite);
331343
}
332344

@@ -374,7 +386,7 @@ class DynamicPage extends UI5Element {
374386
}
375387

376388
updateMediaRange() {
377-
this.mediaRange = MediaRange.getCurrentRange(MediaRange.RANGESETS.RANGE_4STEPS, this.getDomRef()!.offsetWidth);
389+
this.mediaRange = MediaRange.getCurrentRange(MediaRange.RANGESETS.RANGE_4STEPS, this.getDomRef()?.offsetWidth);
378390
}
379391
}
380392

packages/fiori/src/DynamicPageTitle.hbs

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,48 @@
99
aria-labelledby="{{_ariaLabelledBy}}"
1010
aria-describedby="{{_id}}-toggle-description">
1111
</span>
12-
<div class="ui5-dynamic-page-title--top-area">
13-
<slot name="breadcrumbs"></slot>
1412

15-
{{#if mobileNavigationActions}}
16-
<slot name="navigationBar"></slot>
17-
{{/if}}
18-
</div>
13+
{{#if hasSnappedTitleOnMobile}}
14+
<div id="{{_id}}-heading" class="ui5-dynamic-page--snapped-title-on-mobile">
15+
<ui5-title size="H4">{{snappedTitleOnMobileText}}</ui5-title>
16+
<ui5-icon name="slim-arrow-down" mode="Decorative"></ui5-icon>
17+
</div>
18+
{{else}}
19+
<div class="ui5-dynamic-page-title--top-area">
20+
<slot name="breadcrumbs"></slot>
1921

20-
<div class="ui5-dynamic-page-title--wrapper"
21-
@ui5-_min-content-width-change={{onMinContentWidthChange}}>
22-
<div id="{{_id}}-heading" class="ui5-dynamic-page-title--heading">
23-
<slot name="{{headingSlotName}}"></slot>
22+
{{#if mobileNavigationActions}}
23+
<slot name="navigationBar"></slot>
24+
{{/if}}
2425
</div>
2526

26-
{{#if hasContent}}
27-
<div class="ui5-dynamic-page-title--content"
28-
style="{{styles.content}}">
29-
<slot></slot>
27+
<div class="ui5-dynamic-page-title--wrapper"
28+
@ui5-_min-content-width-change={{onMinContentWidthChange}}>
29+
<div id="{{_id}}-heading" class="ui5-dynamic-page-title--heading">
30+
<slot name="{{headingSlotName}}"></slot>
3031
</div>
31-
{{/if}}
3232

33-
<div class="ui5-dynamic-page-title--actions"
34-
style="{{styles.actions}}">
35-
<slot name="actionsBar"></slot>
36-
{{#unless mobileNavigationActions}}
37-
{{#if _needsSeparator}}
38-
<div class="ui5-dynamic-page-title--actions-separator"></div>
39-
{{/if}}
40-
<slot name="navigationBar"></slot>
41-
{{/unless}}
33+
{{#if hasContent}}
34+
<div class="ui5-dynamic-page-title--content"
35+
style="{{styles.content}}">
36+
<slot></slot>
37+
</div>
38+
{{/if}}
39+
40+
<div class="ui5-dynamic-page-title--actions"
41+
style="{{styles.actions}}">
42+
<slot name="actionsBar"></slot>
43+
{{#unless mobileNavigationActions}}
44+
{{#if _needsSeparator}}
45+
<div class="ui5-dynamic-page-title--actions-separator"></div>
46+
{{/if}}
47+
<slot name="navigationBar"></slot>
48+
{{/unless}}
49+
</div>
4250
</div>
43-
</div>
4451

45-
<slot name="{{subheadingSlotName}}"></slot>
52+
<slot name="{{subheadingSlotName}}"></slot>
53+
{{/if}}
54+
4655
<span id="{{_id}}-toggle-description" class="ui5-hidden-text">{{_ariaDescribedbyText}}</span>
4756
</div>

packages/fiori/src/DynamicPageTitle.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import { isEnter, isSpace } from "@ui5/webcomponents-base/dist/Keys.js";
1212
import type Toolbar from "@ui5/webcomponents/dist/Toolbar.js";
1313
import type { ToolbarMinWidthChangeEventDetail } from "@ui5/webcomponents/dist/Toolbar.js";
1414
import ToolbarItemOverflowBehavior from "@ui5/webcomponents/dist/types/ToolbarItemOverflowBehavior.js";
15-
import { isDesktop } from "@ui5/webcomponents-base/dist/Device.js";
15+
import { isDesktop, isPhone } from "@ui5/webcomponents-base/dist/Device.js";
16+
import Icon from "@ui5/webcomponents/dist/Icon.js";
17+
import Title from "@ui5/webcomponents/dist/Title.js";
1618

1719
// Template
1820
import DynamicPageTitleTemplate from "./generated/templates/DynamicPageTitleTemplate.lit.js";
@@ -63,6 +65,7 @@ import {
6365
renderer: litRender,
6466
styles: DynamicPageTitleCss,
6567
template: DynamicPageTitleTemplate,
68+
dependencies: [Title, Icon],
6669
})
6770

6871
/**
@@ -81,6 +84,33 @@ class DynamicPageTitle extends UI5Element {
8184
@property({ type: Boolean })
8285
snapped = false;
8386

87+
/**
88+
* Defines if snapped title on mobile is enabled.
89+
*
90+
* Using this property enables you to provide a simple, single-line title that takes less space
91+
* on the smaller phone screens when the DynamicPageHeader is in its collapsed (snapped) state.
92+
*
93+
* **Note:** The content set in `snappedTitleOnMobileText` overrides all other content set in the `DynamicPageTitle` slots
94+
* and is only visible on phone screen sizes when the header is in snapped state.
95+
*
96+
* @public
97+
*/
98+
@property({ type: Boolean })
99+
snappedTitleOnMobile = false;
100+
101+
/**
102+
* Defines the text of the snapped title on mobile.
103+
*
104+
* The only content that is displayed in the DynamicPageTitle when it is viewed on a mobile device
105+
* and the DynamicPageHeader is in collapsed (snapped) state.
106+
*
107+
* **Note:** This property takes effect if the `snappedTitleOnMobile` property is set to `true`.
108+
*
109+
* @public
110+
*/
111+
@property({ type: String })
112+
snappedTitleOnMobileText = "";
113+
84114
/**
85115
* Defines if the mobileNavigationActions are shown.
86116
*
@@ -244,6 +274,12 @@ class DynamicPageTitle extends UI5Element {
244274
return this.interactive ? "0" : undefined;
245275
}
246276

277+
get hasSnappedTitleOnMobile() {
278+
return this.snapped
279+
&& (this.snappedTitleOnMobile ?? false)
280+
&& isPhone();
281+
}
282+
247283
get _headerExpanded() {
248284
return !this.snapped;
249285
}

packages/fiori/src/themes/DynamicPage.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,11 @@
126126

127127
:host([media-range="XL"]) ::slotted([slot="headerArea"]) {
128128
padding: var(--_ui5_dynamic_page_header_padding_XL);
129+
}
130+
131+
/* snappedTitleOnMobile */
132+
:host([_header-snapped]) ::slotted([slot="headerArea"]) {
133+
height: 0;
134+
padding: 0;
135+
visibility: hidden;
129136
}

packages/fiori/src/themes/DynamicPageTitle.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
box-shadow: var(--sapContent_HeaderShadow);
3636
}
3737

38+
:host([snapped][snapped-title-on-mobile]) {
39+
min-height: var(--_ui5_dynamic_page_snapped_title_on_mobile_min_height);
40+
}
41+
3842
/* breadcrumbs */
3943
::slotted([ui5-breadcrumbs][slot="breadcrumbs"]) {
4044
padding: var(--_ui5_dynamic_page_title_breadcrumbs_padding_top) 0
@@ -88,6 +92,17 @@
8892
min-width: 1px;
8993
}
9094

95+
.ui5-dynamic-page--snapped-title-on-mobile {
96+
display: flex;
97+
justify-content: space-between;
98+
align-items: center;
99+
pointer-events: none;
100+
101+
[ui5-title] {
102+
line-height: var(--_ui5_dynamic_page_snapped_title_on_mobile_line_height);
103+
}
104+
}
105+
91106
.ui5-dynamic-page-title--content {
92107
padding: 0 0 0 1rem;
93108
flex-shrink: 1.6;

packages/fiori/src/themes/base/DynamicPageTitle-parameters.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@
1616

1717
--_ui5_dynamic_page_title_hover_background: var(--sapObjectHeader_Hover_Background);
1818

19+
--_ui5_dynamic_page_snapped_title_on_mobile_line_height: 2rem;
20+
--_ui5_dynamic_page_snapped_title_on_mobile_min_height: 2rem;
1921
}

0 commit comments

Comments
 (0)