mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-23 14:01:20 +08:00

BREAKING CHANGES: Colors should be passed in the `color` input on components, not added individually as an attribute on the component. For example: ``` <ion-tabs primary> ``` Becomes ``` <ion-tabs color=”primary”> ``` Or to bind an expression to color: ``` <ion-navbar [color]="barColor"> ... </ion-navbar> ``` ```ts @Component({ templateUrl: 'build/pages/about/about.html' }) export class AboutPage { barColor: string; constructor(private nav: NavController, platform: Platform) { this.barColor = platform.is('android') ? 'primary' : 'light'; } } ``` Reason for this change: It was difficult to dynamically add colors to components, especially if the name of the color attribute was unknown in the template. This change keeps the css flat since we aren’t chaining color attributes on components and instead we assign a class to the component which includes the color’s name. This allows you to easily toggle a component between multiple colors. Speeds up performance because we are no longer reading through all of the attributes to grab the color ones. references #7467 closes #7087 closes #7401 closes #7523
321 lines
8.7 KiB
TypeScript
321 lines
8.7 KiB
TypeScript
import { Attribute, ChangeDetectionStrategy, Component, ElementRef, Input, Renderer, ViewEncapsulation } from '@angular/core';
|
|
|
|
import { Config } from '../../config/config';
|
|
import { isTrueProperty } from '../../util/util';
|
|
|
|
|
|
/**
|
|
* @name Button
|
|
* @module ionic
|
|
*
|
|
* @description
|
|
* Buttons are simple components in Ionic. They can consist of text and icons
|
|
* and be enhanced by a wide range of attributes.
|
|
*
|
|
* @property [outline] - A transparent button with a border.
|
|
* @property [clear] - A transparent button without a border.
|
|
* @property [round] - A button with rounded corners.
|
|
* @property [block] - A button that fills its parent container with a border-radius.
|
|
* @property [full] - A button that fills its parent container without a border-radius or borders on the left/right.
|
|
* @property [small] - A button with size small.
|
|
* @property [large] - A button with size large.
|
|
* @property [disabled] - A disabled button.
|
|
* @property [fab] - A floating action button.
|
|
* @property [fab-left] - Position a fab button to the left.
|
|
* @property [fab-right] - Position a fab button to the right.
|
|
* @property [fab-center] - Position a fab button towards the center.
|
|
* @property [fab-top] - Position a fab button towards the top.
|
|
* @property [fab-bottom] - Position a fab button towards the bottom.
|
|
* @property [fab-fixed] - Makes a fab button have a fixed position.
|
|
* @property [color] - Dynamically set which predefined color this button should use (e.g. primary, secondary, danger, etc).
|
|
*
|
|
* @usage
|
|
*
|
|
* ```html
|
|
*
|
|
* <!-- Colors -->
|
|
* <button ion-button>Default</button>
|
|
*
|
|
* <button ion-button color="secondary">Secondary</button>
|
|
*
|
|
* <button ion-button color="danger">Danger</button>
|
|
*
|
|
* <button ion-button color="light">Light</button>
|
|
*
|
|
* <button ion-button color="dark">Dark</button>
|
|
*
|
|
* <!-- Shapes -->
|
|
* <button ion-button full>Full Button</button>
|
|
*
|
|
* <button ion-button block>Block Button</button>
|
|
*
|
|
* <button ion-button round>Round Button</button>
|
|
*
|
|
* <button ion-button fab>FAB</button>
|
|
*
|
|
* <!-- Outline -->
|
|
* <button ion-button full outline>Outline + Full</button>
|
|
*
|
|
* <button ion-button block outline>Outline + Block</button>
|
|
*
|
|
* <button ion-button round outline>Outline + Round</button>
|
|
*
|
|
* <button ion-button fab outline>FAB</button>
|
|
*
|
|
* <!-- Icons -->
|
|
* <button ion-button icon-left>
|
|
* <ion-icon name="star"></ion-icon>
|
|
* Left Icon
|
|
* </button>
|
|
*
|
|
* <button ion-button icon-right>
|
|
* Right Icon
|
|
* <ion-icon name="star"></ion-icon>
|
|
* </button>
|
|
*
|
|
* <button ion-button icon-only>
|
|
* <ion-icon name="star"></ion-icon>
|
|
* </button>
|
|
*
|
|
* <!-- Sizes -->
|
|
* <button ion-button large>Large</button>
|
|
*
|
|
* <button ion-button>Default</button>
|
|
*
|
|
* <button ion-button small>Small</button>
|
|
* ```
|
|
*
|
|
* @demo /docs/v2/demos/button/
|
|
* @see {@link /docs/v2/components#buttons Button Component Docs}
|
|
*/
|
|
@Component({
|
|
selector: '[ion-button]',
|
|
// NOTE: template must not contain spaces between elements
|
|
template: '<span class="button-inner"><ng-content></ng-content></span><ion-button-effect></ion-button-effect>',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
encapsulation: ViewEncapsulation.None,
|
|
})
|
|
export class Button {
|
|
private _role: string = 'button'; // bar-button
|
|
private _mt: boolean = false; // menutoggle
|
|
private _size: string = null; // large/small/default
|
|
private _style: string = 'default'; // outline/clear/solid
|
|
private _shape: string = null; // round/fab
|
|
private _display: string = null; // block/full
|
|
private _color: string = null; // primary/secondary
|
|
private _disabled: boolean = false; // disabled
|
|
private _init: boolean;
|
|
|
|
/**
|
|
* @input {string} Large button.
|
|
*/
|
|
@Input()
|
|
set large(val: boolean) {
|
|
this._attr('_size', 'large', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} Small button.
|
|
*/
|
|
@Input()
|
|
set small(val: boolean) {
|
|
this._attr('_size', 'small', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} Default button.
|
|
*/
|
|
@Input()
|
|
set default(val: boolean) {
|
|
this._attr('_size', 'default', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} A transparent button with a border.
|
|
*/
|
|
@Input()
|
|
set outline(val: boolean) {
|
|
this._attr('_style', 'outline', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} A transparent button without a border.
|
|
*/
|
|
@Input()
|
|
set clear(val: boolean) {
|
|
this._attr('_style', 'clear', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} Force a solid button. Useful for buttons within an item.
|
|
*/
|
|
@Input()
|
|
set solid(val: boolean) {
|
|
this._attr('_style', 'solid', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} A button with rounded corners.
|
|
*/
|
|
@Input()
|
|
set round(val: boolean) {
|
|
this._attr('_shape', 'round', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} A floating action button.
|
|
*/
|
|
@Input()
|
|
set fab(val: boolean) {
|
|
this._attr('_shape', 'fab', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} A button that fills its parent container with a border-radius.
|
|
*/
|
|
@Input()
|
|
set block(val: boolean) {
|
|
this._attr('_display', 'block', val);
|
|
}
|
|
|
|
/**
|
|
* @input {string} A button that fills its parent container without a border-radius or borders on the left/right.
|
|
*/
|
|
@Input()
|
|
set full(val: boolean) {
|
|
this._attr('_display', 'full', val);
|
|
}
|
|
|
|
_attr(type: string, attrName: string, attrValue: boolean) {
|
|
if (type === '_style') {
|
|
this._setColor(this._color, isTrueProperty(attrValue));
|
|
}
|
|
this._setClass(this[type], false);
|
|
if (isTrueProperty(attrValue)) {
|
|
this[type] = attrName;
|
|
this._setClass(attrName, true);
|
|
} else {
|
|
// Special handling for '_style' which defaults to 'default'.
|
|
this[type] = (type === '_style' ? 'default' : null);
|
|
this._setClass(this[type], true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @input {string} Dynamically set which predefined color this button should use (e.g. primary, secondary, danger, etc).
|
|
*/
|
|
@Input()
|
|
set color(val: string) {
|
|
this._updateColor(val);
|
|
}
|
|
|
|
constructor(
|
|
@Attribute('menuToggle') menuToggle: string,
|
|
@Attribute('ion-button') ionButton: string,
|
|
config: Config,
|
|
private _elementRef: ElementRef,
|
|
private _renderer: Renderer
|
|
) {
|
|
let element = _elementRef.nativeElement;
|
|
|
|
if (config.get('hoverCSS') === false) {
|
|
_renderer.setElementClass(element, 'disable-hover', true);
|
|
}
|
|
|
|
if (element.hasAttribute('disabled')) {
|
|
this._disabled = true;
|
|
}
|
|
|
|
if (ionButton.trim().length > 0) {
|
|
this.setRole(ionButton);
|
|
}
|
|
|
|
// menuToggle can be added with or without a string
|
|
// but if the attribute isn't added it will be null
|
|
if (menuToggle !== null) {
|
|
this._mt = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
ngAfterContentInit() {
|
|
this._init = true;
|
|
this._assignCss(true);
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
_updateColor(newColor: string) {
|
|
this._setColor(this._color, false);
|
|
this._setColor(newColor, true);
|
|
this._color = newColor;
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
addClass(className: string) {
|
|
this._renderer.setElementClass(this._elementRef.nativeElement, className, true);
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
setRole(val: string) {
|
|
this._assignCss(false);
|
|
this._role = val;
|
|
this._assignCss(true);
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
private _assignCss(assignCssClass: boolean) {
|
|
let role = this._role;
|
|
if (role) {
|
|
this._renderer.setElementClass(this._elementRef.nativeElement, role, assignCssClass); // button
|
|
|
|
this._setClass('menutoggle', this._mt); // menutoggle
|
|
|
|
this._setClass(this._style, assignCssClass); // button-clear
|
|
this._setClass(this._shape, assignCssClass); // button-round
|
|
this._setClass(this._display, assignCssClass); // button-full
|
|
this._setClass(this._size, assignCssClass); // button-small
|
|
this._setColor(this._color, assignCssClass); // button-secondary, bar-button-secondary
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
_setClass(type: string, assignCssClass: boolean) {
|
|
if (type && this._init) {
|
|
this._renderer.setElementClass(this._elementRef.nativeElement, this._role + '-' + type.toLowerCase(), assignCssClass);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
_setColor(color: string, isAdd: boolean) {
|
|
if (color && this._init) {
|
|
// The class should begin with the button role
|
|
// button, bar-button
|
|
let className = this._role;
|
|
|
|
// If the role is not a bar-button, don't apply the solid style
|
|
let style = this._style;
|
|
style = (this._role !== 'bar-button' && style === 'solid' ? 'default' : style);
|
|
|
|
className += (style !== null && style !== '' && style !== 'default' ? '-' + style.toLowerCase() : '');
|
|
|
|
if (color !== null && color !== '') {
|
|
this._renderer.setElementClass(this._elementRef.nativeElement, `${className}-${color}`, isAdd);
|
|
}
|
|
}
|
|
}
|
|
}
|