feat(a11y): add dynamic font scaling (#28314)

Issue number: resolves #24638, resolves #18592

---------

<!-- 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 have requested that Ionic Framework support the dynamic type
feature on iOS for accessibility purposes. Ionic applications do not
respond to font scaling on iOS which can create inaccessible
applications particularly for users with low vision. Ionic apps on
Android devices currently support the Android equivalent due to
functionality in the Chromium webview.

Developers have also requested a way of adjusting the fonts in their
Ionic UI components consistently.

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

- Ionic components now use `rem` instead of `px` where appropriate. This
means devs can change the font size on `html` and the text in supported
Ionic components will scale up/down appropriately
- Add support for Dynamic Type on iOS (the iOS version of Dynamic Font
Scaling)

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

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

---------

Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com>
Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
Co-authored-by: Shawn Taylor <shawn@ionic.io>
Co-authored-by: ionitron <hi@ionicframework.com>
Co-authored-by: Sean Perkins <sean@ionic.io>
Co-authored-by: Sean Perkins <13732623+sean-perkins@users.noreply.github.com>
Co-authored-by: Amanda Johnston <90629384+amandaejohnston@users.noreply.github.com>
This commit is contained in:
Liam DeBeasi
2023-10-10 17:38:09 -04:00
committed by GitHub
parent 57e2476370
commit f8067819ee
546 changed files with 2364 additions and 396 deletions

55
core/package-lock.json generated
View File

@@ -10,7 +10,7 @@
"license": "MIT",
"dependencies": {
"@stencil/core": "^4.4.0",
"ionicons": "^7.1.2",
"ionicons": "^7.2.1",
"tslib": "^2.1.0"
},
"devDependencies": {
@@ -44,7 +44,7 @@
"jest-cli": "^27.5.1",
"prettier": "^2.6.1",
"rollup": "^2.26.4",
"sass": "^1.26.10",
"sass": "^1.33.0",
"serve": "^14.0.1",
"stylelint": "^13.13.1",
"stylelint-order": "^4.1.0"
@@ -5328,23 +5328,11 @@
}
},
"node_modules/ionicons": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.2.tgz",
"integrity": "sha512-zZ4njAqSP39H8RRvZhJvkHsv7cBjYE/VfInH218Osf2UVxJITSOutTTd25MW+tAXKN5fheYzclUXUsF55JHUDg==",
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.2.1.tgz",
"integrity": "sha512-2pvCM7DGVEtbbj48PJzQrCADCQrqjU1nUYX9l9PyEWz3ZfdnLdAouqwPxLdl8tbaF9cE7OZRSlyQD7oLOLnGoQ==",
"dependencies": {
"@stencil/core": "^2.18.0"
}
},
"node_modules/ionicons/node_modules/@stencil/core": {
"version": "2.22.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.22.2.tgz",
"integrity": "sha512-r+vbxsGNcBaV1VDOYW25lv4QfXTlNoIb5GpUX7rZ+cr59yqYCZC5tlV+IzX6YgHKW62ulCc9M3RYtTfHtNbNNw==",
"bin": {
"stencil": "bin/stencil"
},
"engines": {
"node": ">=12.10.0",
"npm": ">=6.0.0"
"@stencil/core": "^4.0.3"
}
},
"node_modules/is-alphabetical": {
@@ -8859,12 +8847,12 @@
"dev": true
},
"node_modules/sass": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.30.0.tgz",
"integrity": "sha512-26EUhOXRLaUY7+mWuRFqGeGGNmhB1vblpTENO1Z7mAzzIZeVxZr9EZoaY1kyGLFWdSOZxRMAufiN2mkbO6dAlw==",
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.33.0.tgz",
"integrity": "sha512-9v0MUXnSi62FtfjqcwZ+b8B9FIxdwFEb3FPUkjEPXWd0b5KcnPGSp2XF9WrzcH1ZxedfgJVTdA3A1j4eEj53xg==",
"dev": true,
"dependencies": {
"chokidar": ">=2.0.0 <4.0.0"
"chokidar": ">=3.0.0 <4.0.0"
},
"bin": {
"sass": "sass.js"
@@ -14297,18 +14285,11 @@
}
},
"ionicons": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.2.tgz",
"integrity": "sha512-zZ4njAqSP39H8RRvZhJvkHsv7cBjYE/VfInH218Osf2UVxJITSOutTTd25MW+tAXKN5fheYzclUXUsF55JHUDg==",
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.2.1.tgz",
"integrity": "sha512-2pvCM7DGVEtbbj48PJzQrCADCQrqjU1nUYX9l9PyEWz3ZfdnLdAouqwPxLdl8tbaF9cE7OZRSlyQD7oLOLnGoQ==",
"requires": {
"@stencil/core": "^2.18.0"
},
"dependencies": {
"@stencil/core": {
"version": "2.22.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.22.2.tgz",
"integrity": "sha512-r+vbxsGNcBaV1VDOYW25lv4QfXTlNoIb5GpUX7rZ+cr59yqYCZC5tlV+IzX6YgHKW62ulCc9M3RYtTfHtNbNNw=="
}
"@stencil/core": "^4.0.3"
}
},
"is-alphabetical": {
@@ -16874,12 +16855,12 @@
"dev": true
},
"sass": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.30.0.tgz",
"integrity": "sha512-26EUhOXRLaUY7+mWuRFqGeGGNmhB1vblpTENO1Z7mAzzIZeVxZr9EZoaY1kyGLFWdSOZxRMAufiN2mkbO6dAlw==",
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.33.0.tgz",
"integrity": "sha512-9v0MUXnSi62FtfjqcwZ+b8B9FIxdwFEb3FPUkjEPXWd0b5KcnPGSp2XF9WrzcH1ZxedfgJVTdA3A1j4eEj53xg==",
"dev": true,
"requires": {
"chokidar": ">=2.0.0 <4.0.0"
"chokidar": ">=3.0.0 <4.0.0"
}
},
"saxes": {

View File

@@ -32,7 +32,7 @@
],
"dependencies": {
"@stencil/core": "^4.4.0",
"ionicons": "^7.1.2",
"ionicons": "^7.2.1",
"tslib": "^2.1.0"
},
"devDependencies": {
@@ -66,7 +66,7 @@
"jest-cli": "^27.5.1",
"prettier": "^2.6.1",
"rollup": "^2.26.4",
"sass": "^1.26.10",
"sass": "^1.33.0",
"serve": "^14.0.1",
"stylelint": "^13.13.1",
"stylelint-order": "^4.1.0"

View File

File diff suppressed because one or more lines are too long

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -131,11 +131,11 @@
.action-sheet-button {
@include padding($action-sheet-ios-button-padding);
height: $action-sheet-ios-button-height;
min-height: $action-sheet-ios-button-height;
font-size: $action-sheet-ios-button-font-size;
contain: strict;
contain: content;
}
.action-sheet-button .action-sheet-icon {

View File

@@ -50,7 +50,7 @@ $action-sheet-ios-title-padding-start: $action-sheet-
$action-sheet-ios-title-color: $text-color-step-600 !default;
/// @prop - Font size of the action sheet title
$action-sheet-ios-title-font-size: 13px !default;
$action-sheet-ios-title-font-size: dynamic-font-min(1, 13px) !default;
/// @prop - Font weight of the action sheet title
$action-sheet-ios-title-font-weight: 400 !default;
@@ -75,7 +75,7 @@ $action-sheet-ios-title-border-color: rgba($text-col
// --------------------------------------------------
/// @prop - Font size of the action sheet sub title
$action-sheet-ios-sub-title-font-size: 13px !default;
$action-sheet-ios-sub-title-font-size: dynamic-font-min(1, 13px) !default;
/// @prop - Padding top of the action sheet sub title
$action-sheet-ios-sub-title-padding-top: 6px !default;
@@ -97,19 +97,19 @@ $action-sheet-ios-sub-title-padding-start: $action-sheet-
$action-sheet-ios-button-height: 56px !default;
/// @prop - Padding of the action sheet button
$action-sheet-ios-button-padding: 18px !default;
$action-sheet-ios-button-padding: 14px !default;
/// @prop - Text color of the action sheet button
$action-sheet-ios-button-text-color: ion-color(primary, base) !default;
/// @prop - Font size of the action sheet button icon
$action-sheet-ios-button-icon-font-size: 28px !default;
$action-sheet-ios-button-icon-font-size: dynamic-font-min(1, 28px) !default;
/// @prop - Padding right of the action sheet button icon
$action-sheet-ios-button-icon-padding-right: .3em !default;
/// @prop - Font size of the action sheet button
$action-sheet-ios-button-font-size: 20px !default;
$action-sheet-ios-button-font-size: dynamic-font-min(1, 20px) !default;
/// @prop - Border color alpha of the action sheet button
$action-sheet-ios-button-border-color-alpha: .08 !default;

View File

@@ -67,13 +67,13 @@
position: relative;
height: $action-sheet-md-button-height;
min-height: $action-sheet-md-button-height;
font-size: $action-sheet-md-button-font-size;
text-align: $action-sheet-md-text-align;
contain: strict;
contain: content;
overflow: hidden;
}

View File

@@ -26,7 +26,7 @@ $action-sheet-md-title-height: 60px !default;
$action-sheet-md-title-color: rgba($text-color-rgb, 0.54) !default;
/// @prop - Font size of the action sheet title
$action-sheet-md-title-font-size: 16px !default;
$action-sheet-md-title-font-size: dynamic-font(16px) !default;
/// @prop - Padding top of the action sheet title
$action-sheet-md-title-padding-top: 20px !default;
@@ -45,7 +45,7 @@ $action-sheet-md-title-padding-start: $action-sheet-md-title-p
// --------------------------------------------------
/// @prop - Font size of the action sheet sub title
$action-sheet-md-sub-title-font-size: 14px !default;
$action-sheet-md-sub-title-font-size: dynamic-font(14px) !default;
/// @prop - Padding top of the action sheet sub title
$action-sheet-md-sub-title-padding-top: 16px !default;
@@ -70,10 +70,10 @@ $action-sheet-md-button-height: 52px !default;
$action-sheet-md-button-text-color: $text-color-step-150 !default;
/// @prop - Font size of the action sheet button
$action-sheet-md-button-font-size: 16px !default;
$action-sheet-md-button-font-size: dynamic-font(16px) !default;
/// @prop - Padding top of the action sheet button
$action-sheet-md-button-padding-top: 0 !default;
$action-sheet-md-button-padding-top: 12px !default;
/// @prop - Padding end of the action sheet button
$action-sheet-md-button-padding-end: 16px !default;
@@ -91,7 +91,7 @@ $action-sheet-md-button-background: transparent !default;
// --------------------------------------------------
/// @prop - Font size of the icon in the action sheet button
$action-sheet-md-icon-font-size: 24px !default;
$action-sheet-md-icon-font-size: dynamic-font(24px) !default;
/// @prop - Margin top of the icon in the action sheet button
$action-sheet-md-icon-margin-top: 0 !default;

View File

@@ -126,7 +126,10 @@
justify-content: flex-end;
height: 100%;
/* Fallback for browsers that do not support dvh */
max-height: 100vh;
max-height: 100dvh;
}
.action-sheet-group {

View File

@@ -86,3 +86,37 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
});
});
});
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('action-sheet: font scaling'), () => {
test('should scale text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 36px;
}
</style>
<ion-action-sheet></ion-action-sheet>
<script>
const actionSheet = document.querySelector('ion-action-sheet');
actionSheet.header = 'Header';
actionSheet.subHeader = 'Sub Header';
actionSheet.buttons = ['Ok', { role: 'cancel', text: 'Cancel' }];
</script>
`,
config
);
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const actionSheet = page.locator('ion-action-sheet');
await actionSheet.evaluate((el: HTMLIonActionSheetElement) => el.present());
await ionActionSheetDidPresent.next();
await expect(actionSheet).toHaveScreenshot(screenshot(`action-sheet-scale`));
});
});
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -255,13 +255,19 @@
}
.alert-button {
/**
* This padding ensures that alerts
* with multiple buttons render on separate lines
* so the text does not run up against the edge of the button.
*/
@include padding-horizontal($alert-ios-button-padding);
@include margin($alert-ios-button-margin);
@include border-radius($alert-ios-button-border-radius);
flex: $alert-ios-button-flex;
min-width: $alert-ios-button-min-width;
height: $alert-ios-button-min-height;
height: $alert-ios-button-height;
border-top: $alert-ios-button-border-width $alert-ios-button-border-style $alert-ios-button-border-color;
border-right: $alert-ios-button-border-width $alert-ios-button-border-style $alert-ios-button-border-color;

View File

@@ -6,10 +6,10 @@
// --------------------------------------------------
/// @prop - Font size of the alert
$alert-ios-font-size: 14px !default;
$alert-ios-font-size: dynamic-font-min(1, 14px) !default;
/// @prop - Max width of the alert
$alert-ios-max-width: 270px !default;
$alert-ios-max-width: dynamic-font-clamp(1, 270px, 1.2) !default;
/// @prop - Border radius of the alert
$alert-ios-border-radius: 13px !default;
@@ -48,13 +48,13 @@ $alert-ios-title-color: $text-color !default;
$alert-ios-title-margin-top: 8px !default;
/// @prop - Font size of the alert title
$alert-ios-title-font-size: 17px !default;
$alert-ios-title-font-size: dynamic-font-min(1, 17px) !default;
/// @prop - Font weight of the alert title
$alert-ios-title-font-weight: 600 !default;
/// @prop - Font size of the alert sub title
$alert-ios-sub-title-font-size: 14px !default;
$alert-ios-sub-title-font-size: dynamic-font-min(1, 14px) !default;
/// @prop - Text color of the alert sub title
$alert-ios-sub-title-text-color: $text-color-step-400 !default;
@@ -72,7 +72,7 @@ $alert-ios-message-padding-bottom: 21px !default;
$alert-ios-message-padding-start: $alert-ios-message-padding-end !default;
/// @prop - Font size of the alert message
$alert-ios-message-font-size: 13px !default;
$alert-ios-message-font-size: dynamic-font-min(1, 13px) !default;
/// @prop - Text align of the alert message
$alert-ios-message-text-align: center !default;
@@ -137,11 +137,23 @@ $alert-ios-button-margin: 0 !default;
/// @prop - Min width of the alert button
$alert-ios-button-min-width: 50% !default;
/// @prop - Minimum height of the alert button
$alert-ios-button-min-height: 44px !default;
/// @prop - Height of the alert button
/**
* We want the height of the button to
* scale with the text so the next never runs
* into the edge of the button. We change the height
* instead of adding padding because we would need to offset
* the height the padding and the border. Since the border uses
* a hairline (<1px) width, this will cause subpixel rendering
* differences across browsers.
*/
$alert-ios-button-height: dynamic-font-min(1, 44px) !default;
/// @prop - Padding of the alert button
$alert-ios-button-padding: 8px !default;
/// @prop - Font size of the alert button
$alert-ios-button-font-size: 17px !default;
$alert-ios-button-font-size: dynamic-font-min(1, 17px) !default;
/// @prop - Color of the text in the alert button
$alert-ios-button-text-color: ion-color(primary, base) !default;
@@ -252,10 +264,10 @@ $alert-ios-checkbox-margin-bottom: 10px !default;
$alert-ios-checkbox-margin-start: 16px !default;
/// @prop - Size of the checkbox in the alert
$alert-ios-checkbox-size: 24px !default;
$alert-ios-checkbox-size: dynamic-font-max(24px, 2.75) !default;
/// @prop - Border width of the checkbox in the alert
$alert-ios-checkbox-border-width: 1px !default;
$alert-ios-checkbox-border-width: dynamic-font(1px) !default;
/// @prop - Border style of the checkbox in the alert
$alert-ios-checkbox-border-style: solid !default;
@@ -276,16 +288,16 @@ $alert-ios-checkbox-background-color-off: $item-ios-background !de
$alert-ios-checkbox-background-color-on: ion-color(primary, base) !default;
/// @prop - Top of the icon in the checkbox alert
$alert-ios-checkbox-icon-top: math.div($alert-ios-checkbox-size, 6) !default;
$alert-ios-checkbox-icon-top: calc($alert-ios-checkbox-size / 6) !default;
/// @prop - Start of the icon in the checkbox alert
$alert-ios-checkbox-icon-start: math.div($alert-ios-checkbox-size, 3) + 1px !default;
$alert-ios-checkbox-icon-start: calc($alert-ios-checkbox-size / 3 + 1px) !default;
/// @prop - Width of the icon in the checkbox alert
$alert-ios-checkbox-icon-width: math.div($alert-ios-checkbox-size, 6) + 1px !default;
$alert-ios-checkbox-icon-width: calc($alert-ios-checkbox-size / 6 + 1px) !default;
/// @prop - Height of the icon in the checkbox alert
$alert-ios-checkbox-icon-height: $alert-ios-checkbox-size * 0.5 !default;
$alert-ios-checkbox-icon-height: calc($alert-ios-checkbox-size * 0.5) !default;
/// @prop - Border width of the icon in the checkbox alert
$alert-ios-checkbox-icon-border-width: $alert-ios-checkbox-border-width !default;

View File

@@ -192,6 +192,10 @@
flex: 1;
// Required for the checkbox icon to stay on the screen without
// being squished when the font size scales up.
width: calc(100% - $alert-md-checkbox-label-padding-start);
color: $alert-md-checkbox-label-text-color;
font-size: $alert-md-checkbox-label-font-size;

View File

@@ -5,7 +5,7 @@
// --------------------------------------------------
/// @prop - Font size of the alert
$alert-md-font-size: 14px !default;
$alert-md-font-size: dynamic-font(14px) !default;
/// @prop - Max width of the alert
$alert-md-max-width: 280px !default;
@@ -38,13 +38,13 @@ $alert-md-head-text-align: start !default;
$alert-md-title-color: $text-color !default;
/// @prop - Font size of the alert title
$alert-md-title-font-size: 20px !default;
$alert-md-title-font-size: dynamic-font(20px) !default;
/// @prop - Font weight of the alert title
$alert-md-title-font-weight: 500 !default;
/// @prop - Font size of the alert sub title
$alert-md-sub-title-font-size: 16px !default;
$alert-md-sub-title-font-size: dynamic-font(16px) !default;
/// @prop - Text color of the alert sub title
$alert-md-sub-title-text-color: $text-color !default;
@@ -62,7 +62,7 @@ $alert-md-message-padding-bottom: $alert-md-message-padding-top !def
$alert-md-message-padding-start: $alert-md-message-padding-end !default;
/// @prop - Font size of the alert message
$alert-md-message-font-size: 16px !default;
$alert-md-message-font-size: dynamic-font(16px) !default;
/// @prop - Text color of the alert message
$alert-md-message-text-color: $text-color-step-450 !default;
@@ -239,7 +239,7 @@ $alert-md-radio-label-padding-bottom: $alert-md-radio-label-padding-top
$alert-md-radio-label-padding-start: $alert-md-radio-label-padding-end + 26px !default;
/// @prop - Font size of the label for the radio alert
$alert-md-radio-label-font-size: 16px !default;
$alert-md-radio-label-font-size: dynamic-font(16px) !default;
/// @prop - Text color of the label for the radio alert
$alert-md-radio-label-text-color: $text-color-step-150 !default;
@@ -314,7 +314,7 @@ $alert-md-checkbox-label-padding-start: $alert-md-checkbox-label-padding-e
$alert-md-checkbox-label-text-color: $text-color-step-150 !default;
/// @prop - Font size of the label for the checkbox in the alert
$alert-md-checkbox-label-font-size: 16px !default;
$alert-md-checkbox-label-font-size: dynamic-font(16px) !default;
/// @prop - Height of the tappable inputs in the checkbox alert
$alert-md-tappable-height: $item-md-min-height !default;

View File

@@ -10,10 +10,10 @@ $alert-min-width: 250px !default;
$alert-max-height: 90% !default;
/// @prop - Line height of the alert button
$alert-button-line-height: 20px !default;
$alert-button-line-height: dynamic-font(20px) !default;
/// @prop - Font size of the alert button
$alert-button-font-size: 14px !default;
$alert-button-font-size: dynamic-font(14px) !default;
/// @prop - Minimum height of a textarea in the alert
$alert-input-min-height: 37px !default;

View File

@@ -95,3 +95,139 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
});
});
});
/**
* This behavior does not vary across directions
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('alert: font scaling'), () => {
test('should scale text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 36px;
}
</style>
<ion-alert header="Header" sub-header="Sub Header" message="Message"></ion-alert>
<script>
const alert = document.querySelector('ion-alert');
alert.buttons = ['Ok', 'Cancel'];
</script>
`,
config
);
const alert = page.locator('ion-alert');
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
await alert.evaluate((el: HTMLIonAlertElement) => el.present());
await ionAlertDidPresent.next();
await expect(page).toHaveScreenshot(screenshot(`alert-scale`));
});
test('should scale text on larger font sizes with checkboxes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 36px;
}
</style>
<ion-alert header="Header" sub-header="Sub Header" message="Message"></ion-alert>
<script>
const alert = document.querySelector('ion-alert');
alert.inputs = [
{ type: 'checkbox', value: 'a', label: 'Checkbox A', checked: true },
{ type: 'checkbox', value: 'b', label: 'Checkbox B' },
{ type: 'checkbox', value: 'c', label: 'Checkbox C' },
{ type: 'checkbox', value: 'd', label: 'Checkbox D' },
];
alert.buttons = ['Ok', 'Cancel'];
</script>
`,
config
);
const alert = page.locator('ion-alert');
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
await alert.evaluate((el: HTMLIonAlertElement) => el.present());
await ionAlertDidPresent.next();
await expect(page).toHaveScreenshot(screenshot(`alert-checkbox-scale`));
});
test('should scale text on larger font sizes with radios', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 36px;
}
</style>
<ion-alert header="Header" sub-header="Sub Header" message="Message"></ion-alert>
<script>
const alert = document.querySelector('ion-alert');
alert.inputs = [
{ type: 'radio', value: 'a', label: 'Radio A', checked: true },
{ type: 'radio', value: 'b', label: 'Radio B' },
{ type: 'radio', value: 'c', label: 'Radio C' },
{ type: 'radio', value: 'd', label: 'Radio D' },
];
alert.buttons = ['Ok', 'Cancel'];
</script>
`,
config
);
const alert = page.locator('ion-alert');
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
await alert.evaluate((el: HTMLIonAlertElement) => el.present());
await ionAlertDidPresent.next();
await expect(page).toHaveScreenshot(screenshot(`alert-radio-scale`));
});
test('should scale text on larger font sizes with text fields', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 36px;
}
</style>
<ion-alert header="Header" sub-header="Sub Header" message="Message"></ion-alert>
<script>
const alert = document.querySelector('ion-alert');
alert.inputs = [
{ type: 'text', value: 'My Input', label: 'Input' },
{ type: 'textarea', value: 'My Textarea', label: 'Textarea' },
];
alert.buttons = ['Ok', 'Cancel'];
</script>
`,
config
);
const alert = page.locator('ion-alert');
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
await alert.evaluate((el: HTMLIonAlertElement) => el.present());
await ionAlertDidPresent.next();
await expect(page).toHaveScreenshot(screenshot(`alert-text-fields-scale`));
});
});
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

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: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -13,10 +13,26 @@
--color: #{$back-button-ios-color};
--icon-margin-end: 1px;
--icon-margin-start: -4px;
/**
* The icon should be sized relative
* to the size of the text which is
* why we use em here instead of rem.
* This allows developers to override
* the text font size while ensuring that
* the icon is sized relative to that.
*/
--icon-font-size: 1.6em;
--min-height: 32px;
font-size: 17px;
/**
* Main content should be prioritized over the back
* button which is why a maximum font size is applied.
* Also, we want the text to remain readable
* so a minimum font size is applied.
* Using 1.294 instead of 1.3 aligns the text
* with the icon a bit nicer in Firefox.
*/
font-size: dynamic-font-clamp(1, 17px, 1.294);
}
.button-native {

View File

@@ -13,14 +13,14 @@
--color: #{$back-button-md-color};
--icon-margin-end: 0;
--icon-margin-start: 0;
--icon-font-size: 24px;
--icon-font-size: #{dynamic-font(24px)};
--icon-font-weight: normal;
--min-height: 32px;
--min-width: 44px;
--padding-start: 12px;
--padding-end: 12px;
font-size: 14px;
font-size: dynamic-font(14px);
font-weight: 500;
text-transform: uppercase;
@@ -30,7 +30,14 @@
--border-radius: 50%;
min-width: 48px;
height: 48px;
min-height: 48px;
/**
* This allows the icon only button to
* keep its circular shape even when the
* text scales up.
*/
aspect-ratio: 1 / 1;
}
.button-native {

View File

@@ -0,0 +1,29 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('back-button: font scaling'), () => {
test('should scale text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 36px;
}
</style>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button default-href="/" text="Back"></ion-back-button>
</ion-buttons>
</ion-toolbar>
`,
config
);
const backButton = page.locator('ion-back-button');
await expect(backButton).toHaveScreenshot(screenshot(`back-button-scale`));
});
});
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -6,4 +6,13 @@
:host {
@include border-radius($badge-ios-border-radius);
/**
* "-apple-system-body" on iOS never goes smaller than
* 14px according to https://developer.apple.com/design/human-interface-guidelines/typography#Specifications.
* However, we still keep the max() usage here for consistency
* with other components and in case "-apple-system-body" does
* go smaller than 14px in the future.
*/
font-size: dynamic-font-min(1, $badge-baseline-font-size);
}

