Miss any of our Open RFC calls?Watch the recordings here! »

mat-tab-swiper

1.1.16 • Public • Published

Material Tab Swiper

First complete material tab swiper that works as a web component, which means that it can be embedded into React, Angular, Vue, Ember and most importantly, simple VanillaJS extremely easily.

The API to use this is very straightforward. Default tab background and highlighter has a color. But you can change them easily according to your need with input. The tabs' minimum width is (container-width / number of tabs), but they can be as wide as they require. They don't have to be the same width. The highlighter animation will work in its own way.

This component is made with Stencil, a fast, robust, easy to use web-component generation tool.

Demo

Please visit this link to see a working demo of Material Tab Swiper.

Installation

NPM: npm i mat-tab-swiper
CDN: <script src="https://unpkg.com/mat-tab-swiper/dist/mattabswiper.js"></script>

Framework Integration

React

Install the component with npm i mat-tab-swiper. In your 'index.js' file, you have to do the following:

import { applyPolyfills, defineCustomElements } from 'mat-tab-swiper/loader';
...
applyPolyfills().then(() => {
  defineCustomElements();
});

Angular

Install the component with npm i mat-tab-swiper. For angular you have to do the following in app.module.ts

import { applyPolyfills, defineCustomElements } from 'mat-tab-swiper/loader';
...
applyPolyfills().then(() => {
  defineCustomElements();
});

Then you can import 'CUSTOM_ELEMENTS_SCHEMA' like following in your lazy loaded module where you will use it.
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
Then you need to add it to 'schemas' array inside NgModule like following

@NgModule({
  declarations: [...],
  imports: [...],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})

Then you are ready to use it as an angular custom element

Vue

Install the component with npm i mat-tab-swiper
Then do the following in 'main.js' file

import { applyPolyfills, defineCustomElements } from 'test-components/loader';
...
applyPolyfills().then(() => {
  defineCustomElements();
});

Now the 'mat-tab-swiper' should be available to use in any component.

Ember

It is really easy to integrate with Ember. Ember even has an add-on to integrate with Stencil components. Go to this page to know how to integrate with Ember.

Javascript

Getting started in VanillaJS is very easy. Just add the script tag at top and get started.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Swiper</title>
    <script src="https://unpkg.com/mat-tab-swiper/dist/mattabswiper.js"></script>
</head>

<body>

    <mat-tab-swiper>
        <mat-swiper tab="Tab1">
            ...
        </mat-swiper>
        <mat-swiper tab="Tab2">
            ...
        </mat-swiper>
        <mat-swiper tab="Tab3">
            ...
        </mat-swiper>
    </mat-tab-swiper>

</body>

</html>

For more on this, please read in detail about how to integrate web-components in your framework.

How To Use

After you install it with npm i mat-tab-swiper or use script tag like,<script src="https://unpkg.com/mat-tab-swiper/dist/mattabswiper.js"></script>, just add the following html to get your tabswiper up and running.

<mat-tab-swiper>
    <mat-swiper tab="Tab1">
        ...
    </mat-swiper>
    <mat-swiper tab="Tab2">
        ...
    </mat-swiper>
    <mat-swiper tab="Tab3">
        ...
    </mat-swiper>
</mat-tab-swiper>

You are done!!

The tabswiper has a few inputs and events to help you out with your custom needs be it css or functional. Following shows the advanced use in various frameworks.

React

You can pass the inputs to this component exactly the way you do in any other component. But to access events, you assign eventlistener to the element like following.

<mat-tab-swiper ref={(ref)=> this.tabSwiperRef = ref}>
    <mat-swiper tab="Tab1">
        ...
    </mat-swiper>
    <mat-swiper tab="Tab2">
        ...
    </mat-swiper>
    <mat-swiper tab="Tab3">
        ...
    </mat-swiper>
</mat-tab-swiper>

...

componentDidMount() {
    this.tabSwiperRef.addEventListener('slidemove', (e) => {
        // 'slidemove' gives the moving direction as output
    })
}

Angular

The input and output event work exactly the same way it does in normal angular component. If you want to access the element in the ts file, use '@ViewChild' as ElementRef.

Vue

If you want to access the TabSwiper's element, you can use 'ref'. For passing input data and accessing output events, it works in the exact way as any other custom components.

Javascript

For VanillaJS, you can pass input and access event in following way.

let matTabSwiper = document.querySelector('mat-tab-swiper')

The default initial slide index is 0 but you can also initialize with an input property 'activeIndex', matTabSwiper.activeIndex = 1

You can pass tab's css properties the same way. The input's name is 'tabCssProperties'. It has an interface as,

{
    background: string
    highlighterBackground: string
    textColor: string
}

You can pass the properties the same way,

matTabSwiper.tabCssProperties = {
    background: '#fc3535',
    highlighterBackground: '#000',
    textColor: '#000'
}

The events are simple js events. So, you can access events in normal js way. The below code shows accessing 'slidechanged' event.

matTabSwiper.addEventListener('slidechanged', (e) => {
    // e.detail.index is a valid slide index
})

Input Properties

activeIndex

Active slide index as initial slide. It takes a valid number as slide index. Defaults to 0.

sliderSpeed

Slider animation speed in ms. Speed for slide and tab transition is denoted by this. It takes a number. Default is 300.

tabCssProperties

Css properties for tabs container. It has an interface as following,

{
    background: string
    highlighterBackground: string
    textColor: string
}

Defaults to,

{
    background: '#bad97d',
    highlighterBackground: '#000',
    textColor: '#000'
}

