Skip to content

Commit 36ffb61

Browse files
merge feature-8.6
2 parents 9edf92d + 10fd81c commit 36ffb61

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1637
-1
lines changed

docs/api/datetime.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import CustomizingButtonTexts from '@site/static/usage/v8/datetime/buttons/custo
3636
import HighlightedDatesArray from '@site/static/usage/v8/datetime/highlightedDates/array/index.md';
3737
import HighlightedDatesCallback from '@site/static/usage/v8/datetime/highlightedDates/callback/index.md';
3838

39+
import ShowAdjacentDays from '@site/static/usage/v8/datetime/show-adjacent-days/index.md';
40+
3941
import MultipleDateSelection from '@site/static/usage/v8/datetime/multiple/index.md';
4042

4143
import GlobalTheming from '@site/static/usage/v8/datetime/styling/global-theming/index.md';
@@ -248,6 +250,18 @@ import Wheel from '@site/static/usage/v8/datetime/presentation/wheel/index.md';
248250

249251
<Wheel />
250252

253+
## Show Adjacent Days
254+
255+
If the `showAdjacentDays` property is set to `true`, days from the previous and next month will be displayed in the calendar view to fill any empty spaces at the beginning or end of the month. When a user clicks on an enabled adjacent day, the calendar will smoothly animate to show that month's view.
256+
257+
The calendar view always displays 6 rows when `showAdjacentDays` is enabled, so days from the previous or next month will be shown as needed to fill the grid. For example, even if a month starts on the first day of the week and ends within the fifth row, days from the next month will appear at the end to complete the sixth row.
258+
259+
:::note
260+
This property is only supported when using `presentation="date"` and `preferWheel="false"`.
261+
:::
262+
263+
<ShowAdjacentDays />
264+
251265
## Multiple Date Selection
252266

253267
If the `multiple` property is set to `true`, multiple dates can be selected from the calendar picker. Clicking a selected date will deselect it.

