npm-polymer-elements
Version:
Polymer Elements package for npm
230 lines (193 loc) • 7.51 kB
HTML
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html">
<link rel="import" href="../paper-styles/default-theme.html">
<link rel="import" href="../paper-styles/typography.html">
<!--
`<paper-badge>` is a circular text badge that is displayed on the top right
corner of an element, representing a status or a notification. It will badge
the anchor element specified in the `for` attribute, or, if that doesn't exist,
centered to the parent node containing it.
Badges can also contain an icon by adding the `icon` attribute and setting
it to the id of the desired icon. Please note that you should still set the
`label` attribute in order to keep the element accessible. Also note that you will need to import
the `iron-iconset` that includes the icons you want to use. See [iron-icon](../iron-icon)
for more information on how to import and use icon sets.
Example:
<div style="display:inline-block">
<span>Inbox</span>
<paper-badge label="3"></paper-badge>
</div>
<div>
<paper-button id="btn">Status</paper-button>
<paper-badge icon="favorite" for="btn" label="favorite icon"></paper-badge>
</div>
<div>
<paper-icon-button id="account-box" icon="account-box" alt="account-box"></paper-icon-button>
<paper-badge icon="social:mood" for="account-box" label="mood icon"></paper-badge>
</div>
### Styling
The following custom properties and mixins are available for styling:
Custom property | Description | Default
----------------|-------------|----------
`--paper-badge-background` | The background color of the badge | `--accent-color`
`--paper-badge-opacity` | The opacity of the badge | `1.0`
`--paper-badge-text-color` | The color of the badge text | `white`
`--paper-badge-width` | The width of the badge circle | `20px`
`--paper-badge-height` | The height of the badge circle | `20px`
`--paper-badge-margin-left` | Optional spacing added to the left of the badge. | `0px`
`--paper-badge-margin-bottom` | Optional spacing added to the bottom of the badge. | `0px`
`--paper-badge` | Mixin applied to the badge | `{}`
@group Paper Elements
@element paper-badge
@demo demo/index.html
-->
<dom-module id="paper-badge">
<template>
<style>
:host {
display: block;
position: absolute;
outline: none;
}
iron-icon {
--iron-icon-width: 12px;
--iron-icon-height: 12px;
}
.badge {
@apply(--layout);
@apply(--layout-center-center);
@apply(--paper-font-common-base);
font-weight: normal;
font-size: 11px;
border-radius: 50%;
margin-left: var(--paper-badge-margin-left, 0px);
margin-bottom: var(--paper-badge-margin-bottom, 0px);
width: var(--paper-badge-width, 20px);
height: var(--paper-badge-height, 20px);
background-color: var(--paper-badge-background, --accent-color);
opacity: var(--paper-badge-opacity, 1.0);
color: var(--paper-badge-text-color, white);
@apply(--paper-badge);
}
</style>
<div class="badge">
<iron-icon hidden$="{{!_computeIsIconBadge(icon)}}" icon="{{icon}}"></iron-icon>
<span id="badge-text" hidden$="{{_computeIsIconBadge(icon)}}">{{label}}</span>
</div>
</template>
<script>
Polymer({
is: 'paper-badge',
hostAttributes: {
tabindex: '0',
role: 'status'
},
behaviors: [
Polymer.IronResizableBehavior
],
listeners: {
'iron-resize': 'updatePosition'
},
properties: {
/**
* The id of the element that the badge is anchored to. This element
* must be a sibling of the badge.
*/
for: {
type: String,
observer: '_forChanged'
},
/**
* The label displayed in the badge. The label is centered, and ideally
* should have very few characters.
*/
label: {
type: String,
observer: '_labelChanged'
},
/**
* An iron-icon ID. When given, the badge content will use an
* `<iron-icon>` element displaying the given icon ID rather than the
* label text. However, the label text will still be used for
* accessibility purposes.
*/
icon: {
type: String,
value: ''
}
},
attached: function() {
this._updateTarget();
},
_forChanged: function() {
// The first time the property is set is before the badge is attached,
// which means we're not ready to position it yet.
if (!this.isAttached) {
return;
}
this._updateTarget();
},
_labelChanged: function() {
this.setAttribute('aria-label', this.label);
},
_updateTarget: function() {
this._target = this.target;
this.async(this.notifyResize, 1);
},
_computeIsIconBadge: function(icon) {
return icon.length > 0;
},
/**
* Returns the target element that this badge is anchored to. It is
* either the element given by the `for` attribute, or the immediate parent
* of the badge.
*/
get target () {
var parentNode = Polymer.dom(this).parentNode;
// If the parentNode is a document fragment, then we need to use the host.
var ownerRoot = Polymer.dom(this).getOwnerRoot();
var target;
if (this.for) {
target = Polymer.dom(ownerRoot).querySelector('#' + this.for);
} else {
target = parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE ?
ownerRoot.host : parentNode;
}
return target;
},
/**
* Repositions the badge relative to its anchor element. This is called
* automatically when the badge is attached or an `iron-resize` event is
* fired (for exmaple if the window has resized, or your target is a
* custom element that implements IronResizableBehavior).
*
* You should call this in all other cases when the achor's position
* might have changed (for example, if it's visibility has changed, or
* you've manually done a page re-layout).
*/
updatePosition: function() {
if (!this._target)
return;
if (!this.offsetParent)
return;
var parentRect = this.offsetParent.getBoundingClientRect();
var targetRect = this._target.getBoundingClientRect();
var thisRect = this.getBoundingClientRect();
this.style.left = targetRect.left - parentRect.left +
(targetRect.width - thisRect.width / 2) + 'px';
this.style.top = targetRect.top - parentRect.top -
(thisRect.height / 2) + 'px';
}
})
</script>
</dom-module>