refactor(chip): add color input, remove some styling, move styles to mode files

references #5386
closes #7717
closes #7467
This commit is contained in:
Brandy Carney
2016-08-24 17:21:31 -04:00
parent 0dece7252b
commit 144ffe3b03
16 changed files with 523 additions and 352 deletions

24
demos/chip/index.ts Normal file
View File

@ -0,0 +1,24 @@
import { Component } from '@angular/core';
import { ionicBootstrap } from 'ionic-angular';
@Component({
templateUrl: 'main.html'
})
class ApiDemoPage {
delete(chip: Element) {
chip.remove();
}
}
@Component({
template: '<ion-nav [root]="root"></ion-nav>'
})
class ApiDemoApp {
root = ApiDemoPage;
}
ionicBootstrap(ApiDemoApp);

96
demos/chip/main.html Normal file
View File

@ -0,0 +1,96 @@
<ion-header>
<ion-toolbar>
<ion-title>Chips</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding style="text-align:center">
<h2>Text Chips</h2>
<ion-chip>
<ion-label>Default</ion-label>
</ion-chip>
<ion-chip>
<ion-label color="secondary">Secondary Label</ion-label>
</ion-chip>
<ion-chip>
<ion-label>Another With Longer Text</ion-label>
</ion-chip>
<h2>Color Chips</h2>
<ion-chip color="primary">
<ion-icon name="heart" color="dark"></ion-icon>
<ion-label>Primary</ion-label>
</ion-chip>
<ion-chip color="secondary">
<ion-label color="dark">Secondary w/ Dark label</ion-label>
</ion-chip>
<ion-chip color="danger">
<ion-label>Danger</ion-label>
</ion-chip>
<h2>Icon Chips</h2>
<ion-chip>
<ion-icon name="pin"></ion-icon>
<ion-label>Default</ion-label>
</ion-chip>
<ion-chip>
<ion-label>Secondary</ion-label>
<ion-icon name="pin" color="secondary"></ion-icon>
</ion-chip>
<h2>Avatar Chips</h2>
<ion-chip>
<ion-avatar>
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y">
</ion-avatar>
<ion-label>Default</ion-label>
</ion-chip>
<ion-chip>
<ion-label>Right Avatar</ion-label>
<ion-avatar>
<img src="https://gravatar.com/avatar/d249a09fecac4da036d26c5002af2c94?d=identicon&f=y">
</ion-avatar>
</ion-chip>
<h2>Delete Chips</h2>
<ion-chip #chip1>
<ion-label>Default</ion-label>
<button ion-button clear (click)="delete(chip1)">
<ion-icon name="close-circle"></ion-icon>
</button>
</ion-chip>
<ion-chip #chip2>
<ion-icon name="pin" color="primary"></ion-icon>
<ion-label>With Icon</ion-label>
<button ion-button clear (click)="delete(chip2)">
<ion-icon name="close-circle"></ion-icon>
</button>
</ion-chip>
<ion-chip #chip3>
<ion-avatar>
<img src="https://gravatar.com/avatar/83b4748bf7e821165ecccd4c090d96e1?d=identicon&f=y">
</ion-avatar>
<ion-label>With Avatar</ion-label>
<button ion-button clear color="dark" (click)="delete(chip3)">
<ion-icon name="close-circle"></ion-icon>
</button>
</ion-chip>
</ion-content>

View File

@ -7,6 +7,7 @@ export { Backdrop } from './components/backdrop/backdrop';
export { Badge } from './components/badge/badge';
export { Button } from './components/button/button';
export { Checkbox } from './components/checkbox/checkbox';
export { Chip } from './components/chip/chip';
export { Content } from './components/content/content';
export { DateTime } from './components/datetime/datetime';
export { Icon } from './components/icon/icon';

View File

