diff --git a/BREAKING.md b/BREAKING.md index fa6a2f67322..b76cebd4638 100644 --- a/BREAKING.md +++ b/BREAKING.md @@ -58,14 +58,15 @@ The following breaking changes apply to `ion-button`: 1. The `border-radius` of the `ios` button is now `6px` at every size, instead of `6px`, `14px` and `16px` for the small, default and large sizes. The `md` button now defaults to `999px` instead of `4px`. Both follow the iOS and Material Design 3 guidelines. To revert to the previous appearance, set the `shape` to `"soft"` for `md`. For `ios`, set `IonButton.shape.soft.border.radius` for global styles or `--ion-button-shape-soft-border-radius` for component-specific styles to `14px`, and to `6px` and `16px` on small and large buttons. 2. Icon-only buttons in the `start` and `end` slots of `ion-input`, `ion-select` and `ion-textarea` now follow the button's `shape` instead of always being circles. For `ios`, set the `shape` to `"round"` to keep them circular. 3. The font size of `clear` buttons in the `ios` theme now matches the other fills at each size, instead of `17px` at the default size. To keep the previous size, set `--ion-button-size-medium-font-size` to `17px` on those buttons. -4. The `ios` button is now `28px`, `34px` and `50px` tall at the small, default and large sizes, with less padding, following the iOS guidelines. To revert to the previous appearance, set `IonButton.size..min.height` for global styles or `--ion-button-size--min-height` for component-specific styles to `2.1em`, `3.1em` and `3.1em`, and the padding (`IonButton.size..padding` or `--ion-button-size--padding-*`) to `4px 0.9em`, `13px 1em` and `17px 1em`. +4. The `ios` button is now `28px`, `34px` and `50px` tall at the small, default and large sizes, with less padding, following the iOS guidelines. To revert to the previous appearance, set `IonButton.size..min.height` for global styles or `--ion-button-size--min-height` for component-specific styles to `2.1em`, `3.1em` and `3.1em`, and the padding (`IonButton.size..padding` or `--ion-button-size--padding-*`) to `4px 0.9em`, `13px 1em` and `17px 1em`, along with the previous font sizes from item 7. 5. Icon-only buttons are now squares as tall as a text button of the same size. In `md`, this makes them a few pixels smaller at the small and default sizes and larger at the large size. To change their size, set the size's `min.height` as described above. 6. The `md` button follows Material Design 2 for its spacing, outline, elevation and disabled state. [6](#version-10x-button-md-material-design-2) -7. CSS variables have been replaced. [7](#version-10x-button-replaced-css-variables) -8. `--padding-*` CSS variables are no longer part of the documented public API (but remain functional). [8](#version-10x-button-padding-variables) -9. The fill, size, shape and expand classes have been renamed. [9](#version-10x-button-renamed-classes) -10. The `default` size has been deprecated. [10](#version-10x-button-deprecated-default-size) -11. Theme classes (`ion-button.md`, `ion-button.ios`) are no longer supported. [11](#version-10x-button-theme-classes) +7. The `ios` button follows iOS 17 for its font, icons and disabled state. [7](#version-10x-button-ios-17) +8. CSS variables have been replaced. [8](#version-10x-button-replaced-css-variables) +9. `--padding-*` CSS variables are no longer part of the documented public API (but remain functional). [9](#version-10x-button-padding-variables) +10. The fill, size, shape and expand classes have been renamed. [10](#version-10x-button-renamed-classes) +11. The `default` size has been deprecated. [11](#version-10x-button-deprecated-default-size) +12. Theme classes (`ion-button.md`, `ion-button.ios`) are no longer supported. [12](#version-10x-button-theme-classes)
Material Design 2 in md
@@ -86,6 +87,24 @@ The `md` button now uses the Material Design 2 values below. To keep a previous Buttons in toolbars keep their previous colors when disabled and have no elevation on hover or focus. +
iOS 17 in ios
+ +The `ios` button now uses the iOS 17 values below. To keep a previous value, set the token for global styles, or the matching `--ion-button-*` CSS variable for component-specific styles. Replace `` with `solid`, `outline` or `clear`, and `` with `small`, `medium` or `large`. Values in `em` are relative to the font size, so reverting the font size also needs the previous `em` values. + +| Property | Previous | New | Token | +|---|---|---|---| +| Font size | `13px`, `16px` and `20px` | `15px`, `15px` and `17px` | `IonButton.size..font.size` | +| Font weight of solid and outline | `500` | `400` | `IonButton.hue.bold..default.font.weight` | +| Horizontal padding | `0.77em`, `0.875em` and `1em` | `0.6667em`, `0.9333em` and `1.1765em` (same pixels at the new font size) | `IonButton.size..padding.start` and `.end` | +| Min height | `2.16em`, `2.125em` and `2.5em` | `1.8667em`, `2.2667em` and `2.9412em` (same pixels at the new font size) | `IonButton.size..min.height` | +| Icon size next to a label | `1.35em` | `1.2em` | `IonButton.size..icon.font.size` | +| Icon spacing | `0.3em` into the padding and a `0.3em` gap | at the padding edge and a `0.2222em` gap (`4px` at the default size) | `IonButton.size..icon.leading.margin` and `.trailing.margin` | +| Icon-only icon size | `1.308125em`, `1.125em` and `0.9em` | `1.1333em`, `1.2em` and `1.0588em` (same pixels at the new font size) | `IonButton.size..iconOnly.icon.font.size` | +| Spinner in a button | the spinner's own size (`28px` by default) | `1.2em` by default (`18px` at the default size), with the other spinner sizes in their usual ratio to it | `IonButton.size..spinner.size..width` and `.height` | +| Disabled | the whole button at `0.5` opacity | the text color at `25%`, which outline also uses for its border, and on solid, an `8%` container | `IonButton.hue.bold..disabled.opacity`, `.color`, `.background` and `.border.color` | + +Buttons in toolbars keep their previous colors when disabled. +
Replaced CSS variables
Use the new token structure for global styles, or the corresponding CSS variable for component-specific overrides. Replace `` with `solid`, `outline` or `clear`, and `` with `crisp`, `soft`, `round` or `rectangular`. Buttons with a `color` read the same tokens under `semantic`, for example `IonButton.hue.bold.solid.semantic.default.background`. diff --git a/core/src/themes/ios/default.tokens.ts b/core/src/themes/ios/default.tokens.ts index 76e688530b1..25f5e7529b9 100644 --- a/core/src/themes/ios/default.tokens.ts +++ b/core/src/themes/ios/default.tokens.ts @@ -351,7 +351,7 @@ export const defaultTheme: DefaultTheme = { color: ionColor('primary', 'contrast'), font: { - weight: 'var(--ion-font-weight-medium)', + weight: 'var(--ion-font-weight-normal)', }, }, @@ -371,9 +371,8 @@ export const defaultTheme: DefaultTheme = { }, disabled: { - background: ionColor('primary', 'base'), - - opacity: '0.5', + background: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.08), + color: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.25), }, // Any of the semantic colors like primary, secondary, etc. @@ -399,7 +398,8 @@ export const defaultTheme: DefaultTheme = { }, disabled: { - background: currentColor('base'), + background: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.08), + color: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.25), }, }, }, @@ -422,7 +422,7 @@ export const defaultTheme: DefaultTheme = { }, font: { - weight: 'var(--ion-font-weight-medium)', + weight: 'var(--ion-font-weight-normal)', }, }, @@ -446,7 +446,11 @@ export const defaultTheme: DefaultTheme = { disabled: { background: 'transparent', - opacity: '0.5', + border: { + color: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.25), + }, + + color: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.25), }, semantic: { @@ -476,6 +480,12 @@ export const defaultTheme: DefaultTheme = { disabled: { background: 'transparent', + + border: { + color: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.25), + }, + + color: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.25), }, }, }, @@ -517,8 +527,7 @@ export const defaultTheme: DefaultTheme = { disabled: { background: 'transparent', - - opacity: '0.5', + color: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.25), }, semantic: { @@ -544,6 +553,7 @@ export const defaultTheme: DefaultTheme = { disabled: { background: 'transparent', + color: rgba('var(--ion-text-color-rgb, 0, 0, 0)', 0.25), }, }, }, @@ -554,40 +564,40 @@ export const defaultTheme: DefaultTheme = { size: { small: { min: { - height: 'clamp(23px, 2.16em, 54px)', + height: 'clamp(23px, 1.8667em, 54px)', }, padding: { top: 'var(--ion-spacing-xxs)', - end: '0.77em', + end: '0.6667em', bottom: 'var(--ion-spacing-xxs)', - start: '0.77em', + start: '0.6667em', }, font: { - size: `min(${dynamicFont(global.root, 13)}, 39px)`, + size: `min(${dynamicFont(global.root, 15)}, 45px)`, }, icon: { font: { - size: '1.35em', + size: '1.2em', }, leading: { margin: { top: '0', - end: '0.3em', + end: '0.2222em', bottom: '0', - start: '-0.3em', + start: '0', }, }, trailing: { margin: { top: '0', - end: '-0.2em', + end: '0', bottom: '0', - start: '0.3em', + start: '0.2222em', }, }, }, @@ -606,7 +616,37 @@ export const defaultTheme: DefaultTheme = { * The values were provided through a native iOS app. * min font size: 12px, default font size: 17px, max font size: 40px */ - size: 'clamp(12.1394px, 1.308125em, 40.1856px)', + size: 'clamp(12.1394px, 1.1333em, 40.1856px)', + }, + }, + }, + + spinner: { + // `medium`, the default, matches the icon; the other sizes keep their standalone ratio to it + size: { + xsmall: { + height: '0.6857em', + width: '0.6857em', + }, + + small: { + height: '0.8571em', + width: '0.8571em', + }, + + medium: { + height: '1.2em', + width: '1.2em', + }, + + large: { + height: '1.5429em', + width: '1.5429em', + }, + + xlarge: { + height: '2.0571em', + width: '2.0571em', }, }, }, @@ -614,40 +654,40 @@ export const defaultTheme: DefaultTheme = { medium: { min: { - height: 'clamp(30px, 2.125em, 60px)', + height: 'clamp(30px, 2.2667em, 60px)', }, padding: { top: '7px', - end: '0.875em', + end: '0.9333em', bottom: '7px', - start: '0.875em', + start: '0.9333em', }, font: { - size: `min(${dynamicFont(global.root, 16)}, 48px)`, + size: `min(${dynamicFont(global.root, 15)}, 45px)`, }, icon: { font: { - size: '1.35em', + size: '1.2em', }, leading: { margin: { top: '0', - end: '0.3em', + end: '0.2222em', bottom: '0', - start: '-0.3em', + start: '0', }, }, trailing: { margin: { top: '0', - end: '-0.2em', + end: '0', bottom: '0', - start: '0.3em', + start: '0.2222em', }, }, }, @@ -666,7 +706,37 @@ export const defaultTheme: DefaultTheme = { * The values were provided through a native iOS app. * min font size: 15px, default font size: 18px, max font size: 43px */ - size: 'clamp(15.12px, 1.125em, 43.02px)', + size: 'clamp(15.12px, 1.2em, 43.02px)', + }, + }, + }, + + spinner: { + // `medium`, the default, matches the icon; the other sizes keep their standalone ratio to it + size: { + xsmall: { + height: '0.6857em', + width: '0.6857em', + }, + + small: { + height: '0.8571em', + width: '0.8571em', + }, + + medium: { + height: '1.2em', + width: '1.2em', + }, + + large: { + height: '1.5429em', + width: '1.5429em', + }, + + xlarge: { + height: '2.0571em', + width: '2.0571em', }, }, }, @@ -674,40 +744,40 @@ export const defaultTheme: DefaultTheme = { large: { min: { - height: 'clamp(46px, 2.5em, 78px)', + height: 'clamp(46px, 2.9412em, 78px)', }, padding: { top: '14px', - end: '1em', + end: '1.1765em', bottom: '14px', - start: '1em', + start: '1.1765em', }, font: { - size: `min(${dynamicFont(global.root, 20)}, 60px)`, + size: `min(${dynamicFont(global.root, 17)}, 51px)`, }, icon: { font: { - size: '1.35em', + size: '1.2em', }, leading: { margin: { top: '0', - end: '0.3em', + end: '0.2222em', bottom: '0', - start: '-0.3em', + start: '0', }, }, trailing: { margin: { top: '0', - end: '-0.2em', + end: '0', bottom: '0', - start: '0.3em', + start: '0.2222em', }, }, }, @@ -726,7 +796,37 @@ export const defaultTheme: DefaultTheme = { * The values were provided through a native iOS app. * min font size: 15px, default font size: 18px, max font size: 43px */ - size: 'clamp(15.12px, 0.9em, 43.056px)', + size: 'clamp(15.12px, 1.0588em, 43.056px)', + }, + }, + }, + + spinner: { + // `medium`, the default, matches the icon; the other sizes keep their standalone ratio to it + size: { + xsmall: { + height: '0.6857em', + width: '0.6857em', + }, + + small: { + height: '0.8571em', + width: '0.8571em', + }, + + medium: { + height: '1.2em', + width: '1.2em', + }, + + large: { + height: '1.5429em', + width: '1.5429em', + }, + + xlarge: { + height: '2.0571em', + width: '2.0571em', }, }, }, @@ -850,6 +950,21 @@ export const defaultTheme: DefaultTheme = { activated: { color: `var(--ion-toolbar-background, ${ionColor('primary', 'contrast')})`, }, + + // In a toolbar, a disabled button keeps its colors and fades + disabled: { + background: 'var(--ion-button-hue-bold-solid-default-background)', + color: 'var(--ion-button-hue-bold-solid-default-color)', + + opacity: '0.5', + }, + + semantic: { + disabled: { + background: 'var(--ion-button-hue-bold-solid-semantic-default-background)', + color: 'var(--ion-button-hue-bold-solid-semantic-default-color)', + }, + }, }, outline: { @@ -873,6 +988,31 @@ export const defaultTheme: DefaultTheme = { activated: { background: `var(--ion-toolbar-color, ${ionColor('primary', 'base')})`, }, + + // In a toolbar, a disabled button keeps its colors and fades + disabled: { + background: 'var(--ion-button-hue-bold-outline-default-background)', + + border: { + color: 'var(--ion-button-hue-bold-outline-default-border-color)', + }, + + color: 'var(--ion-button-hue-bold-outline-default-color)', + + opacity: '0.5', + }, + + semantic: { + disabled: { + background: 'var(--ion-button-hue-bold-outline-semantic-default-background)', + + border: { + color: 'var(--ion-button-hue-bold-outline-semantic-default-border-color)', + }, + + color: 'var(--ion-button-hue-bold-outline-semantic-default-color)', + }, + }, }, clear: { @@ -891,6 +1031,19 @@ export const defaultTheme: DefaultTheme = { activated: { color: `var(--ion-toolbar-color, ${ionColor('primary', 'foreground')})`, }, + + // In a toolbar, a disabled button keeps its colors and fades + disabled: { + color: 'var(--ion-button-hue-bold-clear-default-color)', + + opacity: '0.5', + }, + + semantic: { + disabled: { + color: 'var(--ion-button-hue-bold-clear-semantic-default-color)', + }, + }, }, }, }, @@ -960,10 +1113,6 @@ export const defaultTheme: DefaultTheme = { hover: { background: 'transparent', }, - - activated: { - background: 'transparent', - }, }, clear: {