Giter Club home page Giter Club logo

react-responsive-tabs's Introduction

React responsive tabs

Your feedback is highly appreciated!

Please, file an issue if something went wrong or let me know via Twitter @maslianok

Responsive

  • Hide tabs under the 'Show more' option when they don't fit into the screen
  • Transform tabs into the accordion when the wrapper width reaches the transformWidth value

Responsive tabs

Accessible

The component outputs HTML code that follows accessibility principles (aka WAI-ARIA) and uses ARIA attributes such as role, aria-selected, aria-controls, aria-labeledby etc.

Accessible tabs

Fast

We are using react-resize-detector. No timers. Just pure event-based element resize detection.

Installation

npm install react-responsive-tabs

Demo

Local demo

# 1. clone the repository
git clone https://github.com/maslianok/react-responsive-tabs.git

# 2. Install react-responsive-tabs dependencies. You must do it because we use raw library code in the example
cd react-responsive-tabs
npm install

# 3. Install dependencies to run the example
cd examples
npm install

# 4. Finally run the example
npm start

Example

import React, { Component } from 'react';
import { render } from 'react-dom';
import Tabs from 'react-responsive-tabs';

// IMPORTANT you need to include the default styles
import 'react-responsive-tabs/styles.css';

const presidents = [
  { name: 'George Washington', biography: '...' },
  { name: 'Theodore Roosevelt', biography: '...' },
];

function getTabs() {
  return presidents.map((president, index) => ({
    title: president.name,
    getContent: () => president.biography,
    /* Optional parameters */
    key: index,
    tabClassName: 'tab',
    panelClassName: 'panel',
  }));
}

const App = () => <Tabs items={getTabs()} />;

render(<App />, document.getElementById('root'));

API

All entities listed below should be used as props to the Tabs component.

Prop Type Description Default
items Array Tabs data Item[]
beforeChange Function Fires right before a tab changes. Return false to prevent the tab change undefined
onChange Function onChange callback undefined
selectedTabKey Number/String Selected tab undefined
showMore Bool Whether to show Show more or not true
showMoreLabel String/Node Show more tab name ...
transform Bool Transform to accordion when the wrapper width is less than transformWidth. true
transformWidth Number Transform width. 800
unmountOnExit Bool Whether to unmount inactive tabs from DOM tree or not true
tabsWrapperClass String Wrapper class undefined
tabClassName String Tab class undefined
panelClassName String Tab panel class undefined
allowRemove Bool Allows tabs removal. false
removeActiveOnly Bool Only active tab has removal option false
showInkBar Bool Add MaterialUI InkBar effect false
uid any An optional external id. The component rerenders when it changes undefined

Item

Prop Type Description
title String Tab title
getContent Function A function that returns data that will be rendered when tab become active
content String Use this prop insted of getContent. This is a sync version of getContent. The data will be always rendered in a hidden div. Sometimes it may be useful for SEO
key Number A uniq tab id
tabClassName String Tab class name
panelClassName String Panel class name

License

MIT

react-responsive-tabs's People

Contributors

alexanderdormann-twt avatar bghveding avatar coderbit-net avatar datbth avatar dcworldwide avatar dependabot[bot] avatar janaborchardt-twt avatar maslianok avatar petrdamborsky avatar snannan268 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

react-responsive-tabs's Issues

Typescript definition

Can you create the typescript definition file upload the node module pack at @types/react-responsive-tabs?

Replace js-stylesheet with standard stylesheet

Is there are any specific reason why js-stylesheet is used in this module?
Looks like it's much easier to use standard css file, isn't it?

One of the reasons: at the moment it's impossible to switch-off JSS.

Tab Content not re-rendering on props change

I'm having issues re-rendering a tab's content. Perhaps https://github.com/maslianok/react-responsive-tabs/blob/master/src/components/Tab.js#L8 is blocking my re-rendering from happening.

Example

I have a tab as follows:

tabItems.push({
			key: 2,
			title: "Equipment & Maintenance",
			getContent: () => {
				console.log(this.props.dimensions.width)
				return <DataTable
					rowData={rowData}
					width={this.props.dimensions.width}>
					// table content here 
				</DataTable>
			}
		})

