@redocly/theme 0.71.0-next.4 → 0.71.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/Buttons/MobileMenuButton.d.ts +8 -0
- package/lib/components/Buttons/MobileMenuButton.js +58 -0
- package/lib/components/Catalog/CatalogFilter/CatalogFilter.js +1 -1
- package/lib/components/Feedback/Mood.js +1 -1
- package/lib/components/Feedback/Rating.js +1 -1
- package/lib/components/Feedback/Scale.js +1 -1
- package/lib/components/Feedback/Sentiment.js +1 -1
- package/lib/components/Filter/Filter.js +1 -1
- package/lib/components/MCP/McpConnectionTabs.d.ts +1 -1
- package/lib/components/MCP/McpConnectionTabs.js +24 -1
- package/lib/components/MissingTranslationNotice/MissingTranslationNotice.d.ts +11 -0
- package/lib/components/MissingTranslationNotice/MissingTranslationNotice.js +83 -0
- package/lib/components/MissingTranslationNotice/variables.d.ts +1 -0
- package/lib/components/MissingTranslationNotice/variables.dark.d.ts +1 -0
- package/lib/components/MissingTranslationNotice/variables.dark.js +10 -0
- package/lib/components/MissingTranslationNotice/variables.js +29 -0
- package/lib/components/Navbar/Navbar.js +10 -18
- package/lib/components/PageActions/PageActions.js +1 -0
- package/lib/components/Select/Select.js +1 -2
- package/lib/core/hooks/use-active-section-id.js +8 -0
- package/lib/core/hooks/use-focus-trap.js +6 -5
- package/lib/core/hooks/use-page-actions.d.ts +1 -1
- package/lib/core/hooks/use-page-actions.js +47 -35
- package/lib/core/styles/dark.js +4 -2
- package/lib/core/styles/global.js +70 -68
- package/lib/core/types/hooks.d.ts +2 -5
- package/lib/core/types/l10n.d.ts +2 -1
- package/lib/core/utils/get-ai-prompt-link.d.ts +3 -1
- package/lib/core/utils/get-ai-prompt-link.js +1 -0
- package/lib/core/utils/mcp.d.ts +1 -0
- package/lib/core/utils/mcp.js +4 -0
- package/lib/icons/GrokIcon/GrokIcon.d.ts +25 -0
- package/lib/icons/GrokIcon/GrokIcon.js +23 -0
- package/lib/icons/McpIcon/McpIcon.d.ts +25 -0
- package/lib/icons/McpIcon/McpIcon.js +24 -0
- package/lib/icons/TranslateIcon/TranslateIcon.d.ts +25 -0
- package/lib/icons/TranslateIcon/TranslateIcon.js +21 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +4 -0
- package/lib/layouts/CodeWalkthroughLayout.js +9 -1
- package/lib/layouts/DocumentationLayout.js +2 -0
- package/lib/markdoc/default.d.ts +2 -0
- package/lib/markdoc/default.js +2 -0
- package/package.json +4 -3
- package/src/components/Buttons/MobileMenuButton.tsx +45 -0
- package/src/components/Catalog/CatalogFilter/CatalogFilter.tsx +2 -2
- package/src/components/CatalogClassic/CatalogClassicInfoBlock.tsx +1 -1
- package/src/components/Feedback/Feedback.tsx +1 -3
- package/src/components/Feedback/Mood.tsx +1 -1
- package/src/components/Feedback/Rating.tsx +1 -1
- package/src/components/Feedback/Scale.tsx +1 -1
- package/src/components/Feedback/Sentiment.tsx +1 -1
- package/src/components/Filter/Filter.tsx +2 -2
- package/src/components/MCP/McpConnectionTabs.tsx +56 -2
- package/src/components/MissingTranslationNotice/MissingTranslationNotice.tsx +113 -0
- package/src/components/MissingTranslationNotice/variables.dark.ts +7 -0
- package/src/components/MissingTranslationNotice/variables.ts +26 -0
- package/src/components/Navbar/Navbar.tsx +15 -30
- package/src/components/PageActions/PageActions.tsx +1 -0
- package/src/components/Search/FilterFields/SearchFilterFieldSelect.tsx +1 -1
- package/src/components/Select/Select.tsx +1 -2
- package/src/core/hooks/__mocks__/use-theme-hooks.ts +1 -1
- package/src/core/hooks/use-active-section-id.ts +13 -0
- package/src/core/hooks/use-codeblock-tabs-controls.ts +1 -1
- package/src/core/hooks/use-focus-trap.ts +8 -7
- package/src/core/hooks/use-page-actions.ts +73 -43
- package/src/core/styles/dark.ts +2 -0
- package/src/core/styles/global.ts +2 -0
- package/src/core/types/hooks.ts +2 -2
- package/src/core/types/l10n.ts +15 -2
- package/src/core/utils/get-ai-prompt-link.ts +5 -2
- package/src/core/utils/mcp.ts +4 -0
- package/src/icons/GrokIcon/GrokIcon.tsx +24 -0
- package/src/icons/McpIcon/McpIcon.tsx +37 -0
- package/src/icons/TranslateIcon/TranslateIcon.tsx +22 -0
- package/src/index.ts +4 -0
- package/src/layouts/CodeWalkthroughLayout.tsx +11 -1
- package/src/layouts/DocumentationLayout.tsx +2 -0
- package/src/markdoc/default.ts +2 -0
- package/src/markdoc/tags/code-walkthrough.ts +1 -1
|
@@ -2,19 +2,22 @@ import { useEffect } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import type { RefObject } from 'react';
|
|
4
4
|
|
|
5
|
+
const FOCUSABLE_SELECTOR =
|
|
6
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
7
|
+
|
|
5
8
|
export function useFocusTrap(containerRef: RefObject<HTMLElement | null>): void {
|
|
6
9
|
useEffect(() => {
|
|
7
10
|
const trapElement = containerRef.current;
|
|
8
11
|
|
|
9
12
|
if (!trapElement) return;
|
|
10
13
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
);
|
|
14
|
-
const firstElement = focusableElements[0];
|
|
14
|
+
const getFocusableElements = () =>
|
|
15
|
+
trapElement.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR);
|
|
15
16
|
|
|
16
17
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
17
18
|
if (event.key === 'Tab') {
|
|
19
|
+
const focusableElements = getFocusableElements();
|
|
20
|
+
const firstElement = focusableElements[0];
|
|
18
21
|
const lastElement = focusableElements[focusableElements.length - 1];
|
|
19
22
|
if (event.shiftKey && document.activeElement === firstElement) {
|
|
20
23
|
lastElement?.focus();
|
|
@@ -28,9 +31,7 @@ export function useFocusTrap(containerRef: RefObject<HTMLElement | null>): void
|
|
|
28
31
|
|
|
29
32
|
trapElement.addEventListener('keydown', handleKeyDown);
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
firstElement.focus();
|
|
33
|
-
}
|
|
34
|
+
getFocusableElements()[0]?.focus();
|
|
34
35
|
|
|
35
36
|
return () => {
|
|
36
37
|
trapElement.removeEventListener('keydown', handleKeyDown);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useMemo, useCallback } from 'react';
|
|
2
|
+
import type { ComponentType } from 'react';
|
|
2
3
|
|
|
3
4
|
import type { PageProps, UiAccessibleConfig } from '@redocly/config';
|
|
4
5
|
import type { PageAction, MCPClientType, McpConnectionParams } from '../types';
|
|
@@ -6,6 +7,8 @@ import type { PageAction, MCPClientType, McpConnectionParams } from '../types';
|
|
|
6
7
|
import { CopyIcon } from '@redocly/theme/icons/CopyIcon/CopyIcon';
|
|
7
8
|
import { ChatGptIcon } from '@redocly/theme/icons/ChatGptIcon/ChatGptIcon';
|
|
8
9
|
import { ClaudeIcon } from '@redocly/theme/icons/ClaudeIcon/ClaudeIcon';
|
|
10
|
+
import { GrokIcon } from '@redocly/theme/icons/GrokIcon/GrokIcon';
|
|
11
|
+
import { McpIcon } from '@redocly/theme/icons/McpIcon/McpIcon';
|
|
9
12
|
import { MarkdownFullIcon } from '@redocly/theme/icons/MarkdownFullIcon/MarkdownFullIcon';
|
|
10
13
|
import { VSCodeIcon } from '@redocly/theme/icons/VSCodeIcon/VSCodeIcon';
|
|
11
14
|
import { CursorIcon } from '@redocly/theme/icons/CursorIcon/CursorIcon';
|
|
@@ -30,9 +33,11 @@ const DEFAULT_ENABLED_ACTIONS = [
|
|
|
30
33
|
'view',
|
|
31
34
|
'chatgpt',
|
|
32
35
|
'claude',
|
|
33
|
-
'
|
|
34
|
-
'docs-mcp-vscode',
|
|
36
|
+
'grok',
|
|
35
37
|
'docs-mcp-claude',
|
|
38
|
+
'docs-mcp-vscode',
|
|
39
|
+
'docs-mcp-cursor',
|
|
40
|
+
'copy-mcp-url',
|
|
36
41
|
] as const;
|
|
37
42
|
|
|
38
43
|
export type PageActionType =
|
|
@@ -40,9 +45,11 @@ export type PageActionType =
|
|
|
40
45
|
| 'view'
|
|
41
46
|
| 'chatgpt'
|
|
42
47
|
| 'claude'
|
|
43
|
-
| '
|
|
44
|
-
| 'docs-mcp-vscode'
|
|
48
|
+
| 'grok'
|
|
45
49
|
| 'docs-mcp-claude'
|
|
50
|
+
| 'docs-mcp-vscode'
|
|
51
|
+
| 'docs-mcp-cursor'
|
|
52
|
+
| 'copy-mcp-url'
|
|
46
53
|
// Used in OpenAPI docs x-mcp
|
|
47
54
|
| 'mcp-cursor'
|
|
48
55
|
| 'mcp-vscode';
|
|
@@ -115,10 +122,52 @@ export function usePageActions(
|
|
|
115
122
|
: combineUrls(origin, removeTrailingSlash(pathname) + '.md');
|
|
116
123
|
const externalAiPrompt = `Read ${mdPageUrl} and answer questions based on the content.`;
|
|
117
124
|
|
|
125
|
+
const createAiPromptAction =
|
|
126
|
+
(
|
|
127
|
+
target: 'chatgpt' | 'claude' | 'grok',
|
|
128
|
+
iconComponent: ComponentType,
|
|
129
|
+
texts: Pick<PageAction, 'buttonText' | 'title' | 'description'>,
|
|
130
|
+
) =>
|
|
131
|
+
(): PageAction => {
|
|
132
|
+
const link = getAiPromptLink(target, externalAiPrompt);
|
|
133
|
+
return {
|
|
134
|
+
...texts,
|
|
135
|
+
iconComponent,
|
|
136
|
+
link,
|
|
137
|
+
onClick: () => {
|
|
138
|
+
telemetry.sendPageActionsClickedMessage([
|
|
139
|
+
{
|
|
140
|
+
...getBaseDataAttributes('pageActions', 'button'),
|
|
141
|
+
actionType: target,
|
|
142
|
+
},
|
|
143
|
+
]);
|
|
144
|
+
window.location.href = link;
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
|
|
118
149
|
const actionHandlers: Record<PageActionType, () => PageAction> = {
|
|
119
150
|
'docs-mcp-cursor': createMCPHandler('cursor', false),
|
|
120
151
|
'docs-mcp-vscode': createMCPHandler('vscode', false),
|
|
121
152
|
'docs-mcp-claude': createMCPHandler('claude', false),
|
|
153
|
+
'copy-mcp-url': () => ({
|
|
154
|
+
buttonText: translate('page.actions.connectMcp.copyUrl', 'Copy MCP server URL'),
|
|
155
|
+
title: translate('page.actions.connectMcp.copyUrl', 'Copy MCP server URL'),
|
|
156
|
+
description: translate(
|
|
157
|
+
'page.actions.connectMcp.copyUrlDescription',
|
|
158
|
+
'Copy the MCP server URL to the clipboard',
|
|
159
|
+
),
|
|
160
|
+
iconComponent: McpIcon,
|
|
161
|
+
onClick: () => {
|
|
162
|
+
ClipboardService.copyCustom(mcpConfig.serverUrl);
|
|
163
|
+
telemetry.sendPageActionsClickedMessage([
|
|
164
|
+
{
|
|
165
|
+
...getBaseDataAttributes('pageActions', 'button'),
|
|
166
|
+
actionType: 'copy-mcp-url',
|
|
167
|
+
},
|
|
168
|
+
]);
|
|
169
|
+
},
|
|
170
|
+
}),
|
|
122
171
|
'mcp-cursor': createMCPHandler('cursor', true),
|
|
123
172
|
'mcp-vscode': createMCPHandler('vscode', true),
|
|
124
173
|
|
|
@@ -163,45 +212,23 @@ export function usePageActions(
|
|
|
163
212
|
},
|
|
164
213
|
}),
|
|
165
214
|
|
|
166
|
-
chatgpt: (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
description: translate('page.actions.chatGptDescription', 'Get insights from ChatGPT'),
|
|
172
|
-
iconComponent: ChatGptIcon,
|
|
173
|
-
link,
|
|
174
|
-
onClick: () => {
|
|
175
|
-
telemetry.sendPageActionsClickedMessage([
|
|
176
|
-
{
|
|
177
|
-
...getBaseDataAttributes('pageActions', 'button'),
|
|
178
|
-
actionType: 'chatgpt',
|
|
179
|
-
},
|
|
180
|
-
]);
|
|
181
|
-
window.location.href = link;
|
|
182
|
-
},
|
|
183
|
-
};
|
|
184
|
-
},
|
|
215
|
+
chatgpt: createAiPromptAction('chatgpt', ChatGptIcon, {
|
|
216
|
+
buttonText: translate('page.actions.chatGptButtonText', 'Open in ChatGPT'),
|
|
217
|
+
title: translate('page.actions.chatGptTitle', 'Open in ChatGPT'),
|
|
218
|
+
description: translate('page.actions.chatGptDescription', 'Get insights from ChatGPT'),
|
|
219
|
+
}),
|
|
185
220
|
|
|
186
|
-
claude: (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
...getBaseDataAttributes('pageActions', 'button'),
|
|
198
|
-
actionType: 'claude',
|
|
199
|
-
},
|
|
200
|
-
]);
|
|
201
|
-
window.location.href = link;
|
|
202
|
-
},
|
|
203
|
-
};
|
|
204
|
-
},
|
|
221
|
+
claude: createAiPromptAction('claude', ClaudeIcon, {
|
|
222
|
+
buttonText: translate('page.actions.claudeButtonText', 'Open in Claude'),
|
|
223
|
+
title: translate('page.actions.claudeTitle', 'Open in Claude'),
|
|
224
|
+
description: translate('page.actions.claudeDescription', 'Get insights from Claude'),
|
|
225
|
+
}),
|
|
226
|
+
|
|
227
|
+
grok: createAiPromptAction('grok', GrokIcon, {
|
|
228
|
+
buttonText: translate('page.actions.grokButtonText', 'Open in Grok'),
|
|
229
|
+
title: translate('page.actions.grokTitle', 'Open in Grok'),
|
|
230
|
+
description: translate('page.actions.grokDescription', 'Get insights from Grok'),
|
|
231
|
+
}),
|
|
205
232
|
};
|
|
206
233
|
|
|
207
234
|
return (themeConfig.navigation?.actions?.items || actions || DEFAULT_ENABLED_ACTIONS)
|
|
@@ -215,6 +242,7 @@ export function usePageActions(
|
|
|
215
242
|
isPublic,
|
|
216
243
|
mcpUrl,
|
|
217
244
|
mcpConfig.isMcpDisabled,
|
|
245
|
+
mcpConfig.serverUrl,
|
|
218
246
|
pageSlug,
|
|
219
247
|
actions,
|
|
220
248
|
translate,
|
|
@@ -311,7 +339,7 @@ function shouldHideAction(
|
|
|
311
339
|
return true;
|
|
312
340
|
}
|
|
313
341
|
|
|
314
|
-
const actionDependsOnLlmsTxt = ['view', 'copy', 'chatgpt', 'claude'].includes(action);
|
|
342
|
+
const actionDependsOnLlmsTxt = ['view', 'copy', 'chatgpt', 'claude', 'grok'].includes(action);
|
|
315
343
|
|
|
316
344
|
if (actionDependsOnLlmsTxt) {
|
|
317
345
|
// Can't use any actions if search is globally disabled (markdown files are not generated)
|
|
@@ -345,10 +373,12 @@ function shouldHideActionByType(
|
|
|
345
373
|
switch (action) {
|
|
346
374
|
case 'chatgpt':
|
|
347
375
|
case 'claude':
|
|
376
|
+
case 'grok':
|
|
348
377
|
return !isPublic;
|
|
349
378
|
case 'docs-mcp-cursor':
|
|
350
379
|
case 'docs-mcp-vscode':
|
|
351
380
|
case 'docs-mcp-claude':
|
|
381
|
+
case 'copy-mcp-url':
|
|
352
382
|
return Boolean(mcpUrl) || isMcpDisabled;
|
|
353
383
|
case 'mcp-cursor':
|
|
354
384
|
case 'mcp-vscode':
|
package/src/core/styles/dark.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { pageActionsDarkMode } from '@redocly/theme/components/PageActions/varia
|
|
|
16
16
|
import { tooltipDarkMode } from '@redocly/theme/components/Tooltip/variables.dark';
|
|
17
17
|
import { bannerDarkMode } from '@redocly/theme/components/Banner/variables.dark';
|
|
18
18
|
import { admonitionDarkMode } from '@redocly/theme/components/Admonition/variables.dark';
|
|
19
|
+
import { missingTranslationNoticeDarkMode } from '@redocly/theme/components/MissingTranslationNotice/variables.dark';
|
|
19
20
|
import { codeBlockDarkMode } from '@redocly/theme/components/CodeBlock/variables.dark';
|
|
20
21
|
|
|
21
22
|
import { activeBrandPaletteDark } from './palette.dark';
|
|
@@ -363,6 +364,7 @@ export const darkMode = css`
|
|
|
363
364
|
${tooltipDarkMode}
|
|
364
365
|
${bannerDarkMode}
|
|
365
366
|
${admonitionDarkMode}
|
|
367
|
+
${missingTranslationNoticeDarkMode}
|
|
366
368
|
${badgesDarkMode}
|
|
367
369
|
${numberedListDarkMode}
|
|
368
370
|
${activeBrandPaletteDark}
|
|
@@ -18,6 +18,7 @@ import { dropdown } from '@redocly/theme/components/Dropdown/variables';
|
|
|
18
18
|
import { tooltip } from '@redocly/theme/components/Tooltip/variables';
|
|
19
19
|
import { checkbox } from '@redocly/theme/icons/CheckboxIcon/variables';
|
|
20
20
|
import { admonition } from '@redocly/theme/components/Admonition/variables';
|
|
21
|
+
import { missingTranslationNotice } from '@redocly/theme/components/MissingTranslationNotice/variables';
|
|
21
22
|
import { footer } from '@redocly/theme/components/Footer/variables';
|
|
22
23
|
import { button } from '@redocly/theme/components/Button/variables';
|
|
23
24
|
import { aiAssistantButton, connectMcpButton } from '@redocly/theme/components/Buttons/variables';
|
|
@@ -1295,6 +1296,7 @@ const replay = css`
|
|
|
1295
1296
|
export const tokens = css`
|
|
1296
1297
|
${accordion}
|
|
1297
1298
|
${admonition}
|
|
1299
|
+
${missingTranslationNotice}
|
|
1298
1300
|
${apiReferenceDocs}
|
|
1299
1301
|
${apiReferencePanels}
|
|
1300
1302
|
${badges}
|
package/src/core/types/hooks.ts
CHANGED
|
@@ -39,7 +39,7 @@ import type {
|
|
|
39
39
|
ToolCall,
|
|
40
40
|
} from './search';
|
|
41
41
|
import type { SubmitFeedbackParams } from './feedback';
|
|
42
|
-
import type { TFunction } from './l10n';
|
|
42
|
+
import type { Locale, TFunction } from './l10n';
|
|
43
43
|
import type { BreadcrumbItem } from './breadcrumb';
|
|
44
44
|
import type { UseConsentResult } from './consent';
|
|
45
45
|
|
|
@@ -234,5 +234,5 @@ export type ThemeHooks = {
|
|
|
234
234
|
export type L10nConfig = {
|
|
235
235
|
currentLocale: string;
|
|
236
236
|
defaultLocale: string;
|
|
237
|
-
locales:
|
|
237
|
+
locales: Locale[];
|
|
238
238
|
};
|
package/src/core/types/l10n.ts
CHANGED
|
@@ -157,11 +157,16 @@ export type TranslationKey =
|
|
|
157
157
|
| 'page.mcpNotAllowed.snippets.chatgptApp.headline'
|
|
158
158
|
| 'page.mcpNotAllowed.snippets.chatgptApp.instruction'
|
|
159
159
|
| 'page.mcpNotAllowed.snippets.codexCli.headline'
|
|
160
|
+
| 'page.mcpNotAllowed.snippets.grokBuild.headline'
|
|
161
|
+
| 'page.mcpNotAllowed.snippets.grokApp.headline'
|
|
162
|
+
| 'page.mcpNotAllowed.snippets.grokApp.instruction'
|
|
163
|
+
| 'page.mcpNotAllowed.snippets.grokApp.openConnectors'
|
|
160
164
|
| 'page.mcpNotAllowed.snippets.prompt.headline'
|
|
161
165
|
| 'page.mcpNotAllowed.snippets.prompt.hint'
|
|
162
166
|
| 'page.mcpNotAllowed.snippets.json.hint'
|
|
163
167
|
| 'page.mcpNotAllowed.tabs.claude'
|
|
164
168
|
| 'page.mcpNotAllowed.tabs.chatgpt'
|
|
169
|
+
| 'page.mcpNotAllowed.tabs.grok'
|
|
165
170
|
| 'page.mcpNotAllowed.tabs.json'
|
|
166
171
|
| 'page.lastUpdated.timeago'
|
|
167
172
|
| 'page.lastUpdated.on'
|
|
@@ -292,6 +297,9 @@ export type TranslationKey =
|
|
|
292
297
|
| 'page.actions.claudeTitle'
|
|
293
298
|
| 'page.actions.claudeButtonText'
|
|
294
299
|
| 'page.actions.claudeDescription'
|
|
300
|
+
| 'page.actions.grokTitle'
|
|
301
|
+
| 'page.actions.grokButtonText'
|
|
302
|
+
| 'page.actions.grokDescription'
|
|
295
303
|
| 'page.actions.cursorMcpButtonText'
|
|
296
304
|
| 'page.actions.cursorMcpTitle'
|
|
297
305
|
| 'page.actions.cursorMcpDescription'
|
|
@@ -308,6 +316,8 @@ export type TranslationKey =
|
|
|
308
316
|
| 'page.actions.connectMcp.codexDescription'
|
|
309
317
|
| 'page.actions.connectMcp.copyConfig'
|
|
310
318
|
| 'page.actions.connectMcp.copyConfigDescription'
|
|
319
|
+
| 'page.actions.connectMcp.copyUrl'
|
|
320
|
+
| 'page.actions.connectMcp.copyUrlDescription'
|
|
311
321
|
| 'page.actions.connectMcp.moreOptions'
|
|
312
322
|
| 'page.actions.moreActions'
|
|
313
323
|
| 'promptTag.copy.buttonText'
|
|
@@ -556,9 +566,12 @@ export type TranslationKey =
|
|
|
556
566
|
| 'consent.category.analytics.description'
|
|
557
567
|
| 'consent.category.marketing.title'
|
|
558
568
|
| 'consent.category.marketing.description'
|
|
559
|
-
| 'consent.settingsLink'
|
|
569
|
+
| 'consent.settingsLink'
|
|
570
|
+
| 'missingTranslationNotice.title'
|
|
571
|
+
| 'missingTranslationNotice.content'
|
|
572
|
+
| 'missingTranslationNotice.close';
|
|
560
573
|
|
|
561
|
-
export type Locale = { code: string; name: string };
|
|
574
|
+
export type Locale = { code: string; name: string; showMissingTranslationNotice?: boolean };
|
|
562
575
|
|
|
563
576
|
export type TFunction = (
|
|
564
577
|
// A workaround for literals + strings Typescript autosuggestion: 'https://github.com/microsoft/TypeScript/issues/29729'
|
|
@@ -2,9 +2,12 @@ import type { AiPromptTarget } from '../types/prompt';
|
|
|
2
2
|
|
|
3
3
|
type AiPromptEndpoint = { baseUrl: string; queryParam: string };
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type AiPromptLinkTarget = AiPromptTarget | 'grok';
|
|
6
|
+
|
|
7
|
+
const AI_PROMPT_ENDPOINTS: Record<AiPromptLinkTarget, AiPromptEndpoint> = {
|
|
6
8
|
chatgpt: { baseUrl: 'https://chat.openai.com', queryParam: 'q' },
|
|
7
9
|
claude: { baseUrl: 'https://claude.ai/new', queryParam: 'q' },
|
|
10
|
+
grok: { baseUrl: 'https://grok.com/', queryParam: 'q' },
|
|
8
11
|
// Encoding: https://cursor.com/docs/integrations/deeplinks
|
|
9
12
|
cursor: { baseUrl: 'https://cursor.com/link/prompt', queryParam: 'text' },
|
|
10
13
|
};
|
|
@@ -22,7 +25,7 @@ const AI_PROMPT_ENDPOINTS: Record<AiPromptTarget, AiPromptEndpoint> = {
|
|
|
22
25
|
* // 'https://claude.ai/new?q=Summarize+this+page'
|
|
23
26
|
* ```
|
|
24
27
|
*/
|
|
25
|
-
export function getAiPromptLink(target:
|
|
28
|
+
export function getAiPromptLink(target: AiPromptLinkTarget, prompt: string): string {
|
|
26
29
|
const { baseUrl, queryParam } = AI_PROMPT_ENDPOINTS[target];
|
|
27
30
|
const url = new URL(baseUrl);
|
|
28
31
|
url.searchParams.set(queryParam, prompt);
|
package/src/core/utils/mcp.ts
CHANGED
|
@@ -58,6 +58,10 @@ export function generateClaudeCodeCommand(config: McpConnectionParams): string {
|
|
|
58
58
|
return `claude mcp add --transport http ${slugifyMcpServerName(config.serverName)} ${config.url}`;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
export function generateGrokBuildCommand(config: McpConnectionParams): string {
|
|
62
|
+
return `grok mcp add --transport http ${slugifyMcpServerName(config.serverName)} ${config.url}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
export function generateCodexCommand(config: McpConnectionParams): string {
|
|
62
66
|
return `codex mcp add ${slugifyMcpServerName(config.serverName)} --url ${config.url}`;
|
|
63
67
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import type { IconProps } from '@redocly/theme/icons/types';
|
|
5
|
+
|
|
6
|
+
import { getCssColorVariable } from '@redocly/theme/core/utils';
|
|
7
|
+
|
|
8
|
+
const Icon = (props: IconProps) => (
|
|
9
|
+
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
|
10
|
+
<path d="M6.6345 9.6347L10.6239 6.6862C10.8195 6.5417 11.0991 6.598 11.1923 6.8226C11.6827 8.0067 11.4636 9.4297 10.4877 10.4067C9.5119 11.3837 8.1541 11.5979 6.9131 11.1099L5.5573 11.7384C7.5019 13.0691 9.8631 12.74 11.3387 11.2617C12.5091 10.0899 12.8716 8.4926 12.5327 7.0522L12.5357 7.0553C12.0442 4.9393 12.6566 4.0935 13.9109 2.364C13.9406 2.3229 13.9703 2.2819 14 2.2399L12.3493 3.8925V3.8874L6.6335 9.6357" />
|
|
11
|
+
<path d="M5.8113 10.3513C4.4156 9.0165 4.6562 6.9507 5.8471 5.7594C6.7277 4.8777 8.1705 4.5179 9.43 5.0469L10.7827 4.4215C10.539 4.2452 10.2266 4.0555 9.8682 3.9223C8.2483 3.2549 6.3089 3.587 4.9921 4.9044C3.7254 6.1726 3.3271 8.1225 4.0111 9.7864C4.5221 11.03 3.6844 11.9096 2.8407 12.7974C2.5417 13.1122 2.2417 13.4269 2 13.7601L5.8102 10.3523" />
|
|
12
|
+
</svg>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export const GrokIcon = styled(Icon).attrs({
|
|
16
|
+
'data-component-name': 'icons/GrokIcon/GrokIcon',
|
|
17
|
+
})`
|
|
18
|
+
path {
|
|
19
|
+
fill: ${({ color }) => getCssColorVariable(color)};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
height: ${({ size }) => size || '16px'};
|
|
23
|
+
width: ${({ size }) => size || '16px'};
|
|
24
|
+
`;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import type { IconProps } from '@redocly/theme/icons/types';
|
|
5
|
+
|
|
6
|
+
import { getCssColorVariable } from '@redocly/theme/core/utils';
|
|
7
|
+
|
|
8
|
+
const Icon = (props: IconProps) => (
|
|
9
|
+
<svg viewBox="14 13 150 154" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
|
10
|
+
<path
|
|
11
|
+
d="M23.5996 85.2532L86.2021 22.6507C94.8457 14.0071 108.86 14.0071 117.503 22.6507C126.147 31.2942 126.147 45.3083 117.503 53.9519L70.2254 101.23"
|
|
12
|
+
strokeWidth="11"
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
/>
|
|
15
|
+
<path
|
|
16
|
+
d="M70.8789 100.578L117.504 53.952C126.148 45.3083 140.163 45.3083 148.806 53.952L149.132 54.278C157.776 62.9216 157.776 76.9357 149.132 85.5792L92.5139 142.198C89.6327 145.079 89.6327 149.75 92.5139 152.631L104.14 164.257"
|
|
17
|
+
strokeWidth="11"
|
|
18
|
+
strokeLinecap="round"
|
|
19
|
+
/>
|
|
20
|
+
<path
|
|
21
|
+
d="M101.853 38.3013L55.553 84.6011C46.9094 93.2447 46.9094 107.258 55.553 115.902C64.1966 124.546 78.2106 124.546 86.8543 115.902L133.154 69.6025"
|
|
22
|
+
strokeWidth="11"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
/>
|
|
25
|
+
</svg>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export const McpIcon = styled(Icon).attrs({
|
|
29
|
+
'data-component-name': 'icons/McpIcon/McpIcon',
|
|
30
|
+
})`
|
|
31
|
+
path {
|
|
32
|
+
stroke: ${({ color }) => getCssColorVariable(color)};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
height: ${({ size }) => size || '16px'};
|
|
36
|
+
width: ${({ size }) => size || '16px'};
|
|
37
|
+
`;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import type { IconProps } from '@redocly/theme/icons/types';
|
|
5
|
+
|
|
6
|
+
import { getCssColorVariable } from '@redocly/theme/core/utils';
|
|
7
|
+
|
|
8
|
+
const Icon = (props: IconProps) => (
|
|
9
|
+
<svg viewBox="0 0 24 24" fill="inherit" xmlns="http://www.w3.org/2000/svg" {...props}>
|
|
10
|
+
<path d="M12.87 15.07L10.33 12.56L10.36 12.53C12.1 10.59 13.34 8.36 14.07 6H17V4H10V2H8V4H1V6H12.17C11.5 7.92 10.44 9.75 9 11.35C8.07 10.32 7.3 9.19 6.69 8H4.69C5.42 9.63 6.42 11.17 7.67 12.56L2.58 17.58L4 19L9 14L12.11 17.11L12.87 15.07ZM18.5 10H16.5L12 22H14L15.12 19H19.87L21 22H23L18.5 10ZM15.88 17L17.5 12.67L19.12 17H15.88Z" />
|
|
11
|
+
</svg>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export const TranslateIcon = styled(Icon).attrs({
|
|
15
|
+
'data-component-name': 'icons/TranslateIcon/TranslateIcon',
|
|
16
|
+
})`
|
|
17
|
+
path {
|
|
18
|
+
fill: ${({ color }) => getCssColorVariable(color)};
|
|
19
|
+
}
|
|
20
|
+
height: ${({ size }) => size || '20px'};
|
|
21
|
+
width: ${({ size }) => size || '20px'};
|
|
22
|
+
`;
|
package/src/index.ts
CHANGED
|
@@ -46,6 +46,8 @@ export * from '@redocly/theme/components/Markdown/styles/heading-anchor';
|
|
|
46
46
|
export * from '@redocly/theme/components/Markdown/styles/links';
|
|
47
47
|
/* Admonition */
|
|
48
48
|
export * from '@redocly/theme/components/Admonition/Admonition';
|
|
49
|
+
/* MissingTranslationNotice */
|
|
50
|
+
export * from '@redocly/theme/components/MissingTranslationNotice/MissingTranslationNotice';
|
|
49
51
|
/* ApiOnboarding */
|
|
50
52
|
export * from '@redocly/theme/components/ApiOnboarding/AppCustomAttributes';
|
|
51
53
|
/* Navbar */
|
|
@@ -193,6 +195,8 @@ export * from '@redocly/theme/icons/SpinnerIcon/SpinnerIcon';
|
|
|
193
195
|
export * from '@redocly/theme/icons/ChatGptIcon/ChatGptIcon';
|
|
194
196
|
export * from '@redocly/theme/icons/CopyIcon/CopyIcon';
|
|
195
197
|
export * from '@redocly/theme/icons/ClaudeIcon/ClaudeIcon';
|
|
198
|
+
export * from '@redocly/theme/icons/GrokIcon/GrokIcon';
|
|
199
|
+
export * from '@redocly/theme/icons/McpIcon/McpIcon';
|
|
196
200
|
export * from '@redocly/theme/icons/CleanIcon/CleanIcon';
|
|
197
201
|
export * from '@redocly/theme/icons/GraphqlIcon/GraphqlIcon';
|
|
198
202
|
export * from '@redocly/theme/icons/DeselectIcon/DeselectIcon';
|
|
@@ -5,6 +5,7 @@ import type { JSX } from 'react';
|
|
|
5
5
|
|
|
6
6
|
import { H1_CLASS } from '@redocly/theme/core/constants';
|
|
7
7
|
import { breakpoints } from '@redocly/theme/core/utils';
|
|
8
|
+
import { MissingTranslationNotice } from '@redocly/theme/components/MissingTranslationNotice/MissingTranslationNotice';
|
|
8
9
|
|
|
9
10
|
export type CodeWalkthroughLayoutProps = React.PropsWithChildren<{
|
|
10
11
|
className?: string;
|
|
@@ -16,7 +17,10 @@ export function CodeWalkthroughLayout({
|
|
|
16
17
|
}: CodeWalkthroughLayoutProps): JSX.Element {
|
|
17
18
|
return (
|
|
18
19
|
<LayoutWrapper data-component-name="Layout/CodeWalkthroughLayout" className={className}>
|
|
19
|
-
<ContentWrapper>
|
|
20
|
+
<ContentWrapper>
|
|
21
|
+
<Notice />
|
|
22
|
+
{children}
|
|
23
|
+
</ContentWrapper>
|
|
20
24
|
</LayoutWrapper>
|
|
21
25
|
);
|
|
22
26
|
}
|
|
@@ -29,6 +33,12 @@ const LayoutWrapper = styled.div.attrs(({ className }) => ({
|
|
|
29
33
|
width: 100%;
|
|
30
34
|
`;
|
|
31
35
|
|
|
36
|
+
const Notice = styled(MissingTranslationNotice)`
|
|
37
|
+
max-width: var(--md-content-max-width);
|
|
38
|
+
margin-left: auto;
|
|
39
|
+
margin-right: auto;
|
|
40
|
+
`;
|
|
41
|
+
|
|
32
42
|
const ContentWrapper = styled.section`
|
|
33
43
|
width: 100%;
|
|
34
44
|
--md-content-font-size: var(--font-size-lg);
|
|
@@ -10,6 +10,7 @@ import { H1_CLASS } from '@redocly/theme/core/constants';
|
|
|
10
10
|
import { CodeSnippetProvider } from '@redocly/theme/core/contexts/CodeSnippetContext';
|
|
11
11
|
import { DocumentationLayoutTop } from '@redocly/theme/layouts/DocumentationLayoutTop';
|
|
12
12
|
import { DocumentationLayoutBottom } from '@redocly/theme/layouts/DocumentationLayoutBottom';
|
|
13
|
+
import { MissingTranslationNotice } from '@redocly/theme/components/MissingTranslationNotice/MissingTranslationNotice';
|
|
13
14
|
|
|
14
15
|
type DocumentationLayoutProps = {
|
|
15
16
|
tableOfContent: React.ReactNode;
|
|
@@ -48,6 +49,7 @@ export function DocumentationLayout({
|
|
|
48
49
|
>
|
|
49
50
|
<ContentWrapper>
|
|
50
51
|
<DocumentationLayoutTop config={config} editPage={editPage} lastModified={lastModified} />
|
|
52
|
+
<MissingTranslationNotice />
|
|
51
53
|
{children}
|
|
52
54
|
<DocumentationLayoutBottom feedback={feedback} nextPage={nextPage} prevPage={prevPage} />
|
|
53
55
|
</ContentWrapper>
|
package/src/markdoc/default.ts
CHANGED
|
@@ -33,6 +33,7 @@ import { icon } from '@redocly/theme/markdoc/tags/icon';
|
|
|
33
33
|
import { connectMcp } from '@redocly/theme/markdoc/tags/connect-mcp';
|
|
34
34
|
import { loginButton } from '@redocly/theme/markdoc/tags/login-button';
|
|
35
35
|
import { diagram } from '@redocly/theme/markdoc/tags/diagram';
|
|
36
|
+
import { visibility } from '@redocly/theme/markdoc/tags/visibility';
|
|
36
37
|
import { prompt } from '@redocly/theme/markdoc/tags/prompt';
|
|
37
38
|
|
|
38
39
|
export const tags = {
|
|
@@ -61,5 +62,6 @@ export const tags = {
|
|
|
61
62
|
[connectMcp.tagName]: connectMcp.schema,
|
|
62
63
|
[loginButton.tagName]: loginButton.schema,
|
|
63
64
|
[diagram.tagName]: diagram.schema,
|
|
65
|
+
[visibility.tagName]: visibility.schema,
|
|
64
66
|
[prompt.tagName]: prompt.schema,
|
|
65
67
|
};
|