Tiny Angular library to create overlays for tooltips, modals, dropdowns, alerts, toastr, popovers, menus, and more
Demo and documentation
step 1: Install from npm or yarn
npm install toppy // or
yarn add toppystep 2: Import ToppyModule in your main module
import { ToppyModule } from 'toppy';
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, ToppyModule], // <==
  bootstrap: [AppComponent]
})
export class AppModule {}step 3: Import Toppy service in your component
import { Toppy } from 'toppy'; // <==
@Component({
  selector: 'app-root',
  template: '<div #el>Click me</div>'
})
export class AppComponent {
  @ViewChild('el', { read: ElementRef })
  el: ElementRef;
  constructor(private _toppy: Toppy) {}
  ngOnInit() {
    const position = new RelativePosition({
      placement: OutsidePlacement.BOTTOM_LEFT,
      src: this.el.nativeElement
    });
    this.overlay = this._toppy
      .position(position)
      .content('hello') // content
      .create();
  }
  open() {
    this.overlay.open();
  }
  close() {
    this.overlay.close();
  }
}Toppy allows to use string, html, TemplateRef, Component as overlay content.
Plain text
this.overlay = this._toppy
  .position(position)
  .content(`some plain text content`) // simple text
  .create();HTML content
this.overlay = this._toppy
  .position(position)
  .content(`<div>any HTML content</div>`, { hasHTML: true }) // html
  .create();Using TemplateRef
<ng-template #tpl>Hello world!</ng-template>@ViewChild('tpl') tpl:TemplateRef<any>;
this.overlay = this._toppy
  .position(position)
  .content(this.tpl) // template ref
  .create();Component
// host component
@Component({
  template: '<div>Hello</div>'
})
export class HelloComponent {}this.overlay = this._toppy
  .position(position)
  .content(HelloComponent) // <==
  .create();Dont forget to add host component in
entryComponentsin module
Position determines the location and size of the overlay. There are four positions:
Relative position
Overlay position that is relative to specific element. These are used in tooltips, popovers, dropdowns, menus
new RelativePosition({
  src: HTMLElement, // target element
  placement: OutsidePlacement, // location of the content
  width: string | number, // content width eg, `auto`, 150, `30%`
  height: string | number, // content height eg, `auto`, 150, `30%`
  autoUpdate: boolean // update position when window scroll/resize/drag
});Relative position supports 12 placements:
OutsidePlacement.BOTTOM;
OutsidePlacement.BOTTOM_LEFT;
OutsidePlacement.BOTTOM_RIGHT;
OutsidePlacement.LEFT;
OutsidePlacement.LEFT_BOTTOM;
OutsidePlacement.LEFT_TOP;
OutsidePlacement.RIGHT;
OutsidePlacement.RIGHT_BOTTOM;
OutsidePlacement.RIGHT_TOP;
OutsidePlacement.TOP;
OutsidePlacement.TOP_LEFT;
OutsidePlacement.TOP_RIGHT;Global position
Overlay position that is relative to window viewport. These are used in modals, alerts, toastr
new GlobalPosition({
  placement: InsidePlacement, // location of the content.
  width: string | number, // content width eg, `auto`, `150`, `30%`
  height: string | number, //content height eg, `auto`, 150, `30%`
  offset: number // oustide space of the content, in px
});Global position supports 9 placements:
InsidePlacement.BOTTOM;
InsidePlacement.BOTTOM_LEFT;
InsidePlacement.BOTTOM_RIGHT;
InsidePlacement.LEFT;
InsidePlacement.RIGHT;
InsidePlacement.TOP;
InsidePlacement.TOP_LEFT;
InsidePlacement.TOP_RIGHT;
InsidePlacement.CENTER;Slide position
Overlay position that is relative to window viewport. These are used in side panels, sidebars, blade
new SlidePosition({
  placement: SlidePlacement, // rigth or left
  width: string // width eg, '300px' or '30%'
});Slide position supports 2 placements:
SlidePlacement.LEFT;
SlidePlacement.RIGHT;Fullscreen position
Overlay that occupies complete size of the viewport.
new FullScreenPosition();this.toppy
  .position(position: ToppyPosition)
  .config(configuration: ToppyConfig = {})
  .content('hello')
  .create();| property | for | 
|---|---|
| backdrop | boolean· whether to show backdrop layer · default:false | 
| closeOnEsc | boolean· clicking Escape button will close overlay · default:false | 
| closeOnDocClick | boolean· dismiss on clicking outside of content · default:false | 
| listenWindowEvents | boolean· auto adjust the position on scroll/resize · default:true | 
| containerClass | string· overlay container class name · default:t-overlay | 
| wrapperClass | string· overlay wrapper class name · default:'' | 
| backdropClass | string· overlay backdrop class name · default:'' | 
| bodyClass | string· body class when overlay is open · default:t-open | 
| windowResizeCallback | function· triggered on window scroll | 
| docClickCallback | function· triggered on document click | 
When you host a component, you can control the overlay through ToppyOverlay service. Using this service you can access all properties that is provided in content. Also the properties comes with close.
this.overlay = this._toppy
  .position(position)
  .content(HelloComponent, { propName: 'toppy-test-prop' })
  .create();
this.overlay.listen('t_compins').subscribe(comp => {
  console.log('component is ready!', comp); // returns HelloComponent
});// host component
@Component({
  template: '<div>Some text</div>'
})
export class HelloComponent {
  constructor(public overlay: ToppyOverlay) {
    console.log(this.overlay.props.propName); // will return 'toppy-test-prop'
  }
  close() {
    this.overlay.close();
  }
}This is very similar to above one. When you use template as a content, you can pass additional data to it.
this.overlay = this._toppy
  .position(position)
  .content(template, { name: 'Johny' })
  .create();Then in your template you can refer the data like this,
<ng-template #tpl let-toppy>
  <div>Hello <span [innerText]="toppy.name"></span> !</div>
  <button (click)="toppy.close()">Close</button>
</ng-template>Method close is automatically binded.
When you use Plain text as a content, optionally you can able to set a class name to that div block.
this.overlay = this._toppy
  .position(position)
  .content('some content', { class: 'tooltip' })
  .create();/* Toppy */
Toppy.position(position: ToppyPosition):Toppy
Toppy.config(config: ToppyConfig):Toppy
Toppy.content(data: ContentData, props: ContentProps = {}):Toppy
Toppy.create(key: string = ''):ToppyControl
Toppy.getCtrl(id: string):ToppyControl
Toppy.destroy():void/* ToppyControl */
ToppyControl.open():void
ToppyControl.close():void
ToppyControl.toggle():void
ToppyControl.onDocumentClick():Observable<any>
ToppyControl.onWindowResize():Observable<any>
ToppyControl.changePosition(newPosition: ToppyPosition): void
ToppyControl.updateContent(content: ContentData, props: ContentProps = {}):void
ToppyControl.updatePosition(config:object):ToppyControl
ToppyControl.listen(eventName:string):Observable<any>/* events */
`t_open`, `t_close`, `t_dynpos`, `t_detach`, `t_posupdate`, `t_compins`;Any kind of contributions ( Typo fix, documentation, code quality, performance, refactor, pipeline, etc., ) are welcome. :)
▶ Icons ━ icons8
▶ Illustrations ━ undraw
▶ Font icons ━ feathers
Found a bug? Have some idea? Or do you have questions? File it here
MIT