@ -3,17 +3,64 @@
// iOS Chip
// --------------------------------------------------
/// @prop - Margin of the chip
$chip-ios-margin: 2px 0 !default;
/// @prop - Height of the chip
$chip-ios-height: 32px !default;
/// @prop - Border radius of the chip
$chip-ios-border-radius: 16px !default;
/// @prop - Font size of the chip
$chip-ios-font-size: 13px !default;
/// @prop - Text color of the chip
$chip-ios-text-color: rgba(0, 0, 0, .87) !default;
/// @prop - Background color of the chip
$chip-ios-background-color: rgba(0, 0, 0, .12) !default;
/// @prop - Margin of the label in the chip
$chip-ios-label-margin: 0 10px !default;
/// @prop - Background color of the icon in the chip
$chip-ios-icon-background-color: color($colors-ios, primary) !default;
/// @prop - Text color of the icon in the chip
$chip-ios-icon-text-color: color-contrast($colors-ios, $chip-ios-icon-background-color) !default;
ion-chip {
margin: $chip-ios-margin;
height: $chip-ios-height;
border-radius: $chip-ios-border-radius;
font-size: $chip-ios-font-size;
line-height: $chip-ios-height;
color: $chip-ios-text-color;
background: $chip-ios-background-color;
> ion-label {
margin: $chip-ios-label-margin;
}
> ion-icon {
color: $chip-ios-icon-text-color;
background-color: $chip-ios-icon-background-color;
}
}
// Generate iOS Chip Colors
// --------------------------------------------------
@each $color-name, $color-base, $color-contrast in get-colors($colors-ios) {
ion-chip {
ion-icon[#{$color-name}] {
.chip-#{$color-name},
ion-chip .icon-#{$color-name} {
color: $color-contrast;
background-color: $color-base;
}
}
}

View File

@ -3,17 +3,64 @@
// Material Design Chip
// --------------------------------------------------
/// @prop - Margin of the chip
$chip-md-margin: 2px 0 !default;
/// @prop - Height of the chip
$chip-md-height: 32px !default;
/// @prop - Border radius of the chip
$chip-md-border-radius: 16px !default;
/// @prop - Font size of the chip
$chip-md-font-size: 13px !default;
/// @prop - Text color of the chip
$chip-md-text-color: rgba(0, 0, 0, .87) !default;
/// @prop - Background color of the chip
$chip-md-background-color: rgba(0, 0, 0, .12) !default;
/// @prop - Margin of the label in the chip
$chip-md-label-margin: 0 10px !default;
/// @prop - Background color of the icon in the chip
$chip-md-icon-background-color: color($colors-md, primary) !default;
/// @prop - Text color of the icon in the chip
$chip-md-icon-text-color: color-contrast($colors-md, $chip-md-icon-background-color) !default;
ion-chip {
margin: $chip-md-margin;
height: $chip-md-height;
border-radius: $chip-md-border-radius;
font-size: $chip-md-font-size;
line-height: $chip-md-height;
color: $chip-md-text-color;
background: $chip-md-background-color;
> ion-label {
margin: $chip-md-label-margin;
}
> ion-icon {
color: $chip-md-icon-text-color;
background-color: $chip-md-icon-background-color;
}
}
// Generate Material Design Chip Colors
// --------------------------------------------------
@each $color-name, $color-base, $color-contrast in get-colors($colors-md) {
ion-chip {
ion-icon[#{$color-name}] {
.chip-#{$color-name},
ion-chip .icon-#{$color-name} {
color: $color-contrast;
background-color: $color-base;
}
}
}

View File