this.props.dimensions.width tracks the width of the table's parent panel. This width of this panel can be re-sized by the user within my app. After they finish resizing the panel, this.props.dimensions.width will be updated with a new value. I need the table rendered within my tab, to re-render using the new width.

How can we change shouldComponentUpdate to support this scenario? I can prove it is an issue with shouldComponentUpdate, as if I switch between tabs and then switch back to this tab, the table re-renders to the correct width.

Warning: Tabs has a method called shouldComponentUpdate().

I encountered this warning while using react-responsive-tabs:

Warning: Tabs has a method called shouldComponentUpdate(). shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.

I suppose using Component instead of PureComponent will resolve the issue.

API for classes names doesn't match

Actual RRT props don't match ones described in API documentation.

        var _item$key = item.key,
            key = _item$key === undefined ? index : _item$key,
            title = item.title,
            content = item.content,
            getContent = item.getContent,
            disabled = item.disabled,
            tabClassName = item.tabClassName,
            panelClassName = item.panelClassName;

Where:

`wrapperClass` - doesn't apply
`tabClass` actually is `tabClassName`
`panelClass` actually is `panelClassName`

Center align tabs

Is there a way to configure tabs to be center aligned? Spreading out from the middle?

Issue rendering basic tabs

I am getting the following error:

Exception thrown by hook while handling onSetChildren: Invariant Violation: Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().

Here is the code:

import React, { Component } from 'react';
import Tabs from 'react-responsive-tabs';

import 'react-responsive-tabs/styles.css';

class WWNG_Sales_MemberTabs extends Component {
    constructor(props) {
        super(props)
        this.state = {
            memberNumber: "",
            items: [],
        }
    }

    componentWillReceiveProps(props) {
        this.setState({ memberNumber: props.memberNumber }, () => {
            this.getItems()
        })
    }

    getItems() {
        var items = []
        items.push({ title: "Usage", getContent: () => "Usage", key: 0, tabClassName: "tab", panelClassName: "panel" })
        items.push({ title: "Transactions", getContent: () => "Transactions", key: 1, tabClassName: "tab", panelClassName: "panel" })
        items.push({ title: "Correspondence", getContent: () => "Correspondence", key: 2, tabClassName: "tab", panelClassName: "panel" })
        items.push({ title: "History", getContent: () => "History", key: 3, tabClassName: "tab", panelClassName: "panel" })
        items.push({ title: "Card Printing", getContent: () => "Card Printing", key: 4, tabClassName: "tab", panelClassName: "panel" })

        this.setState({ items: items })
    }

    render() {
        return (
            <div>
                <Tabs items={this.state.items} />
            </div>
        );
    }
}

export default WWNG_Sales_MemberTabs;

Debugging code is on npm?

I've installed this component via npm and am seeing some strange behaviour that I don't quite understand.

On running this the first time, the debugger kicked in... which was strange. I've opened up the react-responsive-tabs folder in node_moduels and in lib/index.js, there's numerous console.log statements and even a debugger line.

Screen Shot 2021-07-07 at 9 38 37 AM

When viewing the source code here on Github, those lines don't exist.

Did some debugging code accidentally make it on npm?

I thought I was seeing things, so did a rm -rf node_modules && npm install again... and sure enough, those items are still there.

allowRemove is rendering "X" underneath tab titles

I've built a custom remove function but I would prefer to use the native allowRemove function. It is rendering the exit button "X" underneath the tab titles.

render() {
return (
<Tabs
allowRemove={true}
items={this.getTabs()}
tabsWrapperClass={"subTabs"}
onChange={this.props.onSubTabChange}
/>
);
}
getTabs = () => {
return this.state.subTabs.map((subTab, index) => ({
title: subTab.name,
getContent: () => subTab.tabContent,
/* Optional parameters */
key: index,
tabClassName: "tab",
panelClassName: "panel"
}));
};

.subTabs {
width: 314px;
margin-right: auto;
margin-left: auto;
display: flex;
}

Thank you in advance!

An Option To Prevent Tab From Changing

Is it possible to display a confirm prompt when another tab is clicked before it switches? Like let's say when you have an unsaved work on the page and you would like to prevent tab navigation, so that the user can choose to stay or leave the page.
Or else how can I disable tab navigation? Such that it remains on one tab and the other tabs are disabled.

"Show More" menu doesn't appear with tabs

