Skip to content

Commit 91d8987

Browse files
committed
refactor: align all inputs to use same CSS for styling
- all input like elements such as Input, MultiComboBox, Select use the same CSS for styling host - all icons than needs to be styled as input icons have a common CSS - InputIcon.css - users can now overstyle all input elements by setting styles to host - fixes tiny bug in Select when Picker is open - icon background color should be pressed - adds a better keyboard handling for MultiComboBox FIXES: #766
1 parent 3af76de commit 91d8987

19 files changed

+300
-262
lines changed

packages/main/src/DatePicker.hbs

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
<ui5-icon
2121
slot="icon"
2222
src="sap-icon://appointment-2"
23-
class="{{classes.icon}} ui5-datepicker-icon"
2423
tabindex="-1"
2524
accessible-name="{{openIconTitle}}"
2625
show-tooltip
2726
@click="{{togglePicker}}"
27+
input-icon
28+
?pressed="{{_isPickerOpen}}"
2829
></ui5-icon>
2930
{{/unless}}
3031
</ui5-input>

packages/main/src/DatePicker.js

-8
Original file line numberDiff line numberDiff line change
@@ -541,14 +541,6 @@ class DatePicker extends UI5Element {
541541
return this.getFormat().parse(this.value);
542542
}
543543

544-
get classes() {
545-
return {
546-
icon: {
547-
"ui5-datepicker-icon--pressed": this._isPickerOpen,
548-
},
549-
};
550-
}
551-
552544
get styles() {
553545
return {
554546
main: {

packages/main/src/MultiComboBox.hbs

+36-28
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,45 @@
1-
<div class="ui5-multi-combobox-root">
2-
<ui5-input id="ui5-multi-combobox-input"
1+
<div class="ui5-multi-combobox-root"
2+
@focusin={{rootFocusIn}}
3+
@focusout={{rootFocusOut}}
4+
>
5+
<ui5-tokenizer slot="_beginContent"
6+
show-more
7+
class="ui5-multi-combobox-tokenizer"
8+
?disabled="{{disabled}}"
9+
@ui5-showMoreItemsPress="{{_showMorePopover}}"
10+
@ui5-tokenDelete="{{_tokenDelete}}"
11+
@focusout="{{_tokenizerFocusOut}}"
12+
?expanded="{{expandedTokenizer}}"
13+
>
14+
{{#each items}}
15+
{{#if this.selected}}
16+
<ui5-token ?readonly="{{../readonly}}" class="ui5-multi-combobox-token" data-ui5-id="{{this._id}}" >{{this.textContent}}</ui5-token>
17+
{{/if}}
18+
{{/each}}
19+
</ui5-tokenizer>
20+
21+
<input id="ui5-multi-combobox-input"
322
value="{{value}}"
423
placeholder="{{placeholder}}"
524
?disabled={{disabled}}
625
?readonly={{readonly}}
726
value-state="{{valueState}}"
8-
@ui5-input="{{_inputLiveChange}}"
9-
@ui5-change={{_inputChange}}
10-
@keydown="{{_keydown}}">
11-
12-
<ui5-tokenizer slot="_beginContent"
13-
show-more
14-
class="ui5-multi-combobox-tokenizer"
15-
?disabled="{{disabled}}"
16-
@ui5-showMoreItemsPress="{{_showMorePopover}}"
17-
@ui5-tokenDelete="{{_tokenDelete}}"
18-
@focusout="{{_tokenizerFocusOut}}"
19-
>
20-
{{#each items}}
21-
{{#if this.selected}}
22-
<ui5-token ?readonly="{{../readonly}}" class="ui5-multi-combobox-token" data-ui5-id="{{this._id}}" >{{this.textContent}}</ui5-token>
23-
{{/if}}
24-
{{/each}}
25-
</ui5-tokenizer>
27+
@input="{{_inputLiveChange}}"
28+
@change={{_inputChange}}
29+
@keydown="{{_keydown}}"
30+
@focusin="{{_focusin}}"
31+
@focusout="{{_focusout}}">
32+
</input>
2633

27-
{{#unless readonly}}
28-
<ui5-icon src="sap-icon://slim-arrow-down"
29-
slot="icon"
30-
@click={{_showAllItemsPopover}}
31-
class="{{classes.icon}}"
32-
></ui5-icon>
33-
{{/unless}}
34-
</ui5-input>
34+
{{#unless readonly}}
35+
<ui5-icon src="sap-icon://slim-arrow-down"
36+
input-icon
37+
slot="icon"
38+
tabindex="-1"
39+
@click={{_showAllItemsPopover}}
40+
?pressed="{{_iconPressed}}"
41+
></ui5-icon>
42+
{{/unless}}
3543

3644
<ui5-popover
3745
class="ui5-multi-combobox-selected-items-popover"

packages/main/src/MultiComboBox.js

+67-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
22
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
33
import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js";
4-
import { isShow, isDown } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js";
4+
import { isShow, isDown, isBackSpace } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js";
55
import "./icons/slim-arrow-down.js";
66
import MultiComboBoxTemplate from "./generated/templates/MultiComboBoxTemplate.lit.js";
77
import Input from "./Input.js";
@@ -121,6 +121,14 @@ const metadata = {
121121
type: Boolean,
122122
},
123123

124+
/**
125+
* Indicates whether the input is focssed
126+
* @private
127+
*/
128+
focused: {
129+
type: Boolean,
130+
},
131+
124132
_filteredItems: {
125133
type: Object,
126134
},
@@ -129,6 +137,14 @@ const metadata = {
129137
type: Boolean,
130138
noAttribute: true,
131139
},
140+
141+
/**
142+
* Indicates whether the tokenizer is expanded or collapsed(shows the n more label)
143+
* @private
144+
*/
145+
expandedTokenizer: {
146+
type: Boolean,
147+
},
132148
},
133149
events: /** @lends sap.ui.webcomponents.main.MultiComboBox.prototype */ {
134150
/**
@@ -236,6 +252,7 @@ class MultiComboBox extends UI5Element {
236252
this._filteredItems = [];
237253
this._inputLastValue = "";
238254
this._deleting = false;
255+
this._validationTimeout = null;
239256
}
240257

241258
_inputChange() {
@@ -248,6 +265,12 @@ class MultiComboBox extends UI5Element {
248265

249266
_showAllItemsPopover() {
250267
this._togglePopover(false);
268+
269+
this._inputDom.focus();
270+
}
271+
272+
get _inputDom() {
273+
return this.shadowRoot.querySelector("#ui5-multi-combobox-input");
251274
}
252275

253276
_inputLiveChange(event) {
@@ -256,12 +279,17 @@ class MultiComboBox extends UI5Element {
256279
const filteredItems = this._filterItems(value);
257280
const oldValueState = this.valueState;
258281

282+
if (this._validationTimeout) {
283+
return;
284+
}
285+
259286
if (!filteredItems.length && value && !this.allowCustomValues) {
260287
input.value = this._inputLastValue;
261-
input.valueState = "Error";
288+
this.valueState = "Error";
262289

263-
setTimeout(() => {
264-
input.valueState = oldValueState;
290+
this._validationTimeout = setTimeout(() => {
291+
this.valueState = oldValueState;
292+
this._validationTimeout = null;
265293
}, 2000);
266294
return;
267295
}
@@ -298,11 +326,10 @@ class MultiComboBox extends UI5Element {
298326

299327
if (tokensCount === 0 && this._deleting) {
300328
setTimeout(() => {
301-
this.shadowRoot.querySelector("ui5-input").focus();
329+
this.shadowRoot.querySelector("input").focus();
330+
this._deleting = false;
302331
}, 0);
303332
}
304-
305-
this._deleting = false;
306333
}
307334

308335
_keydown(event) {
@@ -317,6 +344,17 @@ class MultiComboBox extends UI5Element {
317344
list._itemNavigation.current = 0;
318345
list.items[0].focus();
319346
}
347+
348+
if (isBackSpace(event) && event.target.value === "") {
349+
const lastTokenIndex = this._tokenizer.tokens.length - 1;
350+
351+
if (lastTokenIndex < 0) {
352+
return;
353+
}
354+
355+
this._tokenizer.tokens[lastTokenIndex].focus();
356+
this._tokenizer._itemNav.currentIndex = lastTokenIndex;
357+
}
320358
}
321359

322360
_filterItems(value) {
@@ -362,6 +400,14 @@ class MultiComboBox extends UI5Element {
362400
popover && popover.openBy(this);
363401
}
364402

403+
_focusin() {
404+
this.focused = true;
405+
}
406+
407+
_focusout() {
408+
this.focused = false;
409+
}
410+
365411
onBeforeRendering() {
366412
this._inputLastValue = this.value;
367413

@@ -373,7 +419,7 @@ class MultiComboBox extends UI5Element {
373419
morePopover && morePopover.close();
374420
}
375421

376-
const input = this.shadowRoot.querySelector("ui5-input");
422+
const input = this.shadowRoot.querySelector("input");
377423

378424
if (input && !input.value) {
379425
this._filteredItems = this.items;
@@ -383,6 +429,19 @@ class MultiComboBox extends UI5Element {
383429
this._filteredItems = filteredItems;
384430
}
385431

432+
get _tokenizer() {
433+
return this.shadowRoot.querySelector("ui5-tokenizer");
434+
}
435+
436+
rootFocusIn() {
437+
this.expandedTokenizer = true;
438+
}
439+
440+
rootFocusOut(event) {
441+
if (!this.shadowRoot.contains(event.relatedTarget) && !this._deleting) {
442+
this.expandedTokenizer = false;
443+
}
444+
}
386445

387446
get editable() {
388447
return !this.readonly;
@@ -392,15 +451,6 @@ class MultiComboBox extends UI5Element {
392451
return this.readonly ? "None" : "MultiSelect";
393452
}
394453

395-
get classes() {
396-
return {
397-
icon: {
398-
[`ui5-multi-combobox-icon-root-pressed`]: this._iconPressed,
399-
[`ui5-multi-combobox-icon`]: true,
400-
},
401-
};
402-
}
403-
404454
static async define(...params) {
405455
await Promise.all([
406456
Input.define(),

packages/main/src/Select.hbs

+5-3
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@
3333
</ui5-popover>
3434
{{/if}}
3535

36-
<div class="ui5-select-icon-root" @click="{{_togglePopover}}">
37-
<ui5-icon src="sap-icon://slim-arrow-down" class="ui5-select-icon"
36+
<ui5-icon
37+
@click="{{_togglePopover}}"
38+
src="sap-icon://slim-arrow-down"
39+
input-icon
40+
?pressed="{{_iconPressed}}"
3841
></ui5-icon>
39-
</div>
4042

4143
<slot name="formSupport"></slot>
4244
</div>

packages/main/src/Select.js

+13
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ const metadata = {
100100
noAttribute: true,
101101
},
102102

103+
_iconPressed: {
104+
type: Boolean,
105+
noAttribute: true,
106+
},
107+
103108
/**
104109
* @private
105110
*/
@@ -312,6 +317,8 @@ class Select extends UI5Element {
312317
}
313318

314319
_applyFocusAfterOpen() {
320+
this._toggleIcon();
321+
315322
if (!this._currentlySelectedOption) {
316323
return;
317324
}
@@ -371,6 +378,8 @@ class Select extends UI5Element {
371378
}
372379

373380
_afterClose() {
381+
this._toggleIcon();
382+
374383
if (this._escapePressed) {
375384
this._select(this._selectedIndexBeforeOpen);
376385
this._escapePressed = false;
@@ -380,6 +389,10 @@ class Select extends UI5Element {
380389
}
381390
}
382391

392+
_toggleIcon() {
393+
this._iconPressed = !this._iconPressed;
394+
}
395+
383396
get _currentSelectedItem() {
384397
return this.shadowRoot.querySelector(`#${this.options[this._selectedIndex]._id}-li`);
385398
}

packages/main/src/Token.js

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ const metadata = {
5858
readonly: { type: Boolean },
5959

6060
_tabIndex: { type: String, defaultValue: "-1", noAttribute: true },
61+
62+
overflows: { type: Boolean },
6163
},
6264

6365
events: /** @lends sap.ui.webcomponents.main.Token.prototype */ {

packages/main/src/Tokenizer.hbs

-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
<div class="{{classes.wrapper}}">
22
<div class="{{classes.content}}" @ui5-delete={{_tokenDelete}}>
3-
<div class="ui5-tokenizer-token-placeholder">
4-
<div style="display: inline-block"></div>
5-
</div>
63
{{#each tokens}}
74
<slot name="{{this._individualSlot}}"></slot>
85
{{/each}}

0 commit comments

Comments
 (0)