@redocly/theme 0.69.0-next.0 → 0.69.0-next.10

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.
Files changed (293) hide show
  1. package/lib/components/Accordion/Accordion.js +5 -1
  2. package/lib/components/Accordion/variables.js +1 -1
  3. package/lib/components/Admonition/Admonition.d.ts +1 -1
  4. package/lib/components/Admonition/Admonition.js +1 -1
  5. package/lib/components/Admonition/variables.dark.js +2 -2
  6. package/lib/components/Admonition/variables.js +10 -10
  7. package/lib/components/Badge/Badge.d.ts +3 -1
  8. package/lib/components/Badge/Badge.js +7 -2
  9. package/lib/components/Banner/variables.dark.js +2 -0
  10. package/lib/components/Banner/variables.js +3 -1
  11. package/lib/components/Breadcrumbs/Breadcrumb.js +1 -1
  12. package/lib/components/Breadcrumbs/variables.js +1 -1
  13. package/lib/components/Button/ButtonGroup.d.ts +3 -5
  14. package/lib/components/Button/ButtonGroup.js +25 -5
  15. package/lib/components/Button/variables.js +27 -4
  16. package/lib/components/Buttons/ConnectMCPButton.js +39 -123
  17. package/lib/components/Buttons/CopyButton.js +12 -1
  18. package/lib/components/Buttons/variables.d.ts +0 -1
  19. package/lib/components/Buttons/variables.js +3 -44
  20. package/lib/components/Catalog/CatalogEntities.js +1 -0
  21. package/lib/components/Catalog/CatalogEntity/CatalogEntityLinks.js +1 -1
  22. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +1 -1
  23. package/lib/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath.js +1 -1
  24. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.js +5 -3
  25. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +1 -1
  26. package/lib/components/Catalog/CatalogFilter/CatalogFilterSelect.js +1 -0
  27. package/lib/components/Catalog/CatalogViewModeToggle.d.ts +1 -1
  28. package/lib/components/Catalog/CatalogViewModeToggle.js +2 -43
  29. package/lib/components/Catalog/variables.js +5 -5
  30. package/lib/components/CatalogClassic/variables.js +2 -2
  31. package/lib/components/CodeBlock/CodeBlock.js +2 -1
  32. package/lib/components/CodeBlock/CodeBlockContainer.js +1 -0
  33. package/lib/components/Dropdown/Dropdown.d.ts +10 -20
  34. package/lib/components/Dropdown/Dropdown.js +13 -2
  35. package/lib/components/Dropdown/DropdownMenuItemContent.d.ts +9 -0
  36. package/lib/components/Dropdown/DropdownMenuItemContent.js +56 -0
  37. package/lib/components/Dropdown/variables.js +19 -2
  38. package/lib/components/Feedback/Mood.js +18 -14
  39. package/lib/components/Feedback/Rating.js +18 -13
  40. package/lib/components/Feedback/Scale.js +27 -22
  41. package/lib/components/Feedback/Sentiment.js +17 -13
  42. package/lib/components/Filter/FilterInput.js +4 -2
  43. package/lib/components/Filter/FilterSelect.js +1 -0
  44. package/lib/components/Filter/variables.js +2 -2
  45. package/lib/components/Image/variables.js +5 -3
  46. package/lib/components/JsonViewer/Helpers.js +12 -42
  47. package/lib/components/LanguagePicker/variables.js +1 -1
  48. package/lib/components/MCP/McpConnectionTabs.d.ts +7 -0
  49. package/lib/components/MCP/McpConnectionTabs.js +151 -0
  50. package/lib/components/Markdown/Markdown.js +1 -1
  51. package/lib/components/Markdown/styles/base-table.js +8 -0
  52. package/lib/components/Markdown/variables.js +1 -1
  53. package/lib/components/Menu/MenuItem.js +1 -1
  54. package/lib/components/Menu/variables.js +1 -1
  55. package/lib/components/Navbar/variables.js +1 -1
  56. package/lib/components/PageActions/PageActions.js +4 -6
  57. package/lib/components/PageActions/PageActionsMenuItem.d.ts +4 -4
  58. package/lib/components/PageActions/PageActionsMenuItem.js +27 -43
  59. package/lib/components/Panel/Panel.js +5 -1
  60. package/lib/components/Panel/variables.js +1 -1
  61. package/lib/components/Product/variables.js +2 -1
  62. package/lib/components/ReplayGate/ReplayGate.d.ts +1 -0
  63. package/lib/components/Search/FilterFields/SearchFilterFieldSelect.js +22 -32
  64. package/lib/components/Search/SearchAiDialog.js +4 -1
  65. package/lib/components/Search/SearchAiMessage.js +1 -1
  66. package/lib/components/Search/SearchAiNegativeFeedbackForm.js +2 -2
  67. package/lib/components/Search/SearchDialog.js +2 -2
  68. package/lib/components/Search/SearchItem.js +6 -3
  69. package/lib/components/Search/SearchRecent.js +1 -0
  70. package/lib/components/Search/SearchSuggestedPages.js +1 -0
  71. package/lib/components/Search/variables.js +9 -5
  72. package/lib/components/Segmented/Segmented.js +3 -3
  73. package/lib/components/Select/Select.js +30 -23
  74. package/lib/components/Select/variables.js +3 -3
  75. package/lib/components/Sidebar/Sidebar.js +2 -38
  76. package/lib/components/SplitButton/SplitButton.d.ts +21 -0
  77. package/lib/components/SplitButton/SplitButton.js +37 -0
  78. package/lib/components/Switch/variables.dark.js +2 -2
  79. package/lib/components/Switch/variables.js +2 -2
  80. package/lib/components/Tag/variables.js +2 -2
  81. package/lib/components/Tags/variables.js +1 -1
  82. package/lib/components/Toast/variables.js +1 -1
  83. package/lib/components/Tooltip/AnchorTooltip.js +2 -2
  84. package/lib/components/Tooltip/JsTooltip.js +2 -2
  85. package/lib/components/UserMenu/variables.js +1 -1
  86. package/lib/core/constants/accordion.d.ts +3 -0
  87. package/lib/core/constants/accordion.js +7 -0
  88. package/lib/core/constants/index.d.ts +1 -0
  89. package/lib/core/constants/index.js +1 -0
  90. package/lib/core/constants/mcp.d.ts +4 -0
  91. package/lib/core/constants/mcp.js +10 -1
  92. package/lib/core/constants/search.js +2 -2
  93. package/lib/core/contexts/PageActionsContext.d.ts +5 -0
  94. package/lib/core/contexts/PageActionsContext.js +10 -0
  95. package/lib/core/contexts/index.d.ts +1 -0
  96. package/lib/core/contexts/index.js +1 -0
  97. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.js +5 -17
  98. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.js +1 -0
  99. package/lib/core/hooks/menu/use-menu-item-expanded.js +1 -0
  100. package/lib/core/hooks/use-active-heading.js +59 -15
  101. package/lib/core/hooks/use-active-section-id.js +3 -1
  102. package/lib/core/hooks/use-connect-mcp-button.d.ts +1 -1
  103. package/lib/core/hooks/use-connect-mcp-button.js +16 -13
  104. package/lib/core/hooks/use-control.js +3 -0
  105. package/lib/core/hooks/use-local-state.js +1 -0
  106. package/lib/core/hooks/use-mcp-config.d.ts +2 -0
  107. package/lib/core/hooks/use-mcp-config.js +14 -4
  108. package/lib/core/hooks/use-mobile-menu.js +10 -2
  109. package/lib/core/styles/global.js +56 -49
  110. package/lib/core/styles/palette.js +2 -0
  111. package/lib/core/types/button-group.d.ts +2 -0
  112. package/lib/core/types/button-group.js +3 -0
  113. package/lib/core/types/catalog.d.ts +2 -4
  114. package/lib/core/types/common.d.ts +2 -0
  115. package/lib/core/types/hooks.d.ts +1 -0
  116. package/lib/core/types/index.d.ts +1 -0
  117. package/lib/core/types/l10n.d.ts +1 -1
  118. package/lib/core/types/mcp.d.ts +1 -1
  119. package/lib/core/utils/RenderWithLink.d.ts +2 -0
  120. package/lib/core/utils/RenderWithLink.js +20 -0
  121. package/lib/core/utils/index.d.ts +1 -0
  122. package/lib/core/utils/index.js +1 -0
  123. package/lib/core/utils/mcp.d.ts +5 -0
  124. package/lib/core/utils/mcp.js +35 -0
  125. package/lib/icons/CodexIcon/CodexIcon.d.ts +25 -0
  126. package/lib/icons/CodexIcon/CodexIcon.js +22 -0
  127. package/lib/icons/LinkIcon/LinkIcon.js +1 -1
  128. package/lib/index.d.ts +2 -0
  129. package/lib/index.js +2 -0
  130. package/lib/layouts/McpNotAllowed.js +10 -10
  131. package/lib/markdoc/components/Accordion/Accordion.d.ts +9 -0
  132. package/lib/markdoc/components/Accordion/Accordion.js +132 -0
  133. package/lib/markdoc/components/Accordion/AccordionGroup.d.ts +5 -0
  134. package/lib/markdoc/components/Accordion/AccordionGroup.js +29 -0
  135. package/lib/markdoc/components/Accordion/variables.d.ts +1 -0
  136. package/lib/markdoc/components/Accordion/variables.js +40 -0
  137. package/lib/markdoc/components/Cards/Card.d.ts +8 -1
  138. package/lib/markdoc/components/Cards/Card.js +55 -16
  139. package/lib/markdoc/components/Cards/CardBadge.d.ts +9 -0
  140. package/lib/markdoc/components/Cards/CardBadge.js +30 -0
  141. package/lib/markdoc/components/Cards/CardIcon.d.ts +5 -4
  142. package/lib/markdoc/components/Cards/CardIcon.js +6 -3
  143. package/lib/markdoc/components/Cards/variables.dark.js +32 -0
  144. package/lib/markdoc/components/Cards/variables.js +81 -7
  145. package/lib/markdoc/components/CodeWalkthrough/CodePanel.js +1 -0
  146. package/lib/markdoc/components/CodeWalkthrough/CodeStep.js +1 -1
  147. package/lib/markdoc/components/CodeWalkthrough/variables.js +2 -1
  148. package/lib/markdoc/components/Heading/Heading.js +5 -2
  149. package/lib/markdoc/components/Tabs/TabList.js +6 -2
  150. package/lib/markdoc/components/Tabs/Tabs.js +4 -2
  151. package/lib/markdoc/components/Tabs/variables.js +4 -4
  152. package/lib/markdoc/components/default.d.ts +2 -0
  153. package/lib/markdoc/components/default.js +2 -0
  154. package/lib/markdoc/default.d.ts +4 -0
  155. package/lib/markdoc/default.js +4 -0
  156. package/lib/markdoc/tags/accordion-group.d.ts +2 -0
  157. package/lib/markdoc/tags/accordion-group.js +10 -0
  158. package/lib/markdoc/tags/accordion.d.ts +2 -0
  159. package/lib/markdoc/tags/accordion.js +14 -0
  160. package/lib/markdoc/tags/admonition.js +1 -1
  161. package/lib/markdoc/tags/card.js +14 -0
  162. package/lib/markdoc/tags/connect-mcp.js +2 -1
  163. package/package.json +19 -10
  164. package/src/components/Accordion/Accordion.tsx +7 -3
  165. package/src/components/Accordion/variables.ts +1 -1
  166. package/src/components/Admonition/Admonition.tsx +2 -2
  167. package/src/components/Admonition/variables.dark.ts +2 -2
  168. package/src/components/Admonition/variables.ts +10 -10
  169. package/src/components/Badge/Badge.tsx +16 -2
  170. package/src/components/Banner/variables.dark.ts +2 -0
  171. package/src/components/Banner/variables.ts +3 -1
  172. package/src/components/Breadcrumbs/Breadcrumb.tsx +1 -1
  173. package/src/components/Breadcrumbs/variables.ts +1 -1
  174. package/src/components/Button/ButtonGroup.tsx +28 -10
  175. package/src/components/Button/variables.ts +27 -4
  176. package/src/components/Buttons/ConnectMCPButton.tsx +88 -145
  177. package/src/components/Buttons/CopyButton.tsx +14 -2
  178. package/src/components/Buttons/variables.ts +2 -44
  179. package/src/components/Catalog/CatalogEntities.tsx +1 -0
  180. package/src/components/Catalog/CatalogEntity/CatalogEntityLinks.tsx +1 -1
  181. package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +1 -1
  182. package/src/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath.tsx +1 -1
  183. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.tsx +6 -4
  184. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +1 -1
  185. package/src/components/Catalog/CatalogFilter/CatalogFilterSelect.tsx +1 -0
  186. package/src/components/Catalog/CatalogViewModeToggle.tsx +2 -17
  187. package/src/components/Catalog/variables.ts +5 -5
  188. package/src/components/CatalogClassic/variables.ts +2 -2
  189. package/src/components/CodeBlock/CodeBlock.tsx +2 -1
  190. package/src/components/CodeBlock/CodeBlockContainer.tsx +1 -0
  191. package/src/components/Dropdown/Dropdown.tsx +25 -4
  192. package/src/components/Dropdown/DropdownMenuItemContent.tsx +72 -0
  193. package/src/components/Dropdown/variables.ts +19 -2
  194. package/src/components/Feedback/Mood.tsx +22 -15
  195. package/src/components/Feedback/Rating.tsx +22 -14
  196. package/src/components/Feedback/Scale.tsx +40 -32
  197. package/src/components/Feedback/Sentiment.tsx +21 -14
  198. package/src/components/Filter/FilterInput.tsx +5 -3
  199. package/src/components/Filter/FilterSelect.tsx +1 -0
  200. package/src/components/Filter/variables.ts +2 -2
  201. package/src/components/Image/variables.ts +5 -3
  202. package/src/components/JsonViewer/Helpers.tsx +13 -9
  203. package/src/components/LanguagePicker/variables.ts +1 -1
  204. package/src/components/MCP/McpConnectionTabs.tsx +263 -0
  205. package/src/components/Markdown/Markdown.tsx +2 -1
  206. package/src/components/Markdown/styles/base-table.ts +8 -0
  207. package/src/components/Markdown/variables.ts +1 -1
  208. package/src/components/Menu/MenuItem.tsx +2 -2
  209. package/src/components/Menu/variables.ts +1 -1
  210. package/src/components/Navbar/variables.ts +1 -1
  211. package/src/components/PageActions/PageActions.tsx +22 -23
  212. package/src/components/PageActions/PageActionsMenuItem.tsx +41 -55
  213. package/src/components/Panel/Panel.tsx +7 -3
  214. package/src/components/Panel/variables.ts +1 -1
  215. package/src/components/Product/variables.ts +2 -1
  216. package/src/components/ReplayGate/ReplayGate.tsx +3 -0
  217. package/src/components/Search/FilterFields/SearchFilterFieldSelect.tsx +32 -40
  218. package/src/components/Search/SearchAiDialog.tsx +4 -1
  219. package/src/components/Search/SearchAiMessage.tsx +1 -1
  220. package/src/components/Search/SearchAiNegativeFeedbackForm.tsx +2 -2
  221. package/src/components/Search/SearchDialog.tsx +2 -2
  222. package/src/components/Search/SearchItem.tsx +7 -1
  223. package/src/components/Search/SearchRecent.tsx +1 -0
  224. package/src/components/Search/SearchSuggestedPages.tsx +1 -0
  225. package/src/components/Search/variables.ts +9 -5
  226. package/src/components/Segmented/Segmented.tsx +6 -3
  227. package/src/components/Select/Select.tsx +36 -22
  228. package/src/components/Select/variables.ts +3 -3
  229. package/src/components/Sidebar/Sidebar.tsx +2 -6
  230. package/src/components/SplitButton/SplitButton.tsx +95 -0
  231. package/src/components/Switch/variables.dark.ts +2 -2
  232. package/src/components/Switch/variables.ts +2 -2
  233. package/src/components/Tag/variables.ts +2 -2
  234. package/src/components/Tags/variables.ts +1 -1
  235. package/src/components/Toast/variables.ts +1 -1
  236. package/src/components/Tooltip/AnchorTooltip.tsx +2 -2
  237. package/src/components/Tooltip/JsTooltip.tsx +2 -2
  238. package/src/components/UserMenu/variables.ts +1 -1
  239. package/src/core/constants/accordion.ts +4 -0
  240. package/src/core/constants/index.ts +1 -0
  241. package/src/core/constants/mcp.ts +14 -0
  242. package/src/core/constants/search.ts +2 -2
  243. package/src/core/contexts/PageActionsContext.tsx +7 -0
  244. package/src/core/contexts/index.ts +1 -0
  245. package/src/core/hooks/code-walkthrough/use-code-walkthrough-controls.ts +6 -20
  246. package/src/core/hooks/code-walkthrough/use-code-walkthrough-steps.ts +1 -0
  247. package/src/core/hooks/menu/use-menu-item-expanded.ts +1 -0
  248. package/src/core/hooks/use-active-heading.ts +79 -15
  249. package/src/core/hooks/use-active-section-id.ts +3 -1
  250. package/src/core/hooks/use-connect-mcp-button.ts +23 -15
  251. package/src/core/hooks/use-control.ts +5 -1
  252. package/src/core/hooks/use-local-state.ts +1 -0
  253. package/src/core/hooks/use-mcp-config.ts +15 -4
  254. package/src/core/hooks/use-mobile-menu.ts +11 -3
  255. package/src/core/openapi/index.ts +1 -1
  256. package/src/core/styles/global.ts +19 -12
  257. package/src/core/styles/palette.ts +2 -0
  258. package/src/core/types/button-group.ts +2 -0
  259. package/src/core/types/catalog.ts +2 -4
  260. package/src/core/types/common.ts +3 -0
  261. package/src/core/types/hooks.ts +1 -0
  262. package/src/core/types/index.ts +1 -0
  263. package/src/core/types/l10n.ts +29 -1
  264. package/src/core/types/mcp.ts +1 -1
  265. package/src/core/utils/RenderWithLink.tsx +19 -0
  266. package/src/core/utils/index.ts +1 -0
  267. package/src/core/utils/mcp.ts +39 -0
  268. package/src/icons/CodexIcon/CodexIcon.tsx +23 -0
  269. package/src/icons/LinkIcon/LinkIcon.tsx +1 -1
  270. package/src/index.ts +2 -0
  271. package/src/layouts/McpNotAllowed.tsx +37 -11
  272. package/src/markdoc/components/Accordion/Accordion.tsx +128 -0
  273. package/src/markdoc/components/Accordion/AccordionGroup.tsx +41 -0
  274. package/src/markdoc/components/Accordion/variables.ts +37 -0
  275. package/src/markdoc/components/Cards/Card.tsx +79 -14
  276. package/src/markdoc/components/Cards/CardBadge.tsx +39 -0
  277. package/src/markdoc/components/Cards/CardIcon.tsx +16 -5
  278. package/src/markdoc/components/Cards/variables.dark.ts +32 -0
  279. package/src/markdoc/components/Cards/variables.ts +81 -7
  280. package/src/markdoc/components/CodeWalkthrough/CodePanel.tsx +1 -0
  281. package/src/markdoc/components/CodeWalkthrough/CodeStep.tsx +1 -1
  282. package/src/markdoc/components/CodeWalkthrough/variables.ts +2 -1
  283. package/src/markdoc/components/Heading/Heading.tsx +7 -4
  284. package/src/markdoc/components/Tabs/TabList.tsx +6 -2
  285. package/src/markdoc/components/Tabs/Tabs.tsx +4 -2
  286. package/src/markdoc/components/Tabs/variables.ts +4 -4
  287. package/src/markdoc/components/default.ts +2 -0
  288. package/src/markdoc/default.ts +4 -0
  289. package/src/markdoc/tags/accordion-group.ts +8 -0
  290. package/src/markdoc/tags/accordion.ts +12 -0
  291. package/src/markdoc/tags/admonition.ts +1 -1
  292. package/src/markdoc/tags/card.ts +14 -0
  293. package/src/markdoc/tags/connect-mcp.ts +3 -1