Hey there, this plugin is extremely nice and well done :)

The only problem I'm having is that when the number of tabs exceeds the width of the panel container, it does not show the "..." for showing more, it just keeps breaking down into multiple rows. I even tried putting your raw example into my project and it still won't show the "..." Any clue what might be the cause? Here are the relevant versions of the modules being used:

"react": "15.0.1",
"react-dom": "15.0.1",

tabs

Possible improvements

Hi!

Great effort at making this component however I have a few improvements which would be super additions in my opinion:

-> Have item as a child like so

<Tabs>
	<Item title='item 1'>
		{/* content goes here */}
	</Item>

	<Item title='item 2'>
		{/* content goes here */}
	</Item>
</Tabs>

-> Fix issue for older browsers
I see that you are using flex but this is not widely supported and not so good if you have an application which needs to support older browsers. See caniuse. IE support still required in many cases -_-

Cannot read property 'offsetWidth' of undefined

Hello, the release of the newest version (1.1.2) seems to have a bug. I get this error after updating:

index.js:65 Uncaught TypeError: Cannot read property 'offsetWidth' of undefined
    at Object.Tabs._this.onResize (index.js:65)
    at invokeFunc (index.js:160)
    at leadingEdge (index.js:170)
    at Object.debounced [as onResize] (index.js:235)
    at ResizeDetector.componentDidMount (ResizeDetector.js:69)
    at eval (ReactCompositeComponent.js:264)
    at measureLifeCyclePerf (ReactCompositeComponent.js:75)
    at eval (ReactCompositeComponent.js:263)
    at CallbackQueue.notifyAll (CallbackQueue.js:76)
    at ReactReconcileTransaction.close (ReactReconcileTransaction.js:80)

wrapperClass not showing

Where should the wrapperClass appear in the markup?

I have the following code and the tabClass and panelClass are showing up in the markup but the wrapperClass is not. Anything obvious I am doing wrong?

/*Other component stuff... */

return (
    <div className={componentClass}>
        <Tabs 
          wrapperClass={styles.cp_delveWebpart__tabs} // This doesn't work.
          tabClass={styles.cp_delveWebpart__tabItem} // This works.
          panelClass={styles.cp_delveWebpart__tabContent} // This works.
          items={this.loadTabItems()}
          transformWidth={768}
          showInkBar={true}
         />
    </div>
);

Issue with styles

Hi!
Everything is working fine except that tabs are only shown as an accordion. I render Tabs in a modal window - maybe it affects somehow?

my code:

import React from 'react';
import Tabs from 'react-responsive-tabs';

const trfTabs = [{ id: 0, name: 'Смена тарифа', content: '...' }, { id: 1, name: 'Сравнение тарифов', content: '...' }];

function getTabs() {
  return trfTabs.map(tab => ({
    key: tab.id, // - optional
    tabClassName: 'tab', // - optional
    panelClassName: 'panel', // - optional
    title: tab.name,
    transformWidth: 400,
    getContent: () => tab.content,
  }));
}

const ChangeTariffComponent = () => {

  return (
  <div className="change-tariff-wrapper">
    <Tabs items={getTabs()} />
  </div>
  );
};

Hidden tabs and Visible tabs list

@maslianok Is there a way where we can find the visible tabs and hidden tabs at any point of time?
I mean to ask can we know the list of tabs that are visible and the list of tabs that are under the 'show more' dropdown?

And also if a tab is selected from dropdown list can we show the selected tab name instead of '...' ?

Missing dependency?

Thanks for this excellent plugin.

I'm a bit confused I'm trying to import it in my project and I get this error:

ERROR in ./~/react-responsive-tabs/lib/index.js
Module build failed: ReferenceError: Unknown plugin "transform-class-properties" specified in "/Users/me/Development/sites/project/node_modules/react-responsive-tabs/.babelrc" at 0, attempted to resolve relative to "/Users/me/Development/sites/project/node_modules/react-responsive-tabs"

I'm using node 6.9.0 and the associated npm 3.10.8

Do I need to install babel-plugin-transform-class-properties?

Thanks.

Programatically trigger tab change

In a situation where by I have two tabs on a particular page, I want to be able to reload the page and switch back programmatically to the tab that I was on before.

Error on console

