PluginProbe
Code Snippets / 3.10.0-beta.1
Code Snippets v3.10.0-beta.1
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 / Toolbar.tsx

Toolbar.tsx in Code Snippets 3.10.0-beta.1, at js/components/common/Toolbar.tsx

179 lines 4.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { __, _x } from '@wordpress/i18n'
2 import classnames from 'classnames'
3 import React, { useState } from 'react'
4 import { isLicensed, shouldShowUpsell } from '../../utils/screen'
5 import { buildUrl, fetchQueryParam } from '../../utils/urls'
6 import { BlueprintIcon, CommunityIcon, LibraryIcon, SettingsIcon, SnippetsIcon } from './icons/ToolbarIcons'
7 import { UpsellDialog } from './UpsellDialog'
8 import type { ReactNode } from 'react'
9
10 export const SUBPAGES = ['snippets', 'blueprints', 'cloud-community', 'cloud-library'] as const
11
12 interface NavLink {
13 name: string
14 url?: string
15 label: string
16 external?: boolean
17 icon?: ReactNode
18 pro?: boolean
19 pageSlug?: string
20 subpage?: typeof SUBPAGES[number]
21 end?: boolean
22 }
23
24 const UPPER_NAV_LINKS: readonly NavLink[] = [
25 {
26 name: 'docs',
27 url: 'https://codesnippets.pro/docs',
28 label: __('Docs', 'code-snippets'),
29 external: true
30 },
31 {
32 name: 'cloud',
33 url: 'https://codesnippets.cloud/',
34 label: __('Cloud Dashboard', 'code-snippets'),
35 external: true
36 },
37 {
38 name: 'welcome',
39 url: window.CODE_SNIPPETS?.urls.welcome,
40 label: __("What's New", 'code-snippets'),
41 pageSlug: 'code-snippets-welcome'
42 },
43 {
44 name: 'import-snippets',
45 url: window.CODE_SNIPPETS?.urls.import,
46 label: _x('Import', 'snippets', 'code-snippets'),
47 pageSlug: 'import-code-snippets'
48 }
49 ]
50
51 const LOWER_NAV_LINKS: readonly NavLink[] = [
52 {
53 name: 'snippets',
54 url: window.CODE_SNIPPETS?.urls.manage,
55 label: __('Snippets', 'code-snippets'),
56 icon: <SnippetsIcon aria-hidden="true" />,
57 pageSlug: 'snippets'
58 },
59 {
60 name: 'cloud-community',
61 label: __('Community Cloud', 'code-snippets'),
62 icon: <CommunityIcon aria-hidden="true" />,
63 subpage: 'cloud-community'
64 },
65 {
66 name: 'cloud-library',
67 label: __('My Library', 'code-snippets'),
68 icon: <LibraryIcon aria-hidden="true" />,
69 pro: true,
70 subpage: 'cloud-library'
71 },
72 {
73 name: 'blueprints',
74 label: __('Blueprints', 'code-snippets'),
75 icon: <BlueprintIcon />,
76 pro: true,
77 subpage: 'blueprints'
78 },
79 {
80 name: 'settings',
81 url: window.CODE_SNIPPETS?.urls.settings,
82 label: __('Settings', 'code-snippets'),
83 icon: <SettingsIcon aria-hidden="true" />,
84 pageSlug: 'snippets-settings',
85 end: true
86 }
87 ]
88
89 interface UpperNavProps {
90 setIsUpsellDialogOpen: (isOpen: boolean) => void
91 }
92
93 const UpperNav: React.FC<UpperNavProps> = ({ setIsUpsellDialogOpen }) =>
94 <div className="code-snippets-toolbar-upper">
95 <div className="logo">
96 <img
97 src={`${window.CODE_SNIPPETS?.urls.plugin}/assets/icon.svg`}
98 alt={__('Code Snippets logo', 'code-snippets')}
99 aria-hidden="true"
100 />
101
102 <div>{__('Code Snippets', 'code-snippets')}</div>
103 </div>
104
105 <nav aria-label={__('Main links', 'code-snippets')}>
106 <ul>
107 {UPPER_NAV_LINKS.map(link =>
108 <li key={link.name}>
109 <a
110 href={link.url}
111 className={classnames(`${link.name}-link`, { 'active-link': isActiveLink(link) })}
112 {...link.external && { target: '_blank', rel: 'noopener noreferrer' }}
113 >
114 {link.label}
115 </a>
116 </li>)}
117
118 {shouldShowUpsell() && (
119 <li>
120 <a
121 className="button button-large button-secondary"
122 href="https://codesnippets.pro/pricing/"
123 target="_blank" rel="noopener noreferrer"
124 onClick={event => {
125 event.preventDefault()
126 setIsUpsellDialogOpen(true)
127 }}
128 >
129 {__('Upgrade to Pro', 'code-snippets')}
130 </a>
131 </li>)}
132 </ul>
133 </nav>
134 </div>
135
136 const currentPage = fetchQueryParam('page')
137 const currentSubpage = fetchQueryParam('subpage')
138
139 const isActiveLink = ({ pageSlug, subpage }: Readonly<NavLink>): boolean => {
140 if (subpage) {
141 return currentSubpage === subpage
142 }
143 if (pageSlug) {
144 return !currentSubpage && currentPage === pageSlug
145 }
146 return false
147 }
148
149 const LowerNav = () =>
150 <div className="code-snippets-toolbar-lower">
151 <nav aria-label={__('Main features', 'code-snippets')}>
152 <ul>
153 {LOWER_NAV_LINKS.map(link =>
154 <li key={link.name} className={link.end ? 'toolbar-end-item' : undefined}>
155 <a
156 href={link.url ?? buildUrl(window.CODE_SNIPPETS?.urls.manage, { subpage: link.name })}
157 className={classnames(`${link.name}-link`, { 'active-link': isActiveLink(link) })}
158 >
159 {link.icon}
160 <span className="toolbar-nav-label">{link.label}</span>
161 {link.pro && !isLicensed() && <span className="pro-chip">{__('Pro', 'code-snippets')}</span>}
162 </a>
163 </li>)}
164 </ul>
165 </nav>
166 </div>
167
168 export const Toolbar = () => {
169 const [isUpsellDialogOpen, setIsUpsellDialogOpen] = useState(false)
170
171 return (
172 <div className="code-snippets-toolbar">
173 <UpperNav setIsUpsellDialogOpen={setIsUpsellDialogOpen} />
174 <LowerNav />
175 <UpsellDialog isOpen={isUpsellDialogOpen} setIsOpen={setIsUpsellDialogOpen} />
176 </div>
177 )
178 }
179