@@ -22,7 +22,7 @@ export const languagePicker = css`
22
22
  --language-picker-dropdown-item-padding-vertical: var(--dropdown-menu-item-padding-vertical); // @presenter Spacing
23
23
  --language-picker-dropdown-item-separator-padding-top: var(--dropdown-menu-item-separator-padding-top ); // @presenter Spacing
24
24
  --language-picker-dropdown-item-separator-padding-bottom: var(--dropdown-menu-item-separator-padding-bottom ); // @presenter Spacing
25
- --language-picker-dropdown-item-border-radius: var(--dropdown-menu-item-border-radius ); // @presenter BorderRadius
25
+ --language-picker-dropdown-item-border-radius: var(--dropdown-menu-item-border-radius); // @presenter BorderRadius
26
26
  --language-picker-dropdown-item-bg-color-active: var(--dropdown-menu-item-bg-color-active); // @presenter Color
27
27
  --language-picker-dropdown-item-bg-color-hover: var(--dropdown-menu-item-bg-color-hover); // @presenter Color
28
28
  --language-picker-dropdown-item-bg-color-disabled: var(--dropdown-menu-item-bg-color-disabled); // @presenter Color
@@ -0,0 +1,263 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { JSX, ReactNode } from 'react';
5
+ import type { TFunction } from '@redocly/theme/core/types';
6
+
7
+ import { useMCPConfig, useThemeHooks } from '@redocly/theme/core/hooks';
8
+ import {
9
+ generateClaudeCodeCommand,
10
+ generateClaudeDesktopConfig,
11
+ generateCodexCommand,
12
+ generateMcpInstallPrompt,
13
+ } from '@redocly/theme/core/utils';
14
+ import { CodeBlock } from '@redocly/theme/components/CodeBlock/CodeBlock';
15
+ import { ClaudeIcon } from '@redocly/theme/icons/ClaudeIcon/ClaudeIcon';
16
+ import { ChatGptIcon } from '@redocly/theme/icons/ChatGptIcon/ChatGptIcon';
17
+ import { Tabs, TabsSize } from '@redocly/theme/markdoc/components/Tabs/Tabs';
18
+ import { TabItemFragment } from '@redocly/theme/markdoc/components/Tabs/TabItemFragment';
19
+ import { NumberedList } from '@redocly/theme/markdoc/components/NumberedList/NumberedList';
20
+ import { NumberedItem } from '@redocly/theme/markdoc/components/NumberedList/NumberedItem';
21
+
22
+ export type McpConnectionTab = 'claude' | 'chatgpt' | 'json';
23
+
24
+ export type McpConnectionTabsProps = {
25
+ options?: McpConnectionTab[];
26
+ className?: string;
27
+ };
28
+
29
+ const DEFAULT_TAB_OPTIONS: McpConnectionTab[] = ['claude', 'chatgpt', 'json'];
30
+
31
+ const TAB_LABELS: Record<
32
+ McpConnectionTab,
33
+ { translationKey: string; defaultLabel: string; icon?: React.ComponentType }
34
+ > = {
35
+ claude: {
36
+ translationKey: 'page.mcpNotAllowed.tabs.claude',
37
+ defaultLabel: 'Claude',
38
+ icon: ClaudeIcon,
39
+ },
40
+ chatgpt: {
41
+ translationKey: 'page.mcpNotAllowed.tabs.chatgpt',
42
+ defaultLabel: 'ChatGPT',
43
+ icon: ChatGptIcon,
44
+ },
45
+ json: { translationKey: 'page.mcpNotAllowed.tabs.json', defaultLabel: 'JSON' },
46
+ };
47
+
48
+ type TabClient = { headline: string; content: ReactNode };
49
+
50
+ // The report control is docs feedback, not useful on the connection page.
51
+ const CODE_BLOCK_HEADER = { controls: { copy: {}, report: { hidden: true } } };
52
+
53
+ export function McpConnectionTabs({
54
+ options = DEFAULT_TAB_OPTIONS,
55
+ className,
56
+ }: McpConnectionTabsProps): JSX.Element | null {
57
+ const { useTranslate } = useThemeHooks();
58
+ const { translate } = useTranslate();
59
+ const { serverName, serverUrl, isMcpDisabled } = useMCPConfig();
60
+ // The SSR markup of error pages is cached with the build-time origin, so the
61
+ // tabs remount after hydration to pick up the real browser origin.
62
+ const [hydrated, setHydrated] = useState(false);
63
+
64
+ useEffect(() => setHydrated(true), []);
65
+
66
+ if (isMcpDisabled) {
67
+ return null;
68
+ }
69
+
70
+ const connection = { serverName, url: serverUrl };
71
+
72
+ return (
73
+ <McpConnectionTabsWrapper
74
+ key={hydrated ? 'client' : 'ssr'}
75
+ data-component-name="MCP/McpConnectionTabs"
76
+ data-testid="mcp-connection-tabs"
77
+ className={className}
78
+ >
79
+ <Tabs size={TabsSize.SMALL}>
80
+ {options.map((option) => {
81
+ const { translationKey, defaultLabel, icon: TabIcon } = TAB_LABELS[option];
82
+
83
+ return (
84
+ <TabItemFragment
85
+ key={option}
86
+ label={translate(translationKey, defaultLabel)}
87
+ icon={TabIcon ? <TabIcon /> : undefined}
88
+ >
89
+ {renderTabContent(option, connection, translate)}
90
+ </TabItemFragment>
91
+ );
92
+ })}
93
+ </Tabs>
94
+ </McpConnectionTabsWrapper>
95
+ );
96
+ }
97
+
98
+ function renderTabContent(
99
+ option: McpConnectionTab,
100
+ connection: { serverName: string; url: string },
101
+ translate: TFunction,
102
+ ): ReactNode {
103
+ const terminalHint = (
104
+ <TabHint>
105
+ {translate('page.mcpNotAllowed.snippets.terminal.hint', 'Run this command in your terminal:')}
106
+ </TabHint>
107
+ );
108
+
109
+ const urlBlock = <CodeBlock lang="text" source={connection.url} header={CODE_BLOCK_HEADER} />;
110
+
111
+ const assistantPromptClient: TabClient = {
112
+ headline: translate('page.mcpNotAllowed.snippets.prompt.headline', 'Prompt'),
113
+ content: (
114
+ <>
115
+ <TabHint>
116
+ {translate(
117
+ 'page.mcpNotAllowed.snippets.prompt.hint',
118
+ 'Or paste this prompt into the chat to have it add the server for you:',
119
+ )}
120
+ </TabHint>
121
+ <CodeBlock
122
+ lang="text"
123
+ source={generateMcpInstallPrompt(connection)}
124
+ header={CODE_BLOCK_HEADER}
125
+ wrapContents
126
+ />
127
+ </>
128
+ ),
129
+ };
130
+
131
+ switch (option) {
132
+ case 'claude':
133
+ return renderClientList([
134
+ {
135
+ headline: translate('page.mcpNotAllowed.snippets.claudeCode.headline', 'Claude Code'),
136
+ content: (
137
+ <>
138
+ {terminalHint}
139
+ <CodeBlock
140
+ lang="shell"
141
+ source={generateClaudeCodeCommand(connection)}
142
+ header={CODE_BLOCK_HEADER}
143
+ wrapContents
144
+ />
145
+ </>
146
+ ),
147
+ },
148
+ {
149
+ headline: translate(
150
+ 'page.mcpNotAllowed.snippets.claudeDesktop.headline',
151
+ 'Claude Desktop',
152
+ ),
153
+ content: (
154
+ <>
155
+ <TabHint>
156
+ {translate(
157
+ 'page.mcpNotAllowed.snippets.claudeDesktop.instruction',
158
+ 'In Claude Desktop, open Settings → Developer → Edit Config, add this to the configuration file, and restart Claude Desktop:',
159
+ )}
160
+ </TabHint>
161
+ <CodeBlock
162
+ lang="json"
163
+ source={generateClaudeDesktopConfig(connection)}
164
+ header={CODE_BLOCK_HEADER}
165
+ />
166
+ </>
167
+ ),
168
+ },
169
+ ]);
170
+ case 'chatgpt':
171
+ return renderClientList([
172
+ {
173
+ headline: translate('page.mcpNotAllowed.snippets.codexCli.headline', 'Codex CLI'),
174
+ content: (
175
+ <>
176
+ {terminalHint}
177
+ <CodeBlock
178
+ lang="shell"
179
+ source={generateCodexCommand(connection)}
180
+ header={CODE_BLOCK_HEADER}
181
+ wrapContents
182
+ />
183
+ </>
184
+ ),
185
+ },
186
+ {
187
+ headline: translate(
188
+ 'page.mcpNotAllowed.snippets.chatgptApp.headline',
189
+ 'ChatGPT desktop app',
190
+ ),
191
+ content: (
192
+ <>
193
+ <TabHint>
194
+ {translate(
195
+ 'page.mcpNotAllowed.snippets.chatgptApp.instruction',
196
+ 'In the ChatGPT desktop app, go to Settings → Plugins → MCPs and add a server with the "Streamable HTTP" type and this URL (restart the app afterwards):',
197
+ )}
198
+ </TabHint>
199
+ {urlBlock}
200
+ </>
201
+ ),
202
+ },
203
+ assistantPromptClient,
204
+ ]);
205
+ case 'json':
206
+ return (
207
+ <>
208
+ <TabHint>
209
+ {translate(
210
+ 'page.mcpNotAllowed.snippets.json.hint',
211
+ 'Add this server entry to your MCP client configuration file:',
212
+ )}
213
+ </TabHint>
214
+ <CodeBlock
215
+ lang="json"
216
+ source={JSON.stringify(
217
+ { [connection.serverName]: { url: connection.url, description: 'MCP Server' } },
218
+ null,
219
+ 2,
220
+ )}
221
+ header={CODE_BLOCK_HEADER}
222
+ />
223
+ </>
224
+ );
225
+ }
226
+ }
227
+
228
+ function renderClientList(clients: TabClient[]): ReactNode {
229
+ return (
230
+ <NumberedList>
231
+ {clients.map((client, index) => (
232
+ <NumberedItem
233
+ key={index}
234
+ type="dot"
235
+ size="small"
236
+ headline={client.headline}
237
+ index={index + 1}
238
+ isLast={index === clients.length - 1}
239
+ >
240
+ {client.content}
241
+ </NumberedItem>
242
+ ))}
243
+ </NumberedList>
244
+ );
245
+ }
246
+
247
+ const McpConnectionTabsWrapper = styled.div`
248
+ --md-numbered-list-margin: 0 0 var(--spacing-sm);
249
+
250
+ font-size: var(--page-mcp-405-snippets-font-size);
251
+ line-height: var(--page-mcp-405-snippets-line-height);
252
+ text-align: left;
253
+
254
+ /* The copy control floats over the code, so wrapped lines need room to clear it. */
255
+ pre[data-testid='source-code'] {
256
+ padding-right: var(--page-mcp-405-snippets-code-padding-right);
257
+ }
258
+ `;
259
+
260
+ const TabHint = styled.p`
261
+ margin: 0 0 var(--spacing-xs);
262
+ color: var(--page-mcp-405-snippets-hint-text-color);
263
+ `;
@@ -7,6 +7,7 @@ import { markdownBaseTableCss } from '@redocly/theme/components/Markdown/styles/
7
7
  import { markdownLinksCss } from '@redocly/theme/components/Markdown/styles/links';
8
8
  import { headingAnchorCss } from '@redocly/theme/components/Markdown/styles/heading-anchor';
9
9
  import {
10
+ ACCORDION_SELECTOR,
10
11
  ANCHOR_CLASS,
11
12
  H1_CLASS,
12
13
  H2_CLASS,
@@ -172,7 +173,7 @@ export const Markdown = styled.main
172
173
  margin: var(--md-hr-margin-vertical) 0;
173
174
  }
174
175
 
175
- details {
176
+ details:not(${ACCORDION_SELECTOR}) {
176
177
  margin: 1.125em 0;
177
178
 
178
179
  summary {
@@ -45,6 +45,14 @@ export const markdownBaseTableCss = css`
45
45
  background-color: var(--md-table-header-bg-color);
