Skip to content

Commit aa5d109

Browse files
feat(button): add spinner sizes for ionic theme (#30233)
1 parent ab81f3d commit aa5d109

File tree

8 files changed

+250
-20
lines changed

8 files changed

+250
-20
lines changed

core/src/components/button/button.common.scss

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,11 @@
211211
flex-shrink: 0;
212212
}
213213

214-
// Button Icons
214+
// Button Icons & Spinners
215215
// --------------------------------------------------
216216

217-
::slotted(ion-icon) {
217+
::slotted(ion-icon),
218+
::slotted(ion-spinner) {
218219
pointer-events: none;
219220
}
220221

core/src/components/button/button.ionic.scss

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,6 @@
9393
// Button Sizes
9494
// -------------------------------------------------------------------------------
9595

96-
/* Extra Small and Small Button */
97-
:host(.button-xsmall),
98-
:host(.button-small) {
99-
::slotted(ion-icon[slot="start"]) {
100-
@include globals.margin-horizontal(null, globals.$ion-space-100);
101-
}
102-
103-
::slotted(ion-icon[slot="end"]) {
104-
@include globals.margin-horizontal(globals.$ion-space-100, null);
105-
}
106-
}
107-
10896
/* Extra Small Button */
10997
:host(.button-xsmall) {
11098
--padding-top: #{globals.$ion-space-100};
@@ -172,6 +160,25 @@
172160
aspect-ratio: 1 / 1;
173161
}
174162

163+
// Button with Spinner
164+
// -------------------------------------------------------------------------------
165+
::slotted(ion-spinner) {
166+
--color: currentColor;
167+
}
168+
169+
/* Button containing only a spinner */
170+
::slotted(ion-spinner[slot="start"]),
171+
::slotted(ion-spinner[slot="end"]),
172+
::slotted(ion-spinner[slot="icon-only"]) {
173+
width: globals.$ion-space-500;
174+
height: globals.$ion-space-500;
175+
}
176+
177+
:host(.button-xlarge) ::slotted(ion-spinner) {
178+
width: globals.$ion-space-600;
179+
height: globals.$ion-space-600;
180+
}
181+
175182
// Button Shapes
176183
// -------------------------------------------------------------------------------
177184

@@ -246,26 +253,40 @@
246253
font-size: globals.$ion-font-size-500;
247254
}
248255

