Compare commits

..

8 Commits

Author SHA1 Message Date
Shawn Taylor
4dffb10875 chore(): create reusable test header 2024-03-29 13:39:14 -04:00
Sean Perkins
5234224700 chore(playwright): combine test configs for themes and modes (#29206)
Issue number: N/A

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Developers are not able to easily add the "ionic" theme to existing test
cases, without running the test against both iOS and MD mode:

```ts
configs({ themes: ['ios', 'md', 'ionic'] })
// Generates 4 test cases
// - iOS theme on iOS mode
// - MD theme on MD mode
// - Ionic theme on iOS mode
// - Ionic theme on MD mode
```

With the separation of `mode` into look and feel, the majority of test
cases do not require testing the mode behavior and instead only need to
test the visual theme that is applied to the component.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Removes the `themes` option from the `configs` test generator object.

```ts
configs({ modes: ['ios', 'md', 'ionic-md'] })
```

- Combines `theme` and `mode` into the existing `modes` test generator
object
- The new options are `ionic-ios` and `ionic-md`, to run the Ionic theme
against the respective mode.
- This path was preferred to avoid deprecating and migrating all
existing tests.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

I do not have a strong preference on the semantics of `ionic-ios` vs.
`ios-ionic` (theme first vs. mode first). If anyone has an opinion or
alternative suggestion, please add a comment.

---------

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
2024-03-28 12:52:09 -04:00
Sean Perkins
6d6fd4af1b chore: sync next with feature-8.0 (#29225)
Issue number: N/A

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Syncs the `next` branch with the latest from `feature-8.0`.


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2024-03-27 10:14:18 -04:00
Sean Perkins
7cfee535ac chore(angular): update component wrappers output 2024-03-27 00:15:06 -04:00
Sean Perkins
167e311474 Merge remote-tracking branch 'origin/feature-8.0' into sp/sync-next-03-27 2024-03-27 00:13:38 -04:00
Liam DeBeasi
7eae6ec591 refactor(button): update focus ring to avoid additional API (#29223) 2024-03-26 13:40:11 -04:00
Liam DeBeasi
6c500fd6b2 feat(input): add input-password-toggle component (#29175)
Issue number: Internal

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

When given a password input it is hard to know what users are typing as
the contents of the input are obscured. As a result, it is a common
pattern to have a button that lets users temporarily toggle the
visibility of the password so they can correct any mistakes. Ionic
currently has the infrastructure for developers to implement this on
their own, but this use case is so common that the team thinks it is
worth having this functionality built-in to Ionic.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Introduces the `ion-input-password-toggle` component. This component
is a button that toggles the visibility of the text in the input it is
slotted into.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->


⚠️ Give co-author credit to
https://github.com/ionic-team/ionic-framework/pull/29141 on merge.

Docs PR: https://github.com/ionic-team/ionic-docs/pull/3541

Note: We did not do the approach listed in the other PR due to
https://github.com/ionic-team/ionic-framework/pull/29141#discussion_r1523631811.

---------

Co-authored-by: OS-giulianasilva <OS-giulianasilva@users.noreply.github.com>
2024-03-25 13:22:06 -04:00
Liam DeBeasi
6e477b743e refactor(searchbar): autocapitalize defaults to off (#29107)
BREAKING CHANGE: The `autocapitalize` property on Searchbar now defaults to `'off'`.
2024-03-22 09:13:15 -04:00
260 changed files with 1432 additions and 953 deletions

View File

@@ -30,6 +30,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Progress bar](#version-8x-progress-bar)
- [Radio](#version-8x-radio)
- [Range](#version-8x-range)
- [Searchbar](#version-8x-searchbar)
- [Select](#version-8x-select)
- [Textarea](#version-8x-textarea)
- [Toggle](#version-8x-toggle)
@@ -264,6 +265,10 @@ For more information on styling toast buttons, refer to the [Toast Theming docum
- The `legacy` property and support for the legacy syntax, which involved placing an `ion-range` inside of an `ion-item` with an `ion-label`, have been removed. Ionic will also no longer attempt to automatically associate form controls with sibling `<label>` elements as these label elements are now used inside the form control. Developers should provide a label (either visible text or `aria-label`) directly to the form control. For more information on migrating from the legacy range syntax, refer to the [Range documentation](https://ionicframework.com/docs/api/range#migrating-from-legacy-range-syntax).
<h4 id="version-8x-searchbar">Searchbar</h4>
- The `autocapitalize` property now defaults to `'off'`.
<h4 id="version-8x-select">Select</h4>
- The `legacy` property and support for the legacy syntax, which involved placing an `ion-select` inside of an `ion-item` with an `ion-label`, have been removed. Ionic will also no longer attempt to automatically associate form controls with sibling `<label>` elements as these label elements are now used inside the form control. Developers should provide a label (either visible text or `aria-label`) directly to the form control. For more information on migrating from the legacy select syntax, refer to the [Select documentation](https://ionicframework.com/docs/api/select#migrating-from-legacy-select-syntax).

View File

@@ -265,7 +265,6 @@ ion-button,css-prop,--padding-start
ion-button,css-prop,--padding-top
ion-button,css-prop,--ripple-color
ion-button,css-prop,--transition
ion-button,part,focus-ring
ion-button,part,native
ion-buttons,scoped
@@ -604,7 +603,7 @@ ion-input,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secon
ion-input,prop,counter,boolean,false,false,false
ion-input,prop,counterFormatter,((inputLength: number, maxLength: number) => string) | undefined,undefined,false,false
ion-input,prop,debounce,number | undefined,undefined,false,false
ion-input,prop,disabled,boolean,false,false,false
ion-input,prop,disabled,boolean,false,false,true
ion-input,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
ion-input,prop,errorText,string | undefined,undefined,false,false
ion-input,prop,fill,"outline" | "solid" | undefined,undefined,false,false
@@ -621,7 +620,7 @@ ion-input,prop,multiple,boolean | undefined,undefined,false,false
ion-input,prop,name,string,this.inputId,false,false
ion-input,prop,pattern,string | undefined,undefined,false,false
ion-input,prop,placeholder,string | undefined,undefined,false,false
ion-input,prop,readonly,boolean,false,false,false
ion-input,prop,readonly,boolean,false,false,true
ion-input,prop,required,boolean,false,false,false
ion-input,prop,shape,"round" | undefined,undefined,false,false
ion-input,prop,spellcheck,boolean,false,false,false
@@ -654,6 +653,12 @@ ion-input,css-prop,--placeholder-font-style
ion-input,css-prop,--placeholder-font-weight
ion-input,css-prop,--placeholder-opacity
ion-input-password-toggle,shadow
ion-input-password-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-input-password-toggle,prop,hideIcon,string | undefined,undefined,false,false
ion-input-password-toggle,prop,mode,"ios" | "md",undefined,false,false
ion-input-password-toggle,prop,showIcon,string | undefined,undefined,false,false
ion-item,shadow
ion-item,prop,button,boolean,false,false,false
ion-item,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
@@ -1266,7 +1271,7 @@ ion-row,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-searchbar,scoped
ion-searchbar,prop,animated,boolean,false,false,false
ion-searchbar,prop,autocapitalize,string,undefined,true,false
ion-searchbar,prop,autocapitalize,string,'off',false,false
ion-searchbar,prop,autocomplete,"name" | "email" | "tel" | "url" | "on" | "off" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "photo",'off',false,false
ion-searchbar,prop,autocorrect,"off" | "on",'off',false,false
ion-searchbar,prop,cancelButtonIcon,string,config.get('backButtonIcon', arrowBackSharp) as string,false,false
@@ -1672,4 +1677,7 @@ ion-toolbar,css-prop,--opacity
ion-toolbar,css-prop,--padding-bottom
ion-toolbar,css-prop,--padding-end
ion-toolbar,css-prop,--padding-start
ion-toolbar,css-prop,--padding-top
ion-toolbar,css-prop,--padding-top
test-header,scoped
test-header,prop,testTitle,string | undefined,undefined,false,false

51
core/package-lock.json generated
View File

@@ -43,7 +43,7 @@
"jest-cli": "^29.7.0",
"prettier": "^2.6.1",
"rollup": "^2.26.4",
"sass": "^1.72.0",
"sass": "^1.33.0",
"serve": "^14.0.1",
"stylelint": "^13.13.1",
"stylelint-order": "^4.1.0"
@@ -5149,12 +5149,6 @@
"node": ">= 4"
}
},
"node_modules/immutable": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
"integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==",
"dev": true
},
"node_modules/import-fresh": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
@@ -8610,20 +8604,18 @@
"dev": true
},
"node_modules/sass": {
"version": "1.72.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.72.0.tgz",
"integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==",
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.33.0.tgz",
"integrity": "sha512-9v0MUXnSi62FtfjqcwZ+b8B9FIxdwFEb3FPUkjEPXWd0b5KcnPGSp2XF9WrzcH1ZxedfgJVTdA3A1j4eEj53xg==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
"chokidar": ">=3.0.0 <4.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=14.0.0"
"node": ">=8.9.0"
}
},
"node_modules/semver": {
@@ -8796,15 +8788,6 @@
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.13",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
@@ -13716,12 +13699,6 @@
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
"dev": true
},
"immutable": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
"integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==",
"dev": true
},
"import-fresh": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
@@ -16209,14 +16186,12 @@
"dev": true
},
"sass": {
"version": "1.72.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.72.0.tgz",
"integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==",
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.33.0.tgz",
"integrity": "sha512-9v0MUXnSi62FtfjqcwZ+b8B9FIxdwFEb3FPUkjEPXWd0b5KcnPGSp2XF9WrzcH1ZxedfgJVTdA3A1j4eEj53xg==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
"chokidar": ">=3.0.0 <4.0.0"
}
},
"semver": {
@@ -16353,12 +16328,6 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"dev": true
},
"source-map-support": {
"version": "0.5.13",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",

View File

@@ -65,7 +65,7 @@
"jest-cli": "^29.7.0",
"prettier": "^2.6.1",
"rollup": "^2.26.4",
"sass": "^1.72.0",
"sass": "^1.33.0",
"serve": "^14.0.1",
"stylelint": "^13.13.1",
"stylelint-order": "^4.1.0"

View File

@@ -1471,6 +1471,25 @@ export namespace Components {
*/
"value"?: string | number | null;
}
interface IonInputPasswordToggle {
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* The icon that can be used to represent hiding a password. If not set, the "eyeOff" Ionicon will be used.
*/
"hideIcon"?: string;
/**
* The mode determines which platform styles to use.
*/
"mode"?: "ios" | "md";
/**
* The icon that can be used to represent showing a password. If not set, the "eye" Ionicon will be used.
*/
"showIcon"?: string;
"type": TextFieldTypes;
}
interface IonItem {
/**
* If `true`, a button tag will be rendered and the item will be tappable.
@@ -3741,6 +3760,9 @@ export namespace Components {
*/
"theme"?: "ios" | "md" | "ionic";
}
interface TestHeader {
"testTitle"?: string;
}
}
export interface IonAccordionGroupCustomEvent<T> extends CustomEvent<T> {
detail: T;
@@ -4323,6 +4345,12 @@ declare global {
prototype: HTMLIonInputElement;
new (): HTMLIonInputElement;
};
interface HTMLIonInputPasswordToggleElement extends Components.IonInputPasswordToggle, HTMLStencilElement {
}
var HTMLIonInputPasswordToggleElement: {
prototype: HTMLIonInputPasswordToggleElement;
new (): HTMLIonInputPasswordToggleElement;
};
interface HTMLIonItemElement extends Components.IonItem, HTMLStencilElement {
}
var HTMLIonItemElement: {
@@ -5112,6 +5140,12 @@ declare global {
prototype: HTMLIonToolbarElement;
new (): HTMLIonToolbarElement;
};
interface HTMLTestHeaderElement extends Components.TestHeader, HTMLStencilElement {
}
var HTMLTestHeaderElement: {
prototype: HTMLTestHeaderElement;
new (): HTMLTestHeaderElement;
};
interface HTMLElementTagNameMap {
"ion-accordion": HTMLIonAccordionElement;
"ion-accordion-group": HTMLIonAccordionGroupElement;
@@ -5147,6 +5181,7 @@ declare global {
"ion-infinite-scroll": HTMLIonInfiniteScrollElement;
"ion-infinite-scroll-content": HTMLIonInfiniteScrollContentElement;
"ion-input": HTMLIonInputElement;
"ion-input-password-toggle": HTMLIonInputPasswordToggleElement;
"ion-item": HTMLIonItemElement;
"ion-item-divider": HTMLIonItemDividerElement;
"ion-item-group": HTMLIonItemGroupElement;
@@ -5205,6 +5240,7 @@ declare global {
"ion-toast": HTMLIonToastElement;
"ion-toggle": HTMLIonToggleElement;
"ion-toolbar": HTMLIonToolbarElement;
"test-header": HTMLTestHeaderElement;
}
}
declare namespace LocalJSX {
@@ -6689,6 +6725,25 @@ declare namespace LocalJSX {
*/
"value"?: string | number | null;
}
interface IonInputPasswordToggle {
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* The icon that can be used to represent hiding a password. If not set, the "eyeOff" Ionicon will be used.
*/
"hideIcon"?: string;
/**
* The mode determines which platform styles to use.
*/
"mode"?: "ios" | "md";
/**
* The icon that can be used to represent showing a password. If not set, the "eye" Ionicon will be used.
*/
"showIcon"?: string;
"type"?: TextFieldTypes;
}
interface IonItem {
/**
* If `true`, a button tag will be rendered and the item will be tappable.
@@ -8121,7 +8176,7 @@ declare namespace LocalJSX {
/**
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user. Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
*/
"autocapitalize": string;
"autocapitalize"?: string;
/**
* Set the input's autocomplete property.
*/
@@ -9029,6 +9084,9 @@ declare namespace LocalJSX {
*/
"theme"?: "ios" | "md" | "ionic";
}
interface TestHeader {
"testTitle"?: string;
}
interface IntrinsicElements {
"ion-accordion": IonAccordion;
"ion-accordion-group": IonAccordionGroup;
@@ -9064,6 +9122,7 @@ declare namespace LocalJSX {
"ion-infinite-scroll": IonInfiniteScroll;
"ion-infinite-scroll-content": IonInfiniteScrollContent;
"ion-input": IonInput;
"ion-input-password-toggle": IonInputPasswordToggle;
"ion-item": IonItem;
"ion-item-divider": IonItemDivider;
"ion-item-group": IonItemGroup;
@@ -9122,6 +9181,7 @@ declare namespace LocalJSX {
"ion-toast": IonToast;
"ion-toggle": IonToggle;
"ion-toolbar": IonToolbar;
"test-header": TestHeader;
}
}
export { LocalJSX as JSX };
@@ -9162,6 +9222,7 @@ declare module "@stencil/core" {
"ion-infinite-scroll": LocalJSX.IonInfiniteScroll & JSXBase.HTMLAttributes<HTMLIonInfiniteScrollElement>;
"ion-infinite-scroll-content": LocalJSX.IonInfiniteScrollContent & JSXBase.HTMLAttributes<HTMLIonInfiniteScrollContentElement>;
"ion-input": LocalJSX.IonInput & JSXBase.HTMLAttributes<HTMLIonInputElement>;
"ion-input-password-toggle": LocalJSX.IonInputPasswordToggle & JSXBase.HTMLAttributes<HTMLIonInputPasswordToggleElement>;
"ion-item": LocalJSX.IonItem & JSXBase.HTMLAttributes<HTMLIonItemElement>;
"ion-item-divider": LocalJSX.IonItemDivider & JSXBase.HTMLAttributes<HTMLIonItemDividerElement>;
"ion-item-group": LocalJSX.IonItemGroup & JSXBase.HTMLAttributes<HTMLIonItemGroupElement>;
@@ -9220,6 +9281,7 @@ declare module "@stencil/core" {
"ion-toast": LocalJSX.IonToast & JSXBase.HTMLAttributes<HTMLIonToastElement>;
"ion-toggle": LocalJSX.IonToggle & JSXBase.HTMLAttributes<HTMLIonToggleElement>;
"ion-toolbar": LocalJSX.IonToolbar & JSXBase.HTMLAttributes<HTMLIonToolbarElement>;
"test-header": LocalJSX.TestHeader & JSXBase.HTMLAttributes<HTMLTestHeaderElement>;
}
}
}

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
@import "../accordion/accordion.vars";
// Accordion Group

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Accordion
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Accordion
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Action Sheet
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Action Sheet
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Action Sheet
// --------------------------------------------------

View File

@@ -1,5 +1,5 @@
@use "sass:math";
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
@import "../item/item.ios.vars";
// iOS Alert

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
@import "../item/item.md.vars";
// Material Design Alert

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Alert
// --------------------------------------------------

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Avatar

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Avatar

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Avatar

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Back Button
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Back Button
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Back Button
// --------------------------------------------------

View File

@@ -1 +1 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";

View File

@@ -1 +1 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";

View File

@@ -1 +1 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Badge
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Badge
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Badge
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Breadcrumb
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Breadcrumb
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Breadcrumb
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Breadcrumbs
// --------------------------------------------------

View File

@@ -156,26 +156,9 @@
// -------------------------------------------------------------------------------
// Only show the focus ring when the button is focused
:host(.ion-focused) {
--overflow: visible;
.button-native::after {
@include border-radius(inherit);
}
}
.button-focus-ring {
@include position(-4px, -4px, -4px, -4px);
@include border-radius(inherit);
position: absolute;
transition: border-color 0.3s;
border: var(--focus-ring-width) solid var(--focus-ring-color);
content: "";
box-sizing: border-box;
:host(.ion-focused) .button-native {
outline: var(--focus-ring-width) solid var(--focus-ring-color);
outline-offset: 2px;
}
// Fill Solid Button

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// Ionic Button
// -------------------------------------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Button
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Button
// --------------------------------------------------

View File

@@ -20,7 +20,6 @@ import type { RouterDirection } from '../router/utils/interface';
* @slot end - Content is placed to the right of the button text in LTR, and to the left in RTL.
*
* @part native - The native HTML button or anchor element that wraps all child elements.
* @part focus-ring - The visual indicator that appears as an outline around the button when focused. Only available for the Ionic theme.
*/
@Component({
tag: 'ion-button',
@@ -418,7 +417,6 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
<slot name="end"></slot>
</span>
{theme === 'md' && <ion-ripple-effect type={this.rippleType}></ion-ripple-effect>}
{theme === 'ionic' && <div part="focus-ring" class="button-focus-ring"></div>}
</TagType>
</Host>
);

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Button
// --------------------------------------------------

View File

@@ -4,7 +4,7 @@ import { configs, test } from '@utils/test/playwright';
/**
* Fill="clear" does not render differently based on the direction.
*/
configs({ directions: ['ltr'], themes: ['ios', 'md', 'ionic'] }).forEach(({ title, config, screenshot }) => {
configs({ directions: ['ltr'], modes: ['ios', 'md', 'ionic-md'] }).forEach(({ title, config, screenshot }) => {
test.describe(title('button: fill: clear'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/button/test/clear`, config);

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 113 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -74,7 +74,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
/**
* Shape="rectangular" is only available in the Ionic theme.
*/
configs({ directions: ['ltr'], themes: ['ionic'] }).forEach(({ title, screenshot, config }) => {
configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: shape'), () => {
test.describe('rectangular', () => {
test('should not have visual regressions', async ({ page }) => {

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,8 +1,7 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
// TODO: FW-6077 - Limit this test to just the Ionic theme on MD mode.
configs({ directions: ['ltr'], themes: ['ionic', 'md', 'ios'] }).forEach(({ title, screenshot, config }) => {
configs({ directions: ['ltr'], modes: ['ionic-md', 'md', 'ios'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: size'), () => {
test('should render small buttons', async ({ page }) => {
await page.setContent(
@@ -65,7 +64,7 @@ configs({ directions: ['ltr'], themes: ['ionic', 'md', 'ios'] }).forEach(({ titl
/**
* The following tests are specific to the Ionic theme and do not depend on the text direction.
*/
configs({ directions: ['ltr'], themes: ['ionic'] }).forEach(({ title, screenshot, config }) => {
configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: size'), () => {
test('should render xsmall buttons', async ({ page }) => {
await page.setContent(`<ion-button size="xsmall" fill="solid">X-Small Button</ion-button>`, config);

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
@import "../toolbar/toolbar.ios.vars";
// iOS Buttons

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
@import "../toolbar/toolbar.md.vars";
// Material Design Buttons

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
:host {
display: flex;

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Card Header
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Card Content
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Card Content
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Card Header
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Card Header
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Card Header
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Card Subtitle
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Card Subtitle
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Card Subtitle
// --------------------------------------------------
@@ -16,4 +16,4 @@
:host(.ion-color) {
color: current-color(base);
}
}

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Card Title
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Card Title
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Card Title

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Card
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Card
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Card
// --------------------------------------------------

View File

@@ -1,5 +1,5 @@
@use "sass:math";
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
@import "../item/item.ios.vars";
// iOS Checkbox

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
@import "../item/item.md.vars";
// Material Design Checkbox

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
@import "./checkbox.vars.scss";
// Checkbox

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
@import "./chip.vars";
:host {

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
@import "../grid/grid.mixins";
// Grid Column

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Content
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Datetime Button
// --------------------------------------------------

View File

@@ -1,6 +1,6 @@
@import "./datetime.scss";
@import "./datetime.ios.vars.scss";
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
:host {
--background: #{ion-color(light, base)};

View File

@@ -1,6 +1,6 @@
@import "./datetime.scss";
@import "./datetime.md.vars.scss";
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
:host {
--background: var(--ion-color-step-100, var(--ion-background-color-step-100, #ffffff));

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Datetime
// --------------------------------------------------

View File

@@ -31,10 +31,6 @@
}
}
.options-popover {
--width: 300px;
}
ion-modal.ios,
ion-popover.datetime-popover.ios {
--width: 350px;
@@ -49,206 +45,36 @@
ion-datetime {
width: 350px;
}
body.dark {
--ion-color-primary: #428cff;
--ion-color-primary-rgb: 66, 140, 255;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255, 255, 255;
--ion-color-primary-shade: #3a7be0;
--ion-color-primary-tint: #5598ff;
--ion-color-secondary: #50c8ff;
--ion-color-secondary-rgb: 80, 200, 255;
--ion-color-secondary-contrast: #ffffff;
--ion-color-secondary-contrast-rgb: 255, 255, 255;
--ion-color-secondary-shade: #46b0e0;
--ion-color-secondary-tint: #62ceff;
--ion-color-tertiary: #6a64ff;
--ion-color-tertiary-rgb: 106, 100, 255;
--ion-color-tertiary-contrast: #ffffff;
--ion-color-tertiary-contrast-rgb: 255, 255, 255;
--ion-color-tertiary-shade: #5d58e0;
--ion-color-tertiary-tint: #7974ff;
--ion-color-success: #2fdf75;
--ion-color-success-rgb: 47, 223, 117;
--ion-color-success-contrast: #000000;
--ion-color-success-contrast-rgb: 0, 0, 0;
--ion-color-success-shade: #29c467;
--ion-color-success-tint: #44e283;
--ion-color-warning: #ffd534;
--ion-color-warning-rgb: 255, 213, 52;
--ion-color-warning-contrast: #000000;
--ion-color-warning-contrast-rgb: 0, 0, 0;
--ion-color-warning-shade: #e0bb2e;
--ion-color-warning-tint: #ffd948;
--ion-color-danger: #ff4961;
--ion-color-danger-rgb: 255, 73, 97;
--ion-color-danger-contrast: #ffffff;
--ion-color-danger-contrast-rgb: 255, 255, 255;
--ion-color-danger-shade: #e04055;
--ion-color-danger-tint: #ff5b71;
--ion-color-dark: #f4f5f8;
--ion-color-dark-rgb: 244, 245, 248;
--ion-color-dark-contrast: #000000;
--ion-color-dark-contrast-rgb: 0, 0, 0;
--ion-color-dark-shade: #d7d8da;
--ion-color-dark-tint: #f5f6f9;
--ion-color-medium: #989aa2;
--ion-color-medium-rgb: 152, 154, 162;
--ion-color-medium-contrast: #000000;
--ion-color-medium-contrast-rgb: 0, 0, 0;
--ion-color-medium-shade: #86888f;
--ion-color-medium-tint: #a2a4ab;
--ion-color-light: #222428;
--ion-color-light-rgb: 34, 36, 40;
--ion-color-light-contrast: #ffffff;
--ion-color-light-contrast-rgb: 255, 255, 255;
--ion-color-light-shade: #1e2023;
--ion-color-light-tint: #383a3e;
}
/*
* iOS Dark Theme
* -------------------------------------------
*/
.ios body.dark {
--ion-background-color: #000000;
--ion-background-color-rgb: 0, 0, 0;
--ion-text-color: #ffffff;
--ion-text-color-rgb: 255, 255, 255;
--ion-color-step-50: #0d0d0d;
--ion-color-step-100: #1a1a1a;
--ion-color-step-150: #262626;
--ion-color-step-200: #333333;
--ion-color-step-250: #404040;
--ion-color-step-300: #4d4d4d;
--ion-color-step-350: #595959;
--ion-color-step-400: #666666;
--ion-color-step-450: #737373;
--ion-color-step-500: #808080;
--ion-color-step-550: #8c8c8c;
--ion-color-step-600: #999999;
--ion-color-step-650: #a6a6a6;
--ion-color-step-700: #b3b3b3;
--ion-color-step-750: #bfbfbf;
--ion-color-step-800: #cccccc;
--ion-color-step-850: #d9d9d9;
--ion-color-step-900: #e6e6e6;
--ion-color-step-950: #f2f2f2;
--ion-item-background: #000000;
--ion-card-background: #1c1c1d;
}
.ios body.dark ion-modal {
--ion-background-color: var(--ion-color-step-100);
--ion-toolbar-background: var(--ion-color-step-150);
--ion-toolbar-border-color: var(--ion-color-step-250);
--ion-item-background: var(--ion-color-step-150);
}
/*
* Material Design Dark Theme
* -------------------------------------------
*/
.md body.dark {
--ion-background-color: #121212;
--ion-background-color-rgb: 18, 18, 18;
--ion-text-color: #ffffff;
--ion-text-color-rgb: 255, 255, 255;
--ion-border-color: #222222;
--ion-color-step-50: #1e1e1e;
--ion-color-step-100: #2a2a2a;
--ion-color-step-150: #363636;
--ion-color-step-200: #414141;
--ion-color-step-250: #4d4d4d;
--ion-color-step-300: #595959;
--ion-color-step-350: #656565;
--ion-color-step-400: #717171;
--ion-color-step-450: #7d7d7d;
--ion-color-step-500: #898989;
--ion-color-step-550: #949494;
--ion-color-step-600: #a0a0a0;
--ion-color-step-650: #acacac;
--ion-color-step-700: #b8b8b8;
--ion-color-step-750: #c4c4c4;
--ion-color-step-800: #d0d0d0;
--ion-color-step-850: #dbdbdb;
--ion-color-step-900: #e7e7e7;
--ion-color-step-950: #f3f3f3;
--ion-item-background: #1e1e1e;
--ion-toolbar-background: #1f1f1f;
--ion-tab-bar-background: #1f1f1f;
--ion-card-background: #1e1e1e;
}
</style>
</head>
<body>
<ion-app>
<ion-header translucent="true">
<ion-toolbar>
<ion-title>Datetime - Basic</ion-title>
<ion-buttons slot="end">
<ion-button id="popover-trigger">Options</ion-button>
</ion-buttons>
<ion-popover class="options-popover" trigger="popover-trigger">
<ion-list lines="none">
<ion-item>
<ion-checkbox>Dark Mode</ion-checkbox>
</ion-item>
<ion-item detail="true" href="?ionic:mode=ios">
<ion-label>iOS Mode</ion-label>
</ion-item>
<ion-item detail="true" href="?ionic:mode=md">
<ion-label>MD Mode</ion-label>
</ion-item>
<test-header test-title="Datetime - Basic">
<div slot="items">
<ion-item>
<ion-toggle id="titleToggle">Show Default Title</ion-toggle>
</ion-item>
<ion-item>
<ion-toggle id="titleToggle">Show Default Title</ion-toggle>
</ion-item>
<ion-item>
<ion-toggle id="buttonsToggle">Show Default Buttons</ion-toggle>
</ion-item>
<ion-item>
<ion-toggle id="buttonsToggle">Show Default Buttons</ion-toggle>
</ion-item>
<ion-item>
<ion-input label="Locale" placeholder="default" id="locale"></ion-input>
</ion-item>
<ion-item>
<ion-input label="Locale" placeholder="default" id="locale"></ion-input>
</ion-item>
<ion-item>
<ion-select label="Color" id="color" value="primary">
<ion-select-option value="primary">Primary</ion-select-option>
<ion-select-option value="secondary">Secondary</ion-select-option>
<ion-select-option value="tertiary">Tertiary</ion-select-option>
<ion-select-option value="success">Success</ion-select-option>
<ion-select-option value="warning">Warning</ion-select-option>
<ion-select-option value="danger">Danger</ion-select-option>
</ion-select>
</ion-item>
</ion-list>
</ion-popover>
</ion-toolbar>
</ion-header>
<ion-item>
<ion-select label="Color" id="color" value="primary">
<ion-select-option value="primary">Primary</ion-select-option>
<ion-select-option value="secondary">Secondary</ion-select-option>
<ion-select-option value="tertiary">Tertiary</ion-select-option>
<ion-select-option value="success">Success</ion-select-option>
<ion-select-option value="warning">Warning</ion-select-option>
<ion-select-option value="danger">Danger</ion-select-option>
</ion-select>
</ion-item>
</div>
</test-header>
<ion-content class="ion-padding">
<div class="grid">
<div class="grid-item">
@@ -333,14 +159,6 @@
});
});
const darkModeCheckbox = document.querySelector('ion-checkbox');
darkModeCheckbox.addEventListener('ionChange', (ev) => {
if (ev.detail.checked) {
document.body.classList.add('dark');
} else {
document.body.classList.remove('dark');
}
});
color.addEventListener('ionChange', (ev) => {
datetime.color = ev.target.value;
buttons.forEach((button) => {

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS FAB Button
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design FAB Button
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Floating Action Buttons
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
@import "../fab-button/fab-button.vars";
// Floating Action Button List

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
@import "../fab-button/fab-button.vars";
// Floating Action Button Container

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Footer
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Footer
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Footer
// --------------------------------------------------
@@ -16,4 +16,4 @@ ion-footer {
ion-footer.footer-toolbar-padding ion-toolbar:last-of-type {
padding-bottom: var(--ion-safe-area-bottom, 0);
}
}

View File

@@ -1,5 +1,5 @@
@import "../../themes/globals";
@import "../../themes/mixins";
@import "../../themes/ionic.globals";
@import "../../themes/ionic.mixins";
// Responsive Mixins
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
@import "./grid.mixins";
// Grid

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// iOS Header
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Header
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Header
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.ios";
@import "../../themes/ionic.globals.ios";
// Material Design Infinite Scroll
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals.md";
@import "../../themes/ionic.globals.md";
// Material Design Infinite Scroll
// --------------------------------------------------

View File

@@ -1,4 +1,4 @@
@import "../../themes/globals";
@import "../../themes/ionic.globals";
// Infinite Scroll
// --------------------------------------------------

View File

@@ -0,0 +1,152 @@
import type { ComponentInterface } from '@stencil/core';
import { Component, Element, Host, Prop, h, Watch } from '@stencil/core';
import { printIonWarning } from '@utils/logging';
import { createColorClasses } from '@utils/theme';
import { eyeOff, eye } from 'ionicons/icons';
import { getIonMode } from '../../global/ionic-global';
import type { Color, TextFieldTypes } from '../../interface';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
*/
@Component({
tag: 'ion-input-password-toggle',
/**
* Empty CSS files are required in order for the mode to be inherited to the
* inner ion-button. Otherwise, the setMode callback provided to Stencil will not get called
* and we will default to MD mode.
*/
styleUrls: {
ios: 'input-password-toggle.scss',
md: 'input-password-toggle.scss',
},
shadow: true,
})
export class InputPasswordToggle implements ComponentInterface {
private inputElRef!: HTMLIonInputElement | null;
@Element() el!: HTMLIonInputElement;
/**
* The color to use from your application's color palette.
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
* For more information on colors, see [theming](/docs/theming/basics).
*/
@Prop({ reflect: true }) color?: Color;
/**
* The icon that can be used to represent showing a password. If not set, the "eye" Ionicon will be used.
*/
@Prop() showIcon?: string;
/**
* The icon that can be used to represent hiding a password. If not set, the "eyeOff" Ionicon will be used.
*/
@Prop() hideIcon?: string;
/**
* @internal
*/
@Prop({ mutable: true }) type: TextFieldTypes = 'password';
/**
* Whenever the input type changes we need to re-run validation to ensure the password
* toggle is being used with the correct input type. If the application changes the type
* outside of this component we also need to re-render so the correct icon is shown.
*/
@Watch('type')
onTypeChange(newValue: TextFieldTypes) {
if (newValue !== 'text' && newValue !== 'password') {
printIonWarning(
`ion-input-password-toggle only supports inputs of type "text" or "password". Input of type "${newValue}" is not compatible.`,
this.el
);
return;
}
}
connectedCallback() {
const { el } = this;
const inputElRef = (this.inputElRef = el.closest('ion-input'));
if (!inputElRef) {
printIonWarning(
'No ancestor ion-input found for ion-input-password-toggle. This component must be slotted inside of an ion-input.',
el
);
return;
}
/**
* Important: Set the type in connectedCallback because the default value
* of this.type may not always be accurate. Usually inputs have the "password" type
* but it is possible to have the input to initially have the "text" type. In that scenario
* the wrong icon will show briefly before switching to the correct icon. Setting the
* type here allows us to avoid that flicker.
*/
this.type = inputElRef.type;
}
disconnectedCallback() {
this.inputElRef = null;
}
private togglePasswordVisibility = () => {
const { inputElRef } = this;
if (!inputElRef) {
return;
}
inputElRef.type = inputElRef.type === 'text' ? 'password' : 'text';
};
render() {
const { color, type } = this;
const mode = getIonMode(this);
const showPasswordIcon = this.showIcon ?? eye;
const hidePasswordIcon = this.hideIcon ?? eyeOff;
const isPasswordVisible = type === 'text';
return (
<Host
class={createColorClasses(color, {
[mode]: true,
})}
>
<ion-button
mode={mode}
color={color}
fill="clear"
shape="round"
aria-checked={isPasswordVisible ? 'true' : 'false'}
aria-label="show password"
role="switch"
type="button"
onPointerDown={(ev) => {
/**
* This prevents mobile browsers from
* blurring the input when the password toggle
* button is activated.
*/
ev.preventDefault();
}}
onClick={this.togglePasswordVisibility}
>
<ion-icon
slot="icon-only"
aria-hidden="true"
icon={isPasswordVisible ? hidePasswordIcon : showPasswordIcon}
></ion-icon>
</ion-button>
</Host>
);
}
}

View File

@@ -0,0 +1,23 @@
import AxeBuilder from '@axe-core/playwright';
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('input password toggle: a11y'), () => {
test('should not have accessibility violations', async ({ page }) => {
await page.setContent(
`
<main>
<ion-input label="input" type="password">
<ion-input-password-toggle slot="end"></ion-input-password-toggle>
</ion-input>
</main>
`,
config
);
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
});
});

Some files were not shown because too many files have changed in this diff Show More