46
46
  }
47
47
 
48
+ /* hide the header row when every cell is empty; one labelled cell keeps it visible */
49
+ thead:has(th:empty) {
50
+ display: none;
51
+ }
52
+ thead:has(th:not(:empty)) {
53
+ display: table-header-group;
54
+ }
55
+
48
56
  tr {
49
57
  background-color: var(--md-table-stripe-bg-color);
50
58
  }
@@ -40,7 +40,7 @@ export const markdown = css`
40
40
  --md-table-line-height: var(--line-height-md); // @presenter FontSize
41
41
  --md-table-margin-vertical: 20px; // @presenter Spacing
42
42
  --md-table-bg-color: transparent; // @presenter Color
43
- --md-table-border-radius: var(--border-radius);
43
+ --md-table-border-radius: var(--border-radius-xl);
44
44
 
45
45
  --md-table-border-width: 1px;
46
46
  --md-table-header-bg-color: var(--layer-color);
@@ -122,8 +122,8 @@ function MenuItemImpl(props: React.PropsWithChildren<MenuItemProps>): JSX.Elemen
122
122
  onClick={handleOnClick}
123
123
  onKeyDown={handleExpandOnEnter}
124
124
  ref={labelRef}
125
- role={item.link ? 'none' : 'link'}
126
- tabIndex={!item.link ? 0 : undefined}
125
+ role={item.link || isSeparator ? 'none' : 'link'}
126
+ tabIndex={!item.link && !isSeparator ? 0 : undefined}
127
127
  data-testid="menu-item-label"
128
128
  data-active={item.active}
129
129
  >
@@ -56,7 +56,7 @@ export const menu = css`
56
56
  --menu-item-label-margin: var(--menu-item-label-margin-vertical) var(--menu-item-label-margin-horizontal);
