From d4a5c681e959d99be741e42a9b19a42a419489c5 Mon Sep 17 00:00:00 2001 From: ilhan Date: Mon, 25 Mar 2019 22:43:58 +0200 Subject: [PATCH 1/6] feat(ui5-card): fires headerPress event headerPress is now fired on header click or via ENter and Space keys. Focus and active states are implemented upon those actions. --- packages/main/src/Card.hbs | 6 +- packages/main/src/Card.js | 69 +++++++++++++++++++ packages/main/src/themes/base/Card.less | 21 +++++- .../main/src/themes/sap_belize_hcb/Card.less | 3 +- .../sap/ui/webcomponents/main/pages/Card.html | 9 +++ packages/main/test/specs/Card.spec.js | 16 ++++- 6 files changed, 120 insertions(+), 4 deletions(-) diff --git a/packages/main/src/Card.hbs b/packages/main/src/Card.hbs index 78b307e21695..6d9ddc576b6c 100644 --- a/packages/main/src/Card.hbs +++ b/packages/main/src/Card.hbs @@ -1,5 +1,9 @@
controlData}} class="sapFCard"> -
+
{{#if image}} {{/if}} diff --git a/packages/main/src/Card.js b/packages/main/src/Card.js index b6182c3c5e28..cca85ceb5b88 100644 --- a/packages/main/src/Card.js +++ b/packages/main/src/Card.js @@ -3,6 +3,8 @@ import URI from "@ui5/webcomponents-base/src/types/URI"; import Bootstrap from "@ui5/webcomponents-base/src/Bootstrap"; import ShadowDOM from "@ui5/webcomponents-base/src/compatibility/ShadowDOM"; import { isIconURI } from "@ui5/webcomponents-base/src/IconPool"; +import { isSpace, isEnter, } from "@ui5/webcomponents-base/src/events/PseudoEvents"; +import Function from "@ui5/webcomponents-base/src/types/Function"; import CardRenderer from "./build/compiled/CardRenderer.lit"; import Icon from "./Icon"; @@ -82,6 +84,26 @@ const metadata = { type: URI, defaultValue: null, }, + + _headerActive: { + type: Boolean, + }, + + _headerPress: { + type: Function, + }, + }, + events: /** @lends sap.ui.webcomponents.main.Card.prototype */ { + + /** + * Fired when the ui5-card header is pressed + * click/tap or by using the Enter or Space key. + * + * @event + * @public + * @since 0.10.0 + */ + headerPress: {}, }, }; @@ -107,6 +129,12 @@ const metadata = { * @public */ class Card extends WebComponent { + constructor() { + super(); + + this._headerPress = this.headerPress.bind(this); + } + static get metadata() { return metadata; } @@ -125,6 +153,12 @@ class Card extends WebComponent { image, ctr: state, renderIcon: state.icon && !state.image, + classes: { + header: { + "sapFCardHeader" : true, + "sapFCardHeaderActive": state._headerActive, + }, + }, }; } @@ -133,6 +167,41 @@ class Card extends WebComponent { super.define(...params); } + + headerPress(event) { + const click = event.type === "click"; + const keydown = event.type === "keydown"; + const keyup = event.type === "keyup"; + const space = isSpace(event); + const enter = isEnter(event); + + if (click) { + this.fireEvent("headerPress"); + return; + } + + if (enter && keydown) { + this._headerActive = true; + this.fireEvent("headerPress"); + return; + } + + if (enter && keyup) { + this._headerActive = false; + return; + } + + if (space && keydown) { + this._headerActive = true; + event.preventDefault(); + return + } + + if (space && keyup) { + this._headerActive = false; + this.fireEvent("headerPress"); + } + } } Bootstrap.boot().then(_ => { diff --git a/packages/main/src/themes/base/Card.less b/packages/main/src/themes/base/Card.less index c82390f94d7d..229093e7f5fd 100644 --- a/packages/main/src/themes/base/Card.less +++ b/packages/main/src/themes/base/Card.less @@ -9,6 +9,7 @@ @_ui5_card_header_active_bg: #f0f0f0; @_ui5_card_header_hover_bg: lighten(@_ui5_card_header_active_bg, 4); @_ui5_card_header_border_color: darken(@sapUiTileBackground, 20); +@_ui5_card_focus_border_width: 1px; :host(ui5-card) { display: inline-block; @@ -34,6 +35,7 @@ ui5-card { } .sapFCardHeader { + position: relative; display: flex; align-items: flex-start; background: @sapUiTileBackground; @@ -41,7 +43,24 @@ ui5-card { padding: @_ui5_card_content_padding; } -.sapFCardHeader:hover { +.sapFCardHeader:focus { + outline: none; +} + +.sapFCardHeader:focus:before { + content: ""; + position: absolute; + border: @_ui5_card_focus_border_width dotted @sapUiContentFocusColor; + pointer-events: none; + top: 1px; + left: 1px; + right: 1px; + bottom: 1px; +} + +.sapFCardHeader:hover, +.sapFCardHeader.sapFCardHeaderActive { + cursor: pointer; background: @_ui5_card_header_hover_bg; } diff --git a/packages/main/src/themes/sap_belize_hcb/Card.less b/packages/main/src/themes/sap_belize_hcb/Card.less index 5baae7632c6f..99f77ce69bca 100644 --- a/packages/main/src/themes/sap_belize_hcb/Card.less +++ b/packages/main/src/themes/sap_belize_hcb/Card.less @@ -12,4 +12,5 @@ @_ui5_card_header_hover_bg: @sapUiHighlight; @_ui5_card_header_active_bg: @sapUiHighlight; -@_ui5_card_header_border_color: @sapUiTileBorderColor; \ No newline at end of file +@_ui5_card_header_border_color: @sapUiTileBorderColor; +@_ui5_card_focus_border_width: 0.125rem; \ No newline at end of file diff --git a/packages/main/test/sap/ui/webcomponents/main/pages/Card.html b/packages/main/test/sap/ui/webcomponents/main/pages/Card.html index 2c922fbec501..4be6a2d410c6 100644 --- a/packages/main/test/sap/ui/webcomponents/main/pages/Card.html +++ b/packages/main/test/sap/ui/webcomponents/main/pages/Card.html @@ -26,6 +26,7 @@ @@ -38,7 +39,15 @@ AdWords Campaigns Winter Campaign Results + + + \ No newline at end of file diff --git a/packages/main/test/specs/Card.spec.js b/packages/main/test/specs/Card.spec.js index 316c62359ee6..766606d3a0e1 100644 --- a/packages/main/test/specs/Card.spec.js +++ b/packages/main/test/specs/Card.spec.js @@ -1 +1,15 @@ -const assert = require('assert'); \ No newline at end of file +const assert = require('assert'); +describe("Card general interaction", () => { + browser.url("http://localhost:8080/test-resources/sap/ui/webcomponents/main/pages/Card.html"); + + it("fires headerPress upon click, Enter and Space", () => { + const cardHeader = browser.findElementDeep("#card >>> .sapFCardHeader"); + const field = browser.$("#field"); + + cardHeader.click(); + cardHeader.keys("Space"); + cardHeader.keys("Enter"); + + assert.strictEqual(field.getProperty("value"), "3", "headerPress should be called 3 times"); + }); +}); \ No newline at end of file From 6caf75d0bcfc184be5b31abb328f20b3eded699b Mon Sep 17 00:00:00 2001 From: ilhan Date: Mon, 25 Mar 2019 22:46:41 +0200 Subject: [PATCH 2/6] update doc --- packages/main/src/Card.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/main/src/Card.js b/packages/main/src/Card.js index cca85ceb5b88..6645bb8d488b 100644 --- a/packages/main/src/Card.js +++ b/packages/main/src/Card.js @@ -96,8 +96,8 @@ const metadata = { events: /** @lends sap.ui.webcomponents.main.Card.prototype */ { /** - * Fired when the ui5-card header is pressed - * click/tap or by using the Enter or Space key. + * Fired when the ui5-card header is pressed + * by click/tap or by using the Enter or Space key. * * @event * @public From 445b0a7b3a9ca0b2eba8c955867d87dd31bb5491 Mon Sep 17 00:00:00 2001 From: ilhan Date: Mon, 25 Mar 2019 22:46:41 +0200 Subject: [PATCH 3/6] refacctor code --- packages/main/src/Card.js | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/packages/main/src/Card.js b/packages/main/src/Card.js index cca85ceb5b88..86288798ac6e 100644 --- a/packages/main/src/Card.js +++ b/packages/main/src/Card.js @@ -96,8 +96,8 @@ const metadata = { events: /** @lends sap.ui.webcomponents.main.Card.prototype */ { /** - * Fired when the ui5-card header is pressed - * click/tap or by using the Enter or Space key. + * Fired when the ui5-card header is pressed + * by click/tap or by using the Enter or Space key. * * @event * @public @@ -171,36 +171,41 @@ class Card extends WebComponent { headerPress(event) { const click = event.type === "click"; const keydown = event.type === "keydown"; - const keyup = event.type === "keyup"; - const space = isSpace(event); - const enter = isEnter(event); if (click) { this.fireEvent("headerPress"); return; } - if (enter && keydown) { - this._headerActive = true; - this.fireEvent("headerPress"); + if (isEnter(event)) { + this._handleEnter(keydown); return; } - if (enter && keyup) { - this._headerActive = false; - return; + if (isSpace(event)) { + event.preventDefault(); + this._handleSpace(keydown); } + } - if (space && keydown) { + _handleEnter(keydown) { + if (keydown) { this._headerActive = true; - event.preventDefault(); - return + this.fireEvent("headerPress"); + return; } - if (space && keyup) { - this._headerActive = false; - this.fireEvent("headerPress"); + this._headerActive = false; + } + + _handleSpace(keydown) { + if (keydown) { + this._headerActive = true; + return; } + + this._headerActive = false; + this.fireEvent("headerPress"); } } From 83a07d46ba01ab80d29c68db02a3fee88a533f67 Mon Sep 17 00:00:00 2001 From: ilhan Date: Mon, 25 Mar 2019 22:59:17 +0200 Subject: [PATCH 4/6] correct active state class --- packages/main/src/Card.js | 12 ++++-------- packages/main/src/themes/base/Card.less | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/main/src/Card.js b/packages/main/src/Card.js index 86288798ac6e..655abe9d59c4 100644 --- a/packages/main/src/Card.js +++ b/packages/main/src/Card.js @@ -190,22 +190,18 @@ class Card extends WebComponent { _handleEnter(keydown) { if (keydown) { - this._headerActive = true; this.fireEvent("headerPress"); - return; } - this._headerActive = false; + this._headerActive = keydown; } _handleSpace(keydown) { - if (keydown) { - this._headerActive = true; - return; + if (!keydown) { + this.fireEvent("headerPress"); } - this._headerActive = false; - this.fireEvent("headerPress"); + this._headerActive = keydown; } } diff --git a/packages/main/src/themes/base/Card.less b/packages/main/src/themes/base/Card.less index 229093e7f5fd..a3e3dbdfb892 100644 --- a/packages/main/src/themes/base/Card.less +++ b/packages/main/src/themes/base/Card.less @@ -58,12 +58,12 @@ ui5-card { bottom: 1px; } -.sapFCardHeader:hover, -.sapFCardHeader.sapFCardHeaderActive { +.sapFCardHeader:hover { cursor: pointer; background: @_ui5_card_header_hover_bg; } +.sapFCardHeader.sapFCardHeaderActive, .sapFCardHeader:active { background: @_ui5_card_header_active_bg; } From a39f9ac05168a16e45959ff4c223464cff720cb7 Mon Sep 17 00:00:00 2001 From: ilhan Date: Mon, 25 Mar 2019 23:03:25 +0200 Subject: [PATCH 5/6] fix eslint erros --- packages/main/src/Card.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/main/src/Card.js b/packages/main/src/Card.js index 655abe9d59c4..748c3dbde9f2 100644 --- a/packages/main/src/Card.js +++ b/packages/main/src/Card.js @@ -3,7 +3,7 @@ import URI from "@ui5/webcomponents-base/src/types/URI"; import Bootstrap from "@ui5/webcomponents-base/src/Bootstrap"; import ShadowDOM from "@ui5/webcomponents-base/src/compatibility/ShadowDOM"; import { isIconURI } from "@ui5/webcomponents-base/src/IconPool"; -import { isSpace, isEnter, } from "@ui5/webcomponents-base/src/events/PseudoEvents"; +import { isSpace, isEnter } from "@ui5/webcomponents-base/src/events/PseudoEvents"; import Function from "@ui5/webcomponents-base/src/types/Function"; import CardRenderer from "./build/compiled/CardRenderer.lit"; import Icon from "./Icon"; @@ -96,7 +96,7 @@ const metadata = { events: /** @lends sap.ui.webcomponents.main.Card.prototype */ { /** - * Fired when the ui5-card header is pressed + * Fired when the ui5-card header is pressed * by click/tap or by using the Enter or Space key. * * @event @@ -155,7 +155,7 @@ class Card extends WebComponent { renderIcon: state.icon && !state.image, classes: { header: { - "sapFCardHeader" : true, + "sapFCardHeader": true, "sapFCardHeaderActive": state._headerActive, }, }, From 6d13152f8a3e659abf24298093625a7b63d6fd9a Mon Sep 17 00:00:00 2001 From: ilhan Date: Tue, 26 Mar 2019 13:43:34 +0200 Subject: [PATCH 6/6] split click, keydown and keyup handlers --- packages/main/src/Card.hbs | 6 ++--- packages/main/src/Card.js | 50 ++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/packages/main/src/Card.hbs b/packages/main/src/Card.hbs index 6d9ddc576b6c..efc14dfc4563 100644 --- a/packages/main/src/Card.hbs +++ b/packages/main/src/Card.hbs @@ -1,8 +1,8 @@
controlData}} class="sapFCard">
{{#if image}} diff --git a/packages/main/src/Card.js b/packages/main/src/Card.js index 748c3dbde9f2..04f31b987d39 100644 --- a/packages/main/src/Card.js +++ b/packages/main/src/Card.js @@ -89,7 +89,15 @@ const metadata = { type: Boolean, }, - _headerPress: { + _headerClick: { + type: Function, + }, + + _headerKeydown: { + type: Function, + }, + + _headerKeyup: { type: Function, }, }, @@ -132,7 +140,9 @@ class Card extends WebComponent { constructor() { super(); - this._headerPress = this.headerPress.bind(this); + this._headerClick = this.headerClick.bind(this); + this._headerKeydown = this.headerKeydown.bind(this); + this._headerKeyup = this.headerKeyup.bind(this); } static get metadata() { @@ -168,40 +178,34 @@ class Card extends WebComponent { super.define(...params); } - headerPress(event) { - const click = event.type === "click"; - const keydown = event.type === "keydown"; + headerClick() { + this.fireEvent("headerPress"); + } - if (click) { - this.fireEvent("headerPress"); - return; - } + headerKeydown(event) { + const enter = isEnter(event); + const space = isSpace(event); - if (isEnter(event)) { - this._handleEnter(keydown); + this._headerActive = enter || space; + + if (enter) { + this.fireEvent("headerPress"); return; } - if (isSpace(event)) { + if (space) { event.preventDefault(); - this._handleSpace(keydown); } } - _handleEnter(keydown) { - if (keydown) { - this.fireEvent("headerPress"); - } + headerKeyup(event) { + const space = isSpace(event); - this._headerActive = keydown; - } + this._headerActive = false; - _handleSpace(keydown) { - if (!keydown) { + if (space) { this.fireEvent("headerPress"); } - - this._headerActive = keydown; } }