@@ -5,12 +5,50 @@ import styled from 'styled-components';
55
66const StyledTabs = styled . div `
77 position: relative;
8- left: 8px;
8+ ${ ( { isMultiRow, theme } ) =>
9+ isMultiRow &&
10+ `
11+ button {
12+ flex-grow: 1;
13+ }
14+ button:last-child:before {
15+ border-right: 2px solid ${ theme . borderDark } ;
16+ }
17+ ` }
18+ ` ;
19+
20+ const Row = styled . div . attrs ( ( ) => ( {
21+ 'data-testid' : 'tab-row'
22+ } ) ) `
23+ position: relative;
24+ display: flex;
25+ flex-wrap: no-wrap;
926 text-align: left;
27+ left: 8px;
28+ width: calc(100% - 8px);
29+
30+ &:not(:first-child):before {
31+ content: '';
32+ position: absolute;
33+ right: 0;
34+ left: 0;
35+ height: 100%;
36+ border-right: 2px solid ${ ( { theme } ) => theme . borderDarkest } ;
37+ border-left: 2px solid ${ ( { theme } ) => theme . borderLightest } ;
38+ }
1039` ;
1140
41+ function splitToChunks ( array , parts ) {
42+ const result = [ ] ;
43+ for ( let i = parts ; i > 0 ; i -= 1 ) {
44+ result . push ( array . splice ( 0 , Math . ceil ( array . length / i ) ) ) ;
45+ }
46+ return result ;
47+ }
48+
1249const Tabs = React . forwardRef ( function Tabs ( props , ref ) {
13- const { value, onChange, children, ...otherProps } = props ;
50+ const { value, onChange, children, rows, ...otherProps } = props ;
51+
1452 const childrenWithProps = React . Children . map ( children , child => {
1553 if ( ! React . isValidElement ( child ) ) {
1654 return null ;
@@ -21,22 +59,39 @@ const Tabs = React.forwardRef(function Tabs(props, ref) {
2159 } ;
2260 return React . cloneElement ( child , tabProps ) ;
2361 } ) ;
62+
63+ // split tabs into equal rows and assign key to each row
64+ const tabRows = splitToChunks ( childrenWithProps , rows ) . map ( ( tabs , i ) => ( {
65+ key : i ,
66+ tabs
67+ } ) ) ;
68+
69+ // move row containing currently selected tab to the bottom
70+ const currentlySelectedRowIndex = tabRows . findIndex ( tabRow =>
71+ tabRow . tabs . some ( tab => tab . props . selected )
72+ ) ;
73+ tabRows . push ( tabRows . splice ( currentlySelectedRowIndex , 1 ) [ 0 ] ) ;
74+
2475 return (
25- < StyledTabs { ...otherProps } role = 'tablist' ref = { ref } >
26- { childrenWithProps }
76+ < StyledTabs { ...otherProps } isMultiRow = { rows > 1 } role = 'tablist' ref = { ref } >
77+ { tabRows . map ( row => (
78+ < Row key = { row . key } > { row . tabs } </ Row >
79+ ) ) }
2780 </ StyledTabs >
2881 ) ;
2982} ) ;
3083
3184Tabs . defaultProps = {
3285 onChange : ( ) => { } ,
33- children : null
86+ children : null ,
87+ rows : 1
3488} ;
3589
3690Tabs . propTypes = {
3791 // eslint-disable-next-line react/require-default-props, react/forbid-prop-types
3892 value : propTypes . any ,
3993 onChange : propTypes . func ,
40- children : propTypes . node
94+ children : propTypes . node ,
95+ rows : propTypes . number
4196} ;
4297export default Tabs ;
0 commit comments