<link rel=“import” href=“../polymer/polymer.html”> <link rel=“import” href=“../iron-behaviors/iron-button-state.html”> <link rel=“import” href=“../iron-flex-layout/iron-flex-layout.html”> <link rel=“import” href=“../iron-icons/iron-icons.html”> <link rel=“import” href=“../iron-icon/iron-icon.html”> <link rel=“import” href=“../paper-material/paper-material.html”> <link rel=“import” href=“../paper-styles/paper-styles.html”>
<!– Material Design: [Chips](www.google.com/design/spec/components/chips.html)
`paper-chip` is a small element that represents a complex entity such as a calendar event or a contact. The chip can be in an opened or closed state. In its closed state, it contains an icon and a short title. In its open state, the chip expands to show more detail about the represented entity, as well as (optionally) a “remove” button that removes the chip element from the DOM.
The following child elements may be placed within the chip tag define its content:
* .icon: The icon representing the chip. This may be any element, for example, a `<iron-icon>` or a simple `<span>` with a single letter * .label: The chip label, shown in both closed and opened states * .caption: A secondary label, shown only in the opened state * all other content will be shown in the opened chip
The `removable` attribute can be used to add a button which removes the chip from the DOM.
## Examples:
Removable chip with iron-icon
<paper-chip removable> <iron-icon class="icon" icon="avatars:avatar-1"></iron-icon> <div class="labeL">John Doe</div> <div class="caption">jdoe@example.com</div> </paper-chip>
Basic chip with single letter instead of an icon
<paper-chip label="Jane Doe"> <div class="icon">J</div> <div class="label">jdoe@example.com</div> </paper-chip>
@element paper-chip @blurb A basic “chip” element representing an icon/image and a short piece of text. @homepage bendavis78.github.io/paper-chip/ @demo demo/index.html –>
<dom-module id=“paper-chip”>
<template> <style> :host { display: inline-block; vertical-align: top; position: relative; outline: none; font-size: 14px; cursor: default; margin: 8px 0; height: 32px; overflow: visible; @apply(--paper-chip); } :host([animated]) *, :host([animated]) ::content * { transition: 200ms ease-in; } #main, #chip { border-radius: 16px; } #main { background-color: var(--paper-chip-background-color, --paper-grey-200); position: relative; color: var(--paper-chip-secondary-text-color, --secondary-text-color); @apply(--layout-vertical); } #chip { box-sizing: border-box; height: 32px; @apply(--layout-horizontal); @apply(--layout-center); } paper-material { border-radius: 16px; } #icon { @apply(--layout-horizontal); @apply(--layout-center); @apply(--layout-center-justified); } #icon ::content .icon { margin-right: -4px; width: 32px; height: 32px; line-height: 32px; border-radius: 100%; overflow: hidden; text-align: center; vertical-align: middle; font-size: 16px; font-weight: bold; background-color: var(--paper-chip-icon-background-color, --paper-grey-500); color: var(--paper-chip-icon-text-color, --text-primary-color); @apply(--layout-flex); } #icon ::content iron-icon.icon, #icon ::content iron-icon.icon svg { width: 32px; height: 32px; } #icon ::content iron-icon.icon { vertical-align: bottom; } #label { padding: 0 4px 0 12px; @apply(--layout-flex-auto); @apply(--layout-self-center); } :host([single-line]:not([removable])) #label { padding-right: 12px; } #label ::content .label, #label ::content .caption { display: block; white-space: nowrap; margin: 0; font-weight: normal; font-size: 14px; } #label ::content .label { @apply(--paper-chip-label); } #label ::content .caption { @apply(--paper-chip-caption); } .icon-btn-wrapper { @apply(--layout-self-center); } #removeBtn { position: relative; margin: 0 8px 0 4px; padding: 2px; width: 12px; height: 12px; border-radius: 100%; background-color: var(--paper-chip-removebtn-background-color, --paper-grey-400); color: var(--paper-chip-removebtn-icon-color, --text-primary-color); cursor: pointer; @apply(--paper-chip-removebtn); } #removeBtn iron-icon { width: 12px; height: 12px; display: block; @apply(--paper-chip-removebtn-icon); } :host(:not([removable])) #removeBtn { display: none; } /* pressed state */ :host([pressed]) #main { background-color: var(--paper-chip-pressed-background-color, --paper-grey-300); } /* initially hidden elements */ :host(:not([opened])) #label ::content .caption { color: var(--paper-chip-secondary-text-color, --secondary-text-color); font-size: 0; height: 0; } :host(:not([persist-remove-button]):not([single-line]):not([opened])) #removeBtn, :host(:not([persist-remove-button]):not([single-line]):not([opened])) #removeBtn .icon { width: 0; height: 0; margin: 0; padding: 0; } :host(:not([persist-remove-button]):not([single-line]):not([opened])) #label { padding-right: 12px; } :host(:not([opened])) #content { width: 0; height: 0; min-width: 100%; overflow: hidden; } :host(:not([opened])) #label ::content .label { color: var(--paper-chip-secondary-text-color, --secondary-text-color); } /* opened state */ :host([opened]) #main, :host([opened]) #chip { border-radius: 0; } :host([opened]) #content { height: auto; width: auto; min-width: 100%; overflow: hidden; @apply(--paper-chip-content); } :host([opened]) #chip { height: 72px; } :host([opened]) #chip, :host([opened]) #content ::content > * { padding: 16px 12px; background-color: var(--paper-chip-opened-background-color, --paper-grey-50); } :host([opened]) #label ::content .label { color: var(--paper-chip-primary-text-color, --primary-text-color); font-size: 16px; @apply(--paper-chip-label-opened); } :host([opened]) paper-material { border-radius: 0; } :host([opened]) #icon ::content .icon, :host([opened]) #icon ::content iron-icon.icon svg { font-size: 20px; width: 40px; height: 40px; line-height: 40px; } :host([opened]) #removeBtn { padding: 4px; margin-left: 20px; width: 16px; height: 16px; } :host([opened]) #removeBtn iron-icon { width: 16px; height: 16px; } /* open + active state */ :host([opened][active]) #chip, :host([opened][active]) ::content { background-color: var(--paper-chip-active-color, --accent-color); color: var(--paper-chip-active-text-color, --text-primary-color); } :host([opened][active]) #removeBtn { color: var(--paper-chip-active-color, --accent-color); background-color: var(--paper-chip-active-text-color, --text-primary-color); } :host([opened][active]) #chip #label ::content .label { color: var(--paper-chip-active-text-color, --text-primary-color); } :host([opened][active]) #chip #label ::content h2 { color: var(--paper-chip-active-secondary-text-color, --text-primary-color); } </style> <paper-material id="shadow" elevation="{{_elevation}}" animated$="{{animated}}"> <div id="main"> <div id="chip"> <div id="icon"> <content select=".icon"></content> </div> <div id="label"> <content select=".label"></content> <content select=".caption"></content> </div> <div id="removeBtn" on-tap="remove" aria-label="remove button"> <iron-icon icon="close" class="icon"></iron-icon> </div> </div> <div id="content"> <content></content> </div> </div> </paper-material> </template> <script> Polymer({ is: 'paper-chip', behaviors: [ Polymer.IronButtonState, Polymer.IronControlState, ], properties: { /** * Whether or not the chip is removable. If `true`, a remove button will * be shown. * * @attribute removable * @type boolean * @default false */ removable: { type: Boolean, value: false, reflectToAttribute: true }, /** * Whether or not the chip contains additional content. Single-line chips do not open. */ singleLine: { type: Boolean, value: false, reflectToAttribute: true, observer: '_singleLineChanged', }, /** * Always show remove button */ persistRemoveButton: { type: Boolean, value: false, reflectToAttribute: true, observer: '_singleLineChanged' }, /** * Whether or not the chip uses an animated transition between opened and * closed states * * @attribute animated * @type boolean * @default true */ animated: { type: Boolean, value: false, reflectToAttribute: true }, /** * Whether or not the chip is in its opened state. * * @attribute opened * @type boolean * @default false */ opened: { type: Boolean, value: false, reflectToAttribute: true, notify: true, observer: '_openedChanged' }, /** * Whether or not the chip state is "active". If `true`, the main chip * area will be highlighted when in the opened state. * * @attribute active * @type boolean * @default false */ active: { type: Boolean, value: false, notify: true, reflectToAttribute: true }, _elevation: { type: Number, computed: '_computeElevation(opened, focused, disabled, active, pressed)' }, _keyTarget: { type: Object, value: function() { return this; } }, }, listeners: { tap: '_onTap', blur: '_onBlur' }, hostAttributes: { tabindex: '0' }, ready: function() { if (this.$.removeBtn) { // disable tabindex on remove button so that tabindex can be used for chips this.$.removeBtn.removeAttribute('tabindex'); } }, _computeElevation: function(opened, focused, pressed) { if (focused || pressed) { return 1; } if (opened) { return 4; } return 0; }, _onTap: function() { this.toggleOpened(); }, _onBlur: function() { this.opened = false; }, /** * Fired before the element is removed. This event is cancelable. * * @event remove */ remove: function(event) { event.stopPropagation(); var e = this.fire('remove', {}, {bubbles: false, cancelable: true}); if (!e.defaultPrevented) { this.parentNode.removeChild(this); } }, toggleOpened: function() { if (!this.singleLine) { this.opened = !this.opened; } }, _singleLineChanged: function(singleLine) { if (singleLine && this.opened) { this.opened = false; } }, _openedChanged: function(opened) { if (opened && this.singleLine) { // single-line chips don't open this.opened = false; return; } if (this.animated) { var $content, width, height; $content = this.$.content; width = height = ''; if (this.opened) { // temporarily disable transitions in order to take measurements of // the content area, allowing for a proper css transision. this.animated = false; this.opened = true; width = $content.offsetWidth + 'px'; height = $content.offsetHeight + 'px'; this.opened = false; this._forceReflow(); this.opened = true; this.animated = true; } $content.style.width = width; $content.style.height = height; } }, _forceReflow: function() { return this.offsetHeight; } }); </script>
</dom-module>