249-
:host(.button-small) ::slotted(ion-icon[slot="start"]) {
256+
:host(.button-xsmall) ::slotted(ion-icon[slot="start"]),
257+
:host(.button-xsmall) ::slotted(ion-spinner[slot="start"]),
258+
:host(.button-small) ::slotted(ion-icon[slot="start"]),
259+
:host(.button-small) ::slotted(ion-spinner[slot="start"]) {
250260
@include globals.margin-horizontal(null, globals.$ion-space-200);
251261
}
252262

253-
::slotted(ion-icon[slot="start"]) {
263+
::slotted(ion-icon[slot="start"]),
264+
::slotted(ion-spinner[slot="start"]) {
254265
@include globals.margin-horizontal(null, globals.$ion-space-250);
255266
}
256267

257-
:host(.button-large) ::slotted(ion-icon[slot="start"]) {
268+
:host(.button-large) ::slotted(ion-icon[slot="start"]),
269+
:host(.button-large) ::slotted(ion-spinner[slot="start"]),
270+
:host(.button-xlarge) ::slotted(ion-icon[slot="start"]),
271+
:host(.button-xlarge) ::slotted(ion-spinner[slot="start"]) {
258272
@include globals.margin-horizontal(null, globals.$ion-space-300);
259273
}
260274

261-
:host(.button-small) ::slotted(ion-icon[slot="end"]) {
275+
:host(.button-xsmall) ::slotted(ion-icon[slot="end"]),
276+
:host(.button-xsmall) ::slotted(ion-spinner[slot="end"]),
277+
:host(.button-small) ::slotted(ion-icon[slot="end"]),
278+
:host(.button-small) ::slotted(ion-spinner[slot="end"]) {
262279
@include globals.margin-horizontal(globals.$ion-space-200, null);
263280
}
264281

265-
::slotted(ion-icon[slot="end"]) {
282+
::slotted(ion-icon[slot="end"]),
283+
::slotted(ion-spinner[slot="end"]) {
266284
@include globals.margin-horizontal(globals.$ion-space-250, null);
267285
}
268286

269-
:host(.button-large) ::slotted(ion-icon[slot="end"]) {
287+
:host(.button-large) ::slotted(ion-icon[slot="end"]),
288+
:host(.button-large) ::slotted(ion-spinner[slot="end"]),
289+
:host(.button-xlarge) ::slotted(ion-icon[slot="end"]),
290+
:host(.button-xlarge) ::slotted(ion-spinner[slot="end"]) {
270291
@include globals.margin-horizontal(globals.$ion-space-300, null);
271292
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
4+
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
5+
test.describe(title('button: spinner'), () => {
6+
test('should not have visual regressions', async ({ page }) => {
7+
await page.goto(`/src/components/button/test/spinner`, config);
8+
9+
await page.setIonViewport();
10+
11+
await expect(page).toHaveScreenshot(screenshot(`button-spinner`));
12+
});
13+
});
14+
});
46.2 KB
Loading
62.9 KB
Loading
43.3 KB
Loading
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<!DOCTYPE html>
2+
<html lang="en" dir="ltr">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Button - Spinner</title>
6+
<meta
7+
name="viewport"
8+
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
9+
/>
10+
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
11+
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
12+
<script src="../../../../../scripts/testing/scripts.js"></script>
13+
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
14+
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
15+
</head>
16+
17+
<body>
18+
<ion-app>
19+
<ion-header>
20+
<ion-toolbar>
21+
<ion-title>Button - Spinner</ion-title>
22+
</ion-toolbar>
23+
</ion-header>
24+
25+
<ion-content class="ion-padding" id="content" no-bounce>
26+
<p>
27+
<ion-button>
28+
<ion-spinner slot="start"></ion-spinner>
29+
Left Spinner
30+
</ion-button>
31+
<ion-button href="#">
32+
<ion-spinner slot="start"></ion-spinner>
33+
Left Spinner
34+
</ion-button>
35+
</p>
36+
<p>
37+
<ion-button>
38+
<ion-spinner name="lines" slot="end"></ion-spinner>
39+
Right Spinner
40+
</ion-button>
41+
<ion-button href="#">
42+
<ion-spinner name="lines" slot="end"></ion-spinner>
43+
Right Spinner
44+
</ion-button>
45+
</p>
46+
<p>
47+
<ion-button>
48+
<ion-spinner name="lines-sharp" slot="icon-only"></ion-spinner>
49+
</ion-button>
50+
<ion-button href="#">
51+
<ion-spinner name="lines-sharp" slot="icon-only"></ion-spinner>
52+
</ion-button>
53+
</p>
54+
<p>
55+
<ion-button size="large">
56+
<ion-spinner name="lines-small" slot="start"></ion-spinner>
57+
Left, Large
58+
</ion-button>
59+
<ion-button size="large" href="#">
60+
<ion-spinner name="lines-small" slot="start"></ion-spinner>
61+
Left, Large
62+
</ion-button>
63+
</p>
64+
<p>
65+
<ion-button size="large">
66+
<ion-spinner slot="end"></ion-spinner>
67+
Right, Large
68+
</ion-button>
69+
<ion-button size="large" href="#">
70+
<ion-spinner slot="end"></ion-spinner>
71+
Right, Large
72+
</ion-button>
73+
</p>
74+
<p>
75+
<ion-button size="large">
76+
<ion-spinner slot="icon-only"></ion-spinner>
77+
</ion-button>
78+
<ion-button size="large" href="#">
79+
<ion-spinner slot="icon-only"></ion-spinner>
80+
</ion-button>
81+
</p>
82+
<p>
83+
<ion-button size="small">
84+
<ion-spinner slot="start"></ion-spinner>
85+
Left, Small
86+
</ion-button>
87+
<ion-button size="small" href="#">
88+
<ion-spinner slot="start"></ion-spinner>
89+
Left, Small
90+
</ion-button>
91+
</p>
92+
<p>
93+
<ion-button size="small">
94+
<ion-spinner slot="end"></ion-spinner>
95+
Right, Small
96+
</ion-button>
97+
<ion-button size="small" href="#">
98+
<ion-spinner slot="end"></ion-spinner>
99+
Right, Small
100+
</ion-button>
101+
</p>
102+
<p>
103+
<ion-button size="small">
104+
<ion-spinner slot="icon-only"></ion-spinner>
105+
</ion-button>
106+
<ion-button size="small" href="#">
107+
<ion-spinner slot="icon-only"></ion-spinner>
108+
</ion-button>
109+
</p>
110+
<p>
111+
<ion-button size="xlarge">
112+
<ion-spinner slot="start"></ion-spinner>
113+
Left, Extra Large
114+
</ion-button>
115+
</p>
116+
<p>
117+
<ion-button size="xlarge" href="#">
118+
<ion-spinner slot="start"></ion-spinner>
119+
Left, Extra Large
120+
</ion-button>
121+
</p>
122+
<p>
123+
<ion-button size="xlarge">
124+
<ion-spinner slot="end"></ion-spinner>
125+
Right, Extra Large
126+
</ion-button>
127+
</p>
128+
<p>
129+
<ion-button size="xlarge" href="#">
130+
<ion-spinner slot="end"></ion-spinner>
131+
Right, Extra Large
132+
</ion-button>
133+
</p>
134+
<p>
135+
<ion-button size="xlarge">
136+
<ion-spinner slot="icon-only"></ion-spinner>
137+
</ion-button>
138+
</p>
139+
<p>
140+
<ion-button size="xlarge" href="#">
141+
<ion-spinner slot="icon-only"></ion-spinner>
142+
</ion-button>
143+
</p>
144+
</ion-content>
145+
</ion-app>
146+
</body>
147+
</html>

core/src/components/button/test/theme-ionic/index.html

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ <h4>Preview options</h4>
5252
<ion-select-option value="outline">Outline</ion-select-option>
5353
<ion-select-option value="clear">Clear</ion-select-option>
5454
</ion-select>
55+
56+
<ion-select id="select-color" justify="space-between" interface="alert" label="Color" placeholder="">
57+
<ion-select-option value="">default</ion-select-option>
58+
<ion-select-option value="primary">Primary</ion-select-option>
59+
<ion-select-option value="success">Success</ion-select-option>
60+
<ion-select-option value="warning">Warning</ion-select-option>
61+
<ion-select-option value="neutral">Neutral</ion-select-option>
62+
</ion-select>
5563
</p>
5664

5765
<div id="screenshot-wrapper" class="ion-margin-top">
@@ -86,31 +94,63 @@ <h4>Preview</h4>
8694
</ion-button>
8795
</p>
8896

97+
<p>
98+
<ion-button theme="ionic">
99+
Button
100+
<ion-spinner slot="end" name="lines-small" />
101+
</ion-button>
102+
<ion-button theme="ionic">
103+
<ion-spinner slot="icon-only" name="lines-small"></ion-spinner>
104+
</ion-button>
105+
</p>
106+
<p>
107+
<ion-button theme="ionic">
108+
Button
109+
<ion-spinner slot="start" name="lines-small" />
110+
</ion-button>
111+
</p>
112+
89113
<h4 class="ion-margin-top">States</h4>
90114

91115
<p>
92116
<ion-button theme="ionic">Default</ion-button>
117+
<ion-button theme="ionic">
118+
Button
119+
<ion-spinner slot="end" name="lines-small" />
120+
</ion-button>
93121
<ion-button theme="ionic">
94122
<ion-icon slot="icon-only" name="rocket"></ion-icon>
95123
</ion-button>
96124
</p>
97125

98126
<p>
99127
<ion-button theme="ionic" class="ion-activated">Activated</ion-button>
128+
<ion-button theme="ionic" class="ion-activated">
129+
Button
130+
<ion-spinner slot="end" name="lines-small" />
131+
</ion-button>
100132
<ion-button theme="ionic" class="ion-activated">
101133
<ion-icon slot="icon-only" name="rocket"></ion-icon>
102134
</ion-button>
103135
</p>
104136

105137
<p>
106138
<ion-button theme="ionic" class="ion-focused">Focused</ion-button>
139+
<ion-button theme="ionic" class="ion-focused">
140+
Button
141+
<ion-spinner slot="end" name="lines-small" />
142+
</ion-button>
107143
<ion-button theme="ionic" class="ion-focused ion-margin-start">
108144
<ion-icon slot="icon-only" name="rocket"></ion-icon>
109145
</ion-button>
110146
</p>
111147

112148
<p>
113149
<ion-button theme="ionic" disabled="true">Disabled</ion-button>
150+
<ion-button theme="ionic" disabled="true">
151+
Button
152+
<ion-spinner slot="end" name="lines-small" />
153+
</ion-button>
114154
<ion-button theme="ionic" disabled="true">
115155
<ion-icon slot="icon-only" name="rocket"></ion-icon>
116156
</ion-button>
@@ -150,6 +190,13 @@ <h4 class="ion-margin-top">States</h4>
150190
updateAttr(el, 'fill', e.detail.value);
151191
}
152192
});
193+
194+
const selectColor = document.getElementById('select-color');
195+
selectColor.addEventListener('ionChange', (e) => {
196+
for (const el of listOfBtns) {
197+
updateAttr(el, 'color', e.detail.value);
198+
}
199+
});
153200
</script>
154201
</body>
155202
</html>

0 commit comments

Comments
 (0)