Skip to content

Instantly share code, notes, and snippets.

@devAsadNur
Created March 17, 2025 07:10
Show Gist options
  • Save devAsadNur/a35a0718b81215f0401e6d60a4cb4e97 to your computer and use it in GitHub Desktop.
Save devAsadNur/a35a0718b81215f0401e6d60a4cb4e97 to your computer and use it in GitHub Desktop.
React tabs based on tailwind component
import { useState, Children, cloneElement } from '@wordpress/element';
const Tabs = ( { tabs, children } ) => {
const [ activeTab, setActiveTab ] = useState( tabs[ 0 ]?.id || '' );
return (
<div>
{ /* Mobile Select Dropdown */ }
<div className="grid grid-cols-1 sm:hidden">
<select
value={ activeTab }
onChange={ ( e ) => setActiveTab( e.target.value ) }
aria-label="Select a tab"
className="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white py-2 pl-3 pr-8 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 focus:outline focus:outline-2 focus:-outline-offset-2 focus:text-primary-500"
>
{ tabs.map( ( tab ) => (
<option key={ tab.id } value={ tab.id }>
{ tab.name }
</option>
) ) }
</select>
</div>
{ /* Desktop Tabs */ }
<div className="hidden sm:block">
<div className="border-b border-solid">
<nav aria-label="Tabs" className="-mb-px flex space-x-8">
{ tabs.map( ( tab ) => (
<span
key={ tab.id }
onClick={ () => setActiveTab( tab.id ) }
className={ `whitespace-nowrap border-b-2 px-1 py-4 text-sm font-medium cursor-pointer ${
activeTab === tab.id
? 'text-dokan-btn-tertiary border-dokan-btn'
: 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'
}` }
>
{ tab.name }
</span>
) ) }
</nav>
</div>
</div>
{ /* Tab Content (Passed as Children) */ }
<div className="mt-4">
{ Children.map( children, ( child, index ) =>
cloneElement( child, {
className: `${ child.props.className || '' } ${
activeTab === tabs[ index ]?.id ? 'block' : 'hidden'
}`,
} )
) }
</div>
</div>
);
};
export default Tabs;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment