feat(config): add icon options and align ionic theme with md defaults - #31418
brandyscarney wants to merge 19 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
The default icons have changed for the ionic theme, so all of these screenshot diffs are expected.
…IndeterminateIcon
| .native-wrapper { | ||
| @include mixins.border-radius(var(--border-radius)); | ||
|
|
||
| display: flex; | ||
|
|
||
| position: relative; | ||
|
|
||
| flex-shrink: 0; | ||
|
|
||
| align-items: center; | ||
|
|
||
| width: var(--size); | ||
| height: var(--size); | ||
|
|
||
| transition: var(--transition); | ||
|
|
||
| border-width: var(--border-width); | ||
| border-style: var(--border-style); | ||
| border-color: var(--border-color); | ||
|
|
||
| background: var(--checkbox-background); | ||
|
|
||
| box-sizing: border-box; | ||
| } |
There was a problem hiding this comment.
These styles were the same in the ionic and native files so I moved them to common.
| --border-color: #{globals.$ion-primitives-neutral-800}; | ||
| --checkmark-width: #{globals.$ion-scale-400}; | ||
| --checkmark-height: var(--checkmark-width); | ||
| --checkmark-width: 3; |
There was a problem hiding this comment.
This matches md theme and makes it so all themes are consistently styled.
| .native-wrapper { | ||
| @include globals.border-radius(var(--border-radius)); | ||
|
|
||
| flex-shrink: 0; | ||
|
|
||
| justify-content: center; | ||
|
|
||
| width: var(--size); | ||
| height: var(--size); | ||
|
|
||
| transition: var(--transition); | ||
|
|
||
| border-width: var(--border-width); | ||
| border-style: var(--border-style); | ||
| border-color: var(--border-color); | ||
|
|
||
| background: var(--checkbox-background); | ||
|
|
||
| box-sizing: border-box; | ||
| } |
There was a problem hiding this comment.
These styles were the same in the ionic and native files so I moved them to common.
| > | ||
| {path} | ||
| </svg> | ||
| <div class="native-wrapper" part="container"> |
There was a problem hiding this comment.
I moved the container part to the element wrapping the icon rather than the svg so that the default checkmark and a custom configured icon can be styled consistently. I didn't notice any visual differences when comparing the styles in the docs demo, but this could be a breaking change for anyone targeting the icon specifically as an svg. If the reviewers agree, I can add this to the breaking changes document.
| checkmark CSS properties. An icon set in the config replaces the | ||
| slotted path, so both are styled through the same element. | ||
| */} | ||
| <ion-icon class="checkbox-icon" icon={markIcon} part="icon" aria-hidden="true"> |
There was a problem hiding this comment.
I decided to wrap the default checkmark svg in an ion-icon container so that developers can override the default or a custom configured icon the same way:
ion-checkbox::part(icon) {
color: red;
}| .checkbox-icon { | ||
| @include border-radius(var(--border-radius)); | ||
|
|
||
| width: var(--size); | ||
| height: var(--size); | ||
|
|
||
| transition: var(--transition); | ||
|
|
||
| border-width: var(--border-width); | ||
| border-style: var(--border-style); | ||
| border-color: var(--border-color); | ||
|
|
||
| background: var(--checkbox-background); | ||
|
|
||
| box-sizing: border-box; | ||
| } |
There was a problem hiding this comment.
These styles were moved to the .native-wrapper, making them the same in the ionic and native files so I moved them to common.
There was a problem hiding this comment.
The --checkmark-width now applies the same for all themes, making this have a custom stroke width.
There was a problem hiding this comment.
The --size now applies the same for all themes, making this have a custom checkmark size.
There was a problem hiding this comment.
Really nice cleanup, great work! Two things I'd like to sort out before this goes in.
The new custom icon test reassigns window.Ionic, which drops the mode and theme that setContent injects, so all three of its matrix entries are rendering as md and the ios and ionic baselines aren't testing what they look like they're testing. Separately, ion-alert still has the Phosphor checkmark inlined in its ionic branch, so that's the one spot where the acceptance criteria aren't met yet.
Everything else is nits and a couple of coverage gaps, take or leave those.
| window.Ionic = { | ||
| config: { | ||
| checkboxCheckedIcon: '${phosphorHeart}', | ||
| checkboxIndeterminateIcon: 'star', | ||
| }, | ||
| }; |
There was a problem hiding this comment.
| window.Ionic = { | |
| config: { | |
| checkboxCheckedIcon: '${phosphorHeart}', | |
| checkboxIndeterminateIcon: 'star', | |
| }, | |
| }; | |
| window.Ionic = window.Ionic || {}; | |
| window.Ionic.config = { | |
| ...window.Ionic.config, | |
| checkboxCheckedIcon: '${phosphorHeart}', | |
| checkboxIndeterminateIcon: 'star', | |
| }; |
This seems like a big issue. The setContent helper is the only thing carrying mode and theme from configs(), and it does that by setting window.Ionic in the head, so reassigning the whole object here drops both and all three matrix entries render as md.
You can see it in the committed baselines, the ios and md ones are byte-identical for both tests in all three browsers. Merging instead gives ios 22px, md 18px and ionic 24px, matching a run with no custom config at all. Tests still pass. The snapshots will need regenerating though.
There was a problem hiding this comment.
You're right. I don't know how I didn't notice that the screenshots were all the same theme. 😂
Fixed: 550e889
| ); | ||
|
|
||
| if (theme === 'md') { | ||
| if (theme === 'md' || theme === 'ionic') { |
There was a problem hiding this comment.
Over in ion-alert, this exact path is still inlined in its ionic branch, so a grep for phosphor doesn't find it. That leaves the alert checkbox drawing a filled Phosphor check on ionic while ion-checkbox draws the stroked md polyline, and checkboxCheckedIcon doesn't reach it. You can get there through ion-select with interface="alert" and multiple, or through alertController checkbox inputs.
Dropping the svg won't work on its own since ionic has no border-drawn fallback like ios and md do. Using the same md polyline and switching that stylesheet from fill to stroke at width 3 makes the alert mark match ion-checkbox exactly, with nothing showing when unchecked.
There was a problem hiding this comment.
Good catch! I was looking at the changes done on 08fc0b9 and searching the repository for Phosphor but this was done prior and not documented as being a Phosphor icon.
I changed the checkmark to be entirely done by CSS that is derived from the ion-checkbox so that those would appear identical. The downside is this won't scale with font-size on html (dynamic font scaling). However, that also didn't work before for the ionic theme. I think we should probably look into changing this to match the ion-checkbox implementation with an ion-icon and a wrapped svg. I added a question on the Jira ticket for this so we can discuss it internally.
Fix: 393a0bc
Let me know if you were thinking of a different implementation. I tried a few different ways with border-width and transform but none of them lined up.
| opacity: 0; | ||
| fill: none; | ||
| stroke: currentColor; | ||
| stroke-width: var(--checkmark-width); |
There was a problem hiding this comment.
This fill to stroke change is what makes the ionic indeterminate mark render at all, but nothing screenshots it. The indeterminate test doesn't opt into ionic-md, and the basic test page has no indeterminate checkbox in it. Adding the mode to that spec produces a good snapshot.
Probably a follow-up rather than something for this PR, but back-button, breadcrumb, fab-button and a few of the other components whose ionic default changed here have no ionic snapshots at all, so those swaps aren't verified either.
There was a problem hiding this comment.
Added: 8b271d6
I think getting all of the themes tested properly should be part of the modular ionic work, personally. Ideally it should be done at the time of migrating each component.
| --border-color: #{globals.$ion-primitives-neutral-800}; | ||
| --checkmark-width: #{globals.$ion-scale-400}; | ||
| --checkmark-height: var(--checkmark-width); | ||
| --checkmark-width: 3; |
There was a problem hiding this comment.
This changes what the property means on ionic rather than just its value. Setting --checkmark-width: 22px used to size the svg to 22x22 with a 1px stroke, now it gives you a 22px stroke width, and --checkmark-height is gone entirely. ios and md aren't affected since they already treated it as a stroke width.
I think that's worth a line in the PR body at least, since Mobile UI are the ones most likely to have set it. A stroke override through ::part(container) used to reach the mark on ionic too and no longer does.
There was a problem hiding this comment.
I have added an info panel to the Jira ticket since this is unreleased code, letting Mobile UI know how to replace the removed/changed variables.
| size, | ||
| } = this; | ||
| const theme = getIonTheme(this); | ||
| const markIcon = indeterminate ? this.checkboxIndeterminateIcon : this.checkboxCheckedIcon; |
There was a problem hiding this comment.
Could you destructure these two into the block above rather than reading them off this? The four other components that got a config icon getter in this PR all do it that way.
| checkmark CSS properties. An icon set in the config replaces the | ||
| slotted path, so both are styled through the same element. | ||
| */} | ||
| <ion-icon class="checkbox-icon" icon={markIcon} part="icon" aria-hidden="true"> |
There was a problem hiding this comment.
This is minor and I don't think it needs anything, but since the slotted svg is the fallback, a config icon that has to resolve asynchronously lets the theme's own mark paint first. With a base64 data URL the default check shows for a frame on ios and ionic, two on md, before swapping over. Only the first instance pays it because ionicons caches by URL, so it's small, but someone will report it as a flicker eventually.
There was a problem hiding this comment.
I implemented a fix by only adding the svg when markIcon is undefined, that way there will be no flicker: badfb51
| * Use the icon set in the config. | ||
| * If no icon is set in the config, use the default icon. | ||
| */ | ||
| private get cancelButtonIcon(): string { |
There was a problem hiding this comment.
Nit: every other config icon getter is named after its config key, including the three you added here, so selectModalCancelIcon would match now that this one is config-backed. It's also the only rewritten getter missing the trailing "Return the configured ... icon or the default icon" comment. Up to you!
There was a problem hiding this comment.
I actually was removing the single lines above the return because the comment on top of the getter already explains that. I went through and removed the rest of them but let me know if you want them all added back: 861c01c
| stroke: var(--checkmark-color); | ||
| stroke-width: var(--checkmark-width); | ||
| .checkbox-icon { | ||
| font-size: calc(var(--size) - 2 * var(--border-width)); |
There was a problem hiding this comment.
The --border-width prop accepts thin, medium and thick, and those make this calc() invalid so the font-size falls back to the inherited 16px. With thick the mark goes non-square, ios comes out 12x16 and md 8x16, where before this PR they stayed 22x22 and 18x18. I tried the obvious flex-based replacement and it doesn't fix the keyword case and makes the default one worse, so I don't have a fix to offer, just flagging it in case you think it's worth handling.
There was a problem hiding this comment.
It looks like I could remove that entirely: 73ce038
| * checkmark icon and any configured icon apply color consistently. | ||
| */ | ||
| .checkbox-icon { | ||
| position: relative; |
There was a problem hiding this comment.
| position: relative; |
I don't think anything positions against this any more. None of the four checkbox stylesheets absolutely position a descendant of the icon, and the real positioning moved onto the wrapper in this PR.
| ion-checkbox,part,container | ||
| ion-checkbox,part,error-text | ||
| ion-checkbox,part,helper-text | ||
| ion-checkbox,part,icon |
There was a problem hiding this comment.
The @prop doc for --checkbox-background probably wants to move into the common stylesheet alongside it, otherwise this file keeps listing it for ios and md only. The split predates the PR, but you already moved --checkmark-width's doc across as part of the same consolidation. Up to you!
Issue number: internal
What is the current behavior?
Several components use Phosphor Icons by default only for the
ionictheme.What is the new behavior?
ionictheme, instead replacing them with whatever iconmdusesion-iconas a font.checkboxCheckedIconandcheckboxIndeterminateIconrefresherArrowIconselectModalCancelIconDoes this introduce a breaking change?
The
ionictheme is unreleased so none of what is being removed was ever in the public API. This is for the next major version of Ionic.Other information
Previews: