← All changes
|
js/components/ManageMenu/SnippetsTable/SnippetsTable.tsx
+29
-17
3.10.0-beta.1
→
trunk
View file →
| @@ -1,8 +1,9 @@ | ||
| 1 | 1 | import { __, sprintf } from '@wordpress/i18n' |
| 2 | 2 | import { createInterpolateElement } from '@wordpress/element' |
| 3 | 3 | import React, { useCallback, useMemo } from 'react' |
| 4 | 4 | import classnames from 'classnames' |
| 5 | +import { useHorizontalScrollOverflow } from '../../../hooks/useHorizontalScrollOverflow' | |
| 5 | 6 | import { WithRestAPIContext } from '../../../hooks/useRestAPI' |
| 6 | 7 | import { useSnippetView } from '../../../hooks/useSnippetView' |
| 7 | 8 | import { WithSnippetsAPIContext } from '../../../hooks/useSnippetsAPI' |
| 8 | 9 | import { WithSnippetsListContext, useSnippetsList } from '../../../hooks/useSnippetsList' |
| @@ -27,17 +28,20 @@ | ||
| 27 | 28 | const SnippetTypeTab: React.FC<SnippetTypeTabProps> = ({ type, count }) => { |
| 28 | 29 | const { currentType, setCurrentType } = useSnippetsFilters() |
| 29 | 30 | const tabName = type ?? 'all' |
| 30 | 31 | |
| 32 | + const isActive = type === currentType | |
| 33 | + const isProLocked = type && isProType(type) && !isLicensed() | |
| 34 | + | |
| 31 | 35 | return ( |
| 32 | 36 | <li> |
| 33 | 37 | <a |
| 34 | 38 | href={buildUrl(window.location.href, { type: tabName })} |
| 35 | 39 | className={classnames('snippet-type-link', `${tabName}-type-link`, { |
| 36 | - 'active-type': type === currentType, | |
| 37 | - 'pro-locked-type': type && type !== currentType && !isLicensed() && isProType(type) | |
| 40 | + 'active-type': isActive, | |
| 41 | + 'pro-locked-type': isProLocked && !isActive | |
| 38 | 42 | })} |
| 39 | - aria-current={type === currentType ? 'page' : undefined} | |
| 43 | + aria-current={isActive ? 'page' : undefined} | |
| 40 | 44 | onClick={event => { |
| 41 | 45 | event.preventDefault() |
| 42 | 46 | setCurrentType(type) |
| 43 | 47 | }} |
| @@ -50,15 +54,16 @@ | ||
| 50 | 54 | <span className="snippet-type-name-full">{__('All Snippets', 'code-snippets')}</span> |
| 51 | 55 | <span className="snippet-type-name-short">{__('All', 'code-snippets')}</span> |
| 52 | 56 | </>} |
| 53 | 57 | </span> |
| 54 | - {count && <span className="subnav-count">{count}</span>} | |
| 55 | - {type && isProType(type) && !isLicensed() && <span className="pro-chip">{__('Pro', 'code-snippets')}</span>} | |
| 58 | + {count !== undefined && !isProLocked && <span className="subnav-count">{count}</span>} | |
| 59 | + {isProLocked && <span className="pro-chip">{__('Pro', 'code-snippets')}</span>} | |
| 56 | 60 | </a> |
| 57 | 61 | </li> |
| 58 | 62 | ) |
| 59 | 63 | } |
| 60 | 64 | |
| 65 | + | |
| 61 | 66 | const SafeModeNotice = () => |
| 62 | 67 | window.CODE_SNIPPETS_MANAGE?.isSafeModeActive |
| 63 | 68 | ? <Notice type="error"> |
| 64 | 69 | <p> |
| @@ -78,10 +83,9 @@ | ||
| 78 | 83 | </p> |
| 79 | 84 | </Notice> |
| 80 | 85 | : null |
| 81 | 86 | |
| 82 | -// Counts render immediately from the values localized with the page, then | |
| 83 | -// switch to live values derived from the snippets list once it has loaded. | |
| 87 | +// Counts render immediately from localized values, then switch to live values. | |
| 84 | 88 | const useSnippetTypeCounts = () => { |
| 85 | 89 | const { snippetsList } = useSnippetsList() |
| 86 | 90 | |
| 87 | 91 | const countedSnippets = useMemo( |
| @@ -112,21 +116,29 @@ | ||
| 112 | 116 | const SnippetsTableInner = () => { |
| 113 | 117 | const { snippetView, setSnippetView } = useSnippetView() |
| 114 | 118 | const { currentType } = useSnippetsFilters() |
| 115 | 119 | const { getCount } = useSnippetTypeCounts() |
| 120 | + const { atStart, atEnd, scrollRef } = useHorizontalScrollOverflow() | |
| 116 | 121 | |
| 117 | 122 | return ( |
| 118 | 123 | <> |
| 119 | - <nav | |
| 120 | - className="snippet-type-nav" | |
| 121 | - aria-label={__('Snippet types', 'code-snippets')} | |
| 124 | + <div | |
| 125 | + className={classnames('snippet-type-nav-wrapper', { | |
| 126 | + 'has-scroll-start': !atStart, | |
| 127 | + 'has-scroll-end': !atEnd | |
| 128 | + })} | |
| 122 | 129 | > |
| 123 | - <ul> | |
| 124 | - <SnippetTypeTab count={getCount()} /> | |
| 125 | - {SNIPPET_TYPES.map(type => | |
| 126 | - <SnippetTypeTab key={type} type={type} count={getCount(type)} />)} | |
| 127 | - </ul> | |
| 128 | - </nav> | |
| 130 | + <nav | |
| 131 | + ref={scrollRef} | |
| 132 | + className="snippet-type-nav" | |
| 133 | + aria-label={__('Snippet types', 'code-snippets')} | |
| 134 | + > | |
| 135 | + <ul> | |
| 136 | + <SnippetTypeTab count={getCount()} /> | |
| 137 | + {SNIPPET_TYPES.map(type => <SnippetTypeTab key={type} type={type} count={getCount(type)} />)} | |
| 138 | + </ul> | |
| 139 | + </nav> | |
| 140 | + </div> | |
| 129 | 141 | |
| 130 | 142 | <ScreenMetaSlot /> |
| 131 | 143 | |
| 132 | 144 | <div className="snippets-page-header"> |
| @@ -135,9 +147,9 @@ | ||
| 135 | 147 | __('Local Snippets: %s', 'code-snippets'), |
| 136 | 148 | currentType ? SNIPPET_TYPE_LABELS[currentType] : __('All Snippets', 'code-snippets') |
| 137 | 149 | )}</h1> |
| 138 | 150 | <a href={getSnippetAddNewUrl(currentType)} className="button button-primary"> |
| 139 | - {__('Create new Snippet', 'code-snippets')} | |
| 151 | + {__('Add Snippet', 'code-snippets')} | |
| 140 | 152 | </a> |
| 141 | 153 | </div> |
| 142 | 154 | |
| 143 | 155 | <hr className="wp-header-end" /> |