You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(contributing): update component guide with order for states (ionic-team#29111)
Updates the component guide to use the proper order for the `focused`,
`hover`, and `activated` states. Reorders the sections based on the
recommended order and adds emphasis and blockquotes to call out the
order.
I have created ticket
[FW-6039](https://outsystemsrd.atlassian.net/browse/FW-6039) for
investigating components that don't follow the recommended order here.
---------
Co-authored-by: Sean Perkins <[email protected]>
Copy file name to clipboardExpand all lines: .github/COMPONENT-GUIDE.md
+87-80Lines changed: 87 additions & 80 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,10 +2,10 @@
2
2
3
3
-[Button States](#button-states)
4
4
*[Component Structure](#component-structure)
5
-
*[Activated](#activated)
6
5
*[Disabled](#disabled)
7
6
*[Focused](#focused)
8
7
*[Hover](#hover)
8
+
*[Activated](#activated)
9
9
*[Ripple Effect](#ripple-effect)
10
10
*[Example Components](#example-components)
11
11
*[References](#references)
@@ -21,7 +21,7 @@
21
21
22
22
## Button States
23
23
24
-
Any component that renders a button should have the following states: [`activated`](#activated), [`disabled`](#disabled), [`focused`](#focused), [`hover`](#hover). It should also have a [Ripple Effect](#ripple-effect) component added for Material Design.
24
+
Any component that renders a button should have the following states: [`disabled`](#disabled), [`focused`](#focused), [`hover`](#hover), [`activated`](#activated). It should also have a [Ripple Effect](#ripple-effect) component added for Material Design.
25
25
26
26
### Component Structure
27
27
@@ -89,78 +89,6 @@ The following styles should be set for the CSS to work properly. Note that the `
89
89
```
90
90
91
91
92
-
### Activated
93
-
94
-
The activated state should be enabled for elements with actions on "press". It usually changes the opacity or background of an element.
95
-
96
-
> [!WARNING]
97
-
>`:active` should not be used here as it is not received on mobile Safari unless the element has a `touchstart` listener (which we don't necessarily want to have to add to every element). From [Safari Web Content Guide](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/AdjustingtheTextSize/AdjustingtheTextSize.html):
98
-
>
99
-
>> On iOS, mouse events are sent so quickly that the down or active state is never received. Therefore, the `:active` pseudo state is triggered only when there is a touch event set on the HTML element
100
-
101
-
> Make sure the component has the correct [component structure](#component-structure) before continuing.
102
-
103
-
#### JavaScript
104
-
105
-
The `ion-activatable` class needs to be set on an element that can be activated:
106
-
107
-
```jsx
108
-
render() {
109
-
return (
110
-
<Host class='ion-activatable'>
111
-
<slot></slot>
112
-
</Host>
113
-
);
114
-
}
115
-
```
116
-
117
-
Once that is done, the element will get the `ion-activated` class added on press after a small delay. This delay exists so that the active state does not show up when an activatable element is tapped while scrolling.
118
-
119
-
In addition to setting that class, `ion-activatable-instant` can be set in order to have an instant press with no delay:
* @prop --color-activated: Color of the button when pressed
130
-
* @prop --background-activated: Background of the button when pressed
131
-
* @prop --background-activated-opacity: Opacity of the background when pressed
132
-
*/
133
-
```
134
-
135
-
Style the `ion-activated` class based on the spec for that element:
136
-
137
-
```scss
138
-
:host(.ion-activated) .button-native {
139
-
color: var(--color-activated);
140
-
141
-
&::after {
142
-
background: var(--background-activated);
143
-
144
-
opacity: var(--background-activated-opacity);
145
-
}
146
-
}
147
-
```
148
-
149
-
> Order is important! Activated should be after the focused & hover states.
150
-
151
-
152
-
#### User Customization
153
-
154
-
Setting the activated state on the `::after` pseudo-element allows the user to customize the activated state without knowing what the default opacity is set at. A user can customize in the following ways to have a solid red background on press, or they can leave out `--background-activated-opacity` and the button will use the default activated opacity to match the spec.
155
-
156
-
```css
157
-
ion-button {
158
-
--background-activated: red;
159
-
--background-activated-opacity: 1;
160
-
}
161
-
```
162
-
163
-
164
92
### Disabled
165
93
166
94
The disabled state should be set via prop on all components that render a native button. Setting a disabled state will change the opacity or color of the button and remove click events from firing.
@@ -197,7 +125,8 @@ render() {
197
125
}
198
126
```
199
127
200
-
> Note: if the class being added was for `ion-back-button` it would be `back-button-disabled`.
128
+
> [!NOTE]
129
+
> If the class being added was for `ion-back-button` it would be `back-button-disabled`.
201
130
202
131
#### CSS
203
132
@@ -215,16 +144,18 @@ The following CSS _at the bare minimum_ should be added for the disabled class,
215
144
216
145
TODO
217
146
147
+
218
148
### Focused
219
149
220
-
The focused state should be enabled for elements with actions when tabbed to via the keyboard. This will only work inside of an `ion-app`. It usually changes the opacity or background of an element.
150
+
The focused state should be enabled for elements with actions when tabbed to via the keyboard. This will only work inside of an `ion-app`. It usually changes the opacity or background of an element.
221
151
222
152
> [!WARNING]
223
153
> Do not use `:focus` because that will cause the focus to apply even when an element is tapped (because the element is now focused). Instead, we only want the focus state to be shown when it makes sense which is what the `.ion-focusable` utility mentioned below does.
224
154
225
155
> [!NOTE]
226
156
> The [`:focus-visible`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible) pseudo-class mostly does the same thing as our JavaScript-driven utility. However, it does not work well with Shadow DOM components as the element that receives focus is typically inside of the Shadow DOM, but we usually want to set the `:focus-visible` state on the host so we can style other parts of the component. Using other combinations such as `:has(:focus-visible)` does not work because `:has` does not pierce the Shadow DOM (as that would leak implementation details about the Shadow DOM contents). `:focus-within` does work with the Shadow DOM, but that has the same problem as `:focus` that was mentioned before. Unfortunately, a [`:focus-visible-within` pseudo-class does not exist yet](https://github.com/WICG/focus-visible/issues/151).
227
157
158
+
> [!IMPORTANT]
228
159
> Make sure the component has the correct [component structure](#component-structure) before continuing.
229
160
230
161
#### JavaScript
@@ -234,7 +165,7 @@ The `ion-focusable` class needs to be set on an element that can be focused:
234
165
```jsx
235
166
render() {
236
167
return (
237
-
<Host class='ion-focusable'>
168
+
<Host class="ion-focusable">
238
169
<slot></slot>
239
170
</Host>
240
171
);
@@ -269,7 +200,8 @@ Style the `ion-focused` class based on the spec for that element:
269
200
}
270
201
```
271
202
272
-
> Order is important! Focused should be after the activated and before the hover state.
203
+
> [!IMPORTANT]
204
+
> Order matters! Focused should be **before** the activated and hover states.
273
205
274
206
275
207
#### User Customization
@@ -286,11 +218,12 @@ ion-button {
286
218
287
219
### Hover
288
220
289
-
The [hover state](https://developer.mozilla.org/en-US/docs/Web/CSS/:hover) happens when a user moves their cursor on top of an element without pressing on it. It should not happen on mobile, only on desktop devices that support hover.
221
+
The [hover state](https://developer.mozilla.org/en-US/docs/Web/CSS/:hover) happens when a user moves their cursor on top of an element without pressing on it. It should not happen on mobile, only on desktop devices that support hover.
290
222
291
223
> [!NOTE]
292
224
> Some Android devices [incorrectly report their inputs](https://issues.chromium.org/issues/40855702) which can result in certain devices receiving hover events when they should not.
293
225
226
+
> [!IMPORTANT]
294
227
> Make sure the component has the correct [component structure](#component-structure) before continuing.
295
228
296
229
#### CSS
@@ -321,7 +254,8 @@ Style the `:hover` based on the spec for that element:
321
254
}
322
255
```
323
256
324
-
> Order is important! Hover should be before the activated state.
257
+
> [!IMPORTANT]
258
+
> Order matters! Hover should be **before** the activated state.
325
259
326
260
327
261
#### User Customization
@@ -336,6 +270,79 @@ ion-button {
336
270
```
337
271
338
272
273
+
### Activated
274
+
275
+
The activated state should be enabled for elements with actions on "press". It usually changes the opacity or background of an element.
276
+
277
+
> [!WARNING]
278
+
>`:active` should not be used here as it is not received on mobile Safari unless the element has a `touchstart` listener (which we don't necessarily want to have to add to every element). From [Safari Web Content Guide](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/AdjustingtheTextSize/AdjustingtheTextSize.html):
279
+
>
280
+
>> On iOS, mouse events are sent so quickly that the down or active state is never received. Therefore, the `:active` pseudo state is triggered only when there is a touch event set on the HTML element
281
+
282
+
> [!IMPORTANT]
283
+
> Make sure the component has the correct [component structure](#component-structure) before continuing.
284
+
285
+
#### JavaScript
286
+
287
+
The `ion-activatable` class needs to be set on an element that can be activated:
288
+
289
+
```jsx
290
+
render() {
291
+
return (
292
+
<Host class="ion-activatable">
293
+
<slot></slot>
294
+
</Host>
295
+
);
296
+
}
297
+
```
298
+
299
+
Once that is done, the element will get the `ion-activated` class added on press after a small delay. This delay exists so that the active state does not show up when an activatable element is tapped while scrolling.
300
+
301
+
In addition to setting that class, `ion-activatable-instant` can be set in order to have an instant press with no delay:
* @prop --color-activated: Color of the button when pressed
312
+
* @prop --background-activated: Background of the button when pressed
313
+
* @prop --background-activated-opacity: Opacity of the background when pressed
314
+
*/
315
+
```
316
+
317
+
Style the `ion-activated` class based on the spec for that element:
318
+
319
+
```scss
320
+
:host(.ion-activated) .button-native {
321
+
color: var(--color-activated);
322
+
323
+
&::after {
324
+
background: var(--background-activated);
325
+
326
+
opacity: var(--background-activated-opacity);
327
+
}
328
+
}
329
+
```
330
+
331
+
> [!IMPORTANT]
332
+
> Order matters! Activated should be **after** the focused & hover states.
333
+
334
+
#### User Customization
335
+
336
+
Setting the activated state on the `::after` pseudo-element allows the user to customize the activated state without knowing what the default opacity is set at. A user can customize in the following ways to have a solid red background on press, or they can leave out `--background-activated-opacity` and the button will use the default activated opacity to match the spec.
337
+
338
+
```css
339
+
ion-button {
340
+
--background-activated: red;
341
+
--background-activated-opacity: 1;
342
+
}
343
+
```
344
+
345
+
339
346
### Ripple Effect
340
347
341
348
The ripple effect should be added to elements for Material Design. It *requires* the `ion-activatable` class to be set on the parent element to work, and relative positioning on the parent.
0 commit comments