57
57
  --menu-item-label-padding: var(--menu-item-padding-vertical) var(--menu-item-padding-horizontal);
58
58
  --menu-item-label-gap: var(--spacing-xxs);
59
- --menu-item-label-border-radius: 6px;
59
+ --menu-item-label-border-radius: var(--border-radius-lg);
60
60
  --menu-item-label-chevron-size: 12px;
61
61
  --menu-item-label-chevron-offset: calc(var(--menu-item-label-gap) + var(--menu-item-label-chevron-size));
62
62
 
@@ -27,7 +27,7 @@ export const navbar = css`
27
27
 
28
28
  --navbar-item-line-height: var(--line-height-base);
29
29
  --navbar-item-bg-color-active: var(--bg-color-active);
30
- --navbar-item-border-radius: var(--border-radius);
30
+ --navbar-item-border-radius: var(--border-radius-lg);
31
31
  --navbar-item-bottom-border: none;
32
32
 
33
33
  --navbar-item-text-color-hover: var(--text-color-primary);
@@ -7,13 +7,12 @@ import type { PageAction } from '@redocly/theme/core/types';
7
7
  import { PageActionsMenuItem } from '@redocly/theme/components/PageActions/PageActionsMenuItem';
8
8
  import { DropdownMenuItem } from '@redocly/theme/components/Dropdown/DropdownMenuItem';
9
9
  import { Link } from '@redocly/theme/components/Link/Link';
10
- import { ButtonGroup } from '@redocly/theme/components/Button/ButtonGroup';
11
10
  import { Button } from '@redocly/theme/components/Button/Button';
12
- import { Dropdown } from '@redocly/theme/components/Dropdown/Dropdown';
11
+ import { SplitButton } from '@redocly/theme/components/SplitButton/SplitButton';
13
12
  import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu';
14
13
  import { Spinner } from '@redocly/theme/icons/Spinner/Spinner';
15
14
  import { CheckmarkFilledIcon } from '@redocly/theme/icons/CheckmarkFilledIcon/CheckmarkFilledIcon';
16
- import { PageActionType, usePageActions } from '@redocly/theme/core/hooks';
15
+ import { PageActionType, usePageActions, useThemeHooks } from '@redocly/theme/core/hooks';
17
16
 
18
17
  type ActionState = 'idle' | 'processing' | 'done';
19
18
 
@@ -28,6 +27,8 @@ const ACTION_DONE_DISPLAY_DURATION = 1000;
28
27
  export function PageActions(props: PageActionProps): JSX.Element | null {
29
28
  const { pageSlug, mcpUrl } = props;
30
29
 
30
+ const { useTranslate } = useThemeHooks();
31
+ const { translate } = useTranslate();
31
32
  const actions = usePageActions(pageSlug || '/', mcpUrl, props.actions);
32
33
 
33
34
  const [actionState, setActionState] = useState<ActionState>('idle');
@@ -73,27 +74,25 @@ export function PageActions(props: PageActionProps): JSX.Element | null {
73
74
 
74
75
  return (
75
76
  <PageActionsWrapper data-component-name="PageActions/PageActions">
76
- <ButtonGroup variant="outlined" size="medium">
77
- <Button
78
- icon={renderIcon(buttonAction, actionState)}
79
- to={'link' in buttonAction ? buttonAction.link : undefined}
80
- external
81
- onClick={() => handleActionClick(buttonAction)}
82
- >
83
- {buttonAction.buttonText}
84
- </Button>
85
- {actions.length > 1 ? (
86
- <Dropdown
87
- withArrow
88
- portalled
89
- trigger={<Button aria-label="More actions" />}
90
- placement="bottom"
91
- alignment="end"
77
+ <SplitButton
78
+ portalled
79
+ variant="outlined"
80
+ size="medium"
81
+ toggleAriaLabel={translate('page.actions.moreActions', 'More actions')}
82
+ button={
83
+ <Button
84
+ variant="outlined"
85
+ icon={renderIcon(buttonAction, actionState)}
86
+ to={'link' in buttonAction ? buttonAction.link : undefined}
87
+ external
88
+ onClick={() => handleActionClick(buttonAction)}
92
89
  >
93
- <StyledDropdownMenu>{menuItems}</StyledDropdownMenu>
94
- </Dropdown>
95
- ) : null}
96
- </ButtonGroup>
90
+ {buttonAction.buttonText}
91
+ </Button>
92
+ }
93
+ >
94
+ {actions.length > 1 ? <StyledDropdownMenu>{menuItems}</StyledDropdownMenu> : null}
95
+ </SplitButton>
97
96
  </PageActionsWrapper>
98
97
  );
99
98
  }
@@ -1,73 +1,59 @@
1
1
  import React from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
+ import type { JSX } from 'react';
4
5
  import type { PageAction } from '@redocly/theme/core/types';
5
6
 
7
+ import { DropdownMenuItemContent } from '@redocly/theme/components/Dropdown/DropdownMenuItemContent';
6
8
  import { LaunchIcon } from '@redocly/theme/icons/LaunchIcon/LaunchIcon';
7
9
 
8
- type PageActionsMenuItemProps = {
10
+ export type PageActionsMenuItemProps = {
9
11
  pageAction: PageAction;
12
+ className?: string;
10
13
  };
11
14
 
12
- export function PageActionsMenuItem(props: PageActionsMenuItemProps) {
13
- const { pageAction } = props;
15
+ export function PageActionsMenuItem(props: PageActionsMenuItemProps): JSX.Element {
16
+ const { pageAction, className } = props;
14
17
 
15
18
  return (
16
- <MenuItemWrapper data-component-name="PageActions/PageActionsMenuItem">
17
- <IconWrapper>
18
- <pageAction.iconComponent />
19
- </IconWrapper>
20
- <ContentWrapper>
21
- <Title>
22
- {pageAction.title}
23
- {'link' in pageAction ? (
24
- <LaunchIcon color="var(--page-actions-menu-item-title-icon-color)" size="14px" />
25
- ) : null}
26
- </Title>
27
- <Description>{pageAction.description}</Description>
28
- </ContentWrapper>
19
+ <MenuItemWrapper data-component-name="PageActions/PageActionsMenuItem" className={className}>
20
+ <DropdownMenuItemContent
21
+ icon={<pageAction.iconComponent />}
22
+ title={
23
+ <>
24
+ {pageAction.title}
25
+ {'link' in pageAction ? (
26
+ <LaunchIcon color="var(--page-actions-menu-item-title-icon-color)" size="14px" />
27
+ ) : null}
28
+ </>
29
+ }
30
+ description={pageAction.description}
31
+ />
29
32
  </MenuItemWrapper>
30
33
  );
31
34
  }
32
35
 
33
36
  const MenuItemWrapper = styled.div`