docs/api/input-otp.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
title: "ion-input-otp"
3+
---
4+
import Props from '@ionic-internal/component-api/v8/input-otp/props.md';
5+
import Events from '@ionic-internal/component-api/v8/input-otp/events.md';
6+
import Methods from '@ionic-internal/component-api/v8/input-otp/methods.md';
7+
import Parts from '@ionic-internal/component-api/v8/input-otp/parts.md';
8+
import CustomProps from '@ionic-internal/component-api/v8/input-otp/custom-props.mdx';
9+
import Slots from '@ionic-internal/component-api/v8/input-otp/slots.md';
10+
11+
<head>
12+
<title>ion-input-otp: One-Time Password Input Component</title>
13+
<meta name="description" content="ion-input-otp is a component for entering one-time passwords (OTP) with support for multiple input boxes and automatic focus management." />
14+
</head>
15+
16+
import EncapsulationPill from '@components/page/api/EncapsulationPill';
17+
18+
<EncapsulationPill type="scoped" />
19+
20+
The Input OTP component is a specialized input component designed for entering one-time passwords (OTP). It provides a user-friendly interface for entering verification codes with support for multiple input boxes and automatic focus management.
21+
22+
## Basic Usage
23+
24+
The component provides 4 input boxes by default, which is a common length for many verification codes. The number of input boxes can be customized using the `length` property.
25+
26+
import Basic from '@site/static/usage/v8/input-otp/basic/index.md';
27+
28+
<Basic />
29+
30+
## Type
31+
32+
The `type` property determines the input format, supporting either numeric or alphanumeric verification codes. It accepts two values: `number` and `text`. It uses `type="number"` by default for entering numeric verification codes. When `type="text"` is specified, it accepts alphanumeric input. This flexibility allows handling different OTP formats, whether numeric-only codes (like SMS verification codes) or alphanumeric codes (like backup codes or recovery keys).
33+
34+
The `type` property automatically sets both the `inputmode` and `pattern` attributes:
35+
- When `type="number"`:
36+
- Sets `inputmode="numeric"` to show a numeric keyboard on mobile devices
37+
- Sets `pattern="[\p{N}]"` to allow only numeric input
38+
- When `type="text"`:
39+
- Sets `inputmode="text"` to show a standard keyboard
40+
- Sets `pattern="[\p{L}\p{N}]"` to allow alphanumeric input
41+
42+
See the [Pattern](#pattern) section for more details on pattern validation and customization.
43+
44+
import Type from '@site/static/usage/v8/input-otp/type/index.md';
45+
46+
<Type />
47+
48+
## Shape
49+
50+
The `shape` property controls the border radius of the input boxes, creating rounded or sharp corners.
51+
52+
import Shape from '@site/static/usage/v8/input-otp/shape/index.md';
53+
54+
<Shape />
55+
56+
## Fill
57+
58+
The `fill` property controls the background style of the input boxes, offering bordered or filled backgrounds.
59+
60+
import Fill from '@site/static/usage/v8/input-otp/fill/index.md';
61+
62+
<Fill />
63+
64+
## Size
65+
66+
The `size` property provides different size options for the input boxes.
67+
68+
import Size from '@site/static/usage/v8/input-otp/size/index.md';
69+
70+
<Size />
71+
72+
## Separators
73+
74+
The `separators` property adds visual dividers between one or more of the input boxes. Separators can be defined in three ways:
75+
- Comma-separated string of numbers (e.g., `"1,3"`)
76+
- Array of numbers (e.g., `[1, 3]`)
77+
- String `"all"` to show separators between every input box
78+
79+
The numbers represent the index after which a separator should appear. For example, `"1,3"` displays a separator after the first and third input box. This can be used to create visually distinct groupings of input boxes, but it will still have one value.
80+
81+
import Separators from '@site/static/usage/v8/input-otp/separators/index.md';
82+
83+
<Separators />
84+
85+
## States
86+
87+
The component supports various states for automatic styling of input boxes:
88+
- `disabled` and `readonly` states via respective properties
89+
- Form validation states: `valid` and `invalid` visually indicated through CSS classes
90+
- In Angular: validation states are automatically managed through the framework's value accessors and form validation
91+
- For other frameworks: developers must manually add `ion-valid`, `ion-invalid`, and `ion-touched` classes
92+
- `ion-invalid` styles only display when touched (`ion-touched`)
93+
- `ion-valid` styles only display when focused (`has-focus`)
94+
95+
import States from '@site/static/usage/v8/input-otp/states/index.md';
96+
97+
<States />
98+
99+
## Pattern
100+
101+
The `pattern` property enables custom validation using regular expressions. It accepts a [string regular expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet) or [unicode regular expression](https://www.regular-expressions.info/unicode.html) to validate allowed characters. The `pattern` must match the entire value, not just a subset. Default patterns:
102+
- `type="number"`: `"[\p{N}]"` for matching any kind of numeric character in any script.
103+
- `type="text"`: `"[\p{L}\p{N}]"` for any kind of numeric character in any script and any kind of letter from any language.
104+
105+
The component will prevent users from entering any characters that don't match the specified pattern. Developers can override these defaults by providing their own pattern string to match specific input requirements.
106+
107+
:::tip
108+
When using a custom `pattern`, remember that the `type` property controls which keyboard appears on mobile devices:
109+
- Use `type="number"` for numeric-only patterns to show the numeric keyboard
110+
- Use `type="text"` for patterns that include letters to show the alphanumeric keyboard
111+
:::
112+
113+
import Pattern from '@site/static/usage/v8/input-otp/pattern/index.md';
114+
115+
<Pattern />
116+
117+
## Theming
118+
119+
### Colors
120+
121+
The `color` property changes the color palette for input boxes. For `outline` fills, this property changes the caret color, highlight color and border color. For `solid` fills, this property changes the caret color and highlight color.
122+
123+
:::note
124+
The `color` property does *not* change the text color of the input OTP. For that, use the [`--color` CSS property](#css-custom-properties-1).
125+
:::
126+
127+
import Colors from '@site/static/usage/v8/input-otp/theming/colors/index.md';
128+
129+
<Colors />
130+
131+
### CSS Custom Properties
132+
133+
Input OTP uses scoped encapsulation, which means it will automatically scope its CSS by appending each of the styles with an additional class at runtime. Overriding scoped selectors in CSS requires a [higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) selector. Targeting the `ion-input-otp` for customization will not work; therefore we recommend adding a class and customizing it that way. Due to certain styles being applied based on the `fill`, you may need to override properties on the fills separately.
134+
135+
import CSSProps from '@site/static/usage/v8/input-otp/theming/css-properties/index.md';
136+
137+
<CSSProps />
138+
139+
## Accessibility
140+
141+
### Keyboard Interactions
142+
143+
The keyboard navigation for Input OTP follows the [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/)'s recommendations for composite widgets. It is treated as a composite widget because it contains multiple focusable elements (input boxes) that function as a single control.
144+
145+
These keyboard interactions apply to all `ion-input-otp` elements when the component is not disabled.
146+
147+
| Key | Description |
148+
| --- | --- |
149+
| <kbd>Tab</kbd> | When first tabbing into the component, focus moves to the first empty box. If all boxes are filled, focus moves to the last box. Once inside the component, tabbing moves to the next focusable element on the page. |
150+
| <kbd>Shift</kbd> + <kbd>Tab</kbd> | When tabbing backwards into the component, focus moves to the first empty box. If all boxes are filled, focus moves to the last box. Once inside the component, shift tabbing focus moves to the previous focusable element on the page. |
151+
| <kbd>ArrowRight</kbd> | Moves focus to the next input box, stopping at the first empty box. In RTL mode, moves focus back to any previous box that contains a value. |
152+
| <kbd>ArrowLeft</kbd> | Moves focus back to any previous box that contains a value. In RTL mode, moves focus to the next input box, stopping at the first empty box. |
153+
| Any character matching the `pattern` property | Fills the current box and automatically moves focus to the next empty box. If all boxes are filled, focus remains on the last box. If the current box has a value, override the value with the entered character. In RTL mode, input fills boxes from right to left. |
154+
| <kbd>Backspace</kbd> | In an empty box: moves focus back one box and clears its value. <br/> In a box with a value: clears that value. <br/> With values in boxes to the right: shifts them all one position to the left. In RTL mode, with values in boxes to the left: shifts them all one position to the right. |
155+
| <kbd>Ctrl</kbd> + <kbd>V</kbd> <br/> <kbd>Cmd</kbd> + <kbd>V</kbd> | Pastes content starting from the first box, regardless of which box is currently focused. All existing values are cleared before pasting. For example, if you have "1234" in all boxes and paste "56", the result will be "56" in the first two boxes with the remaining boxes empty. If the pasted content is longer than the available boxes, the extra characters are ignored. |
156+
157+
## Properties
158+
<Props />
159+
160+
## Events
161+
<Events />
162+
163+
## Methods
164+
<Methods />
165+
166+
## CSS Shadow Parts
167+
<Parts />
168+
169+
## CSS Custom Properties
170+
<CustomProps />
171+
172+
## Slots
173+
<Slots />

sidebars.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ module.exports = {
351351
type: 'category',
352352
label: 'Input',
353353
collapsed: false,
354-
items: ['api/input', 'api/input-password-toggle', 'api/textarea'],
354+
items: ['api/input', 'api/input-password-toggle', 'api/input-otp', 'api/textarea'],
355355
},
356356
{
357357
type: 'category',
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```html
2+
<ion-datetime show-adjacent-days="true"></ion-datetime>
3+
```
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
```ts
2+
import { Component } from '@angular/core';
3+
import { IonDatetime } from '@ionic/angular/standalone';
4+
5+
@Component({
6+
selector: 'app-example',
7+
templateUrl: 'example.component.html',
8+
styleUrls: ['example.component.css'],
9+
imports: [IonDatetime],
10+
})
11+
export class ExampleComponent {}
12+
```
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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>Datetime</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@8/dist/ionic/ionic.esm.js"></script>
10+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@8/css/ionic.bundle.css" />
11+
<style>
12+
ion-datetime {
13+
width: 350px;
14+
}
15+
</style>
16+
</head>
17+
18+
<body>
19+
<ion-app>
20+
<ion-content>
21+
<div class="container">
22+
<ion-datetime show-adjacent-days="true"></ion-datetime>
23+
</div>
24+
</ion-content>
25+
</ion-app>
26+
</body>
27+
</html>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
7+
import angular_example_component_html from './angular/example_component_html.md';
8+
import angular_example_component_ts from './angular/example_component_ts.md';
9+
10+
<Playground
11+
version="8"
12+
size="medium"
13+
code={{
14+
javascript,
15+
react,
16+
vue,
17+
angular: {
18+
files: {
19+
'src/app/example.component.html': angular_example_component_html,
20+
'src/app/example.component.ts': angular_example_component_ts,
21+
},
22+
},
23+
}}
24+
src="usage/v8/datetime/show-adjacent-days/demo.html"
25+
/>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```html
2+
<ion-datetime show-adjacent-days="true"></ion-datetime>
3+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
```tsx
2+
import React, { useRef, useEffect } from 'react';
3+
import { IonDatetime } from '@ionic/react';
4+
5+
function Example() {
6+
return <IonDatetime showAdjacentDays={true}></IonDatetime>;
7+
}
8+
export default Example;
9+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
```html
2+
<template>
3+
<ion-datetime show-adjacent-days="true"></ion-datetime>
4+
</template>
5+
6+
<script lang="ts">
7+
import { IonDatetime } from '@ionic/vue';
8+
import { defineComponent } from 'vue';
9+
10+
export default defineComponent({
11+
components: { IonDatetime },
12+
});
13+
</script>
14+
```
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
```html
2+
<ion-input-otp> Didn't get a code? <a href="#">Resend the code</a> </ion-input-otp>
3+
<ion-input-otp length="6"> Didn't get a code? <a href="#">Resend the code</a> </ion-input-otp>
4+
```
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
```ts
2+
import { Component } from '@angular/core';
3+
import { IonInputOtp } from '@ionic/angular/standalone';
4+
5+
@Component({
6+
selector: 'app-example',
7+
templateUrl: 'example.component.html',
8+
styleUrls: ['example.component.css'],
9+
imports: [IonInputOtp],
10+
})
11+
export class ExampleComponent {}
12+
```
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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 OTP</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@8/dist/ionic/ionic.esm.js"></script>
10+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@8/css/ionic.bundle.css" />
11+
12+
<style>
13+
.container {
14+
flex-direction: column;
15+
}
16+
</style>
17+
</head>
18+
19+
<body>
20+
<ion-app>
21+
<ion-content>
22+
<div class="container">
23+
<ion-input-otp> Didn't get a code? <a href="#">Resend the code</a> </ion-input-otp>
24+
<ion-input-otp length="6"> Didn't get a code? <a href="#">Resend the code</a> </ion-input-otp>
25+
</div>
26+
</ion-content>
27+
</ion-app>
28+
</body>
29+
</html>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
7+
import angular_example_component_html from './angular/example_component_html.md';
8+
import angular_example_component_ts from './angular/example_component_ts.md';
9+
10+
<Playground
11+
version="8"
12+
code={{
13+
javascript,
14+
react,
15+
vue,
16+
angular: {
17+
files: {
18+
'src/app/example.component.html': angular_example_component_html,
19+
'src/app/example.component.ts': angular_example_component_ts,
20+
},
21+
},
22+
}}
23+
src="usage/v8/input-otp/basic/demo.html"
24+
/>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
```html
2+
<ion-input-otp> Didn't get a code? <a href="#">Resend the code</a> </ion-input-otp>
3+
<ion-input-otp length="6"> Didn't get a code? <a href="#">Resend the code</a> </ion-input-otp>
4+
```

0 commit comments

Comments
 (0)