Skip to content

Commit dfa2b13

Browse files
fix(item): do not disable entire item if there are multiple inputs (#18696)
references #18655 fixes #18670
1 parent 1f51ab2 commit dfa2b13

File tree

5 files changed

+236
-10
lines changed

5 files changed

+236
-10
lines changed

core/src/components/item/item.scss

+3-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@
149149
// Item: Disabled
150150
// --------------------------------------------------
151151

152-
:host(.item-interactive-disabled) {
152+
:host(.item-interactive-disabled:not(.item-multiple-inputs)) {
153153
cursor: default;
154154
pointer-events: none;
155155
}
@@ -397,7 +397,9 @@ button, a {
397397
// Multiple inputs in an item should have the input
398398
// cover relative to themselves instead of the item
399399

400+
:host(.item-multiple-inputs) ::slotted(ion-checkbox),
400401
:host(.item-multiple-inputs) ::slotted(ion-datetime),
402+
:host(.item-multiple-inputs) ::slotted(ion-radio),
401403
:host(.item-multiple-inputs) ::slotted(ion-select) {
402404
position: relative;
403405
}

core/src/components/item/item.tsx

+16-8
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,26 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
128128
}
129129

130130
componentDidLoad() {
131-
// Check for multiple inputs to change the position to relative
132-
const inputs = this.el.querySelectorAll('ion-select, ion-datetime');
133-
this.multipleInputs = inputs.length > 1 ? true : false;
131+
// The following elements have a clickable cover that is relative to the entire item
132+
const covers = this.el.querySelectorAll('ion-checkbox, ion-datetime, ion-select, ion-radio');
133+
134+
// The following elements can accept focus alongside the previous elements
135+
// therefore if these elements are also a child of item, we don't want the
136+
// input cover on top of those interfering with their clicks
137+
const inputs = this.el.querySelectorAll('ion-input, ion-range, ion-searchbar, ion-segment, ion-textarea, ion-toggle');
138+
139+
// Check for multiple inputs to change the position of the input cover to relative
140+
// for all of the covered inputs above
141+
this.multipleInputs = covers.length + inputs.length > 1;
134142
}
135143

136-
// If the item contains an input including a radio, checkbox, datetime, etc.
137-
// then the item will have a clickable input cover that should
138-
// get the hover, focused and activated states UNLESS it has multiple
139-
// inputs, then those need to individually get the click
144+
// If the item contains an input including a checkbox, datetime, select, or radio
145+
// then the item will have a clickable input cover that covers the item
146+
// that should get the hover, focused and activated states UNLESS it has multiple
147+
// inputs, then those need to individually get each click
140148
private hasCover(): boolean {
141149
const inputs = this.el.querySelectorAll('ion-checkbox, ion-datetime, ion-select, ion-radio');
142-
return inputs.length > 0 && !this.multipleInputs;
150+
return inputs.length === 1 && !this.multipleInputs;
143151
}
144152

145153
// If the item has an href or button property it will render a native
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { newE2EPage } from '@stencil/core/testing';
2+
3+
test('item: disabled', async () => {
4+
const page = await newE2EPage({
5+
url: '/src/components/item/test/disabled?ionic:_testing=true'
6+
});
7+
8+
const compare = await page.compareScreenshot();
9+
expect(compare).toMatchScreenshot();
10+
});
11+
12+
test('item: disabled-rtl', async () => {
13+
const page = await newE2EPage({
14+
url: '/src/components/item/test/disabled?ionic:_testing=true&rtl=true'
15+
});
16+
17+
const compare = await page.compareScreenshot();
18+
expect(compare).toMatchScreenshot();
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
<!DOCTYPE html>
2+
<html dir="ltr">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<title>Item - Disabled</title>
7+
<meta name="viewport"
8+
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
9+
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
10+
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
11+
<script src="../../../../../scripts/testing/scripts.js"></script>
12+
<script src="../../../../../dist/ionic.js"></script>
13+
</head>
14+
15+
<body>
16+
<ion-app>
17+
18+
<ion-header>
19+
<ion-toolbar>
20+
<ion-title>Item: Disabled</ion-title>
21+
</ion-toolbar>
22+
</ion-header>
23+
24+
<ion-content class="ion-padding-vertical">
25+
<ion-list>
26+
<ion-list-header>
27+
<ion-label>Single Input Disabled Items</ion-label>
28+
</ion-list-header>
29+
30+
<ion-item disabled>
31+
<ion-label>Disabled Item</ion-label>
32+
</ion-item>
33+
34+
<ion-item disabled button>
35+
<ion-label>Disabled Item Button</ion-label>
36+
</ion-item>
37+
38+
<ion-item disabled href="#">
39+
<ion-label>Disabled Item Anchor</ion-label>
40+
</ion-item>
41+
42+
<ion-item>
43+
<ion-label>Disabled Datetime</ion-label>
44+
<ion-datetime disabled value="2019"></ion-datetime>
45+
</ion-item>
46+
47+
<ion-item>
48+
<ion-label>Disabled Select</ion-label>
49+
<ion-select disabled>
50+
<ion-select-option value="">No Game Console</ion-select-option>
51+
<ion-select-option value="nes">NES</ion-select-option>
52+
<ion-select-option value="n64" selected>Nintendo64</ion-select-option>
53+
<ion-select-option value="ps">PlayStation</ion-select-option>
54+
<ion-select-option value="genesis">Sega Genesis</ion-select-option>
55+
<ion-select-option value="saturn">Sega Saturn</ion-select-option>
56+
<ion-select-option value="snes">SNES</ion-select-option>
57+
</ion-select>
58+
</ion-item>
59+
60+
<ion-item>
61+
<ion-label>Disabled Input</ion-label>
62+
<ion-input placeholder="Disabled" disabled></ion-input>
63+
</ion-item>
64+
65+
<ion-item>
66+
<ion-label>Disabled Toggle</ion-label>
67+
<ion-toggle disabled checked slot="end"></ion-toggle>
68+
</ion-item>
69+
70+
<ion-item>
71+
<ion-label>Disabled Checkbox</ion-label>
72+
<ion-checkbox disabled checked slot="start"></ion-checkbox>
73+
</ion-item>
74+
75+
<ion-item>
76+
<ion-label>Disabled Range</ion-label>
77+
<ion-range disabled value="10"></ion-range>
78+
</ion-item>
79+
</ion-list>
80+
81+
<ion-list>
82+
<ion-list-header>
83+
<ion-label>Multiple Input Disabled Items</ion-label>
84+
</ion-list-header>
85+
86+
<ion-item>
87+
<ion-checkbox disabled slot="start"></ion-checkbox>
88+
<ion-input placeholder="Disabled Checkbox w/ Input"></ion-input>
89+
</ion-item>
90+
91+
<ion-item>
92+
<ion-checkbox disabled slot="end"></ion-checkbox>
93+
<ion-input placeholder="Disabled Checkbox w/ Input"></ion-input>
94+
</ion-item>
95+
96+
<ion-item>
97+
<ion-radio disabled slot="start"></ion-radio>
98+
<ion-input placeholder="Disabled Radio w/ Input"></ion-input>
99+
</ion-item>
100+
101+
<ion-item>
102+
<ion-radio disabled slot="end"></ion-radio>
103+
<ion-input placeholder="Disabled Radio w/ Input"></ion-input>
104+
</ion-item>
105+
106+
<ion-item>
107+
<ion-checkbox disabled slot="start"></ion-checkbox>
108+
<ion-label>Checkbox + Radio</ion-label>
109+
<ion-radio slot="end"></ion-radio>
110+
</ion-item>
111+
112+
<ion-item>
113+
<ion-checkbox disabled slot="start"></ion-checkbox>
114+
<ion-radio slot="start"></ion-radio>
115+
<ion-label>Checkbox + Radio</ion-label>
116+
</ion-item>
117+
118+
<ion-item>
119+
<ion-label>Disabled Selects</ion-label>
120+
<ion-select placeholder="month">
121+
<ion-select-option value="1">January</ion-select-option>
122+
<ion-select-option value="2">February</ion-select-option>
123+
<ion-select-option value="3">March</ion-select-option>
124+
</ion-select>
125+
<ion-select disabled placeholder="year">
126+
<ion-select-option value="1990">1990</ion-select-option>
127+
<ion-select-option value="1991">1991</ion-select-option>
128+
<ion-select-option value="1992">1992</ion-select-option>
129+
<ion-select-option value="1993">1993</ion-select-option>
130+
<ion-select-option value="1994">1994</ion-select-option>
131+
<ion-select-option value="1995">1995</ion-select-option>
132+
<ion-select-option value="1996">1996</ion-select-option>
133+
<ion-select-option value="1997">1997</ion-select-option>
134+
</ion-select>
135+
</ion-item>
136+
137+
<ion-item>
138+
<ion-checkbox slot="start"></ion-checkbox>
139+
<ion-label>Checkbox + Range</ion-label>
140+
<ion-range disabled value="45"></ion-range>
141+
</ion-item>
142+
143+
<ion-item>
144+
<ion-checkbox slot="start"></ion-checkbox>
145+
<ion-label>Checkbox + Toggle</ion-label>
146+
<ion-toggle disabled value="45"></ion-toggle>
147+
</ion-item>
148+
149+
<ion-item>
150+
<ion-checkbox disabled slot="start"></ion-checkbox>
151+
<ion-label>Checkbox + Buttons</ion-label>
152+
<ion-button slot="end">Default</ion-button>
153+
<ion-button slot="end">Buttons</ion-button>
154+
</ion-item>
155+
156+
<ion-item>
157+
<ion-label>Disabled Input</ion-label>
158+
<ion-input slot="start" placeholder="Disabled" disabled></ion-input>
159+
<ion-segment>
160+
<ion-segment-button value="friends">
161+
<ion-label>Friends</ion-label>
162+
</ion-segment-button>
163+
<ion-segment-button value="enemies">
164+
<ion-label>Enemies</ion-label>
165+
</ion-segment-button>
166+
</ion-segment>
167+
</ion-item>
168+
169+
<ion-item>
170+
<ion-checkbox slot="start" disabled></ion-checkbox>
171+
<ion-label>Disabled Checkbox</ion-label>
172+
<ion-searchbar></ion-searchbar>
173+
</ion-item>
174+
</ion-list>
175+
</ion-content>
176+
177+
<ion-footer>
178+
<ion-toolbar>
179+
<ion-buttons slot="start">
180+
<ion-button onClick="toggleDisabled()">Toggle</ion-button>
181+
</ion-buttons>
182+
</ion-toolbar>
183+
</ion-footer>
184+
</ion-app>
185+
186+
<script>
187+
const disabledEls = document.querySelectorAll("[disabled]");
188+
189+
function toggleDisabled() {
190+
for (var i = 0; i < disabledEls.length; i++) {
191+
disabledEls[i].disabled = !disabledEls[i].disabled;
192+
}
193+
}
194+
195+
</script>
196+
197+
</html>

core/src/components/label/label.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
white-space: normal;
3535
}
3636

37-
:host-context(.item-interactive-disabled) {
37+
:host-context(.item-interactive-disabled:not(.item-multiple-inputs)) {
3838
cursor: default;
3939
opacity: .3;
4040
pointer-events: none;

0 commit comments

Comments
 (0)