View File

@@ -18,8 +18,11 @@ $badge-padding-start: $badge-padding-end !default;
/// @prop - Minimum width of the badge
$badge-min-width: 10px !default;
/// @prop - Baseline font size of the badge
$badge-baseline-font-size: 13px !default;
/// @prop - Font size of the badge
$badge-font-size: 13px !default;
$badge-font-size: dynamic-font($badge-baseline-font-size) !default;
/// @prop - Font weight of the badge
$badge-font-weight: bold !default;

View File

@@ -0,0 +1,25 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('badge: font scaling'), () => {
test('should scale text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 36px;
}
</style>
<ion-badge>123</ion-badge>
`,
config
);
const badge = page.locator('ion-badge');
await expect(badge).toHaveScreenshot(screenshot(`badge-scale`));
});
});
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -10,6 +10,14 @@
--color-hover: #{$breadcrumb-ios-color-active};
--color-focused: var(--color-active);
--background-focused: #{$breadcrumb-ios-background-focused};
/**
* Main content should be prioritized
* on iOS, so we set max font size for breadcrumbs.
* Breadcrumbs can be placed in the content too, so
* we add a min font size to keep the text legible.
*/
font-size: dynamic-font-clamp(1, $breadcrumb-baseline-font-size, 1.375);
}
:host(.breadcrumb-active) {
@@ -58,7 +66,7 @@
::slotted(ion-icon) {
color: $breadcrumb-ios-icon-color;
font-size: 18px;
font-size: dynamic-font-max(18px, 1.2);
}
::slotted(ion-icon[slot="start"]) {
@@ -92,3 +100,7 @@
.breadcrumbs-collapsed-indicator:focus {
background: $breadcrumb-ios-indicator-background-focused;
}
.breadcrumbs-collapsed-indicator ion-icon {
font-size: dynamic-font-max(22px, 1);
}

View File

@@ -53,7 +53,7 @@
::slotted(ion-icon) {
color: $breadcrumb-md-icon-color;
font-size: 18px;
font-size: dynamic-font(18px);
}
::slotted(ion-icon[slot="start"]) {

View File

@@ -156,5 +156,5 @@
.breadcrumbs-collapsed-indicator ion-icon {
margin-top: 1px;
font-size: 22px;
font-size: dynamic-font(22px);
}

View File

@@ -6,8 +6,10 @@
/// @prop - Font weight of the breadcrumb
$breadcrumb-font-weight: 400 !default;
$breadcrumb-baseline-font-size: 16px !default;
/// @prop - Font size of the breadcrumb
$breadcrumb-font-size: 16px !default;
$breadcrumb-font-size: dynamic-font($breadcrumb-baseline-font-size) !default;
/// @prop - Color of the breadcrumb separator
$breadcrumb-separator-color: var(--ion-color-step-550, #73849a) !default;

View File

@@ -12,3 +12,30 @@ configs().forEach(({ config, title }) => {
});
});
});
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('breadcrumbs: font scaling'), () => {
test('should scale text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 36px;
}
</style>
<ion-breadcrumbs max-items="2" items-before-collapse="1">
<ion-breadcrumb>Home</ion-breadcrumb>
<ion-breadcrumb>Electronics</ion-breadcrumb>
<ion-breadcrumb>Photography</ion-breadcrumb>
</ion-breadcrumbs>
`,
config
);
const breadcrumbs = page.locator('ion-breadcrumbs');
await expect(breadcrumbs).toHaveScreenshot(screenshot(`breadcrumbs-scale`));
});
});
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -24,20 +24,6 @@
letter-spacing: #{$button-ios-letter-spacing};
}
/**
* The default buttons in a toolbar
* have a different font size/weight
* than buttons outside of a toolbar on iOS.
* However, we still want the "size"/"strong"
* properties to be usable in a toolbar, so we add
* the .in-buttons selector such that we
* can add the different font size/weight in a toolbar
* but still let "size"/"strong" override it.
*/
:host(.in-buttons) {
font-size: #{$toolbar-ios-button-font-size};
font-weight: 400;
}
// iOS Solid Button
// --------------------------------------------------
@@ -82,6 +68,25 @@
}
// iOS Toolbar Buttons
// --------------------------------------------------
/**
* The default buttons in a toolbar
* have a different font size/weight
* than buttons outside of a toolbar on iOS.
* However, we still want the "size"/"strong"
* properties to be usable in a toolbar, so we add
* the .in-buttons selector such that we
* can add the different font size/weight in a toolbar
* but still let "size"/"strong" override it.
*/
:host(.in-buttons) {
font-size: #{$toolbar-ios-button-font-size};
font-weight: 400;
}
// iOS Button Sizes
// --------------------------------------------------
@@ -127,7 +132,7 @@
}
// iOS strong Button
// iOS Strong Button
// --------------------------------------------------
:host(.button-strong) {

View File

@@ -34,7 +34,9 @@ $button-ios-min-height: 3.1em !default;
$button-ios-border-radius: 14px !default;
/// @prop - Font size of the button text
$button-ios-font-size: 16px !default;
/// The maximum font size is calculated by taking the default font size
/// and multiplying it by 3, since 310% of the default is the maximum
$button-ios-font-size: dynamic-font-max(16px, 3) !default;
/// @prop - Font weight of the button text
$button-ios-font-weight: 500 !default;
@@ -83,7 +85,9 @@ $button-ios-large-min-height: 3.1em !default;
$button-ios-large-border-radius: 16px !default;
/// @prop - Font size of the large button
$button-ios-large-font-size: 20px !default;
/// The maximum font size is calculated by taking the default font size
/// and multiplying it by 3, since 310% of the default is the maximum
$button-ios-large-font-size: dynamic-font-max(20px, 3) !default;
// iOS Small Button
@@ -108,7 +112,9 @@ $button-ios-small-min-height: 2.1em !default;
$button-ios-small-border-radius: 6px !default;
/// @prop - Font size of the small button
$button-ios-small-font-size: 13px !default;
/// The maximum font size is calculated by taking the default font size
/// and multiplying it by 3, since 310% of the default is the maximum
$button-ios-small-font-size: dynamic-font-max(13px, 3) !default;
// iOS Outline Button
@@ -151,13 +157,15 @@ $button-ios-outline-background-color-focused: ion-color(primary, base, $
// --------------------------------------------------
/// @prop - Font size of the clear button
$button-ios-clear-font-size: 17px !default;
/// The maximum font size is calculated by taking the default font size
/// and multiplying it by 3, since 310% of the default is the maximum
$button-ios-clear-font-size: dynamic-font-max(17px, 3) !default;
/// @prop - Font weight of the clear button
$button-ios-clear-font-weight: normal !default;
/// @prop - Letter spacing of the button
$button-ios-letter-spacing: 0 !default;
$button-ios-letter-spacing: 0 !default;
/// @prop - Border color of the clear button
$button-ios-clear-border-color: transparent !default;

View File

@@ -34,7 +34,7 @@ $button-md-min-height: 36px !default;
$button-md-border-radius: 4px !default;
/// @prop - Font size of the button text
$button-md-font-size: 14px !default;
$button-md-font-size: dynamic-font(14px) !default;
/// @prop - Font weight of the button text
$button-md-font-weight: 500 !default;
@@ -78,7 +78,7 @@ $button-md-large-padding-start: $button-md-large-padding
$button-md-large-min-height: 2.8em !default;
/// @prop - Font size of the large button
$button-md-large-font-size: 20px !default;
$button-md-large-font-size: dynamic-font(20px) !default;
// Material Design Small Button
@@ -100,7 +100,7 @@ $button-md-small-padding-start: $button-md-small-padding
$button-md-small-min-height: 2.1em !default;
/// @prop - Font size of the small button
$button-md-small-font-size: 13px !default;
$button-md-small-font-size: dynamic-font(13px) !default;
// Material Design Outline Button

View File

@@ -0,0 +1,82 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('button: font scaling'), () => {
test('should scale default button text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 310%;
}
</style>
<ion-button>Default</ion-button>
`,
config
);
const button = page.locator('ion-button');
await expect(button).toHaveScreenshot(screenshot(`button-default-scale`));
});
test('should scale clear button text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 310%;
}
</style>
<ion-button fill="clear">Clear</ion-button>
`,
config
);
const button = page.locator('ion-button');
await expect(button).toHaveScreenshot(screenshot(`button-clear-scale`));
});
test('should scale small button text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 310%;
}
</style>
<ion-button size="small">Small</ion-button>
`,
config
);
const button = page.locator('ion-button');
await expect(button).toHaveScreenshot(screenshot(`button-small-scale`));
});
test('should scale large button text on larger font sizes', async ({ page }) => {
await page.setContent(
`
<style>
html {
font-size: 310%;
}
</style>
<ion-button size="large">Large</ion-button>
`,
config
);
const button = page.locator('ion-button');
await expect(button).toHaveScreenshot(screenshot(`button-large-scale`));
});
});
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

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