34
- padding: var(--page-actions-menu-item-padding);
35
- display: flex;
36
- flex-direction: row;
37
- align-items: center;
38
- gap: var(--page-actions-menu-item-gap);
39
- `;
40
-
41
- const IconWrapper = styled.div`
42
- color: var(--page-actions-menu-item-icon-color);
43
- border: 1px solid var(--page-actions-menu-item-icon-border-color);
44
- border-radius: var(--page-actions-menu-item-icon-border-radius);
45
- width: var(--page-actions-menu-item-icon-wrapper-size);
46
- height: var(--page-actions-menu-item-icon-wrapper-size);
47
- display: flex;
48
- align-items: center;
49
- justify-content: center;
50
- `;
51
-
52
- const ContentWrapper = styled.div`
53
- display: flex;
54
- flex-direction: column;
55
- gap: var(--page-actions-menu-item-text-gap);
56
- `;
57
-
58
- const Title = styled.div`
59
- font-weight: var(--page-actions-menu-item-title-font-weight);
60
- font-size: var(--page-actions-menu-item-title-font-size);
61
- line-height: var(--page-actions-menu-item-title-line-height);
62
- color: var(--page-actions-menu-item-title-color);
63
- display: flex;
64
- align-items: center;
65
- gap: var(--page-actions-menu-item-title-icon-gap);
66
- `;
67
-
68
- const Description = styled.div`
69
- font-weight: var(--page-actions-menu-item-description-font-weight);
70
- font-size: var(--page-actions-menu-item-description-font-size);
71
- line-height: var(--page-actions-menu-item-description-line-height);
72
- color: var(--page-actions-menu-item-description-color);
37
+ --dropdown-menu-item-content-gap: var(--page-actions-menu-item-gap);
38
+ --dropdown-menu-item-content-padding: var(--page-actions-menu-item-padding);
39
+ --dropdown-menu-item-content-icon-size: var(--page-actions-menu-item-icon-wrapper-size);
40
+ --dropdown-menu-item-content-icon-color: var(--page-actions-menu-item-icon-color);
41
+ --dropdown-menu-item-content-icon-border: 1px solid var(--page-actions-menu-item-icon-border-color);
42
+ --dropdown-menu-item-content-icon-border-radius: var(--page-actions-menu-item-icon-border-radius);
43
+ --dropdown-menu-item-content-text-gap: var(--page-actions-menu-item-text-gap);
44
+ --dropdown-menu-item-content-title-icon-gap: var(--page-actions-menu-item-title-icon-gap);
45
+ --dropdown-menu-item-content-title-font-weight: var(--page-actions-menu-item-title-font-weight);
46
+ --dropdown-menu-item-content-title-font-size: var(--page-actions-menu-item-title-font-size);
47
+ --dropdown-menu-item-content-title-line-height: var(--page-actions-menu-item-title-line-height);
48
+ --dropdown-menu-item-content-title-color: var(--page-actions-menu-item-title-color);
49
+ --dropdown-menu-item-content-description-font-weight: var(
50
+ --page-actions-menu-item-description-font-weight
51
+ );
52
+ --dropdown-menu-item-content-description-font-size: var(
53
+ --page-actions-menu-item-description-font-size
54
+ );
55
+ --dropdown-menu-item-content-description-line-height: var(
56
+ --page-actions-menu-item-description-line-height
57
+ );
58
+ --dropdown-menu-item-content-description-color: var(--page-actions-menu-item-description-color);
73
59
  `;
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import React, { useState } from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
4
  import type { BaseSyntheticEvent, PropsWithChildren, ReactNode, JSX } from 'react';
@@ -34,6 +34,12 @@ export function Panel({
34
34
  }: PropsWithChildren<PanelProps>): JSX.Element {
35
35
  const [isExpanded, setExpanded] = useState(expanded);
36
36
  const [animate, setAnimate] = useState(false);
37
+ const [prevExpanded, setPrevExpanded] = useState(expanded);
38
+
39
+ if (prevExpanded !== expanded) {
40
+ setPrevExpanded(expanded);
41
+ setExpanded(expanded);
42
+ }
37
43
 
38
44
  const toggle = ({ target }: BaseSyntheticEvent): void => {
39
45
  if (target instanceof HTMLAnchorElement || !isExpandable) return;
@@ -42,8 +48,6 @@ export function Panel({
42
48
  onToggle?.(!isExpanded);
43
49
  };
44
50
 
45
- useEffect(() => setExpanded(expanded), [expanded]);
46
-
47
51
  return (
48
52
  <PanelWrapper
49
53
  className={className}
@@ -178,7 +178,7 @@ export const apiReferencePanels = css`
178
178
  * @tokens Panel common
