feat(config): add icon options and align ionic theme with md defaults - #31418
brandyscarney wants to merge 20 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.
| <ion-icon class="checkbox-icon" icon={markIcon} part="icon" aria-hidden="true"> | ||
| {!markIcon && <svg viewBox="0 0 24 24">{path}</svg>} |
There was a problem hiding this comment.
This seems like a big issue, and it comes out of my flicker nit last round, so sorry for sending you down this path.
Gating the svg on !markIcon means a configured icon never gets replaced by the theme's mark. The ion-icon renders its <slot> only while its resolved svg content is empty, and ionicons never clears that content when icon goes away, so once it has loaded anything the slot is gone for good.
You don't need a programmatic change to hit it. Set only checkboxIndeterminateIcon, render an indeterminate checkbox, and one user click leaves the indeterminate icon painted on a now-checked box. With that config the icon renders in every state including checked, so the theme checkmark never appears at all.
Adding a key so the element gets replaced when the mark switches kind fixes it:
| <ion-icon class="checkbox-icon" icon={markIcon} part="icon" aria-hidden="true"> | |
| {!markIcon && <svg viewBox="0 0 24 24">{path}</svg>} | |
| <ion-icon | |
| key={markIcon ? 'config-icon' : 'theme-mark'} | |
| class="checkbox-icon" | |
| icon={markIcon} | |
| part="icon" | |
| aria-hidden="true" | |
| > | |
| {!markIcon && <svg viewBox="0 0 24 24">{path}</svg>} | |
| </ion-icon> |
That holds up across all three config permutations, and with nothing configured the output is identical to what's here now, so the baselines aren't affected. Always rendering the svg and hiding it with CSS doesn't work, since the slot never comes back once it's gone.
Neither new test catches it, since newSpecPage doesn't hydrate ion-icon and the custom icon spec always sets both keys.
| /** | ||
| * @prop --size: Size of the checkbox icon | ||
| * | ||
| * @prop --checkbox-background: Background of the checkbox icon |
There was a problem hiding this comment.
One for the @prop --checkmark-width: Stroke width of the checkbox checkmark line just below, which didn't get the caveat @part mark did.
Setting it does nothing once an icon is set in the config, since it only applies through .checkbox-icon path and can't reach an icon rendering inside the ion-icon shadow root. With --checkmark-width: 10 the stroke comes out 10px without a config icon and 1px with one. The color prop is fine, since that one goes on the host and ionicons picks it up from currentColor.
The same clause you put on @part mark would cover it.
| * @part label - The label text describing the checkbox. | ||
| * @part mark - The checkmark used to indicate the checked state. | ||
| * @part icon - The icon that displays the checked or indeterminate mark. | ||
| * @part mark - The checkmark used to indicate the checked state. Only applies when no icon is set in the config. |
There was a problem hiding this comment.
| * @part mark - The checkmark used to indicate the checked state. Only applies when no icon is set in the config. | |
| * @part mark - The mark used to indicate the checked or indeterminate state. Only applies when no icon is set in the config. |
You widened the icon part to cover both states, and this one still says checked only, but part="mark" is on both branches of getSVGPath for every theme including the indeterminate paths. Someone styling the indeterminate dash would read the part table and think it doesn't apply. The config caveat is right.
| * Otherwise, use the icon set in the config. | ||
| * If no icon is set in the config, use the default icon. | ||
| */ | ||
| get backButtonIcon() { |
There was a problem hiding this comment.
This getter and eight others got the JSDoc treatment but kept a bare signature, so they infer any out of config.get instead of string. The guide section you added shows the annotated form and the other icon getters in core already have it.
There's one catch before you add them, though. Annotating this one breaks the build, since hasIconOnly just below returns this.backButtonIcon && !this.backButtonText and only type-checked while the getter was any. That means changing it to get hasIconOnly(): boolean with a !! on the first operand. The coercion changes no result, so it's two files rather than a one-liner. Up to you whether that belongs here or separately.
| > | ||
| {path} | ||
| </svg> | ||
| <div class="native-wrapper" part="container"> |
There was a problem hiding this comment.
Yeah, I think this should go in the breaking changes doc, since it's a v9 part rather than the unreleased theme. Anything setting fill or stroke through it stops working, and ::part(container) > * now hits a different element.
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: