Skip to content

Commit 97c299d

Browse files
authored
feat(ui5-card): add 'action' slot (#1915)
Provides a new slot, called "action", displayed in the right most part of the header to enable users add a action, in most cases single button. When the action slot is used, the status text would not be displayed (if present). FIXES: #1913
1 parent e7c2518 commit 97c299d

File tree

5 files changed

+91
-12
lines changed

5 files changed

+91
-12
lines changed

packages/main/src/Card.hbs

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@
2929
<div id="{{_id}}-subheading" class="ui5-card-subheading" part="subheading">{{subheading}}</div>
3030
{{/if}}
3131
</div>
32-
<span id="{{_id}}-status" part="status" class="ui5-card-status">{{status}}</span>
32+
33+
{{#if hasAction}}
34+
<slot name="action"></slot>
35+
{{else}}
36+
<span id="{{_id}}-status" part="status" class="ui5-card-status">{{status}}</span>
37+
{{/if}}
3338
</div>
3439
{{/if}}
3540

packages/main/src/Card.js

+24-5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ const metadata = {
5050
avatar: {
5151
type: HTMLElement,
5252
},
53+
54+
/**
55+
* Defines an action, displayed in the right most part of the header.
56+
* <br><br>
57+
* <b>Note:</b> If set, the <code>status</code> text will not be displayed,
58+
* you can either have <code>action</code>, or <code>status</code>.
59+
* @type {HTMLElement[]}
60+
* @slot
61+
* @public
62+
* @since 1.0.0-rc.8
63+
*/
64+
action: {
65+
type: HTMLElement,
66+
},
5367
},
5468
properties: /** @lends sap.ui.webcomponents.main.Card.prototype */ {
5569

@@ -75,6 +89,9 @@ const metadata = {
7589

7690
/**
7791
* Defines the status displayed in the <code>ui5-card</code> header.
92+
* <br><br>
93+
* <b>Note:</b> If the <code>action</code> slot is set, the <code>status</code> will not be displayed,
94+
* you can either have <code>action</code>, or <code>status</code>.
7895
* @type {string}
7996
* @defaultvalue ""
8097
* @public
@@ -121,10 +138,8 @@ const metadata = {
121138
* The <code>ui5-card</code> is a component that represents information in the form of a
122139
* tile with separate header and content areas.
123140
* The content area of a <code>ui5-card</code> can be arbitrary HTML content.
124-
* The header can be used through several properties, such as:
125-
* <code>heading</code>, <code>subheading</code>, <code>status</code>
126-
* and a slot:
127-
* <code>avatar</code>.
141+
* The header can be used through several properties, such as: <code>heading</code>, <code>subheading</code>, <code>status</code>
142+
* and two slots: <code>avatar</code> and <code>action</code>.
128143
*
129144
* <h3>Keyboard handling</h3>
130145
* In case you enable <code>headerInteractive</code> property, you can press the <code>ui5-card</code> header by Space and Enter keys.
@@ -194,7 +209,7 @@ class Card extends UI5Element {
194209
}
195210

196211
get hasHeader() {
197-
return !!(this.heading || this.subheading || this.status || this.avatar);
212+
return !!(this.heading || this.subheading || this.status || this.hasAction || this.avatar);
198213
}
199214

200215
get ariaCardRoleDescription() {
@@ -217,6 +232,10 @@ class Card extends UI5Element {
217232
return !!this.avatar.length;
218233
}
219234

235+
get hasAction() {
236+
return !!this.action.length;
237+
}
238+
220239
static async onDefine() {
221240
await Promise.all([
222241
Icon.define(),

packages/main/src/themes/Card.css

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@
2222
.ui5-card-header {
2323
position: relative;
2424
display: flex;
25-
align-items: flex-start;
25+
align-items: center;
2626
background: var(--sapTile_Background);
2727
border-bottom: 1px solid var(--_ui5_card_header_border_color);
2828
padding: var(--_ui5_card_content_padding);
2929
outline: none;
3030
}
3131

32+
:host([subheading]) .ui5-card-header {
33+
align-items: flex-start;
34+
}
35+
3236
/* Card with no content */
3337
.ui5-card-root.ui5-card--nocontent {
3438
height: auto;

packages/main/test/pages/Card.html

+46
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,52 @@
5656
</ui5-list>
5757
</ui5-card>
5858

59+
60+
<ui5-card heading="Linked activities (5)" class="myCard" status="4 of 10" id="actionCard">
61+
<ui5-list id="myList3" separators="Inner">
62+
<ui5-li icon="horizontal-bullet-chart">
63+
Increase customer satisfaction by 10% using marketing methods
64+
</ui5-li>
65+
<ui5-li icon="opportunity">
66+
Get 1000 survey responses to annual employee survey
67+
</ui5-li>
68+
</ui5-list>
69+
70+
<ui5-button icon="add" slot="action" design="Transparent">
71+
Add activity
72+
</ui5-button>
73+
</ui5-card>
74+
75+
<ui5-card heading="Linked activities (5)" class="myCard" subheading="quick links">
76+
<ui5-list id="myList3" separators="Inner">
77+
<ui5-li icon="horizontal-bullet-chart">
78+
Increase customer satisfaction by 10% using marketing methods
79+
</ui5-li>
80+
<ui5-li icon="opportunity">
81+
Get 1000 survey responses to annual employee survey
82+
</ui5-li>
83+
</ui5-list>
84+
85+
<ui5-button icon="add" slot="action" design="Transparent">
86+
Add activity
87+
</ui5-button>
88+
</ui5-card>
89+
90+
<ui5-card heading="Linked activities (5)">
91+
<ui5-list id="myList3" separators="Inner">
92+
<ui5-li icon="horizontal-bullet-chart">
93+
Increase customer satisfaction by 10% using marketing methods
94+
</ui5-li>
95+
<ui5-li icon="opportunity">
96+
Get 1000 survey responses to annual employee survey
97+
</ui5-li>
98+
</ui5-list>
99+
100+
<ui5-icon name="group" slot="avatar"></ui5-icon>
101+
102+
<ui5-button icon="overflow" slot="action" design="Transparent"></ui5-button>
103+
</ui5-card>
104+
59105
<script>
60106
card.addEventListener("ui5-headerClick", function (event) {
61107
console.log(event);

packages/main/test/specs/Card.spec.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ describe("Card general interaction", () => {
66
it("tests initial rendering", () => {
77
const card = browser.$("#card");
88

9-
assert.ok(card, "Has shadow root");
9+
assert.ok(card.isExisting(), "The component has shadow root.");
1010
});
1111

12-
it("fires headerPress upon click, Enter and Space", () => {
12+
it("tests status not rendered, when action is set", () => {
13+
const status = browser.$("#actionCard").shadow$(".ui5-card-status");
14+
15+
assert.notOk(status.isExisting(), "The status DOM is not rendered.");
16+
});
17+
18+
it("tests headerPress upon click, Enter and Space", () => {
1319
const cardHeader = browser.$("#card").shadow$(".ui5-card-header");
1420
const cardHeader2 = browser.$("#card2").shadow$(".ui5-card-header");
1521
const field = browser.$("#field");
@@ -18,13 +24,12 @@ describe("Card general interaction", () => {
1824
cardHeader.keys("Space");
1925
cardHeader.keys("Enter");
2026

21-
assert.strictEqual(field.getProperty("value"), "3", "headerPress should be called 3 times");
22-
27+
assert.strictEqual(field.getProperty("value"), "3", "The headerPress event should be called 3 times.");
2328

2429
cardHeader2.click();
2530
cardHeader2.keys("Space");
2631
cardHeader2.keys("Enter");
2732

28-
assert.strictEqual(field.getProperty("value"), "3", "events count should remain 3 as the header is not interactive.");
33+
assert.strictEqual(field.getProperty("value"), "3", "The events count should remain 3 as the header is not interactive.");
2934
});
3035
});

0 commit comments

Comments
 (0)