@tygr/tabs
v2.1.0
Published
Tab hook and sass mixin
Downloads
4
Readme
Tygr Tabs
This a simple react hook and sass mixin designed to create tabbed components.
The tabbed component will share as much html as it can between the different tabs, allowing for smooth transitions.
Requirements:
- A react application built with node (webpack, rollup, babel)
- Sass compiler
See the demo/webpack.config.js
file for an example of using react and sass with webpack. The package.json
has the babel config.
Installation:
npm i --save @tygr/tabs
Step 1: use the tabs hook in your component
import React from 'react';
import useTabs from '@tygr/tabs';
export default function Auth() {
const [attributes, setTab, LOGIN, REGISTER, RESET_PASSWORD] = useTabs(
'login',
'register',
'reset-password'
);
return (
<div {...attributes} className="tygr-auth">
<div>...etc</div>
</div>
);
}
The useTabs
hook takes an unspecified number of tab names as parameters. It returns an attributes object to be used for the tab container, a function to set the current tab, and boolean flags for each tab name you passed in. Each flag tells you whether that tab is currently active.
Spread the attributes
object returned from the useTabs
hook over the root element of the tabs container as shown above.
Step 2: use the tabs sass mixin
@use '@tygr/tabs';
.tygr-auth {
@include tabs(login, register, reset-password);
}
The tab names passed in to the tabs
mixin must match the ones passed in to the useTabs
react hook. You should always enclose this mixin within a selector, just like above, because it makes use of the sass parent selector: &
.
Step 3: hide and show elements conditionally using data-tab
<input data-tab="login register" name="password" />
<input data-tab="register" name="confirm-password" />
For elements you want to conditionally show or hide, add the data-tab
attribute with a list of the tab names you would like it to show up under. In this example, the password
input will be shown if the tab is either login
or register
. Likewise, the confirm-password
input will only be shown when the register
tab is active.
Step 4: Use the setTab function to change tabs
<button onClick={setTab('reset-password')}>Reset Password</button>
Use the setTab
higher order function returned from the useTabs
hook in order to change tabs on button clicks. The method is type-safe if using typescript, so you don't have to memorize which name you gave each tab.
Optional: Use the exclusion syntax for data-tab
<label htmlFor="confirm-password" data-tab="!login !reset-password">
Confirm Password
</label>
By using the !
operator, you can exclude an element from certain tabs rather than the default additive behavior.
This operator takes precedence: if a single tab is specified with !
, any additive tabs that are also specified for that element will be ignored.
Optional: Use the tab status flags
Ex 1: Add selected class to current tab button:
<button onClick={setTab('register')} className={REGISTER && 'selected'}>
Register
</button>
Ex 2: Combine flags for easy to read conditionals:
<input
required={LOGIN || REGISTER}
id="password"
data-tab="login register"
type="password"
/>
Optional: use custom css logic for hiding elements
By default, an element with the data-tab=tab-name
attribute for conditional rendering is given the display: none
css property when the tab is not active.
You may replace that logic with your own by passing content to the tabs
mixin:
Ex 1: Using transitions
@import '@tygr/tabs';
.tygr-auth {
[data-tab] {
transition: opacity 1s;
}
@include tabs(login, register, reset-password) {
/**
* These styles are applied when the data-tab
* attribute *DOES NOT* match the current tab
*/
opacity: 0;
}
}
Ex 2: Using animations
@import '@tygr/tabs';
.tygr-auth {
[data-tab] {
animation: _fade-in 1s;
}
@include tabs(login, register, reset-password) {
animation: _fade-out 1s forwards;
}
}
@keyframes _fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes _fade-out {
to {
opacity: 0;
}
}
You can split the sass mixin into multiple calls to apply different transitions for different tabs becoming active:
@import '@tygr/tabs';
.tygr-auth {
// Fade in and out when switching to and from the login and register tabs
@include tabs(login, register) {
opacity: 0;
}
// Shrink and expand when switching to and from the reset-password tab
@include tabs(reset-password) {
transform: scaleY(0);
}
[data-tab] {
/*
* When switching between types of transition effects, both sets of rules will
* apply. In a way, it will blend both effects.
*/
transition: opacity 1s, transform 1s;
}
}
Optional: set an initial tab programmatically
By default, the tab shown is the first one in the list. You can override that by calling the setTab
function within a react effect that runs only once when the component is created:
import React, { useEffect } from 'react';
...
useEffect(setTab('register'), []);
By passing in an empty list to the dependencies
parameter of useEffect
, the effect will not be run for any prop or state updates.
This is useful if you are allowing the consumer of the component to pass in an initial tab via a prop.