Skip to content

Commit 9957376

Browse files
committed
feat(input-otp): convert to shadow
1 parent ab96071 commit 9957376

File tree

7 files changed

+61
-7
lines changed

7 files changed

+61
-7
lines changed

BREAKING.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
1919
- [Card](#version-9x-card)
2020
- [Chip](#version-9x-chip)
2121
- [Grid](#version-9x-grid)
22+
- [Input Otp](#version-9x-input-otp)
2223
- [Radio Group](#version-9x-radio-group)
2324
- [Textarea](#version-9x-textarea)
2425

@@ -149,6 +150,12 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
149150
</ion-grid>
150151
```
151152

153+
<h4 id="version-9x-input-otp">Input Otp</h4>
154+
155+
Converted `ion-input-otp` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
156+
157+
If you were targeting the internals of `ion-input-otp` in your CSS, you will need to target the `group`, `container`, `native`, `separator` or `description` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
158+
152159
<h4 id="version-9x-radio-group">Radio Group</h4>
153160

154161
Converted `ion-radio-group` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).

core/api.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,18 +1035,20 @@ ion-input,css-prop,--placeholder-opacity,ionic
10351035
ion-input,css-prop,--placeholder-opacity,ios
10361036
ion-input,css-prop,--placeholder-opacity,md
10371037

1038-
ion-input-otp,scoped
1038+
ion-input-otp,shadow
10391039
ion-input-otp,prop,autocapitalize,string,'off',false,false
10401040
ion-input-otp,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
10411041
ion-input-otp,prop,disabled,boolean,false,false,true
10421042
ion-input-otp,prop,fill,"outline" | "solid" | undefined,'outline',false,false
10431043
ion-input-otp,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
10441044
ion-input-otp,prop,length,number,4,false,false
1045+
ion-input-otp,prop,mode,"ios" | "md",undefined,false,false
10451046
ion-input-otp,prop,pattern,string | undefined,undefined,false,false
10461047
ion-input-otp,prop,readonly,boolean,false,false,true
10471048
ion-input-otp,prop,separators,number[] | string | undefined,undefined,false,false
10481049
ion-input-otp,prop,shape,"rectangular" | "round" | "soft",'round',false,false
10491050
ion-input-otp,prop,size,"large" | "medium" | "small",'medium',false,false
1051+
ion-input-otp,prop,theme,"ios" | "md" | "ionic",undefined,false,false
10501052
ion-input-otp,prop,type,"number" | "text",'number',false,false
10511053
ion-input-otp,prop,value,null | number | string | undefined,'',false,false
10521054
ion-input-otp,method,setFocus,setFocus(index?: number) => Promise<void>
@@ -1127,6 +1129,11 @@ ion-input-otp,css-prop,--separator-width,md
11271129
ion-input-otp,css-prop,--width,ionic
11281130
ion-input-otp,css-prop,--width,ios
11291131
ion-input-otp,css-prop,--width,md
1132+
ion-input-otp,part,container
1133+
ion-input-otp,part,description
1134+
ion-input-otp,part,group
1135+
ion-input-otp,part,native
1136+
ion-input-otp,part,separator
11301137

11311138
ion-input-password-toggle,shadow
11321139
ion-input-password-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true

core/src/components.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,6 +1779,10 @@ export namespace Components {
17791779
* @default 4
17801780
*/
17811781
"length": number;
1782+
/**
1783+
* The mode determines the platform behaviors of the component.
1784+
*/
1785+
"mode"?: "ios" | "md";
17821786
/**
17831787
* A regex pattern string for allowed characters. Defaults based on type. For numbers (`type="number"`): `"[\p{N}]"` For text (`type="text"`): `"[\p{L}\p{N}]"`
17841788
*/
@@ -1807,6 +1811,10 @@ export namespace Components {
18071811
* @default 'medium'
18081812
*/
18091813
"size": 'small' | 'medium' | 'large';
1814+
/**
1815+
* The theme determines the visual appearance of the component.
1816+
*/
1817+
"theme"?: "ios" | "md" | "ionic";
18101818
/**
18111819
* The type of input allowed in the input boxes.
18121820
* @default 'number'
@@ -7762,6 +7770,10 @@ declare namespace LocalJSX {
77627770
* @default 4
77637771
*/
77647772
"length"?: number;
7773+
/**
7774+
* The mode determines the platform behaviors of the component.
7775+
*/
7776+
"mode"?: "ios" | "md";
77657777
/**
77667778
* Emitted when the input group loses focus.
77677779
*/
@@ -7805,6 +7817,10 @@ declare namespace LocalJSX {
78057817
* @default 'medium'
78067818
*/
78077819
"size"?: 'small' | 'medium' | 'large';
7820+
/**
7821+
* The theme determines the visual appearance of the component.
7822+
*/
7823+
"theme"?: "ios" | "md" | "ionic";
78087824
/**
78097825
* The type of input allowed in the input boxes.
78107826
* @default 'number'

core/src/components/input-otp/input-otp.common.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,13 @@
9494
background: var(--background);
9595
color: var(--color);
9696

97+
font-family: inherit;
9798
font-size: inherit;
9899

99100
text-align: center;
100101
appearance: none;
102+
103+
box-sizing: border-box;
101104
}
102105

103106
:host(.has-focus) .native-input {

core/src/components/input-otp/input-otp.native.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
--highlight-color-valid: #{ion-color(success, base)};
2020
--highlight-color-invalid: #{ion-color(danger, base)};
2121

22+
font-family: $font-family-base;
23+
2224
font-size: dynamic-font(14px);
2325
}
2426

core/src/components/input-otp/input-otp.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,25 @@ import type {
1616
InputOtpInputEventDetail,
1717
} from './input-otp-interface';
1818

19+
/**
20+
* @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
21+
* @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component.
22+
*
23+
* @part group - The container element that wraps all input boxes.
24+
* @part container - The wrapper element for each individual input box.
25+
* @part native - The native input element.
26+
* @part separator - The separator element displayed between input boxes.
27+
* @part description - The container element for the description text.
28+
*/
1929
@Component({
2030
tag: 'ion-input-otp',
2131
styleUrls: {
2232
ios: 'input-otp.ios.scss',
2333
md: 'input-otp.md.scss',
2434
ionic: 'input-otp.ionic.scss',
2535
},
26-
scoped: true,
36+
shadow: true,
37+
formAssociated: true,
2738
})
2839
export class InputOTP implements ComponentInterface {
2940
private inheritedAttributes: Attributes = {};
@@ -817,12 +828,19 @@ export class InputOTP implements ComponentInterface {
817828
'input-otp-readonly': readonly,
818829
})}
819830
>
820-
<div role="group" aria-label="One-time password input" class="input-otp-group" {...inheritedAttributes}>
831+
<div
832+
role="group"
833+
aria-label="One-time password input"
834+
class="input-otp-group"
835+
part="group"
836+
{...inheritedAttributes}
837+
>
821838
{Array.from({ length }).map((_, index) => (
822839
<>
823-
<div class="native-wrapper">
840+
<div class="native-wrapper" part="container">
824841
<input
825842
class="native-input"
843+
part="native"
826844
id={`${inputId}-${index}`}
827845
aria-label={`Input ${index + 1} of ${length}`}
828846
type="text"
@@ -842,7 +860,7 @@ export class InputOTP implements ComponentInterface {
842860
onPaste={this.onPaste}
843861
/>
844862
</div>
845-
{this.showSeparator(index) && <div class="input-otp-separator" />}
863+
{this.showSeparator(index) && <div class="input-otp-separator" part="separator" />}
846864
</>
847865
))}
848866
</div>
@@ -851,6 +869,7 @@ export class InputOTP implements ComponentInterface {
851869
'input-otp-description': true,
852870
'input-otp-description-hidden': !hasDescription,
853871
}}
872+
part="description"
854873
>
855874
<slot></slot>
856875
</div>

packages/angular/src/directives/proxies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,15 +1043,15 @@ This event will not emit when programmatically setting the `value` property.
10431043

10441044

10451045
@ProxyCmp({
1046-
inputs: ['autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'pattern', 'readonly', 'separators', 'shape', 'size', 'type', 'value'],
1046+
inputs: ['autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'mode', 'pattern', 'readonly', 'separators', 'shape', 'size', 'theme', 'type', 'value'],
10471047
methods: ['setFocus']
10481048
})
10491049
@Component({
10501050
selector: 'ion-input-otp',
10511051
changeDetection: ChangeDetectionStrategy.OnPush,
10521052
template: '<ng-content></ng-content>',
10531053
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
1054-
inputs: ['autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'pattern', 'readonly', 'separators', 'shape', 'size', 'type', 'value'],
1054+
inputs: ['autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'mode', 'pattern', 'readonly', 'separators', 'shape', 'size', 'theme', 'type', 'value'],
10551055
})
10561056
export class IonInputOtp {
10571057
protected el: HTMLIonInputOtpElement;

0 commit comments

Comments
 (0)