# code-snippets/4.0.0-beta.2/js/components/common/SubnavTabs.tsx

Code Snippets, version 4.0.0-beta.2. 114 lines.

- Page: https://pluginprobe.com/plugins/code-snippets/4.0.0-beta.2/code/js/components/common/SubnavTabs.tsx
- Raw: https://pluginprobe.com/plugins/code-snippets/4.0.0-beta.2/raw/js/components/common/SubnavTabs.tsx
- Modified: 2026-09-22T07:44:40+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/code-snippets/4.0.0-beta.2/code/js/components/common/SubnavTabs.tsx#L10-L20`.

```tsx
import classnames from 'classnames'
import { __ } from '@wordpress/i18n'
import React from 'react'
import { isLicensed } from '../../utils/screen'
import { useHorizontalScrollOverflow } from '../../hooks/useHorizontalScrollOverflow'
import { fetchQueryParam, updateQueryParams } from '../../utils/urls'

export interface SubnavTab<T extends string> {
	name: T
	label: string
	pro?: boolean
}

export const getTabFromQuery = <Tab extends SubnavTab<string>>(
	tabs: Tab[],
	queryParamName: string
): Tab => {
	const tabParam = fetchQueryParam(queryParamName)

	for (const tab of tabs) {
		if (tab.name === tabParam) {
			return tab
		}
	}

	return tabs[0]
}

interface SubnavTabItemProps<Tab extends SubnavTab<string>> {
	tab: Tab
	currentTab: Tab
	getTabCount?: (tab: Tab) => number | undefined
	setCurrentTab: (tab: Tab) => void
	queryParamName?: string
}

const SubnavTabItem = <Tab extends SubnavTab<string>>({
	tab,
	currentTab,
	getTabCount,
	setCurrentTab,
	queryParamName
}: SubnavTabItemProps<Tab>) => {
	const count = getTabCount?.(tab)

	return (
		<li>
			<button
				type="button"
				className={classnames('snippet-type-link', `${tab.name}-subnav-link`, {
					'active-type': tab.name === currentTab.name
				})}
				aria-current={tab.name === currentTab.name ? 'page' : undefined}
				onClick={() => {
					setCurrentTab(tab)

					if (queryParamName) {
						updateQueryParams({ [queryParamName]: tab.name })
					}
				}}
			>
				<span>{tab.label}</span>
				{count !== undefined && <span className="subnav-count">{count}</span>}
				{tab.pro && !isLicensed() && <span className="pro-chip">{__('Pro', 'code-snippets')}</span>}
			</button>
		</li>
	)
}

export interface SubnavTabsProps<Tab extends SubnavTab<string>> {
	tabs: readonly Tab[]
	ariaLabel: string
	className?: string
	currentTab: Tab
	getTabCount?: (tab: Tab) => number | undefined
	setCurrentTab: (tab: Tab) => void
	queryParamName?: string
}

export const SubnavTabs = <Tab extends SubnavTab<string>>({
	tabs,
	ariaLabel,
	className,
	currentTab,
	getTabCount,
	setCurrentTab,
	queryParamName
}: SubnavTabsProps<Tab>) => {
	const { atStart, atEnd, scrollRef } = useHorizontalScrollOverflow()

	return (
		<div
			className={classnames('snippet-type-nav-wrapper', {
				'has-scroll-start': !atStart,
				'has-scroll-end': !atEnd
			})}
		>
			<nav ref={scrollRef} className={classnames('snippet-type-nav', className)} aria-label={ariaLabel}>
				<ul>
					{tabs.map(tab =>
						<SubnavTabItem
							key={tab.name}
							tab={tab}
							currentTab={currentTab}
							getTabCount={getTabCount}
							setCurrentTab={setCurrentTab}
							queryParamName={queryParamName}
						/>)}
				</ul>
			</nav>
		</div>
	)
}

```
