Skip to content

Commit ea8c1e2

Browse files
feat(input, textarea, select): add section for start and end slots (#3271)
1 parent 2c86917 commit ea8c1e2

File tree

21 files changed

+452
-0
lines changed

21 files changed

+452
-0
lines changed

docs/api/input.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,22 @@ Please submit bug reports with Maskito to the [Maskito Github repository](https:
148148

149149
:::
150150

151+
## Start and End Slots (experimental)
152+
153+
The `start` and `end` slots can be used to place icons, buttons, or prefix/suffix text on either side of the input.
154+
155+
Note that this feature is considered experimental because it relies on a simulated version of [Web Component slots](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots). As a result, the simulated behavior may not exactly match the native slot behavior.
156+
157+
:::note
158+
In most cases, [Icon](./icon.md) components placed in these slots should have `aria-hidden="true"`. See the [Icon accessibility docs](https://ionicframework.com/docs/api/icon#accessibility) for more information.
159+
160+
If slot content is meant to be interacted with, it should be wrapped in an interactive element such as a [Button](./button.md). This ensures that the content can be tabbed to.
161+
:::
162+
163+
import StartEndSlots from '@site/static/usage/v7/input/start-end-slots/index.md';
164+
165+
<StartEndSlots />
166+
151167
## Theming
152168

153169
### Colors

docs/api/select.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,20 @@ import InterfaceOptionsExample from '@site/static/usage/v7/select/customization/
173173

174174
<InterfaceOptionsExample />
175175

176+
## Start and End Slots
177+
178+
The `start` and `end` slots can be used to place icons, buttons, or prefix/suffix text on either side of the select. If the slot content is clicked, the select will not open.
179+
180+
:::note
181+
In most cases, [Icon](./icon.md) components placed in these slots should have `aria-hidden="true"`. See the [Icon accessibility docs](https://ionicframework.com/docs/api/icon#accessibility) for more information.
182+
183+
If slot content is meant to be interacted with, it should be wrapped in an interactive element such as a [Button](./button.md). This ensures that the content can be tabbed to.
184+
:::
185+
186+
import StartEndSlots from '@site/static/usage/v7/select/start-end-slots/index.md';
187+
188+
<StartEndSlots />
189+
176190
## Customization
177191

178192
There are two units that make up the Select component and each need to be styled separately. The `ion-select` element is represented on the view by the selected value(s), or placeholder if there is none, and dropdown icon. The interface, which is defined in the [Interfaces](#interfaces) section above, is the dialog that opens when clicking on the `ion-select`. The interface contains all of the options defined by adding `ion-select-option` elements. The following sections will go over the differences between styling these.

docs/api/textarea.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,22 @@ import ClearOnEditPlayground from '@site/static/usage/v7/textarea/clear-on-edit/
109109

110110
<ClearOnEditPlayground />
111111

112+
## Start and End Slots (experimental)
113+
114+
The `start` and `end` slots can be used to place icons, buttons, or prefix/suffix text on either side of the textarea.
115+
116+
Note that this feature is considered experimental because it relies on a simulated version of [Web Component slots](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots). As a result, the simulated behavior may not exactly match the native slot behavior.
117+
118+
:::note
119+
In most cases, [Icon](./icon.md) components placed in these slots should have `aria-hidden="true"`. See the [Icon accessibility docs](https://ionicframework.com/docs/api/icon#accessibility) for more information.
120+
121+
If slot content is meant to be interacted with, it should be wrapped in an interactive element such as a [Button](./button.md). This ensures that the content can be tabbed to.
122+
:::
123+
124+
import StartEndSlots from '@site/static/usage/v7/textarea/start-end-slots/index.md';
125+
126+
<StartEndSlots />
127+
112128
## Migrating from Legacy Textarea Syntax
113129

114130
A simpler textarea syntax was introduced in Ionic 7.0. This new syntax reduces the boilerplate required to setup an textarea, resolves accessibility issues, and improves the developer experience.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
```html
2+
<ion-list>
3+
<ion-item>
4+
<ion-input labelPlacement="stacked" label="Email" placeholder="email@domain.com">
5+
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
6+
<ion-button fill="clear" slot="end" aria-label="Show/hide">
7+
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
8+
</ion-button>
9+
</ion-input>
10+
</ion-item>
11+
</ion-list>
12+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Input</title>
7+
<link rel="stylesheet" href="../../../common.css" />
8+
<script src="../../../common.js"></script>
9+
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@7/dist/ionic/ionic.esm.js"></script>
10+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@7/css/ionic.bundle.css" />
11+
</head>
12+
13+
<body>
14+
<ion-app>
15+
<ion-content>
16+
<div class="container">
17+
<ion-list>
18+
<ion-item>
19+
<ion-input label-placement="stacked" label="Email" placeholder="email@domain.com">
20+
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
21+
<ion-button fill="clear" slot="end" aria-label="Show/hide">
22+
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
23+
</ion-button>
24+
</ion-input>
25+
</ion-item>
26+
</ion-list>
27+
</div>
28+
</ion-content>
29+
</ion-app>
30+
</body>
31+
</html>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import Playground from '@site/src/components/global/Playground';
2+
3+
import javascript from './javascript.md';
4+
import react from './react.md';
5+
import vue from './vue.md';
6+
import angular from './angular.md';
7+
8+
<Playground
9+
version="7"
10+
code={{
11+
javascript,
12+
react,
13+
vue,
14+
angular,
15+
}}
16+
src="usage/v7/input/start-end-slots/demo.html"
17+
/>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
```html
2+
<ion-list>
3+
<ion-item>
4+
<ion-input label-placement="stacked" label="Email" placeholder="email@domain.com">
5+
<ion-icon slot="start" name="lock-closed" aria-hidden="true"></ion-icon>
6+
<ion-button fill="clear" slot="end" aria-label="Show/hide">
7+
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
8+
</ion-button>
9+
</ion-input>
10+
</ion-item>
11+
</ion-list>
12+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
```tsx
2+
import React from 'react';
3+
import { IonButton, IonIcon, IonInput, IonItem, IonList } from '@ionic/react';
4+
import { eye, lockClosed } from 'ionicons/icons';
5+
6+
function Example() {
7+
return (
8+
<IonList>
9+
<IonItem>
10+
<IonInput labelPlacement="stacked" label="Email" placeholder="email@domain.com">
11+
<IonIcon slot="start" icon={lockClosed} aria-hidden="true"></IonIcon>
12+
<IonButton fill="clear" slot="end" aria-label="Show/hide">
13+
<IonIcon slot="icon-only" name={eye} aria-hidden="true"></IonIcon>
14+
</IonButton>
15+
</IonInput>
16+
</IonItem>
17+
</IonList>
18+
);
19+
}
20+
export default Example;
21+
```
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
```html
2+
<template>
3+
<ion-list>
4+
<ion-item>
5+
<ion-input label-placement="stacked" label="Email" placeholder="email@domain.com">
6+
<ion-icon slot="start" :icon="lockClosed" aria-hidden="true"></ion-icon>
7+
<ion-button fill="clear" slot="end" aria-label="Show/hide">
8+
<ion-icon slot="icon-only" :icon="eye" aria-hidden="true"></ion-icon>
9+
</ion-button>
10+
</ion-input>
11+
</ion-item>
12+
</ion-list>
13+
</template>
14+
15+
<script lang="ts">
16+
import { IonButton, IonIcon, IonInput, IonItem, IonList } from '@ionic/vue';
17+
import { eye, lockClosed } from 'ionicons/icons';
18+
import { defineComponent } from 'vue';
19+
20+
export default defineComponent({
21+
components: {
22+
IonButton,
23+
IonIcon,
24+
IonInput,
25+
IonItem,
26+
IonList,
27+
},
28+
setup() {
29+
return { eye, lockClosed };
30+
},
31+
});
32+
</script>
33+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
```html
2+
<ion-list>
3+
<ion-item>
4+
<ion-select labelPlacement="stacked" label="Favorite fruit" value="apple">
5+
<ion-icon slot="start" name="leaf" aria-hidden="true"></ion-icon>
6+
<ion-select-option value="apple">Apple</ion-select-option>
7+
<ion-select-option value="banana">Banana</ion-select-option>
8+
<ion-select-option value="orange">Orange</ion-select-option>
9+
<ion-button fill="clear" slot="end" aria-label="Show/hide password">
10+
<ion-icon slot="icon-only" name="eye" aria-hidden="true"></ion-icon>
11+
</ion-button>
12+
</ion-select>
13+
</ion-item>
14+
</ion-list>
15+
```

0 commit comments

Comments
 (0)