PluginProbe
Code Snippets / 4.0.0-beta.2
Code Snippets v4.0.0-beta.2
4.0.0-beta.2 3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 All 65 releases
code-snippets / js / components / common / SubnavTabs.tsx

SubnavTabs.tsx in Code Snippets 4.0.0-beta.2, at js/components/common/SubnavTabs.tsx

114 lines 2.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import classnames from 'classnames'
2 import { __ } from '@wordpress/i18n'
3 import React from 'react'
4 import { isLicensed } from '../../utils/screen'
5 import { useHorizontalScrollOverflow } from '../../hooks/useHorizontalScrollOverflow'
6 import { fetchQueryParam, updateQueryParams } from '../../utils/urls'
7
8 export interface SubnavTab<T extends string> {
9 name: T
10 label: string
11 pro?: boolean
12 }
13
14 export const getTabFromQuery = <Tab extends SubnavTab<string>>(
15 tabs: Tab[],
16 queryParamName: string
17 ): Tab => {
18 const tabParam = fetchQueryParam(queryParamName)
19
20 for (const tab of tabs) {
21 if (tab.name === tabParam) {
22 return tab
23 }
24 }
25
26 return tabs[0]
27 }
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
70 export interface SubnavTabsProps<Tab extends SubnavTab<string>> {
71 tabs: readonly Tab[]
72 ariaLabel: string
73 className?: string
74 currentTab: Tab
75 getTabCount?: (tab: Tab) => number | undefined
76 setCurrentTab: (tab: Tab) => void
77 queryParamName?: string
78 }
79
80 export const SubnavTabs = <Tab extends SubnavTab<string>>({
81 tabs,
82 ariaLabel,
83 className,
84 currentTab,
85 getTabCount,
86 setCurrentTab,
87 queryParamName
88 }: SubnavTabsProps<Tab>) => {
89 const { atStart, atEnd, scrollRef } = useHorizontalScrollOverflow()
90
91 return (
92 <div
93 className={classnames('snippet-type-nav-wrapper', {
94 'has-scroll-start': !atStart,
95 'has-scroll-end': !atEnd
96 })}
97 >
98 <nav ref={scrollRef} className={classnames('snippet-type-nav', className)} aria-label={ariaLabel}>
99 <ul>
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 />)}
109 </ul>
110 </nav>
111 </div>
112 )
113 }
114