Security News
New Python Packaging Proposal Aims to Solve Phantom Dependency Problem with SBOMs
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
react-tabtab-next
Advanced tools
A mobile support, draggable, editable and api based Tab for ReactJS
(!) This lib based on react-tabtab but refactored using Typescript and replacing some deprecated libs
for build a local playground run
npm run demo
also here Codesandbox playground
styled-components
, super easy to customize tab styleInstall it with npm or yarn
npm install @react-tabtab-next/tabtab --save
Then, import the module by module bundler like webpack
, browserify
// es6
import { Tabs, DragTabList, PanelList, Panel, ExtraButton } from '@react-tabtab-next/tabtab';
// not using es6
var Tabtab = require('react-tabtab');
var Tabs = Tabtab.Tabs;
React-tabtab is a tab component with highly customization. You can create a tab in simply setting. You also can create a tab system full with draggable
, async loading
, close and create button
.
All the actions are api based. It means there is no state
in the component. Developers have full control.
import React from 'react';
import { Tabs, Panel, Tab, TabList, PanelList } from '@react-tabtab-next/tabtab';
export const Example = () => {
return (
<Tabs>
<TabList>
<Tab>Tab1</Tab>
<Tab>Tab2</Tab>
</TabList>
<PanelList>
<Panel>Content1</Panel>
<Panel>Content2</Panel>
</PanelList>
</Tabs>
);
};
It's simple to use. Zero configuration!
import React, { Component } from 'react';
import { Tabs, DragTabList, PanelList, Panel, Tab, helpers } from '@react-tabtab-next/tabtab';
const makeData = (number, titlePrefix = 'Tab') => {
const data = [];
for (let i = 0; i < number; i++) {
data.push({
title: `${titlePrefix} ${i}`,
content: <div>Content {i}</div>,
});
}
return data;
};
export default class Drag extends Component {
constructor(props) {
super(props);
this.handleTabChange = this.handleTabChange.bind(this);
this.handleTabSequenceChange = this.handleTabSequenceChange.bind(this);
const tabs = makeData(10, 'Some Tab');
this.state = {
activeIndex: 0,
tabs,
};
}
handleTabChange(index) {
this.setState({ activeIndex: index });
}
handleTabSequenceChange({ oldIndex, newIndex }) {
const { tabs } = this.state;
const updateTabs = helpers.simpleSwitch(tabs, oldIndex, newIndex);
this.setState({ tabs: updateTabs, activeIndex: newIndex });
}
render() {
const { tabs, activeIndex } = this.state;
const tabsTemplate = [];
const panelTemplate = [];
tabs.forEach((tab, index) => {
tabsTemplate.push(<Tab key={index}>{tab.title}</Tab>);
panelTemplate.push(<Panel key={index}>{tab.content}</Panel>);
});
return (
<Tabs
activeIndex={activeIndex}
onTabChange={this.handleTabChange}
onTabSequenceChange={this.handleTabSequenceChange}
customStyle={this.props.customStyle}
>
<DragTabList>{tabsTemplate}</DragTabList>
<PanelList>{panelTemplate}</PanelList>
</Tabs>
);
}
}
ReactDOM.render(<Drag />, document.getElementById('root'));
Based on above example, the different to implement normal tab
or drag tab
is using different wrapper and child.
And all the actions are controllable. You can customize your switch action. But if you don't want to write customized switch logic, you can directly use import {simpleSwitch} from 'react-tabtab/lib/helpers/move'
this built-in function.
<Tabs>
<TabList>
<Tab>Tab1</Tab>
<Tab>Tab2</Tab>
</TabList>
<PanelList>
<Panel>Content1</Panel>
<Panel>Content2</Panel>
</PanelList>
</Tabs>
<Tabs
// customStyle={md}
// activeIndex={activeTab}
// onTabChange={handleOnTabChange}
// onTabSequenceChange={handleOnTabSequenceChange}
ExtraButton={
<ExtraButton
onClick={(e) => {
console.log(e);
}}
>
+
</ExtraButton>
}
>
<DragTabList>
<Tab>Tab1</Tab>
<Tab>Tab2</Tab>
</DragTabList>
<PanelList>
<Panel>Content1</Panel>
<Panel>Content2</Panel>
</PanelList>
</Tabs>
In some case, if the data is large or we want to save the bandwidth, lazy loading the content is possible solution. You can use AsyncPanel
to laze load panel content.
Moreover, you can mix lazy load panel with normal panel!
import React from 'react';
import { Tabs, Panel, Tab, TabList, PanelList, AsyncPanel } from '@react-tabtab-next/tabtab';
const AsyncTabsExmple = () => {
const loadContentFunc = (callback) => {
setTimeout(() => {
callback(null, 'some content');
}, 1000);
};
return (
<Tabs>
<TabList>
<Tab>Tab1</Tab>
<Tab>Tab2</Tab>
</TabList>
<PanelList>
<Panel>Content1</Panel>
<AsyncPanel
loadContent={loadContentFunc}
render={(data) => <div>{JSON.stringify(data)}</div>}
renderLoading={() => <div>Loading...</div>}
cache={true}
/>
</PanelList>
</Tabs>
);
};
export default AsyncTabsExmple;
To implement lazy loading, use AsyncPanel
to wrap your panel content. Remember to provide loadContent
, render
, renderLoading
these 3 props.
In loadContent
props, both callback
and promise
type are supported.
If you use callback
, remember to call callback
when finish async loading.
If you use promise
, need to return promise action.
When data is loading, the panel content will show renderLoading
component.
After finishing loading data, the panel content will show render
component and react-tabtab will pass the loadContent
result as first parameter. So you can customize the component of panel content.
More code examples are avalable here.
<Tabs/>
is the main component of react-tabtab
. Most of the api is passed from it.
props | type | default | |
---|---|---|---|
activeIndex | number | null | control current activeIndex. You need to pass new activeIndex value if you want to show different tab. |
defaultIndex | number | 0 | default selected index if active index is not provided |
showModalButton | boolean number | 4 |
|
showArrowButton | auto boolean | auto |
|
ExtraButton | React Node | null | customize extra button content, example: `+` button |
onTabChange | (tabIndex) => {} | null |
return tabIndex is clicked You can use this api with activeIndex . When user click tab, update activeIndex .
|
onTabSequenceChange | (oldIndex, newIndex) => {} | null |
return changed oldIndex and newIndex value With this api, you can do switch tab very easily. Note:This api is only called by <DragTabList/>
|
onTabClose | (index) => {} | null | When user click close button , this api will return the clicked close button index. |
customStyle |
| theme | customized tab style component |
Use to wrap <Tab/>
.
Use to wrap <Tab/>
.
Normal Tab. Show the children component on tab.
props | type | default | |
---|---|---|---|
closable | boolean | false | whether to show close button |
Example
<Tab>
<i className="fa fa-map-pin"></i>
map tab
</Tab>
Use to wrap <Panel/>
Tab content.
Lazy loading panel content.
props | type | default | |
---|---|---|---|
loadContent * |
(cb) => cb(error, data) or (cb) => Promise
| null | when loadContent finish, call the callback or you can return promise |
render * |
(data) => Component
| null | when finish loading data, render this component |
renderLoading * |
() => Component
| null | when it is loading data, render this component |
cache |
boolean
| true | should cache the data |
react-tabtab-next
is based on styled-components
. Therefore, it's super easy to customize the tab style.
Just extend the default component style and pass it to customStyle
props.
Install tabtab themes
npm install @react-tabtab-next/themes --save
Available themes: md
, bootstrap
, bulma
For example, if you want to use material-design
, import the style and pass to customStyle
props.
Example:
import React, { Component } from 'react';
import { Tabs, TabList, Tab, PanelList, Panel } from '@react-tabtab-next/tabtab';
import { md } from '@react-tabtab-next/themes';
export default class Customized extends Component {
render() {
return (
<Tabs customStyle={md}>
<TabList>
<Tab>Tab1</Tab>
<Tab>Tab2</Tab>
</TabList>
<PanelList>
<Panel>Content1</Panel>
<Panel>Content2</Panel>
</PanelList>
</Tabs>
);
}
}
And now your tab is material design style!
If current theme doesn't meet your demand, follow this three steps and create a new one.
import styled from 'styled-components';
import { styled as styledTabTab } from '@react-tabtab-next/tabtab';
let { TabListStyle, ActionButtonStyle, TabStyle, PanelStyle } = styledTabTab;
import styled from 'styled-components';
import { styled as themeStyled } from '@react-tabtab-next/tabtab';
let { TabList, ActionButton, Tab, Panel } = themeStyled;
TabList = styled(TabList)`
background-color: transparent;
line-height: 1.2;
border: 0;
`;
Tab = styled(Tab)`
padding: 1px 10px;
position: relative;
font-size: 12px;
text-transform: uppercase;
border: 0;
background: transparent;
${(props) => {
return props.active && !props.vertical
? `
border-bottom: 2px solid #ce93d8;
`
: null;
}}
&:hover .tab-label_close-button {
opacity: 1;
}
&:hover {
color: unset;
background: #89898920;
}
`;
ActionButton = styled(ActionButton)`
background-color: transparent;
border-radius: 0;
border: none;
opacity: 0.3;
transition: opacity 0.2s;
& svg {
font-size: 21px;
padding: 0;
}
&:hover {
opacity: 1;
}
`;
Panel = styled(Panel)``;
export { TabList, ActionButton, Tab, Panel };
When you finish the new @react-tabtab-next/theme
style, feel free to add it to theme/
folder and send PR!
npm i
npm run demo
or
yarn install
yarn demo
Build the bundle
npm i
MIT
FAQs
A mobile support, draggable, editable and api based Tab for ReactJS
We found that react-tabtab-next demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
Security News
Socket CEO Feross Aboukhadijeh discusses open source security challenges, including zero-day attacks and supply chain risks, on the Cyber Security Council podcast.
Security News
Research
Socket researchers uncover how threat actors weaponize Out-of-Band Application Security Testing (OAST) techniques across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.