Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
add tabs component
Browse files Browse the repository at this point in the history
  • Loading branch information
nerrad committed Dec 15, 2019
1 parent f2bc708 commit b7150de
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 0 deletions.
108 changes: 108 additions & 0 deletions assets/js/base/components/tabs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* External dependencies
*/
import { useState, useEffect } from '@wordpress/element';
import { find, partial } from 'lodash';
import { withInstanceId } from '@wordpress/compose';
import classnames from 'classnames';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import './style.scss';

const TabButton = ( {
tabId,
onClick,
children,
selected,
ariaLabel,
...rest
} ) => {
return (
<button
role="tab"
type="button"
tabIndex={ selected ? null : -1 }
aria-selected={ selected }
aria-label={ ! ariaLabel ? null : ariaLabel }
id={ tabId }
onClick={ onClick }
{ ...rest }
>
<span className="wc-component__tab-item-content">{ children }</span>
</button>
);
};

const Tabs = ( {
className,
onSelect = () => null,
tabs,
activeClass = 'is-active',
initialTabName,
instanceId,
ariaLabel = __( 'Tabbed Content', 'woo-gutenberg-products-block' ),
children,
} ) => {
const [ selected, setSelected ] = useState( '' );
useEffect( () => {
if ( ! selected ) {
setSelected(
initialTabName || ( tabs.length > 0 ? tabs[ 0 ].name : null )
);
}
}, [ initialTabName, tabs ] );
if ( ! selected ) {
return null;
}
const handleClick = ( tabKey ) => {
setSelected( tabKey );
onSelect( tabKey );
};
const selectedTab = find( tabs, { name: selected } );
const selectedId = `${ instanceId }-${ selectedTab.name }`;
return (
<div className={ classnames( 'wc-component__tabs', className ) }>
<div
role="tablist"
aria-label={ ariaLabel }
className="wc-component__tab-list"
>
{ tabs.map( ( tab ) => (
<TabButton
className={ classnames(
'wc-component__tab-item',
tab.className,
{
[ activeClass ]: tab.name === selected,
}
) }
tabId={ `${ instanceId }-${ tab.name }` }
aria-controls={ `${ instanceId }-${ tab.name }-view` }
selected={ tab.name === selected }
key={ tab.name }
ariaLabel={ tab.ariaLabel || null }
onClick={ partial( handleClick, tab.name ) }
>
{ tab.title() }
</TabButton>
) ) }
</div>
{ selectedTab && (
<div
aria-labelledby={ selectedId }
role="tabpanel"
id={ `${ selectedId }-view` }
className="wc-component__tab-content"
tabIndex="0"
>
{ children( selected ) }
</div>
) }
</div>
);
};

export default withInstanceId( Tabs );
35 changes: 35 additions & 0 deletions assets/js/base/components/tabs/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.wc-component__tabs {
.wc-component__tab-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
> .wc-component__tab-item {
border: none;
flex: auto;
background: transparent;
padding: $gap-small $gap;
color: $black;
outline-offset: -1px;
transition: box-shadow 0.1s linear;
&.is-active {
box-shadow: inset 0 -3px $black;
font-weight: 600;
position: relative;
}
&:focus {
color: $black;
outline-offset: -1px;
outline: 1px dotted $gray-60;
}
.wc-component__tab-item-content {
width: fit-content;
display: block;
margin: auto;
}
}
}
.wc-component__tab-content {
padding: $gap;
}
}

0 comments on commit b7150de

Please sign in to comment.