diff --git a/components/TabbedView/TabbedView.jsx b/components/TabbedView/TabbedView.jsx
index f44440944..520d4ce86 100644
--- a/components/TabbedView/TabbedView.jsx
+++ b/components/TabbedView/TabbedView.jsx
@@ -1,4 +1,4 @@
-import { Component, Children } from 'react';
+import { useState, useEffect, Children } from 'react';
import PropTypes from 'prop-types';
import styled, { css } from 'styled-components';
import {
@@ -159,86 +159,88 @@ const TabPanel = styled.div`
const RenderIf = ({ conditional, children }) => conditional && children;
-class TabbedView extends Component {
- static Tab = Tab;
-
- constructor(props) {
- super(props);
-
- const { children, activeTab } = props;
+function TabbedView({
+ children,
+ activeTab = undefined,
+ skin = 'neutral',
+ theme = {
+ components,
+ baseFontSize: defaultBaseFontSize,
+ breakpoints: defaultBreakpoints,
+ spacing: defaultSpacing,
+ },
+ fluid = false,
+ onTabClick = () => {},
+}) {
+ const [currentTab, setCurrentTab] = useState(activeTab);
+ const tabTitles = Children.toArray(children).map((tab) => tab.props.title);
+ function setDefaultTab() {
+ setCurrentTab(tabTitles[0]);
+ }
- if (activeTab) {
- this.state = { activeTab };
+ useEffect(() => {
+ if (tabTitles.includes(activeTab)) {
+ setCurrentTab(activeTab);
} else {
- const [
- {
- props: { title },
- },
- ] = Children.toArray(children);
- this.state = { activeTab: title };
+ setDefaultTab();
}
- }
+ }, [activeTab]);
- onTabClick = (tab, onTabClick) => {
- this.setState({ activeTab: tab });
+ const handleTabClick = (tab) => {
+ setCurrentTab(tab);
onTabClick(tab);
};
- sanitize = (str) =>
+ const sanitize = (str) =>
str
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(' ', '-')
.toLowerCase();
- render() {
- const { children, skin, theme, fluid, onTabClick } = this.props;
- const { activeTab } = this.state;
-
- return (
- <>
-
- {Children.map(children, ({ props: { title, badge, icon } }) => (
- this.onTabClick(title, onTabClick)}
- skin={skin}
- theme={theme}
- id={`${this.sanitize(title)}-tab`}
- aria-controls={`${this.sanitize(title)}-panel`}
- aria-selected={title === activeTab}
- >
- {icon && {icon}}
- {title && {title}}
- {badge && {badge}}
-
- ))}
-
-
- {Children.map(
- children,
- ({ props: { title, children: tabContent } }) => (
-
-
- {tabContent}
-
-
- ),
- )}
- >
- );
- }
+ const quantityOfItems = Children.count(children);
+
+ return (
+ <>
+
+ {Children.map(children, ({ props: { title, badge, icon } }) => (
+ handleTabClick(title)}
+ skin={skin}
+ theme={theme}
+ id={`${sanitize(title)}-tab`}
+ aria-controls={`${sanitize(title)}-panel`}
+ aria-selected={title === currentTab}
+ >
+ {icon && {icon}}
+ {title && {title}}
+ {badge && {badge}}
+
+ ))}
+
+
+ {Children.map(children, ({ props: { title, children: tabContent } }) => (
+
+
+ {tabContent}
+
+
+ ))}
+ >
+ );
}
+TabbedView.Tab = Tab;
+
TabbedView.propTypes = {
- /** Used to expand all tabs along all the parent width */
fluid: PropTypes.bool,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
@@ -257,19 +259,6 @@ TabbedView.propTypes = {
onTabClick: PropTypes.func,
};
-TabbedView.defaultProps = {
- fluid: false,
- activeTab: undefined,
- skin: 'neutral',
- theme: {
- components,
- baseFontSize: defaultBaseFontSize,
- breakpoints: defaultBreakpoints,
- spacing: defaultSpacing,
- },
- onTabClick: () => {},
-};
-
TabbedView.displayName = 'TabbedView';
export default TabbedView;
diff --git a/components/TabbedView/TabbedView.unit.test.jsx b/components/TabbedView/TabbedView.unit.test.jsx
index c1d4b72d2..6febaeec2 100644
--- a/components/TabbedView/TabbedView.unit.test.jsx
+++ b/components/TabbedView/TabbedView.unit.test.jsx
@@ -117,6 +117,50 @@ describe(' ', () => {
render(Candidates content);
expect(screen.getByText('Candidates content')).toBeInTheDocument();
});
+ it('should be able to change active tab when activeTab props change', () => {
+ const { rerender } = render(
+
+ Candidatos content
+ Empresas content
+ Educação content
+ ,
+ );
+ expect(screen.queryByText('Candidatos content')).not.toBeInTheDocument();
+ expect(screen.getByText('Empresas content')).toBeInTheDocument();
+ expect(screen.queryByText('Educação content')).not.toBeInTheDocument();
+ rerender(
+
+ Candidatos content
+ Empresas content
+ Educação content
+ ,
+ );
+ expect(screen.getByText('Candidatos content')).toBeInTheDocument();
+ expect(screen.queryByText('Empresas content')).not.toBeInTheDocument();
+ expect(screen.queryByText('Educação content')).not.toBeInTheDocument();
+ });
+ it('should not be able to change the active tab when active tab props change to a invalid tab', () => {
+ const { rerender } = render(
+
+ Candidatos content
+ Empresas content
+ Educação content
+ ,
+ );
+ expect(screen.queryByText('Candidatos content')).not.toBeInTheDocument();
+ expect(screen.getByText('Empresas content')).toBeInTheDocument();
+ expect(screen.queryByText('Educação content')).not.toBeInTheDocument();
+ rerender(
+
+ Candidatos content
+ Empresas content
+ Educação content
+ ,
+ );
+ expect(screen.getByText('Candidatos content')).toBeInTheDocument();
+ expect(screen.queryByText('Empresas content')).not.toBeInTheDocument();
+ expect(screen.queryByText('Educação content')).not.toBeInTheDocument();
+ });
});
describe('events', () => {