Warning: You are manually calling a React.PropTypes validation function for the items prop on Tabs. This is deprecated and will not work in production with the next major version. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details.

Is it possible using the latest version of react function on it?
Thank you!!!

Change show more ... with icon

Thank you for this awesome module.

There is no option for changing the show more dots (...) can we change it with the help of icon?

Disabled Tabs

I've tried modified selected tabs using for example

const handleChangeTab = (value) => {
        if (value < 1) {
            setActiveKey(value);
            return true;
        }

        if (value > 0 && isUpdate) {
            console.log('enter: ', true);

            setActiveKey(value);
        } else {
            setActiveKey(0);
        }
        return false;
    };

but still cannot disabled any selected tab.

is there any method to disabled a tab?

Render all tab content on the page?

For SEO purposes I would like to have all tab content available on the page. That way search engines can index the content.
Browsing through the code this doesn't seem possible right now?

Or am I missing an option?
I was expecting 'content' to always get rendered, while getContent would be rendered only when the tab gets visible?

Request: extract the Tabs component without the panel in separate package

Hello,

Do you think it would be possible to extract only the components for the navigation tabs? I like this functionality ( the responsiveness ) but I don't use the content/getContent part because I handle it with react router.

If it's extracted as separate package, this package can depend on it and use it, but also it could be used without the panels and content.

P.S. If you like this idea, I could help with the extraction.

Optional parameters

Optional parameters are not working, I think I'm doing something wrong, I want to include
"transform width: 500" what do I do?.

