PluginProbe
Code Snippets / trunk
Code Snippets vtrunk
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
← All changes | js/components/common/SubnavTabs.tsx +72 -35 3.10.0-beta.1 → trunk View file →
@@ -1,17 +1,18 @@
1 1 import classnames from 'classnames'
2 2 import { __ } from '@wordpress/i18n'
3 3 import React from 'react'
4 4 import { isLicensed } from '../../utils/screen'
5 +import { useHorizontalScrollOverflow } from '../../hooks/useHorizontalScrollOverflow'
5 6 import { fetchQueryParam, updateQueryParams } from '../../utils/urls'
6 7
7 -export interface SubnavTab {
8 - name: string
8 +export interface SubnavTab<T extends string> {
9 + name: T
9 10 label: string
10 11 pro?: boolean
11 12 }
12 13
13 -export const getTabFromQuery = <Tab extends SubnavTab>(
14 +export const getTabFromQuery = <Tab extends SubnavTab<string>>(
14 15 tabs: Tab[],
15 16 queryParamName: string
16 17 ): Tab => {
17 18 const tabParam = fetchQueryParam(queryParamName)
@@ -24,9 +25,50 @@
24 25
25 26 return tabs[0]
26 27 }
27 28
28 -export interface SubnavTabsProps<Tab extends SubnavTab> {
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>> {
29 71 tabs: readonly Tab[]
30 72 ariaLabel: string
31 73 className?: string
32 74 currentTab: Tab
@@ -34,9 +76,9 @@
34 76 setCurrentTab: (tab: Tab) => void
35 77 queryParamName?: string
36 78 }
37 79
38 -export const SubnavTabs = <Tab extends SubnavTab>({
80 +export const SubnavTabs = <Tab extends SubnavTab<string>>({
39 81 tabs,
40 82 ariaLabel,
41 83 className,
42 84 currentTab,
@@ -41,36 +83,31 @@
41 83 className,
42 84 currentTab,
43 85 getTabCount,
44 86 setCurrentTab,
45 - queryParamName,
46 -}: SubnavTabsProps<Tab>) =>
47 - <nav className={classnames('snippet-type-nav', className)} aria-label={ariaLabel}>
48 - <ul>
49 - {tabs.map(tab => {
50 - const count = getTabCount?.(tab)
87 + queryParamName
88 +}: SubnavTabsProps<Tab>) => {
89 + const { atStart, atEnd, scrollRef } = useHorizontalScrollOverflow()
51 90
52 - return (
53 - <li key={tab.name}>
54 - <button
55 - type="button"
56 - className={classnames('snippet-type-link', `${tab.name}-subnav-link`, {
57 - 'active-type': tab.name === currentTab.name
58 - })}
59 - aria-current={tab.name === currentTab.name ? 'page' : undefined}
60 - onClick={() => {
61 - setCurrentTab(tab)
62 -
63 - if (queryParamName) {
64 - updateQueryParams({ [queryParamName]: tab.name })
65 - }
66 - }}
67 - >
68 - <span>{tab.label}</span>
69 - {count && <span className="subnav-count">{count}</span>}
70 - {tab.pro && !isLicensed() && <span className="pro-chip">{__('Pro', 'code-snippets')}</span>}
71 - </button>
72 - </li>
73 - )
91 + return (
92 + <div
93 + className={classnames('snippet-type-nav-wrapper', {
94 + 'has-scroll-start': !atStart,
95 + 'has-scroll-end': !atEnd
74 96 })}
75 - </ul>
76 - </nav>
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 +}