Skip to content

Commit c5c1786

Browse files
authoredMar 19, 2019
feat(ui5-panel): make the header clickable (#204)
1 parent a98f544 commit c5c1786

File tree

8 files changed

+119
-18
lines changed

8 files changed

+119
-18
lines changed
 

‎packages/main/src/Panel.hbs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
{{#if ctr.fixed}}
99
{{> header}}
1010
{{else}}
11-
<header class="{{classes.header}}">
11+
<header @click="{{ctr._header.press}}" class="{{classes.header}}" tabindex="{{headerTabIndex}}">
1212
<ui5-icon
1313
class="{{classes.icon}}"
1414
src="{{ctr._icon.src}}"
1515
title="{{ctr._icon.title}}"
16-
tabindex="0"
16+
tabindex="{{iconTabIndex}}"
1717
aria-expanded="{{expanded}}"
1818
aria-labelledby="{{ariaLabelledBy}}"
1919
@press="{{ctr._icon.press}}"

‎packages/main/src/Panel.js

+41-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { getIconURI } from "@ui5/webcomponents-base/src/sap/ui/webcomponents/bas
44
import slideDown from "@ui5/webcomponents-base/src/sap/ui/webcomponents/base/animations/slideDown";
55
import slideUp from "@ui5/webcomponents-base/src/sap/ui/webcomponents/base/animations/slideUp";
66
import ShadowDOM from "@ui5/webcomponents-base/src/sap/ui/webcomponents/base/compatibility/ShadowDOM";
7+
import { isSpace, isEnter } from "@ui5/webcomponents-base/src/sap/ui/webcomponents/base/events/PseudoEvents";
78
import PanelTemplateContext from "./PanelTemplateContext";
89
import BackgroundDesign from "./types/BackgroundDesign";
910
import PanelAccessibleRole from "./types/PanelAccessibleRole";
@@ -121,6 +122,9 @@ const metadata = {
121122
_icon: {
122123
type: Object,
123124
},
125+
_header: {
126+
type: Object,
127+
},
124128
_contentExpanded: {
125129
type: Boolean,
126130
},
@@ -206,23 +210,54 @@ class Panel extends WebComponent {
206210

207211
this.resourceBundle = getResourceBundle("@ui5/webcomponents");
208212

213+
this._header = {};
214+
209215
this._icon = {};
210216
this._icon.id = `${this.id}-CollapsedImg`;
211217
this._icon.src = getIconURI("navigation-right-arrow");
212-
213218
this._icon.title = this.resourceBundle.getText("PANEL_ICON");
214219
this._icon.functional = true;
215-
this._icon.press = event => { event.preventDefault(); this._toggleOpen(); };
220+
221+
this._toggle = event => { event.preventDefault(); this._toggleOpen(); };
222+
this._noOp = () => {};
216223
}
217224

218225
onBeforeRendering() {
219226
// If the animation is running, it will set the content expanded state at the end
220227
if (!this._animationRunning) {
221228
this._contentExpanded = !this.collapsed;
222229
}
230+
231+
const toggleWithInternalHeader = !this.header;
232+
this._header.press = toggleWithInternalHeader ? this._toggle : this._noOp;
233+
this._icon.press = !toggleWithInternalHeader ? this._toggle : this._noOp;
234+
}
235+
236+
onkeydown(event) {
237+
const headerUsed = this._headerOnTarget(event.ui5target);
238+
239+
if (isEnter(event) && headerUsed) {
240+
this._toggleOpen();
241+
}
242+
243+
if (isSpace(event) && headerUsed) {
244+
event.preventDefault();
245+
}
246+
}
247+
248+
onkeyup(event) {
249+
const headerUsed = this._headerOnTarget(event.ui5target);
250+
251+
if (isSpace(event) && headerUsed) {
252+
this._toggleOpen();
253+
}
223254
}
224255

225256
_toggleOpen() {
257+
if (this.fixed) {
258+
return;
259+
}
260+
226261
this.collapsed = !this.collapsed;
227262
this._animationRunning = true;
228263

@@ -252,6 +287,10 @@ class Panel extends WebComponent {
252287
this.fireEvent("expand", {});
253288
}
254289

290+
_headerOnTarget(target) {
291+
return target.classList.contains("sapMPanelWrappingDiv");
292+
}
293+
255294
static async define(...params) {
256295
await fetchResourceBundle("@ui5/webcomponents");
257296

‎packages/main/src/PanelTemplateContext.js

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ class PanelTemplateContext {
55
expanded: !state.collapsed,
66
ariaLabelledBy: state.header ? undefined : `${state._id}-header`,
77
accRole: state.accessibleRole.toLowerCase(),
8+
headerTabIndex: !state.header ? "0" : undefined,
9+
iconTabIndex: state.header ? "0" : undefined,
810
classes: {
911
main: {
1012
sapMPanel: true,
@@ -13,6 +15,7 @@ class PanelTemplateContext {
1315
sapMPanelWrappingDivTb: state.header,
1416
sapMPanelWrappingDivTbExpanded: state.header && state.collapsed,
1517
sapMPanelWrappingDiv: !state.header,
18+
sapMPanelWrappingDivClickable: !state.header,
1619
sapMPanelWrappingDivExpanded: !state.header && !state.collapsed,
1720
},
1821
icon: {

‎packages/main/src/themes/base/Panel.less

+24
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/* CSS for control ui5-panel */
1010
/* Base theme */
1111
/* ============================ */
12+
@_ui5_panel_focus_border_width: 1px;
1213

1314
:host(ui5-panel) {
1415
display: block;
@@ -99,6 +100,29 @@ ui5-panel {
99100
position: relative;
100101
}
101102

103+
.sapMPanelWrappingDiv {
104+
box-sizing: border-box;
105+
}
106+
107+
.sapMPanelWrappingDiv.sapMPanelWrappingDivClickable {
108+
cursor: pointer;
109+
}
110+
111+
.sapMPanelWrappingDiv.sapMPanelWrappingDivClickable:focus {
112+
outline: none;
113+
}
114+
115+
.sapMPanelWrappingDiv.sapMPanelWrappingDivClickable:focus::after {
116+
content: "";
117+
position: absolute;
118+
border: @_ui5_panel_focus_border_width dotted @sapUiContentFocusColor;
119+
pointer-events: none;
120+
top: 1px;
121+
left: 1px;
122+
right: 1px;
123+
bottom: 1px;
124+
}
125+
102126
.sapMPanelWrappingDivTb .sapMPanelHdrToolbar {
103127
width: 100%;
104128
}

‎packages/main/src/themes/sap_belize_hcb/Panel.less

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
/* Global Belize parameters */
99
/* ============================= */
1010
@import "./base.less";
11-
@import "./global.less";
11+
@import "./global.less";
12+
13+
@_ui5_panel_focus_border_width: 0.125rem;

‎packages/main/test/sap/ui/webcomponents/main/pages/Panel.html

+25-9
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727

2828
<script>
2929
document.addEventListener("DOMContentLoaded", function () {
30-
const myPanel = document.getElementById("panel1");
31-
const input = document.getElementById("helper-input");
32-
33-
myPanel.addEventListener("expand", function (event) {
30+
panel1.addEventListener("expand", function (event) {
3431
console.log(event);
35-
myPanel.headerText = event.detail.expand ? "Click to collapse!" : "Click to expand!";
36-
37-
input.value = parseInt(input.value) + 1;
32+
event.target.headerText = event.detail.expand ? "Click to collapse!" : "Click to expand!";
33+
field1.value = parseInt(field1.value) + 1;
34+
});
35+
panel2.addEventListener("expand", function (event) {
36+
event.target.headerText = event.detail.expand ? "Click to collapse!" : "Click to expand!";
37+
field2.value = parseInt(field2.value) + 1;
3838
});
3939

4040
var button = document.getElementById("b1");
@@ -157,7 +157,7 @@
157157

158158
<br>
159159

160-
<ui5-panel id="panel1" collapsed expandable header-text="Click to expand!">
160+
<ui5-panel id="panel1" collapsed header-text="Click to expand!">
161161

162162
<!-- Content -->
163163
<ui5-title data-ui5-slot="content">This is a demo how to use the &quot;expand&quot; event.</ui5-title>
@@ -168,9 +168,25 @@
168168

169169
</ui5-panel>
170170

171+
<ui5-panel id="panel2" collapsed accessible-role="Complementary">
172+
173+
<!-- Header -->
174+
<div data-ui5-slot="header" class="header">
175+
<ui5-title>Expandable but not expanded</ui5-title>
176+
</div>
177+
178+
<!-- Content -->
179+
<ui5-title data-ui5-slot="content">This is a demo how to use the &quot;expand&quot; event.</ui5-title>
180+
<br>
181+
<ui5-label data-ui5-slot="content" wrap>
182+
Some short text.
183+
</ui5-label>
184+
</ui5-panel>
185+
171186
<br>
172187

173-
<ui5-input id="helper-input" value="0"></ui5-input>
188+
<ui5-input id="field1" value="0"></ui5-input>
189+
<ui5-input id="field2" value="0"></ui5-input>
174190

175191
</body>
176192

‎packages/main/test/sap/ui/webcomponents/main/samples/Panel.sample.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ <h2 class="control-header">Panel</h2>
5353
<section>
5454
<h3>Basic Panel</h3>
5555
<div class="snippet">
56-
<ui5-panel width="100%" accessible-role="Complementary"
56+
<ui5-panel width="100%" accessible-role="Complementary"
5757
header-text="Both expandable and expanded" class="full-width">
5858
<h1 data-ui5-slot="content" class="content-color">I am a native heading!</h1>
5959
<ui5-label data-ui5-slot="content" wrap>Short text.</ui5-label>
@@ -65,6 +65,7 @@ <h1 data-ui5-slot="content" class="content-color">I am a native heading!</h1>
6565
</ui5-panel>
6666
</div>
6767
<pre class="prettyprint lang-html"><xmp>
68+
6869
<ui5-panel width="100%" accessible-role="Complementary"
6970
header-text="Both expandable and expanded" class="full-width">
7071
<h1 data-ui5-slot="content" class="content-color">I am a native heading!</h1>

‎packages/main/test/specs/Panel.spec.js

+19-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,25 @@ const assert = require("assert");
33
describe("Panel general interaction", () => {
44
browser.url("http://localhost:8080/test-resources/sap/ui/webcomponents/main/pages/Panel.html");
55

6-
it("tests expand event", () => {
7-
const icon = browser.findElementDeep("#panel1 >>> ui5-icon");
8-
const field = browser.findElementDeep("#helper-input");
6+
it("tests expand event upon header click", () => {
7+
const header = browser.findElementDeep("#panel1 >>> .sapMPanelWrappingDiv");
8+
const field = browser.$("#field1");
9+
10+
header.click();
11+
browser.pause(500);
12+
13+
header.keys("Space");
14+
browser.pause(500);
15+
16+
header.keys("Enter");
17+
browser.pause(500);
18+
19+
assert.strictEqual(field.getProperty("value"), "3", "Press should be called 3 times");
20+
});
21+
22+
it("tests expand event upon icon click with custom header", () => {
23+
const icon = browser.findElementDeep("#panel2 >>> ui5-icon");
24+
const field = browser.$("#field2");
925

1026
icon.click();
1127
browser.pause(500);

0 commit comments

Comments
 (0)
Please sign in to comment.