179
179
  */
180
180
 
181
- --panel-border-radius: var(--border-radius); // @presenter BorderRadius
181
+ --panel-border-radius: var(--border-radius-xl); // @presenter BorderRadius
182
182
  --panel-border: 1px solid var(--border-color-secondary); // @presenter Border
183
183
 
184
184
  --panel-line-height: var(--line-height-base); // @presenter LineHeight
@@ -25,7 +25,7 @@ export const productPicker = css`
25
25
  --product-picker-dropdown-item-padding-vertical: var(--dropdown-menu-item-padding-vertical); // @presenter Spacing
26
26
  --product-picker-dropdown-item-separator-padding-top: var(--dropdown-menu-item-separator-padding-top ); // @presenter Spacing
27
27
  --product-picker-dropdown-item-separator-padding-bottom: var(--dropdown-menu-item-separator-padding-bottom ); // @presenter Spacing
28
- --product-picker-dropdown-item-border-radius: var(--dropdown-menu-item-border-radius ); // @presenter BorderRadius
28
+ --product-picker-dropdown-item-border-radius: var(--dropdown-menu-item-border-radius); // @presenter BorderRadius
29
29
  --product-picker-dropdown-item-bg-color-active: var(--dropdown-menu-item-bg-color-active); // @presenter Color
30
30
  --product-picker-dropdown-item-bg-color-hover: var(--dropdown-menu-item-bg-color-hover); // @presenter Color
31
31
  --product-picker-dropdown-item-bg-color-disabled: var(--dropdown-menu-item-bg-color-disabled); // @presenter Color
@@ -36,4 +36,5 @@ export const productPicker = css`
36
36
  --product-picker-dropdown-item-color-hover: var(--dropdown-menu-item-color-hover);
37
37
  --product-picker-dropdown-item-border-color-focused: var(--dropdown-menu-item-border-color-focused);
38
38
 
39
+ // @tokens End
39
40
  `;
@@ -10,6 +10,9 @@ export type ReplayGateProps = {
10
10
  // The current OpenAPI description's id (from x-metadata), when known. Lets a custom
11
11
  // ReplayGate vary behavior per API in a multi-API catalog.
12
12
  apiId?: string;
13
+ // Closes the whole Replay overlay. A gate that denies access calls this instead of
14
+ // rendering `children`, so a dismissed gate doesn't leave Replay reachable.
15
+ onClose: () => void;
13
16
  children: React.ReactNode;
14
17
  };
15
18