@ -3,56 +3,62 @@
// Chip
// --------------------------------------------------
$chip-background-color: rgba(0, 0, 0, .12) !default;
$chip-font-size: 13px !default;
$chip-height: 32px !default;
$chip-border-radius: 16px !default;
$chip-padding: 0 12px !default;
$chip-margin: 2px 0 !default;
/// @prop - Border radius of the button in the chip
$chip-button-border-radius: 50% !default;
/// @prop - Margin of the button in the chip
$chip-button-margin: 0 !default;
/// @prop - Width and height of the button in the chip
$chip-button-size: 32px !default;
/// @prop - Border radius of the icon in the chip
$chip-icon-border-radius: 50% !default;
/// @prop - Width and height of the icon in the chip
$chip-icon-size: 32px !default;
/// @prop - Font size of the icon in the chip
$chip-icon-font-size: 18px !default;
/// @prop - Width and height of the avatar in the chip
$chip-avatar-size: 32px !default;
/// @prop - Border radius of the avatar in the chip
$chip-avatar-border-radius: 50% !default;
$chip-label-color: rgba(0, 0, 0, .87) !default;
$chip-icon-color: rgba(0, 0, 0, .87) !default;
$chip-remove-icon-color: rgba(137, 137, 137, .54) !default;
ion-chip {
display: inline-flex;
align-self: center;
margin: $chip-margin;
padding: $chip-padding;
height: $chip-height;
border-radius: $chip-border-radius;
font-size: $chip-font-size;
font-weight: normal;
line-height: $chip-height;
background: $chip-background-color;
vertical-align: middle;
box-sizing: border-box;
ion-label {
margin: 0;
color: $chip-label-color;
.button {
border-radius: $chip-button-border-radius;
margin: $chip-button-margin;
height: $chip-button-size;
width: $chip-button-size;
}
> ion-icon,
> ion-avatar {
margin-left: -12px;
ion-icon {
border-radius: $chip-icon-border-radius;
line-height: $chip-icon-size;
width: 32px;
height: 32px;
font-size: $chip-icon-font-size;
width: $chip-icon-size;
height: $chip-icon-size;
}
border-radius: 50%;
font-size: 18px;
line-height: 32px;
text-align: center;
color: $chip-icon-color;
vertical-align: top;
ion-avatar {
border-radius: $chip-avatar-border-radius;
width: $chip-avatar-size;
height: $chip-avatar-size;
min-width: $chip-avatar-size;
min-height: $chip-avatar-size;
img {
display: block;
@ -62,31 +68,7 @@ ion-chip {
height: 100%;
max-height: 100%;
border-radius: 50%;
border-radius: $chip-avatar-border-radius;
}
+ ion-label {
margin-left: 8px;
}
}
ion-avatar {
min-width: 32px;
min-height: 32px;
}
.button {
margin: 0;
margin-right: -4px;
height: inherit;
}
ion-icon[name="close-circle"] {
margin: 0 -8px 2px -4px;
font-size: 1.4em;
color: $chip-remove-icon-color;
}
}

View File

@ -1,111 +1,132 @@
import { Component, ElementRef, Renderer, Attribute } from '@angular/core';
import { Config } from '../../config/config';
import { Directive, ElementRef, Input, Renderer } from '@angular/core';
/**
* @name Chip
* @module ionic
* @description
* Chips represent complex entities in small blocks, such as a contact.
* @see {@link /docs/v2/components/#chips Chips Component Docs}
*
*
* @usage
*
* ```html
* <ion-chip>
* <ion-label>Default</ion-label>
* </ion-chip>
*
* <ion-chip>
* <ion-label color="secondary">Secondary Label</ion-label>
* </ion-chip>
*
* <ion-chip color="secondary">
* <ion-label color="dark">Secondary w/ Dark label</ion-label>
* </ion-chip>
*
* <ion-chip color="danger">
* <ion-label>Danger</ion-label>
* </ion-chip>
*
* <ion-chip>
* <ion-icon name="pin"></ion-icon>
* <ion-label>Default</ion-label>
* </ion-chip>
*
* <ion-chip>
* <ion-icon name="heart" color="dark"></ion-icon>
* <ion-label>Default</ion-label>
* </ion-chip>
*
* <ion-chip>
* <ion-avatar>
* <img src="img/my-img.png">
* </ion-avatar>
* <ion-label>Default</ion-label>
* </ion-chip>
* ```
*
*
* @advanced
*
* ```html
* <ion-chip #chip1>
* <ion-label>Default</ion-label>
* <button ion-button clear color="light" (click)="delete(chip1)">
* <ion-icon name="close-circle"></ion-icon>
* </button>
* </ion-chip>
*
* <ion-chip #chip2>
* <ion-icon name="pin" color="primary"></ion-icon>
* <ion-label>With Icon</ion-label>
* <button ion-button (click)="delete(chip2)">
* <ion-icon name="close"></ion-icon>
* </button>
* </ion-chip>
*
* <ion-chip #chip3>
* <ion-avatar>
* <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
* </ion-avatar>
* <ion-label>With Avatar</ion-label>
* <button ion-button clear color="dark" (click)="delete(chip3)">
* <ion-icon name="close-circle"></ion-icon>
* </button>
* </ion-chip>
* ```
*
* ```ts
* @Component({
* templateUrl: 'main.html'
* })
* class E2EPage {
* delete(chip: Element) {
* chip.remove();
* }
* }
* ```
*
* @demo /docs/v2/demos/chip/
**/
@Component({
selector: 'ion-chip',
template: '<span class="hide"><ng-content></ng-content></span><ion-label></ion-label><button clear dark (click)="deleteChip()" *ngIf="deletable"><ion-icon name="close-circle"></ion-icon></button>'
@Directive({
selector: 'ion-chip'
})
export class Chip {
private deletable: boolean = false;
/** @internal */
_color: string;
/**
* @input {string} The predefined color to use. For example: `"primary"`, `"secondary"`, `"danger"`.
*/
@Input()
get color(): string {
return this._color;
}
set color(value: string) {
this._updateColor(value);
}
constructor(
config: Config,
private _elementRef: ElementRef,
private _renderer: Renderer
) {
let element = _elementRef.nativeElement;
) { }
this._readAttrs(element);
/**
* @internal
*/
_updateColor(newColor: string) {
this._setElementColor(this._color, false);
this._setElementColor(newColor, true);
this._color = newColor;
}
/**
* @private
* @internal
*/
ngOnInit() {
this._fixContent(this._elementRef.nativeElement);
}
/**
* @private
*/
private _readAttrs(element: HTMLElement) {
let elementAttrs = element.attributes;
let attrName: string;
for (let i = 0, l = elementAttrs.length; i < l; i++) {
if (elementAttrs[i].value !== '') continue;
attrName = elementAttrs[i].name;
if (attrName === 'deletable') {
this._setDeletable();
}
_setElementColor(color: string, isAdd: boolean) {
if (color !== null && color !== '') {
this._renderer.setElementClass(this._elementRef.nativeElement, `chip-${color}`, isAdd);
}
}
/**
* @private
*/
private deleteChip() {
this._elementRef.nativeElement.remove();
}
/**
* @private
*/
private _setDeletable() {
this.deletable = true;
}
/**
* @private
*/
private _fixContent(element: HTMLElement) {
// Take the first text node and add it to the label.
// Take the first icon or avatar and add it to the chip.
// Discard everything else.
let childNodes: NodeList = element.childNodes;
let innerNode: Node = childNodes[0];
let labelNode: Node = childNodes[1];
let addedNodes: NodeList = innerNode.childNodes;
element.removeChild(innerNode);
let missing = {image: true, text: true};
let childNode: Node;
let imageNode: Node;
let text: string;
for (let i = 0, l = addedNodes.length; i < l; i++) {
childNode = addedNodes[i];
if (childNode.nodeType === 3 && missing.text) {
text = childNode.textContent.trim();
if (text !== '') {
labelNode.textContent = text;
missing.text = false;
}
}
if (childNode.nodeType === 1 && missing.image) {
name = childNode.nodeName;
if (childNode.nodeName === 'ION-ICON' || childNode.nodeName === 'ION-AVATAR') {
missing.image = false;
imageNode = childNode;
}
}
}
if (imageNode) {
element.insertBefore(imageNode, element.firstChild);
}
}
}

View File

@ -3,17 +3,68 @@
// Windows Chip
// --------------------------------------------------
/// @prop - Margin of the chip
$chip-wp-margin: 2px 0 !default;
/// @prop - Height of the chip
$chip-wp-height: 32px !default;
/// @prop - Border radius of the chip
$chip-wp-border-radius: 16px !default;
/// @prop - Font size of the chip
$chip-wp-font-size: 13px !default;
/// @prop - Text color of the chip
$chip-wp-text-color: rgba(0, 0, 0, .87) !default;
/// @prop - Background color of the chip
$chip-wp-background-color: rgba(0, 0, 0, .12) !default;
/// @prop - Margin of the label in the chip
$chip-wp-label-margin: 0 10px !default;
/// @prop - Background color of the icon in the chip
$chip-wp-icon-background-color: color($colors-wp, primary) !default;
/// @prop - Text color of the icon in the chip
$chip-wp-icon-text-color: color-contrast($colors-wp, $chip-wp-icon-background-color) !default;
ion-chip {
margin: $chip-wp-margin;
height: $chip-wp-height;
border-radius: $chip-wp-border-radius;
font-size: $chip-wp-font-size;
line-height: $chip-wp-height;
color: $chip-wp-text-color;
background: $chip-wp-background-color;
> ion-label {
margin: $chip-wp-label-margin;
}
> ion-icon {
color: $chip-wp-icon-text-color;
background-color: $chip-wp-icon-background-color;
}
.button {
border: 0;
}
}
// Generate Windows Chip Colors
// --------------------------------------------------
@each $color-name, $color-base, $color-contrast in get-colors($colors-wp) {
ion-chip {
ion-icon[#{$color-name}] {
.chip-#{$color-name},
ion-chip .icon-#{$color-name} {
color: $color-contrast;
background-color: $color-base;
}
}
}

View File

@ -5,7 +5,11 @@ import { ionicBootstrap } from '../../../../../src';
@Component({
templateUrl: 'main.html'
})
class E2EPage {}
class E2EPage {
delete(chip: Element) {
chip.remove();
}
}
@Component({
template: '<ion-nav [root]="rootPage"></ion-nav>'

View File

@ -1,7 +1,7 @@
<ion-header>
<ion-toolbar>
<ion-title>Chips With Text</ion-title>
<ion-title>Chips</ion-title>
</ion-toolbar>
</ion-header>
@ -9,15 +9,88 @@
<ion-content padding style="text-align:center">
<p>
<h2>Text Chips</h2>
<ion-chip>
Default
<ion-label>Default</ion-label>
</ion-chip>
</p>
<p>
<ion-chip>
Another With Longer Text
<ion-label color="secondary">Secondary Label</ion-label>
</ion-chip>
<ion-chip>
<ion-label>Another With Longer Text</ion-label>
</ion-chip>
<h2>Color Chips</h2>
<ion-chip color="primary">
<ion-icon name="heart" color="dark"></ion-icon>
<ion-label>Primary</ion-label>
</ion-chip>
<ion-chip color="secondary">
<ion-label color="dark">Secondary w/ Dark label</ion-label>
</ion-chip>
<ion-chip color="danger">
<ion-label>Danger</ion-label>
</ion-chip>
<h2>Icon Chips</h2>
<ion-chip>
<ion-icon name="pin"></ion-icon>
<ion-label>Default</ion-label>
</ion-chip>
<ion-chip>
<ion-label>Secondary</ion-label>
<ion-icon name="pin" color="secondary"></ion-icon>
</ion-chip>
<h2>Avatar Chips</h2>
<ion-chip>
<ion-avatar>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
</ion-avatar>
<ion-label>Default</ion-label>
</ion-chip>
<ion-chip>
<ion-label>Right Avatar</ion-label>
<ion-avatar>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
</ion-avatar>
</ion-chip>
<h2>Delete Chips</h2>
<ion-chip #chip1>
<ion-label>Default</ion-label>
<button ion-button clear color="light" (click)="delete(chip1)">
<ion-icon name="close-circle"></ion-icon>
</button>
</ion-chip>
<ion-chip #chip2>
<ion-icon name="pin" color="primary"></ion-icon>
<ion-label>With Icon</ion-label>
<button ion-button (click)="delete(chip2)">
<ion-icon name="close"></ion-icon>
</button>
</ion-chip>
<ion-chip #chip3>
<ion-avatar>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
</ion-avatar>
<ion-label>With Avatar</ion-label>
<button ion-button clear color="dark" (click)="delete(chip3)">
<ion-icon name="close-circle"></ion-icon>
</button>
</ion-chip>
</p>
</ion-content>

View File

@ -1,23 +0,0 @@
import { Component } from '@angular/core';
import { ionicBootstrap } from '../../../../../src';
@Component({
templateUrl: 'main.html'
})
class E2EPage {
deleteClicked() {
console.log('deleteClicked');
}
}
@Component({
template: '<ion-nav [root]="rootPage"></ion-nav>'
})
class E2EApp {
rootPage = E2EPage;
}
ionicBootstrap(E2EApp);

View File

@ -1,48 +0,0 @@
<ion-header>
<ion-toolbar>
<ion-title>Chips With Delete</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding style="text-align:center">
<p>
<ion-chip deletable>
Default
</ion-chip>
</p>
<p>
<ion-chip deletable>
<ion-icon name="pin" primary></ion-icon>
With Icon
</ion-chip>
</p>
<p>
<ion-chip deletable>
<ion-avatar>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
</ion-avatar>
With Avatar
</ion-chip>
</p>
<p>
<ion-chip deletable>
<b>This Should Not Be Seen</b>
With Junk Elements
<ion-icon name="pin" primary></ion-icon>
<ion-avatar>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
</ion-avatar>
<hr>
This Should Not Be Seen Either
</ion-chip>
</p>
</ion-content>

View File

@ -1,17 +0,0 @@
import { Component } from '@angular/core';
import { ionicBootstrap } from '../../../../../src';
@Component({
templateUrl: 'main.html'
})
class E2EPage {}
@Component({
template: '<ion-nav [root]="rootPage"></ion-nav>'
})
class E2EApp {
rootPage = E2EPage;
}
ionicBootstrap(E2EApp);

View File

@ -1,49 +0,0 @@
<ion-header>
<ion-toolbar>
<ion-title>Chips With Icon</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding style="text-align:center">
<p>
<ion-chip>
<ion-icon name="pin"></ion-icon>
Default
</ion-chip>
</p>
<p>
<ion-chip>
<ion-icon name="pin" primary></ion-icon>
Primary
</ion-chip>
</p>
<p>
<ion-chip>
<ion-icon name="pin" secondary></ion-icon>
Secondary
</ion-chip>
</p>
<p>
<ion-chip>
<ion-icon name="pin" danger></ion-icon>
Danger
</ion-chip>
</p>
<p>
<ion-chip>
<ion-icon name="pin" light></ion-icon>
Light
</ion-chip>
</p>
<p>
<ion-chip>
<ion-icon name="pin" dark></ion-icon>
Dark
</ion-chip>
</p>
</ion-content>

View File

@ -1,17 +0,0 @@
import { Component } from '@angular/core';
import { ionicBootstrap } from '../../../../../src';
@Component({
templateUrl: 'main.html'
})
class E2EPage {}
@Component({
template: '<ion-nav [root]="rootPage"></ion-nav>'
})
class E2EApp {
rootPage = E2EPage;
}
ionicBootstrap(E2EApp);

View File

@ -1,21 +0,0 @@
<ion-header>
<ion-toolbar>
<ion-title>Chips With Image</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding style="text-align:center">
<p>
<ion-chip>
<ion-avatar>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
</ion-avatar>
Default
</ion-chip>
</p>
</ion-content>