fix(label): keep color when focused on a floating or stacked label (#18576)

fixes #18531
This commit is contained in:
Vlad Topala
2020-10-07 20:32:15 +03:00
committed by GitHub
parent 6549330815
commit 992580a383
6 changed files with 101 additions and 3 deletions

View File

@ -4442,6 +4442,10 @@ declare namespace LocalJSX {
* The mode determines which platform styles to use. * The mode determines which platform styles to use.
*/ */
"mode"?: "ios" | "md"; "mode"?: "ios" | "md";
/**
* Emitted when the color changes.
*/
"onIonColor"?: (event: CustomEvent<StyleEventDetail>) => void;
/** /**
* Emitted when the styles change. * Emitted when the styles change.
*/ */

View File

@ -282,3 +282,14 @@
:host(.item-has-focus:not(.ion-color)) ::slotted(.label-floating) { :host(.item-has-focus:not(.ion-color)) ::slotted(.label-floating) {
color: $label-md-text-color-focused; color: $label-md-text-color-focused;
} }
// Material Design Inputs: Highlight Color
// --------------------------------------------------
:host(.ion-color) {
--highlight-color-focused: #{current-color(contrast)};
}
:host(.item-label-color) {
--highlight-color-focused: #{current-color(base)};
}

View File

@ -28,6 +28,7 @@ import { createColorClasses, hostContext, openURL } from '../../utils/theme';
}) })
export class Item implements ComponentInterface, AnchorInterface, ButtonInterface { export class Item implements ComponentInterface, AnchorInterface, ButtonInterface {
private labelColorStyles = {};
private itemStyles = new Map<string, CssClassMap>(); private itemStyles = new Map<string, CssClassMap>();
@Element() el!: HTMLIonItemElement; @Element() el!: HTMLIonItemElement;
@ -111,6 +112,18 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
*/ */
@Prop() type: 'submit' | 'reset' | 'button' = 'button'; @Prop() type: 'submit' | 'reset' | 'button' = 'button';
@Listen('ionColor')
labelColorChanged(ev: CustomEvent<string>) {
const { color } = this;
// There will be a conflict with item color if
// we apply the label color to item, so we ignore
// the label color if the user sets a color on item
if (color === undefined) {
this.labelColorStyles = ev.detail;
}
}
@Listen('ionStyle') @Listen('ionStyle')
itemStyle(ev: CustomEvent<StyleEventDetail>) { itemStyle(ev: CustomEvent<StyleEventDetail>) {
ev.stopPropagation(); ev.stopPropagation();
@ -212,7 +225,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
} }
render() { render() {
const { detail, detailIcon, download, lines, disabled, href, rel, target, routerAnimation, routerDirection } = this; const { detail, detailIcon, download, labelColorStyles, lines, disabled, href, rel, target, routerAnimation, routerDirection } = this;
const childStyles = {}; const childStyles = {};
const mode = getIonMode(this); const mode = getIonMode(this);
const clickable = this.isClickable(); const clickable = this.isClickable();
@ -236,6 +249,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
aria-disabled={disabled ? 'true' : null} aria-disabled={disabled ? 'true' : null}
class={{ class={{
...childStyles, ...childStyles,
...labelColorStyles,
...createColorClasses(this.color, { ...createColorClasses(this.color, {
'item': true, 'item': true,
[mode]: true, [mode]: true,

View File

@ -44,11 +44,16 @@
@include transform(translateY(50%), scale(.75)); @include transform(translateY(50%), scale(.75));
} }
:host-context(.item-has-focus).label-stacked, :host-context(.item-has-focus).label-stacked:not(.ion-color),
:host-context(.item-has-focus).label-floating { :host-context(.item-has-focus).label-floating:not(.ion-color) {
color: $label-md-text-color-focused; color: $label-md-text-color-focused;
} }
:host-context(.item-has-focus.ion-color).label-stacked:not(.ion-color),
:host-context(.item-has-focus.ion-color).label-floating:not(.ion-color) {
color: #{current-color(contrast)};
}
// MD Typography // MD Typography
// -------------------------------------------------- // --------------------------------------------------

View File

@ -32,6 +32,12 @@ export class Label implements ComponentInterface {
*/ */
@Prop() position?: 'fixed' | 'stacked' | 'floating'; @Prop() position?: 'fixed' | 'stacked' | 'floating';
/**
* Emitted when the color changes.
* @internal
*/
@Event() ionColor!: EventEmitter<StyleEventDetail>;
/** /**
* Emitted when the styles change. * Emitted when the styles change.
* @internal * @internal
@ -44,6 +50,7 @@ export class Label implements ComponentInterface {
this.inRange = !!this.el.closest('ion-range'); this.inRange = !!this.el.closest('ion-range');
this.noAnimate = (this.position === 'floating'); this.noAnimate = (this.position === 'floating');
this.emitStyle(); this.emitStyle();
this.emitColor();
} }
componentDidLoad() { componentDidLoad() {
@ -54,11 +61,25 @@ export class Label implements ComponentInterface {
} }
} }
@Watch('color')
colorChanged() {
this.emitColor();
}
@Watch('position') @Watch('position')
positionChanged() { positionChanged() {
this.emitStyle(); this.emitStyle();
} }
private emitColor() {
const { color } = this;
this.ionColor.emit({
'item-label-color': color !== undefined,
[`ion-color-${color}`]: color !== undefined
});
}
private emitStyle() { private emitStyle() {
const { inRange, position } = this; const { inRange, position } = this;

View File

@ -17,6 +17,11 @@
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-title>Label - Basic</ion-title> <ion-title>Label - Basic</ion-title>
<ion-buttons slot="end">
<ion-button onClick="changeColors()">
Color Change
</ion-button>
</ion-buttons>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
@ -58,10 +63,37 @@
<ion-label position="floating">Floating</ion-label> <ion-label position="floating">Floating</ion-label>
<ion-input></ion-input> <ion-input></ion-input>
</ion-item> </ion-item>
<ion-item class="floating-color">
<ion-label position="floating" color="success">Floating: Success</ion-label>
<ion-input></ion-input>
</ion-item>
<ion-item> <ion-item>
<ion-label position="stacked">Stacked</ion-label> <ion-label position="stacked">Stacked</ion-label>
<ion-input></ion-input> <ion-input></ion-input>
</ion-item> </ion-item>
<ion-item class="stacked-color">
<ion-label position="stacked" color="danger">Stacked: Danger</ion-label>
<ion-input></ion-input>
</ion-item>
</ion-list>
<ion-list>
<ion-item color="tertiary">
<ion-label position="floating">(Item: Tertiary) Floating</ion-label>
<ion-input></ion-input>
</ion-item>
<ion-item color="primary">
<ion-label position="stacked">(Item: Primary) Stacked</ion-label>
<ion-input></ion-input>
</ion-item>
<ion-item class="floating-color" color="tertiary">
<ion-label position="floating" color="success">(Item: Tertiary) Floating: Success</ion-label>
<ion-input></ion-input>
</ion-item>
<ion-item class="stacked-color" color="primary">
<ion-label position="stacked" color="danger">(Item: Primary) Stacked: Danger</ion-label>
<ion-input></ion-input>
</ion-item>
</ion-list> </ion-list>
</ion-content> </ion-content>
@ -70,6 +102,17 @@
color: lightblue; color: lightblue;
} }
</style> </style>
<script>
const labels = document.querySelectorAll('.floating-color ion-label, .stacked-color ion-label');
function changeColors() {
for (label of labels) {
const currentColor = label.color;
label.color = currentColor === 'success' ? 'danger' : 'success';
}
}
</script>
</ion-app> </ion-app>
</body> </body>