| @@ -25,8 +25,49 @@ | ||
| 25 | 25 | |
| 26 | 26 | return tabs[0] |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | +interface SubnavTabItemProps<Tab extends SubnavTab<string>> { | |
| 30 | + tab: Tab | |
| 31 | + currentTab: Tab | |
| 32 | + getTabCount?: (tab: Tab) => number | undefined | |
| 33 | + setCurrentTab: (tab: Tab) => void | |
| 34 | + queryParamName?: string | |
| 35 | +} | |
| 36 | + | |
| 37 | +const SubnavTabItem = <Tab extends SubnavTab<string>>({ | |
| 38 | + tab, | |
| 39 | + currentTab, | |
| 40 | + getTabCount, | |
| 41 | + setCurrentTab, | |
| 42 | + queryParamName | |
| 43 | +}: SubnavTabItemProps<Tab>) => { | |
| 44 | + const count = getTabCount?.(tab) | |
| 45 | + | |
| 46 | + return ( | |
| 47 | + <li> | |
| 48 | + <button | |
| 49 | + type="button" | |
| 50 | + className={classnames('snippet-type-link', `${tab.name}-subnav-link`, { | |
| 51 | + 'active-type': tab.name === currentTab.name | |
| 52 | + })} | |
| 53 | + aria-current={tab.name === currentTab.name ? 'page' : undefined} | |
| 54 | + onClick={() => { | |
| 55 | + setCurrentTab(tab) | |
| 56 | + | |
| 57 | + if (queryParamName) { | |
| 58 | + updateQueryParams({ [queryParamName]: tab.name }) | |
| 59 | + } | |
| 60 | + }} | |
| 61 | + > | |
| 62 | + <span>{tab.label}</span> | |
| 63 | + {count !== undefined && <span className="subnav-count">{count}</span>} | |
| 64 | + {tab.pro && !isLicensed() && <span className="pro-chip">{__('Pro', 'code-snippets')}</span>} | |
| 65 | + </button> | |
| 66 | + </li> | |
| 67 | + ) | |
| 68 | +} | |
| 69 | + | |
| 29 | 70 | export interface SubnavTabsProps<Tab extends SubnavTab<string>> { |
| 30 | 71 | tabs: readonly Tab[] |
| 31 | 72 | ariaLabel: string |
| 32 | 73 | className?: string |
| @@ -42,9 +83,9 @@ | ||
| 42 | 83 | className, |
| 43 | 84 | currentTab, |
| 44 | 85 | getTabCount, |
| 45 | 86 | setCurrentTab, |
| 46 | - queryParamName, | |
| 87 | + queryParamName | |
| 47 | 88 | }: SubnavTabsProps<Tab>) => { |
| 48 | 89 | const { atStart, atEnd, scrollRef } = useHorizontalScrollOverflow() |
| 49 | 90 | |
| 50 | 91 | return ( |
| @@ -55,34 +96,17 @@ | ||
| 55 | 96 | })} |
| 56 | 97 | > |
| 57 | 98 | <nav ref={scrollRef} className={classnames('snippet-type-nav', className)} aria-label={ariaLabel}> |
| 58 | 99 | <ul> |
| 59 | - {tabs.map(tab => { | |
| 60 | - const count = getTabCount?.(tab) | |
| 61 | - | |
| 62 | - return ( | |
| 63 | - <li key={tab.name}> | |
| 64 | - <button | |
| 65 | - type="button" | |
| 66 | - className={classnames('snippet-type-link', `${tab.name}-subnav-link`, { | |
| 67 | - 'active-type': tab.name === currentTab.name | |
| 68 | - })} | |
| 69 | - aria-current={tab.name === currentTab.name ? 'page' : undefined} | |
| 70 | - onClick={() => { | |
| 71 | - setCurrentTab(tab) | |
| 72 | - | |
| 73 | - if (queryParamName) { | |
| 74 | - updateQueryParams({ [queryParamName]: tab.name }) | |
| 75 | - } | |
| 76 | - }} | |
| 77 | - > | |
| 78 | - <span>{tab.label}</span> | |
| 79 | - {count && <span className="subnav-count">{count}</span>} | |
| 80 | - {tab.pro && !isLicensed() && <span className="pro-chip">{__('Pro', 'code-snippets')}</span>} | |
| 81 | - </button> | |
| 82 | - </li> | |
| 83 | - ) | |
| 84 | - })} | |
| 100 | + {tabs.map(tab => | |
| 101 | + <SubnavTabItem | |
| 102 | + key={tab.name} | |
| 103 | + tab={tab} | |
| 104 | + currentTab={currentTab} | |
| 105 | + getTabCount={getTabCount} | |
| 106 | + setCurrentTab={setCurrentTab} | |
| 107 | + queryParamName={queryParamName} | |
| 108 | + />)} | |
| 85 | 109 | </ul> |
| 86 | 110 | </nav> |
| 87 | 111 | </div> |
| 88 | 112 | ) |