Events

All the events are js events. So you can access value through 'event.detail' if value is provided with event.

slidechanged

Fires after slide changed. It also emits the slide index. The index of the slide can be accessed through 'event.detail.index'

transitionend

Fired after transition ends

tabclicked

Fires when a tab is clicked. The index of the tab can be accessed through 'event.detail.index'

slidevisited

Fires when a slide changes. It shows whether the tab is already visited or not. You can make use of it if you are doing differential loading. If you are looking for 'Tab1', 'event.detail.Tab1' returns boolean. It also gives 'currentTab' property which you can access through 'event.detail.currentTab'. Visit Differential Loading section of this page to read in detail.

slidemove

Fired when slide moves, emits direction as 'right' or 'left'. You can access it through 'event.detail.direction'.

receiveswiper

Fires when 'swiper' object is fired. You can use this to manipulate swiper's behaviour. Visit SwiperJS for detailed API.

receiveswiperelement

Fires the swiper-wrapper html-element when ready

receivetabelement

Fires the tab-container html-element when ready

If you want to manipulate the tabs, you can do it through the 'receivetabelement' event by accessing the tab elements. It is using shadowdom so you can not easily access it through normal js. You can do it this way,

let matTabSwiper = document.querySelector('mat-tab-swiper')
matTabSwiper.addEventListener('receivetabelement', (e) => {
    let tabContainer = e.detail
    // If you want to change the fontsize of the tabs, the class of each tab is 'inner-tab'
    let tabs = tabContainer.querySelectorAll('.inner-tab')
    tabs.forEach(element => {
      element.style.fontSize = '20px'
    });
})

Methods

You have to access the element in your framework in order to call any methods.
let matTabSwiper = document.querySelector('mat-tab-swiper')

Use 'ref' for React and Vue and 'Viewchild' for Angular

slideNext

Slides to next slide. Takes no argument.

slidePrevious

Slides to preveious slide. Takes no argument.

slideTo

Slides to the index passed. Suppose you want to slide to 3rd slide. You have to call
matTabSwiper.slideTo(2)

lockSwipe

For locking and unlocking the swipe. Takes a boolean. If you want to lock, you have to pass true. Or false if you want to unlock.
EG: matTabSwiper.lockSwipe(true)

lockNextSwipe

For locking and unlocking the swipe to go to next slide. Takes a boolean. If you want to lock, you have to pass true. Or false if you want to unlock.

lockPrevSwipe

For locking and unlocking the swipe to go to preveious slide. Takes a boolean. If you want to lock, you have to pass true. Or false if you want to unlock.

Differential Loading

Differential loading here means that you load the content inside specific 'mat-swiper' if that slide is at all visited once by the user. Otherwise you end up calling unnecessary API's that user need not see content of and DOM loads unnecesary contents which resides in another slide which user did not visit.

This is not done by default, however you can make use of 'slidevisited' EventListener to achieve this. You can check whether the current swiper if at all visited atleast once. If not visited once, then content inside can be loaded and then thereafter it maintains the state be it the scroll position or other things for succeeding visits. The 'slidevisited' event holds the given tab names as properties and values as boolean whether they have been visited already. It also gives 'currentTab' property which provides the active swipe's tab name.

For a swiper with tab name "Tab1", you can load the content inside it in the following manner.

Suppose you have a variable 'slideVisitedObject' which stores last event data emitted by 'slidevisited' event.

If you are using templating mechanism that conditionally renders content, like simple 'if' for React or '*ngIf' for Angular or 'v-if' for Vue, you can do it in following way:

let matTabSwiper = document.querySelector('mat-tab-swiper')
matTabSwiper.addEventListener('slidevisited', (e) => {
    this.slideVisitedObject = e.detail
})

<mat-swiper tab='Tab1'>
    { if (this.slideVisitedObject.currentTab == 'Tab1' || this.slideVisitedObject['Tab1']) == true } // React

    *ngIf="this.slideVisitedObject.currentTab == 'Tab1' || this.slideVisitedObject['Tab1']) == true" // Angular

    v-if="this.slideVisitedObject.currentTab == 'Tab1' || this.slideVisitedObject['Tab1']) == true" // Vue
</mat-swiper>

*** Do not put the condition on 'mat-swiper' element itself.

If you are using Vanilla JS or DOM manipulation in any framework where you inject the content later, you do the following way:

<mat-tab-swiper>
    <mat-swiper tab="Tab1">
    
    </mat-swiper>
    <mat-swiper tab="Tab2">
    
    </mat-swiper>
    <mat-swiper tab="Tab3">
    
    </mat-swiper>
</mat-tab-swiper>

let matTabSwiper = document.querySelector('mat-tab-swiper')
matTabSwiper.addEventListener('slidevisited', (e) => {
    let slideVisitedObject = e.detail
    if(!slideVisitedObject[slideVisitedObject.currentTab]) { // Truthy checking
        let currentTab = document.querySelector([tab="Tab1"])
        currentTab.innerHTML = <Your Content>
    }
})

For a particular slide, !slideVisitedObject[slideVisitedObject.currentTab] condition will yield only once in its entire lifecycle. So the above code ensures that a tab which is in focus currently but not visited yet once gets loaded and stays in the DOM for succeeding visits without further loading.

Further help

For further help contact juny.ss91@gmail.com if you need help with integration.

Install

npm i mat-tab-swiper

DownloadsWeekly Downloads

52

Version

1.1.16

License

MIT

Unpacked Size

2.15 MB

Total Files

82

Last publish

Collaborators

  • avatar