UNPKG

ember-attacher

Version:
322 lines (231 loc) 10.5 kB
# ember-attacher [![npm version](https://badge.fury.io/js/ember-attacher.svg)](http://badge.fury.io/js/ember-attacher) [![Download count all time](https://img.shields.io/npm/dt/ember-attacher.svg)](https://www.npmjs.com/package/ember-attacher) [![npm](https://img.shields.io/npm/dm/ember-attacher.svg)](https://www.npmjs.com/package/ember-attacher) [![Ember Observer Score](http://emberobserver.com/badges/ember-attacher.svg)](http://emberobserver.com/addons/ember-attacher) [![GitHub CI](https://github.com/tylerturdenpants/ember-attacher/actions/workflows/ci.yml/badge.svg)](https://github.com/tylerturdenpants/ember-attacher/actions/workflows/ci.yml) ## Compatibility ------------------------------------------------------------------------------ ***NOTE*** The addon's dummy application needs a serious upgrade. I [@tylerturdenpants](https://github.com/tylerturdenpants) have removed as much orf the support on flexi and flexi styles that I can, but the dummy app will still produces warnings regarding SASS division. As the only supporter of this addon, a father, and a full time employee at a software company, I really need the help to fully pull flexi out and to revamp the dummy app. Once these blockers are removed I can do the work to bring this addon into the future. ---- * Ember.js v3.20 through v5.12 * Ember CLI v3.13 or above * Node.js v12 or above Tooltips and popovers made easy. Just drop an `<AttachTooltip/>` or `<AttachPopover/>` in a parent and your floating element is ready to go! ```hbs <button> Click me <AttachTooltip> I'm a tooltip! </AttachTooltip> </button> <button class="other-button"> No click me! <AttachPopover @class='ember-attacher' @hideOn='click' @isShown={{true}} @showOn='click' > I'm a popover! </AttachPopover> </button> ``` See [the example site](https://tylerturdenpants.github.io/ember-attacher/) for a demonstration of all available options. ## Installation ```bash ember install ember-attacher ``` If you're upgrading from 1.x to 2.x [see the upgrade guide](./docs/upgrade-guide-2.0.md). ## Components ### `<AttachPopover/>` A popover attacher. * Has no default class or roles. * Does not modify the target in any way. * Adds `aria-hidden` attribute to the floating element ### `<AttachTooltip/>` A tooltip attacher. Subclass of `<AttachPopover/>` * Has the default class `'ember-attacher-floating ember-attacher-tooltip'` * The default tooltip classes can be modified by altering the `tooltipClass` default. See [here](#user-defined-defaults) for details on editing default values. * Default `role` attribute of `tooltip`. * Causes the target to gain an `aria-describedby` attribute set to the tooltip's ID. ## Options Below is a list of all available options, along with their defaults. ```javascript { // The animation used to present the animation. // Options: ['fade', 'fill', 'none', 'perspective', 'scale', 'shift'] animation: 'fill', // Whether or not an arrow will be displayed next to the attachment. arrow: false, // Add listeners that will automatically call an update function // Pass `true` to use the Floating UI default options or Options object to override them // Example: { ancestorScroll: false } // For more details see https://floating-ui.com/docs/autoUpdate autoUpdate: false, // A class that will be applied to the attachment. class: null, // The flip priority of the attacment. // Space-delimited string, any combination of ['left', 'right', 'top', 'bottom'] // // Example: 'left top bottom' flip: null, // The delay, in milliseconds, before the attachment will be hidden. hideDelay: 0, // The duration, in milliseconds, of the hide animation. hideDuration: 300, // Events that will cause the attachment to hide, typically in reference to the target. // // Space-delimited string, any combination of: // ['click', 'clickout', 'mouseleave blur escapekey'] hideOn: 'mouseleave blur escapekey', // Interactive tooltips will not close when clicked or hovered over. interactive: false, // Set this to true if you have an interactive attachment that hides on mouseout and the // attachment is offset from its target. This should only be the case if you are using custom // CSS that offsets that attachment. isOffset: false, // Whether or not the attachment is initially shown. isShown: false, // If true, the attachment will only be inserted into the DOM on the first "show" trigger. // Useful for performance reasons, but will hide your attachment from search engines. lazyRender: false, // A middleware array that will be merged into computePosition options middleware: null, // A function to be fired when the attachment's visibility changes. The new visibility is passed // to the function as an arg. onChange: null, // The initial position of the attachment. // Options: ['left', 'right', 'top', 'bottom'] placement: 'top', // The container where the attachment's DOM will be inserted. floatingElementContainer: '.ember-application', // An options object that will be passed to Floating UI "computePosition" function. floatingUiOptions: null, // NOT RECOMMENDED: We currently allow you to pass an explicit target, but this may be removed // in a future release. // Please provide your thoughts here: https://github.com/kybishop/ember-attacher/issues/109 explicitTarget: null, // Whether or not to render the attachment in place in the DOM, as opposed to // on the floatingElementContainer. NOTE: Rendering in place can cause z-index issues. renderInPlace: false, // The delay, in milliseconds, before the attachment will be shown. showDelay: 0, // The duration, in milliseconds, of the show animation. showDuration: 300, // Events on the target that will cause the attachment to show. For performance reasons, we // recommend using some combination of 'mouseenter', 'focus', and 'click' showOn: 'mouseenter focus', // Whether to add event listeners for attachment show and hide in the capturing phase rather // than the bubbling phase. This should be set to true when there are elements on the page that // are stopping event propagation in the bubbling phase, and as a result preventing correct // showing and hiding of popovers and tooltips. useCapture: false, // The default padding if collision happens. Set "false" if no collision prevention needed overflowPadding: 5 } ``` ## User-defined defaults User-defined defaults can be set in the consuming app or addon's config/environment.js. These defaults will be applied to every `<AttachPopover/>` and `<AttachTooltip/>` ```javascript // config/environment.js module.exports = function(environment) { var ENV = { emberAttacher: { animation: 'shift', arrow: true } }; } ``` You can also set the user-defined defaults separately like so: ```javascript // config/environment.js module.exports = function(environment) { var ENV = { emberAttacher: { tooltip: { animation: 'fade', arrow: true }, popover: { animation: 'shift', arrow: false } } }; } ``` And finally you can do shared defaults along with user-defined separated defaults: ```javascript // config/environment.js module.exports = function(environment) { var ENV = { emberAttacher: { showDuration: 300, hideDuration: 300, tooltip: { animation: 'fade', arrow: true }, popover: { animation: 'shift', arrow: false } } }; } ``` The full list of editable defaults can be seen [here](https://github.com/kybishop/ember-attacher/blob/master/addon/defaults.js). ## Styles `ember-attacher` provides [styles](https://github.com/kybishop/ember-attacher/blob/master/addon/styles/addon.scss#L85) for the default tooltip class, `ember-attacher-tooltip`, but no styles are included for `{{attach-popover}}`. Example styling for a popover [can be found in the dummy app](https://github.com/kybishop/ember-attacher/blob/master/tests/dummy/app/styles/app.scss#L132). Note how the arrow must also be styled to match the popover (background color, size, etc.) ## Testing Use the `isVisible()` test helper to check if an attachment is visible. ```javascript import { click, find } from 'ember-native-dom-helpers'; import { isVisible } from 'ember-attacher'; test('example', async function(assert) { this.render(hbs` <button id="toggle"> Click me, captain! <AttachPopover @id='attachment' @hideOn='click' @showOn='click' > Click-toggled popover <AttachPopover/> </button> `); const attachment = find('#attachment'); assert.equal(isVisible(attachment), false, 'Initially hidden'); await click('#toggle'); // You can also pass in a selector assert.equal(isVisible('#attachment'), true, 'Now shown'); }); ``` ## Development setup See the [Contributing](CONTRIBUTING.md) guide for details. ## FAQ ### How animations are implemented Attachments are composed of two containers: * [An outer container](https://github.com/kybishop/ember-attacher/blob/master/addon/templates/components/attach-popover.hbs#L2) for positioning (via [floating-ui](https://github.com/floating-ui/floating-ui)). * [An inner container](https://github.com/kybishop/ember-attacher/blob/master/addon/templates/components/attach-popover.hbs#L12) for the content. This is the container that is animated. The outer container is positioned right next to the target via the CSS `transform` property. The inner container is required because animations also use `transform`, which would otherwise conflict with the container's position. `transform` and `tansition-duration` are the CSS magic that allows animations to smoothly shift up/down, left/right, etc. Note that animations require an implementation for each position (left, right, top, and bottom): * <https://github.com/kybishop/ember-attacher/blob/master/addon/styles/addon.scss#L67> * <https://github.com/kybishop/ember-attacher/blob/master/addon/styles/_mixins.scss#L75> ## Credits * [tippy.js](https://github.com/atomiks/tippyjs), the library that inspired ember-attacher. * [floating-ui](https://github.com/floating-ui/floating-ui), the library that powers positioning * [ember-tooltips](https://github.com/sir-dunxalot/ember-tooltips), the addon that influenced much of ember-attacher's API.