Skip to content

Commit

Permalink
feat(ui5-dynamic-page): keyboard handling (#7990)
Browse files Browse the repository at this point in the history
* feat(ui5-dynamic-page): keyboard handling

* feat(ui5-dynamic-page): add focus span

* fix: add expand and focus on title click

---------

Co-authored-by: Dobrin Dimchev <[email protected]>
  • Loading branch information
kineticjs and dobrinyonkov authored Dec 18, 2023
1 parent 4b72ed9 commit f379b8e
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 8 deletions.
3 changes: 2 additions & 1 deletion packages/fiori/src/DynamicPage.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<div class="{{classes.root}}">
<div class="{{classes.scrollContainer}}"
@scroll="{{snapOnScroll}}">
<div class="{{classes.headerWrapper}}">
<div class="{{classes.headerWrapper}}"
@ui5-_toggle-title={{onToggleTitle}}>
<slot name="titleArea"></slot>
{{#if headerInTitle}}
<slot name="headerArea"></slot>
Expand Down
29 changes: 24 additions & 5 deletions packages/fiori/src/DynamicPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import customElement from "@ui5/webcomponents-base/dist/decorators/customElement
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import { renderFinished } from "@ui5/webcomponents-base/dist/Render.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import type { ResizeObserverCallback } from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import MediaRange from "@ui5/webcomponents-base/dist/MediaRange.js";
Expand Down Expand Up @@ -137,6 +138,10 @@ class DynamicPage extends UI5Element {
return this.getDomRef()?.querySelector(".ui5-dynamic-page-scroll-container");
}

get headerActions(): DynamicPageHeaderActions | null | undefined {
return this.getDomRef()?.querySelector("ui5-dynamic-page-header-actions");
}

get actionsInTitle(): boolean {
return this.headerSnapped || this.showHeaderInStickArea || this.headerPinned;
}
Expand Down Expand Up @@ -176,7 +181,25 @@ class DynamicPage extends UI5Element {
}, SCROLL_DEBOUNCE_RATE);
}

onExpandClick() {
async onExpandClick() {
this._toggleHeader();
await renderFinished();
this.headerActions?.focusExpandButton();
}

async onPinClick() {
this.headerPinned = !this.headerPinned;
await renderFinished();
this.headerActions?.focusPinButton();
}

async onToggleTitle() {
this._toggleHeader();
await renderFinished();
this.dynamicPageTitle!.focus();
}

_toggleHeader() {
this.showHeaderInStickArea = !this.showHeaderInStickArea;
this.headerSnapped = !this.headerSnapped;
if (this.dynamicPageTitle) {
Expand All @@ -187,10 +210,6 @@ class DynamicPage extends UI5Element {
this.headerPinned = false;
}

onPinClick() {
this.headerPinned = !this.headerPinned;
}

///

_debounce(fn: () => void, delay: number) {
Expand Down
4 changes: 2 additions & 2 deletions packages/fiori/src/DynamicPageHeaderActions.hbs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<div class="{{classes.root}}">
<div class="{{classes.wrapper}}">
<ui5-button @click="{{onExpandClick}}" icon="{{arrowButtonIcon}}" class="ui5-dynamic-page-header-action"></ui5-button>
<ui5-button @click="{{onExpandClick}}" icon="{{arrowButtonIcon}}" class="ui5-dynamic-page-header-action ui5-dynamic-page-header-action-expand"></ui5-button>
{{#unless snapped}}
<ui5-button @click="{{onPinClick}}" icon="{{pinButtonIcon}}" class="ui5-dynamic-page-header-action"></ui5-button>
<ui5-button @click="{{onPinClick}}" icon="{{pinButtonIcon}}" class="ui5-dynamic-page-header-action ui5-dynamic-page-header-action-pin"></ui5-button>
{{/unless}}
</div>
</div>
16 changes: 16 additions & 0 deletions packages/fiori/src/DynamicPageHeaderActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ class DynamicPageHeaderActions extends UI5Element {
return this.pinned ? "pushpin-on" : "pushpin-off";
}

get expandButton(): HTMLElement | null | undefined {
return this.getDomRef()?.querySelector(".ui5-dynamic-page-header-action-expand");
}

get pinButton(): HTMLElement | null | undefined {
return this.getDomRef()?.querySelector(".ui5-dynamic-page-header-action-pin");
}

focusExpandButton() {
this.expandButton?.focus();
}

focusPinButton() {
this.pinButton?.focus();
}

onExpandClick() {
this.fireEvent("expand-button-click");
}
Expand Down
9 changes: 9 additions & 0 deletions packages/fiori/src/DynamicPageTitle.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
<div class="{{classes.root}}">
<span class="{{classes.focusArea}}"
data-sap-focus-ref
tabindex="0"
@click="{{_onclick}}"
@focusout={{_onfocusout}}
@focusin={{_onfocusin}}
@keydown="{{_onkeydown}}">
</span>

<div class="{{classes.topArea}}">
{{#if hasBreadcrumb}}
<div class="{{classes.breadcrumbs}}">
Expand Down
31 changes: 31 additions & 0 deletions packages/fiori/src/DynamicPageTitle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import type { ResizeObserverCallback } from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import { isEnter, isSpace } from "@ui5/webcomponents-base/dist/Keys.js";
import type Toolbar from "@ui5/webcomponents/dist/Toolbar.js";
import type { ToolbarMinWidthChangeEventDetail } from "@ui5/webcomponents/dist/Toolbar.js";

Expand All @@ -30,6 +31,7 @@ import DynamicPageTitleCss from "./generated/themes/DynamicPageTitle.css.js";
*/
@customElement({
tag: "ui5-dynamic-page-title",
fastNavigation: true,
renderer: litRender,
styles: DynamicPageTitleCss,
template: DynamicPageTitleTemplate,
Expand Down Expand Up @@ -75,6 +77,13 @@ class DynamicPageTitle extends UI5Element {
@property({ type: Boolean })
mobileNavigationActions!: boolean;

/**
* Indicates if the elements is on focus
* @private
*/
@property({ type: Boolean })
focused!: boolean;

_handleResize: ResizeObserverCallback;
minContentWidth?: number;
minActionsWidth?: number;
Expand Down Expand Up @@ -115,6 +124,9 @@ class DynamicPageTitle extends UI5Element {
root: {
"ui5-dynamic-page-title-root": true,
},
focusArea: {
"ui5-dynamic-page-title-focus-area": true,
},
topArea: {
"ui5-dynamic-page-title--top-area": true,
},
Expand Down Expand Up @@ -185,6 +197,25 @@ class DynamicPageTitle extends UI5Element {
this.minActionsWidth = event.detail.minWidth;
}
}

_onfocusout() {
this.focused = false;
}

_onfocusin() {
this.focused = true;
}

_onclick() {
this.fireEvent("_toggle-title");
}

_onkeydown(e: KeyboardEvent) {
if (isEnter(e) || isSpace(e)) {
e.preventDefault();
this.fireEvent("_toggle-title");
}
}
}

DynamicPageTitle.define();
Expand Down
16 changes: 16 additions & 0 deletions packages/fiori/src/themes/DynamicPageTitle.css
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,19 @@
.ui5-dynamic-page-title--breadcrumbs {
width: 100%;
}

/* focus */
:host([focused]) {
/* separate change adds proper parameters */
outline: 0.0625rem dotted black;
outline-offset: -0.0625rem;
}

.ui5-dynamic-page-title-focus-area {
outline: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

0 comments on commit f379b8e

Please sign in to comment.