const GobalTabs = ({ array }) => { const getTabs = () => { return array.map((content, index) => ({ title: content.title, getContent: () => content.component, transformWidth: 500, key: index, tabClassName: "tab", panelClassName: "panel", })); }; return <Tabs items={getTabs()} />;

Item is object, checking object equality with '===' will not get expected result.

items.every((item, i) => item !== prevProps.items[i])

As the item is object, so use '===' approach to check the equality will get an incorrect result.

More detail could reference: http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html

Or for here, we could jsut check the title changes or not, since the tab width just related to the title.
Such as:

items.every((item, i) => item.title !== prevProps.items[i].title)

Inconsistent Inkbar position/width when the body font family changes.

Steps to reproduce

image

Result:
The inkbar position doesn't match its position and width related to the selected tab after some font update.

image

Expected result:

The inkbar should match its position and width related to the selected tab.

image

This could happen in projects that has a different font family set because the function to set the tabs dimensions is triggered before the browser applies the font updates (so the tabs widths are set as if they had the browswer default font family).

Seems like lazy rendering breaks selectedTabKey

I have the following component:

 <Tabs selectedTabKey={selectedTabKey} items={tabItems} />

Where selectedTabKey = 1 and the tabItems array has 2 elements, with keys 1 and 2. When I render the tabs component, no tabs contents are rendered. I have to click either tab 1 or 2 to trigger rendering of content.

InkBar gets misplaced

if we use the "showMore" feature and the "InkBar". the tabs inside the showMore don't get higlited properly with the inkbar

Local demo fails build

react-responsive-tabs looks awesome, so wanted to try it. Lacking a UMD distribution ventured into NPM land. Trying the local demo an it failed at: eslint -c .eslintrc src

thanks.

npm dependancy issue

Hi, Could you please make it compatible with latest.

npm ERR! node v6.9.5
npm ERR! npm v3.10.10
npm ERR! code ETARGET

npm ERR! notarget No compatible version found: react-responsive-tabs@^1.1.1
npm ERR! notarget Valid install targets:
npm ERR! notarget 1.0.1, 0.9.0, 0.8.1, 0.8.0, 0.7.1, 0.7.0, 0.6.2, 0.6.1, 0.5.6,
0.5.5, 0.5.4, 0.5.3, 0.5.2, 0.5.1, 0.5.0, 0.4.9, 0.4.8, 0.4.7, 0.4.6, 0.4.5, 0.
4.4, 0.4.3, 0.4.2, 0.4.1, 0.4.0, 0.3.3, 0.3.2, 0.3.1, 0.3.0, 0.2.1, 0.2.0, 0.1.2
, 0.1.1, 0.1.0
npm ERR! notarget
npm ERR! notarget This is most likely not a problem with npm itself.
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.
npm ERR! notarget
npm ERR! notarget It was specified as a dependency of 'material'
npm ERR! notarget

Seems linked to earlier issue raised Release version 1.1.0 to NPM

dependencies inconsistence

When I clone the repo and try to install (at OS X), I am running into issue with one of the eslint plugins.

There's also an error caused by missing babel plugin.

Cannot install and run example because of this.

When re-rendering component the tabs are wrapping.

I am using react-responsive-tabs to display categorized results from a search. As the user types I am re-rendering based on the results. There are times as the number of tabs changes the tabs wrap and do not show the "..." more tab. However if I click on a tab that is not active it fixes itself.

makeTabs = (results) => results.map((item, index) => ({
        title: this.getTitle(item),
        getContent: () => this.getTabContent(item),
        /* Optional parameters */
        key: index,
        tabClassName: "category-tab",
        panelClassName: "panel"
    }))
    
    getTabs = () => {
        const tabData = this.state.groupedResults;
        return (<Tabs selectedTabKey="0" tabsWrapperClass="categorized-results" items={this.makeTabs(tabData)} transform={false}/>);
    }

Screen Shot 2020-02-11 at 2 39 25 PM

Then click a tab that isn't active
Screen Shot 2020-02-11 at 2 40 24 PM

Also an maybe it should be a separate issue but the selectedTabKey needs to reset to the passed in prop when the number of tabs change.

On Tabs removal or tabs addition the tabs component are wrapping without showing 'show more' icon

@maslianok @dcworldwide I still face the same issue even on the latest code. Please help resolve it.
I am using the Tabs Removal example. But still face this issue of tabs wrapping to new line below instead of showing the '...' .

onRemoveTab = (key, evt) => {
    evt.stopPropagation();

    // current tabs
    const { items } = this.state;

    // find index to remove
    const indexToRemove = items.findIndex((tab) => tab.key === key);

    // create a new array without [indexToRemove] item
    const newTabs = [
      ...items.slice(0, indexToRemove),
      ...items.slice(indexToRemove + 1),
    ];

    const nextSelectedIndex = newTabs[indexToRemove]
      ? indexToRemove
      : indexToRemove - 1;

    if (!newTabs[nextSelectedIndex]) {
      alert("You can not delete the last tab!");
      return;
    }

      this.setState({
        items: newTabs,
        selectedTabKey: newTabs[nextSelectedIndex].key,
      });
  };

getTabs = () => {
    return dummyData.map((president, index) => ({
      key: index,
      title: president.name,
      getContent: () => president.biography,
      tabClassName: "tab-wrapper",
      tabClassName: "tab",
      panelClassName: "panel",
    }));
  };

<div className="itemRemoval__wrapper" style={{ marginTop: 120 }}>
        <Tabs
          items={this.state.items}
          selectedTabKey={this.state.selectedTabKey}
          allowRemove
          removeActiveOnly
          onRemove={this.onRemoveTab}
          transform={false}
          showMore={true}
          uid={uniqueId()}
        />
 </div>

Screenshot 2021-04-19 at 11 02 22 PM

What changes need to be done or any workaround for this issue?

I am using react: "^17.0.1"
react-responsive-tabs: "^4.4.0"
react-resize-detector: "^6.6.5"

I am testing on MacBook Chrome browser.

Feature Request: Add ability to include anchor tag in tab

This is a feature request that is mainly for the mobile view of this, when the tabs turn to accordions.

I would like to be able to prepend the tab content (title) with an anchor tag so that I can create jump links from a nav menu. Currently I don't see a way to inject a tag in the tab title to achieve this.

Child components are being rendered even when not active

I was testing case with 30 tabs. Each has a non-trivial content (e.g. component with SVG content, connected to Redux store). Manipulation with content of active tab was very slow, because all 30 components are actually live even when they aren't visible. This makes the usage of these tabs for anything but simple text/image somewhat slow. The (original) 'react-tabs' do not have this behavior.

close already opened accordion in mobile

The current implementation shows an accordion in mobile and when an accordion panel is opened, we have to click another accordion item, to close the previously opened item.
I would like to know if there is a way to click on the already opened accordion panel, to close it (kind of a toggle behavior).

Close individual tabs?

Is there a way to close individual tabs from the UI of the component, similar to closing an individual tab in your browser? The docs don't indicate, but I'm wondering if I'm missing it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.