Skip to content

Commit 6f73533

Browse files
committed
docs(select): add rich content options playground
1 parent 004228d commit 6f73533

11 files changed

Lines changed: 694 additions & 0 deletions

File tree

docs/api/select.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ import StartEndSlots from '@site/static/usage/v9/select/start-end-slots/index.md
201201

202202
<StartEndSlots />
203203

204+
## Rich Content Options
205+
206+
TODO
207+
208+
import RichContentOptions from '@site/static/usage/v9/select/rich-content-options/index.md';
209+
210+
<RichContentOptions />
211+
204212
## Customization
205213

206214
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.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
```html
2+
<ion-list>
3+
@for (selectInterface of selectInterfaces; track selectInterface) {
4+
<ion-item>
5+
<ion-select
6+
[label]="formatInterfaceLabel(selectInterface)"
7+
placeholder="Select one"
8+
[interface]="selectInterface"
9+
[interfaceOptions]="interfaceOptions"
10+
>
11+
<ion-select-option value="airplane" description="Carry-on · Window seat">
12+
<ion-icon slot="start" size="large" aria-hidden="true" name="airplane"></ion-icon>
13+
<span class="option-title">Flight</span>
14+
<span class="option-subtitle">2h 15m · Nonstop</span>
15+
<ion-badge slot="end" color="tertiary">$279</ion-badge>
16+
</ion-select-option>
17+
<ion-select-option value="bus" description="Bike rack · Wi-Fi">
18+
<ion-icon slot="start" size="large" aria-hidden="true" name="bus"></ion-icon>
19+
<span class="option-title">Bus</span>
20+
<span class="option-subtitle">6h 40m · 1 transfer</span>
21+
<ion-badge slot="end" color="tertiary">$39</ion-badge>
22+
</ion-select-option>
23+
<ion-select-option value="car" description="Unlimited miles · GPS">
24+
<ion-icon slot="start" size="large" aria-hidden="true" name="car"></ion-icon>
25+
<span class="option-title">Rental Car</span>
26+
<span class="option-subtitle">5h 10m · Flexible route</span>
27+
<ion-badge slot="end" color="tertiary">$92</ion-badge>
28+
</ion-select-option>
29+
<ion-select-option value="train" description="Reserved seat · Wi-Fi">
30+
<ion-icon slot="start" size="large" aria-hidden="true" name="train"></ion-icon>
31+
<span class="option-title">Train</span>
32+
<span class="option-subtitle">4h 55m · Direct</span>
33+
<ion-badge slot="end" color="tertiary">$64</ion-badge>
34+
</ion-select-option>
35+
</ion-select>
36+
</ion-item>
37+
}
38+
</ion-list>
39+
```
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
```ts
2+
import { Component } from '@angular/core';
3+
import { IonBadge, IonIcon, IonItem, IonList, IonSelect, IonSelectOption } from '@ionic/angular/standalone';
4+
import { addIcons } from 'ionicons';
5+
import { airplane, bus, car, train } from 'ionicons/icons';
6+
7+
@Component({
8+
selector: 'app-example',
9+
templateUrl: 'example.component.html',
10+
imports: [IonBadge, IonIcon, IonItem, IonList, IonSelect, IonSelectOption],
11+
})
12+
export class ExampleComponent {
13+
readonly selectInterfaces = ['alert', 'action-sheet', 'modal', 'popover'];
14+
15+
/* The interfaceOptions property is for demonstration purposes only. */
16+
/* It is not required for the rich options to work. */
17+
readonly interfaceOptions = { header: 'Travel mode' };
18+
19+
constructor() {
20+
addIcons({ airplane, bus, car, train });
21+
}
22+
23+
formatInterfaceLabel(selectInterface: string): string {
24+
return selectInterface
25+
.split('-')
26+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
27+
.join(' ');
28+
}
29+
}
30+
```
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
```css
2+
/* These styles are for demonstration purposes only. */
3+
/* They are not required for the rich options to work. */
4+
5+
/* Alert Interface */
6+
ion-alert.select-alert {
7+
--min-width: 350px;
8+
}
9+
10+
/* Action Sheet Interface */
11+
.action-sheet-button-label {
12+
flex: 1 1 auto;
13+
text-align: start;
14+
}
15+
16+
/* Modal, Popover Interfaces */
17+
ion-popover.select-popover ion-list ion-radio.in-item::part(label),
18+
ion-modal.select-modal ion-list ion-radio.in-item::part(label) {
19+
margin-top: 10px;
20+
margin-bottom: 10px;
21+
}
22+
23+
/* All Interfaces */
24+
.alert-radio-label-text,
25+
.action-sheet-button-label-text,
26+
.select-option-label-text,
27+
.select-option-content {
28+
display: flex;
29+
flex-direction: column;
30+
gap: 2px;
31+
}
32+
33+
/* Custom Select Option Title */
34+
.select-option-content .option-title {
35+
font-size: 1rem;
36+
font-weight: 600;
37+
line-height: initial;
38+
}
39+
40+
/* Custom Select Option Subtitle */
41+
.select-option-content .option-subtitle {
42+
display: block;
43+
font-size: 0.8125rem;
44+
font-weight: 500;
45+
line-height: initial;
46+
}
47+
```
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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>Select - Rich Content Option</title>
7+
<link rel="stylesheet" href="../../common.css" />
8+
<script src="../../common.js"></script>
9+
<script>
10+
window.Ionic = {
11+
config: {
12+
innerHTMLTemplatesEnabled: true,
13+
},
14+
};
15+
</script>
16+
<script
17+
type="module"
18+
src="https://cdn.jsdelivr.net/npm/@ionic/core@8.8.7-dev.11779221548.1d38f927/dist/ionic/ionic.esm.js"
19+
></script>
20+
<link
21+
rel="stylesheet"
22+
href="https://cdn.jsdelivr.net/npm/@ionic/core@8.8.7-dev.11779221548.1d38f927/css/ionic.bundle.css"
23+
/>
24+
25+
<style>
26+
.container > ion-list {
27+
min-width: 400px;
28+
}
29+
30+
/* These styles are for demonstration purposes only. */
31+
/* They are not required for the rich options to work. */
32+
33+
/* Alert Interface */
34+
ion-alert.select-alert {
35+
--min-width: 350px;
36+
}
37+
38+
/* Action Sheet Interface */
39+
.action-sheet-button-label {
40+
flex: 1 1 auto;
41+
text-align: start;
42+
}
43+
44+
/* Modal, Popover Interfaces */
45+
ion-popover.select-popover ion-list ion-radio.in-item::part(label),
46+
ion-modal.select-modal ion-list ion-radio.in-item::part(label) {
47+
margin-top: 10px;
48+
margin-bottom: 10px;
49+
}
50+
51+
/* All Interfaces */
52+
.alert-radio-label-text,
53+
.action-sheet-button-label-text,
54+
.select-option-label-text,
55+
.select-option-content {
56+
display: flex;
57+
flex-direction: column;
58+
gap: 2px;
59+
}
60+
61+
/* Custom Select Option Title */
62+
.select-option-content .option-title {
63+
font-size: 1rem;
64+
font-weight: 600;
65+
line-height: initial;
66+
}
67+
68+
/* Custom Select Option Subtitle */
69+
.select-option-content .option-subtitle {
70+
display: block;
71+
font-size: 0.8125rem;
72+
font-weight: 500;
73+
line-height: initial;
74+
}
75+
</style>
76+
</head>
77+
78+
<body>
79+
<ion-app>
80+
<ion-content class="ion-padding">
81+
<div class="container">
82+
<ion-list>
83+
<!-- Dynamically created Select components will be added here -->
84+
</ion-list>
85+
</div>
86+
</ion-content>
87+
</ion-app>
88+
89+
<script>
90+
/* Helper function to format the interface label */
91+
const formatInterfaceLabel = (selectInterface) => {
92+
return selectInterface
93+
.split('-')
94+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
95+
.join(' ');
96+
};
97+
98+
/* Dynamically create the different Select components */
99+
const selectInterfaces = ['alert', 'action-sheet', 'modal', 'popover'];
100+
101+
selectInterfaces.forEach((selectInterface) => {
102+
const list = document.querySelector('ion-list');
103+
const item = document.createElement('ion-item');
104+
const select = document.createElement('ion-select');
105+
select.label = formatInterfaceLabel(selectInterface);
106+
select.placeholder = 'Select one';
107+
select.interface = selectInterface;
108+
109+
const optionsHTML = `
110+
<ion-select-option value="airplane" description="Carry-on · Window seat">
111+
<ion-icon slot="start" size="large" aria-hidden="true" name="airplane"></ion-icon>
112+
<span class="option-title">Flight</span>
113+
<span class="option-subtitle">2h 15m · Nonstop</span>
114+
<ion-badge slot="end" color="tertiary">$279</ion-badge>
115+
</ion-select-option>
116+
<ion-select-option value="bus" description="Bike rack · Wi-Fi">
117+
<ion-icon slot="start" size="large" aria-hidden="true" name="bus"></ion-icon>
118+
<span class="option-title">Bus</span>
119+
<span class="option-subtitle">6h 40m · 1 transfer</span>
120+
<ion-badge slot="end" color="tertiary">$39</ion-badge>
121+
</ion-select-option>
122+
<ion-select-option value="car" description="Unlimited miles · GPS">
123+
<ion-icon slot="start" size="large" aria-hidden="true" name="car"></ion-icon>
124+
<span class="option-title">Rental Car</span>
125+
<span class="option-subtitle">5h 10m · Flexible route</span>
126+
<ion-badge slot="end" color="tertiary">$92</ion-badge>
127+
</ion-select-option>
128+
<ion-select-option value="train" description="Reserved seat · Wi-Fi">
129+
<ion-icon slot="start" size="large" aria-hidden="true" name="train"></ion-icon>
130+
<span class="option-title">Train</span>
131+
<span class="option-subtitle">4h 55m · Direct</span>
132+
<ion-badge slot="end" color="tertiary">$64</ion-badge>
133+
</ion-select-option>
134+
`;
135+
select.innerHTML = optionsHTML;
136+
137+
/* The interfaceOptions property is for demonstration purposes only. */
138+
/* It is not required for the rich options to work. */
139+
select.interfaceOptions = {
140+
header: 'Travel mode',
141+
};
142+
143+
item.appendChild(select);
144+
list.appendChild(item);
145+
});
146+
</script>
147+
</body>
148+
</html>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import Playground from '@site/src/components/global/Playground';
2+
3+
import javascript_index_html from './javascript/index_html.md';
4+
import javascript_index_ts from './javascript/index_ts.md';
5+
6+
import react_main_tsx from './react/main_tsx.md';
7+
import react_main_css from './react/main_css.md';
8+
9+
import vue from './vue.md';
10+
11+
import angular_example_component_html from './angular/example_component_html.md';
12+
import angular_example_component_ts from './angular/example_component_ts.md';
13+
import angular_global_css from './angular/global_css.md';
14+
15+
<Playground
16+
version="9"
17+
ionicConfig={{ innerHTMLTemplatesEnabled: true }}
18+
code={{
19+
javascript: {
20+
files: {
21+
'index.html': javascript_index_html,
22+
'index.ts': javascript_index_ts,
23+
},
24+
},
25+
react: {
26+
files: {
27+
'src/main.tsx': react_main_tsx,
28+
'src/main.css': react_main_css,
29+
},
30+
},
31+
vue,
32+
angular: {
33+
files: {
34+
'src/app/example.component.html': angular_example_component_html,
35+
'src/app/example.component.ts': angular_example_component_ts,
36+
'src/global.css': angular_global_css,
37+
},
38+
},
39+
}}
40+
size="large"
41+
src="usage/v9/select/rich-content-options/demo.html"
42+
/>

0 commit comments

Comments
 (0)