@redocly/theme 0.69.0-next.5 → 0.69.0-next.7

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 (180) hide show
  1. package/lib/components/Accordion/variables.js +1 -1
  2. package/lib/components/Admonition/variables.js +1 -1
  3. package/lib/components/Banner/variables.dark.js +2 -0
  4. package/lib/components/Banner/variables.js +3 -1
  5. package/lib/components/Breadcrumbs/Breadcrumb.js +1 -1
  6. package/lib/components/Breadcrumbs/variables.js +1 -1
  7. package/lib/components/Button/ButtonGroup.d.ts +3 -5
  8. package/lib/components/Button/ButtonGroup.js +25 -5
  9. package/lib/components/Button/variables.js +27 -4
  10. package/lib/components/Buttons/ConnectMCPButton.js +15 -128
  11. package/lib/components/Buttons/CopyButton.js +12 -1
  12. package/lib/components/Buttons/variables.d.ts +0 -1
  13. package/lib/components/Buttons/variables.js +3 -44
  14. package/lib/components/Catalog/CatalogEntity/CatalogEntityLinks.js +1 -1
  15. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +1 -1
  16. package/lib/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath.js +1 -1
  17. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +1 -1
  18. package/lib/components/Catalog/CatalogFilter/CatalogFilterSelect.js +1 -0
  19. package/lib/components/Catalog/variables.js +5 -5
  20. package/lib/components/CatalogClassic/variables.js +2 -2
  21. package/lib/components/CodeBlock/CodeBlock.js +2 -1
  22. package/lib/components/CodeBlock/CodeBlockContainer.js +1 -0
  23. package/lib/components/Dropdown/Dropdown.d.ts +10 -20
  24. package/lib/components/Dropdown/Dropdown.js +13 -2
  25. package/lib/components/Dropdown/DropdownMenuItemContent.d.ts +9 -0
  26. package/lib/components/Dropdown/DropdownMenuItemContent.js +56 -0
  27. package/lib/components/Dropdown/variables.js +19 -2
  28. package/lib/components/Feedback/Mood.js +18 -14
  29. package/lib/components/Feedback/Rating.js +18 -13
  30. package/lib/components/Feedback/Scale.js +27 -22
  31. package/lib/components/Feedback/Sentiment.js +17 -13
  32. package/lib/components/Filter/FilterSelect.js +1 -0
  33. package/lib/components/Filter/variables.js +2 -2
  34. package/lib/components/Image/variables.js +5 -3
  35. package/lib/components/LanguagePicker/variables.js +1 -1
  36. package/lib/components/Markdown/variables.js +1 -1
  37. package/lib/components/Menu/variables.js +1 -1
  38. package/lib/components/Navbar/variables.js +1 -1
  39. package/lib/components/PageActions/PageActions.js +4 -6
  40. package/lib/components/PageActions/PageActionsMenuItem.d.ts +4 -4
  41. package/lib/components/PageActions/PageActionsMenuItem.js +27 -43
  42. package/lib/components/Panel/variables.js +1 -1
  43. package/lib/components/Product/variables.js +2 -1
  44. package/lib/components/ReplayGate/ReplayGate.d.ts +1 -0
  45. package/lib/components/Search/SearchAiDialog.js +1 -1
  46. package/lib/components/Search/SearchAiMessage.js +1 -1
  47. package/lib/components/Search/SearchAiNegativeFeedbackForm.js +2 -2
  48. package/lib/components/Search/SearchDialog.js +2 -2
  49. package/lib/components/Search/SearchItem.js +1 -0
  50. package/lib/components/Search/SearchRecent.js +1 -0
  51. package/lib/components/Search/SearchSuggestedPages.js +1 -0
  52. package/lib/components/Search/variables.js +8 -5
  53. package/lib/components/Segmented/Segmented.js +3 -3
  54. package/lib/components/Select/Select.js +20 -18
  55. package/lib/components/Select/variables.js +3 -3
  56. package/lib/components/SplitButton/SplitButton.d.ts +21 -0
  57. package/lib/components/SplitButton/SplitButton.js +37 -0
  58. package/lib/components/Switch/variables.dark.js +2 -2
  59. package/lib/components/Switch/variables.js +2 -2
  60. package/lib/components/Tag/variables.js +2 -2
  61. package/lib/components/Tags/variables.js +1 -1
  62. package/lib/components/Toast/variables.js +1 -1
  63. package/lib/components/Tooltip/AnchorTooltip.js +2 -2
  64. package/lib/components/Tooltip/JsTooltip.js +2 -2
  65. package/lib/components/UserMenu/variables.js +1 -1
  66. package/lib/core/constants/mcp.d.ts +2 -0
  67. package/lib/core/constants/mcp.js +3 -1
  68. package/lib/core/constants/search.js +2 -2
  69. package/lib/core/hooks/use-control.js +3 -0
  70. package/lib/core/hooks/use-mcp-config.d.ts +2 -0
  71. package/lib/core/hooks/use-mcp-config.js +14 -4
  72. package/lib/core/styles/global.js +11 -11
  73. package/lib/core/styles/palette.js +2 -0
  74. package/lib/core/types/button-group.d.ts +2 -0
  75. package/lib/core/types/button-group.js +3 -0
  76. package/lib/core/types/catalog.d.ts +2 -6
  77. package/lib/core/types/common.d.ts +2 -0
  78. package/lib/core/types/hooks.d.ts +1 -0
  79. package/lib/core/types/index.d.ts +1 -0
  80. package/lib/core/types/l10n.d.ts +1 -1
  81. package/lib/core/utils/RenderWithLink.d.ts +2 -0
  82. package/lib/core/utils/RenderWithLink.js +20 -0
  83. package/lib/core/utils/index.d.ts +1 -0
  84. package/lib/core/utils/index.js +1 -0
  85. package/lib/icons/LinkIcon/LinkIcon.js +1 -1
  86. package/lib/index.d.ts +2 -0
  87. package/lib/index.js +2 -0
  88. package/lib/layouts/McpNotAllowed.js +5 -7
  89. package/lib/markdoc/components/Cards/variables.js +6 -4
  90. package/lib/markdoc/components/CodeWalkthrough/CodePanel.js +1 -0
  91. package/lib/markdoc/components/CodeWalkthrough/CodeStep.js +1 -1
  92. package/lib/markdoc/components/CodeWalkthrough/variables.js +2 -1
  93. package/lib/markdoc/components/Tabs/TabList.js +6 -2
  94. package/lib/markdoc/components/Tabs/Tabs.js +4 -2
  95. package/lib/markdoc/components/Tabs/variables.js +4 -4
  96. package/package.json +8 -8
  97. package/src/components/Accordion/variables.ts +1 -1
  98. package/src/components/Admonition/variables.ts +1 -1
  99. package/src/components/Banner/variables.dark.ts +2 -0
  100. package/src/components/Banner/variables.ts +3 -1
  101. package/src/components/Breadcrumbs/Breadcrumb.tsx +1 -1
  102. package/src/components/Breadcrumbs/variables.ts +1 -1
  103. package/src/components/Button/ButtonGroup.tsx +28 -10
  104. package/src/components/Button/variables.ts +27 -4
  105. package/src/components/Buttons/ConnectMCPButton.tsx +63 -150
  106. package/src/components/Buttons/CopyButton.tsx +14 -2
  107. package/src/components/Buttons/variables.ts +2 -44
  108. package/src/components/Catalog/CatalogEntity/CatalogEntityLinks.tsx +1 -1
  109. package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +1 -1
  110. package/src/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath.tsx +1 -1
  111. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +1 -1
  112. package/src/components/Catalog/CatalogFilter/CatalogFilterSelect.tsx +1 -0
  113. package/src/components/Catalog/variables.ts +5 -5
  114. package/src/components/CatalogClassic/variables.ts +2 -2
  115. package/src/components/CodeBlock/CodeBlock.tsx +2 -1
  116. package/src/components/CodeBlock/CodeBlockContainer.tsx +1 -0
  117. package/src/components/Dropdown/Dropdown.tsx +25 -4
  118. package/src/components/Dropdown/DropdownMenuItemContent.tsx +72 -0
  119. package/src/components/Dropdown/variables.ts +19 -2
  120. package/src/components/Feedback/Mood.tsx +22 -15
  121. package/src/components/Feedback/Rating.tsx +22 -14
  122. package/src/components/Feedback/Scale.tsx +40 -32
  123. package/src/components/Feedback/Sentiment.tsx +21 -14
  124. package/src/components/Filter/FilterSelect.tsx +1 -0
  125. package/src/components/Filter/variables.ts +2 -2
  126. package/src/components/Image/variables.ts +5 -3
  127. package/src/components/LanguagePicker/variables.ts +1 -1
  128. package/src/components/Markdown/variables.ts +1 -1
  129. package/src/components/Menu/variables.ts +1 -1
  130. package/src/components/Navbar/variables.ts +1 -1
  131. package/src/components/PageActions/PageActions.tsx +22 -23
  132. package/src/components/PageActions/PageActionsMenuItem.tsx +41 -55
  133. package/src/components/Panel/variables.ts +1 -1
  134. package/src/components/Product/variables.ts +2 -1
  135. package/src/components/ReplayGate/ReplayGate.tsx +3 -0
  136. package/src/components/Search/SearchAiDialog.tsx +1 -1
  137. package/src/components/Search/SearchAiMessage.tsx +1 -1
  138. package/src/components/Search/SearchAiNegativeFeedbackForm.tsx +2 -2
  139. package/src/components/Search/SearchDialog.tsx +2 -2
  140. package/src/components/Search/SearchItem.tsx +1 -0
  141. package/src/components/Search/SearchRecent.tsx +1 -0
  142. package/src/components/Search/SearchSuggestedPages.tsx +1 -0
  143. package/src/components/Search/variables.ts +8 -5
  144. package/src/components/Segmented/Segmented.tsx +6 -3
  145. package/src/components/Select/Select.tsx +24 -16
  146. package/src/components/Select/variables.ts +3 -3
  147. package/src/components/SplitButton/SplitButton.tsx +95 -0
  148. package/src/components/Switch/variables.dark.ts +2 -2
  149. package/src/components/Switch/variables.ts +2 -2
  150. package/src/components/Tag/variables.ts +2 -2
  151. package/src/components/Tags/variables.ts +1 -1
  152. package/src/components/Toast/variables.ts +1 -1
  153. package/src/components/Tooltip/AnchorTooltip.tsx +2 -2
  154. package/src/components/Tooltip/JsTooltip.tsx +2 -2
  155. package/src/components/UserMenu/variables.ts +1 -1
  156. package/src/core/constants/mcp.ts +4 -0
  157. package/src/core/constants/search.ts +2 -2
  158. package/src/core/hooks/use-control.ts +5 -1
  159. package/src/core/hooks/use-mcp-config.ts +15 -4
  160. package/src/core/openapi/index.ts +1 -1
  161. package/src/core/styles/global.ts +12 -12
  162. package/src/core/styles/palette.ts +2 -0
  163. package/src/core/types/button-group.ts +2 -0
  164. package/src/core/types/catalog.ts +2 -7
  165. package/src/core/types/common.ts +3 -0
  166. package/src/core/types/hooks.ts +1 -0
  167. package/src/core/types/index.ts +1 -0
  168. package/src/core/types/l10n.ts +8 -1
  169. package/src/core/utils/RenderWithLink.tsx +19 -0
  170. package/src/core/utils/index.ts +1 -0
  171. package/src/icons/LinkIcon/LinkIcon.tsx +1 -1
  172. package/src/index.ts +2 -0
  173. package/src/layouts/McpNotAllowed.tsx +33 -9
  174. package/src/markdoc/components/Cards/variables.ts +6 -4
  175. package/src/markdoc/components/CodeWalkthrough/CodePanel.tsx +1 -0
  176. package/src/markdoc/components/CodeWalkthrough/CodeStep.tsx +1 -1
  177. package/src/markdoc/components/CodeWalkthrough/variables.ts +2 -1
  178. package/src/markdoc/components/Tabs/TabList.tsx +6 -2
  179. package/src/markdoc/components/Tabs/Tabs.tsx +4 -2
  180. package/src/markdoc/components/Tabs/variables.ts +4 -4
@@ -8,9 +8,9 @@ export const tag = css`
8
8
 
9
9
  --tag-border-width: 1px; //@presenter Border
10
10
  --tag-border-style: solid; //@presenter Border
11
- --tag-border-radius: var(--border-radius); // @presenter BorderRadius
11
+ --tag-border-radius: var(--border-radius-md); // @presenter BorderRadius
12
12
  --tag-box-shadow: none; // @presenter Shadow
13
- --tag-border-radius-focused: var(--border-radius); // @presenter BorderRadius
13
+ --tag-border-radius-focused: var(--tag-border-radius); // @presenter BorderRadius
14
14
 
15
15
  --tag-status-dot-color-default: var(--color-persian-green-7);
16
16
  --tag-badge-size: var(--spacing-xs);
@@ -13,6 +13,6 @@ export const httpTag = css`
13
13
  --http-tag-bg-color: none;
14
14
 
15
15
  --counter-tag-padding: 0px var(--spacing-xxs);
16
- --counter-tag-border-radius: var(--border-radius);
16
+ --counter-tag-border-radius: var(--tag-border-radius);
17
17
  --counter-tag-min-width: var(--spacing-md);
18
18
  `
@@ -16,7 +16,7 @@ export const toast = css`
16
16
  --toast-max-width: 360px;
17
17
  --toast-bg-color: var(--layer-color); // @presenter Color
18
18
  --toast-border: var(--border-width) var(--border-style) var(--border-color-secondary); // @presenter Border
19
- --toast-border-radius: var(--border-radius-md); // @presenter BorderRadius
19
+ --toast-border-radius: var(--border-radius-lg); // @presenter BorderRadius
20
20
  --toast-font-family: var(--font-family-base); // @presenter FontFamily
21
21
 
22
22
  /**
@@ -250,7 +250,7 @@ const TooltipBody = styled.span.attrs<{ $anchorName: string }>(({ $anchorName })
250
250
  overflow-wrap: break-word;
251
251
  text-align: left;
252
252
 
253
- border-radius: var(--border-radius-md);
253
+ border-radius: var(--border-radius-lg);
254
254
  transition: opacity 0.3s ease-out;
255
255
 
256
256
  font-size: var(--font-size-base);
@@ -270,7 +270,7 @@ const TooltipBody = styled.span.attrs<{ $anchorName: string }>(({ $anchorName })
270
270
 
271
271
  background: var(--tooltip-bg-color);
272
272
  color: var(--tooltip-text-color);
273
- border: var(--tooltip-border-width, 0) var(--tooltip-border-style, solid)
273
+ border: var(--tooltip-border-width, 2px) var(--tooltip-border-style, solid)
274
274
  var(--tooltip-border-color, transparent);
275
275
  box-shadow: var(--bg-raised-shadow);
276
276
 
@@ -254,7 +254,7 @@ const TooltipBody = styled.span<{
254
254
  word-break: normal;
255
255
  overflow-wrap: break-word;
256
256
 
257
- border-radius: var(--border-radius-md);
257
+ border-radius: var(--border-radius-lg);
258
258
  transition: opacity 0.3s ease-out;
259
259
 
260
260
  font-size: var(--font-size-base);
@@ -274,7 +274,7 @@ const TooltipBody = styled.span<{
274
274
 
275
275
  background: var(--tooltip-bg-color);
276
276
  color: var(--tooltip-text-color);
277
- border: var(--tooltip-border-width, 0) var(--tooltip-border-style, solid)
277
+ border: var(--tooltip-border-width, 2px) var(--tooltip-border-style, solid)
278
278
  var(--tooltip-border-color, transparent);
279
279
  box-shadow: var(--bg-raised-shadow);
280
280
 
@@ -49,7 +49,7 @@ export const userMenu = css`
49
49
  --user-menu-dropdown-item-padding-vertical: var(--dropdown-menu-item-padding-vertical); // @presenter Spacing
50
50
  --user-menu-dropdown-item-separator-padding-top: var(--dropdown-menu-item-separator-padding-top ); // @presenter Spacing
51
51
  --user-menu-dropdown-item-separator-padding-bottom: var(--dropdown-menu-item-separator-padding-bottom ); // @presenter Spacing
52
- --user-menu-dropdown-item-border-radius: var(--dropdown-menu-item-border-radius ); // @presenter BorderRadius
52
+ --user-menu-dropdown-item-border-radius: var(--dropdown-menu-item-border-radius); // @presenter BorderRadius
53
53
  --user-menu-dropdown-item-bg-color-active: var(--dropdown-menu-item-bg-color-active); // @presenter Color
54
54
  --user-menu-dropdown-item-bg-color-hover: var(--dropdown-menu-item-bg-color-hover); // @presenter Color
55
55
  --user-menu-dropdown-item-bg-color-disabled: var(--dropdown-menu-item-bg-color-disabled); // @presenter Color
@@ -2,6 +2,10 @@ import type { MCPOption } from '../types/mcp';
2
2
 
3
3
  export const DEFAULT_MCP_SERVER_NAME = 'mcp-server';
4
4
 
5
+ export const MCP_ROUTE = '/mcp';
6
+
7
+ export const PUBLIC_MCP_ROUTE = '/mcp-public';
8
+
5
9
  export const DEFAULT_MCP_OPTIONS: MCPOption[] = [
6
10
  'cursor',
7
11
  'vscode',
@@ -29,13 +29,13 @@ export const AI_SEARCH_ERROR_CONFIG: Record<AiSearchError, AiSearchErrorConfig>
29
29
  headerKey: 'search.ai.error.header.forbidden',
30
30
  headerDefault: 'Feature Unavailable',
31
31
  messageKey: 'search.ai.error.description.forbidden',
32
- messageDefault: 'AI Search is currently unavailable.',
32
+ messageDefault: 'AI assistant is currently unavailable.',
33
33
  },
34
34
  [AiSearchError.Unauthorized]: {
35
35
  headerKey: 'search.ai.error.header.unauthorized',
36
36
  headerDefault: 'Authentication Required',
37
37
  messageKey: 'search.ai.error.description.unauthorized',
38
- messageDefault: 'You are not authorized to use AI Search.',
38
+ messageDefault: 'You are not authorized to use AI assistant.',
39
39
  },
40
40
  [AiSearchError.HttpRequestFailed]: defaultErrorConfig,
41
41
  [AiSearchError.EmptyResponse]: defaultErrorConfig,
@@ -1,4 +1,4 @@
1
- import { useState, useCallback, useRef } from 'react';
1
+ import { useState, useCallback, useEffect, useRef } from 'react';
2
2
 
3
3
  const DEFAULT_CONTROL_OPEN_DELAY = 300;
4
4
 
@@ -18,6 +18,10 @@ export const useControl = (initialVal = false): UseControlReturnType => {
18
18
  }
19
19
  }, []);
20
20
 
21
+ useEffect(() => {
22
+ return clearOpenTimer;
23
+ }, [clearOpenTimer]);
24
+
21
25
  const handleOpen = useCallback(() => {
22
26
  clearOpenTimer();
23
27
  timeoutRef.current = setTimeout(() => {
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
2
2
 
3
3
  import { useThemeHooks } from './use-theme-hooks';
4
4
  import { IS_BROWSER } from '../utils/dom';
5
- import { DEFAULT_MCP_SERVER_NAME } from '../constants';
5
+ import { DEFAULT_MCP_SERVER_NAME, MCP_ROUTE, PUBLIC_MCP_ROUTE } from '../constants';
6
6
  import { generateMCPDeepLink } from '../utils/mcp';
7
7
  import { withPathPrefix } from '../utils/urls';
8
8
 
@@ -13,20 +13,29 @@ export type McpConfig = {
13
13
  cursorUrl: string;
14
14
  vscodeUrl: string;
15
15
  isMcpDisabled: boolean;
16
+ isPublicEndpointPage: boolean;
17
+ alternateServerUrl?: string;
16
18
  };
17
19
 
18
20
  export function useMCPConfig(): McpConfig {
19
- const { useMcpData } = useThemeHooks();
21
+ const { useMcpData, usePageData } = useThemeHooks();
20
22
 
21
23
  const {
22
- docs: { enabled, name },
24
+ docs: { enabled, name, publicEndpoint },
23
25
  } = useMcpData();
26
+ const pageSlug = usePageData()?.slug;
24
27
 
25
28
  const origin = IS_BROWSER
26
29
  ? window.location.origin
27
30
  : ((globalThis as { SSR_HOSTNAME?: string })['SSR_HOSTNAME'] ?? '');
28
31
  const serverName = name || DEFAULT_MCP_SERVER_NAME;
29
- const serverUrl = `${origin}${withPathPrefix('/mcp')}`;
32
+ const isPublicEndpointPage = pageSlug === withPathPrefix(PUBLIC_MCP_ROUTE);
33
+ const serverUrl = `${origin}${withPathPrefix(isPublicEndpointPage ? PUBLIC_MCP_ROUTE : MCP_ROUTE)}`;
34
+ const alternateServerUrl = isPublicEndpointPage
35
+ ? `${origin}${withPathPrefix(MCP_ROUTE)}`
36
+ : publicEndpoint
37
+ ? `${origin}${withPathPrefix(PUBLIC_MCP_ROUTE)}`
38
+ : undefined;
30
39
  const isMcpDisabled = !enabled || false;
31
40
 
32
41
  const cursorUrl = useMemo(
@@ -46,5 +55,7 @@ export function useMCPConfig(): McpConfig {
46
55
  cursorUrl,
47
56
  vscodeUrl,
48
57
  isMcpDisabled,
58
+ isPublicEndpointPage,
59
+ alternateServerUrl,
49
60
  };
50
61
  }
@@ -1,5 +1,5 @@
1
1
  // This file is intended to provide selective imports from @redocly/theme/core
2
- // to reduce bundle size by exporting only functionality used in the @redocly/openapi-docs package.
2
+ // to reduce bundle size by exporting only functionality used in the @redocly/api-docs package.
3
3
  //
4
4
  // This selective import approach will help with tree shaking and reduce
5
5
  // the overall bundle size by avoiding importing the entire theme package
@@ -20,7 +20,7 @@ import { checkbox } from '@redocly/theme/icons/CheckboxIcon/variables';
20
20
  import { admonition } from '@redocly/theme/components/Admonition/variables';
21
21
  import { footer } from '@redocly/theme/components/Footer/variables';
22
22
  import { button } from '@redocly/theme/components/Button/variables';
23
- import { aiAssistantButton, connectMCPButton } from '@redocly/theme/components/Buttons/variables';
23
+ import { aiAssistantButton } from '@redocly/theme/components/Buttons/variables';
24
24
  import { navbar } from '@redocly/theme/components/Navbar/variables';
25
25
  import { search } from '@redocly/theme/components/Search/variables';
26
26
  import { menu, mobileMenu } from '@redocly/theme/components/Menu/variables';
@@ -454,18 +454,24 @@ const borders = css`
454
454
 
455
455
  --border-color-primary: var(--color-warm-grey-3); // Raised dividers
456
456
  --border-color-secondary: var(--color-warm-grey-2); // Default dividers, borders
457
- --border-color-invers: var(--color-warm-grey-10);
457
+ --border-color-inverse: var(--color-warm-grey-10);
458
+ --border-color-invers: var(--border-color-inverse, var(--color-warm-grey-10)); // Deprecated: use --border-color-inverse
458
459
 
459
460
  /**
460
461
  * @tokens Border Radius
461
462
  * @presenter BorderRadius
462
463
  */
463
464
 
465
+ --border-radius-none: 0;
464
466
  --border-radius: 4px;
465
467
  --border-radius-md: calc(var(--border-radius) * 1.5);
466
468
  --border-radius-lg: calc(var(--border-radius) * 2);
467
469
  --border-radius-xl: calc(var(--border-radius) * 3);
468
470
  --border-radius-xxl: calc(var(--border-radius) * 4);
471
+ --border-radius-xxxl: calc(var(--border-radius) * 6);
472
+ --border-radius-full: 999px;
473
+
474
+ // @tokens End
469
475
  `;
470
476
 
471
477
  const headingsTypography = css`
@@ -824,7 +830,7 @@ const badges = css`
824
830
 
825
831
  --badge-text-color: var(--text-color-inverse); // @presenter Color
826
832
  --badge-bg-color: var(--color-purple-6); // @presenter Color
827
- --badge-border-radius: var(--border-radius); // @presenter BorderRadius
833
+ --badge-border-radius: var(--border-radius-md); // @presenter BorderRadius
828
834
 
829
835
  /**
830
836
  * @tokens Deprecated Badge
@@ -832,7 +838,7 @@ const badges = css`
832
838
 
833
839
  --badge-deprecated-text-color: var(--color-warm-grey-1); // @presenter Color
834
840
  --badge-deprecated-bg-color: var(--color-warning-base); // @presenter Color
835
- --badge-deprecated-border-radius: var(--border-radius); // @presenter BorderRadius
841
+ --badge-deprecated-border-radius: var(--border-radius-md); // @presenter BorderRadius
836
842
 
837
843
  /**
838
844
  * @tokens Webhook Badge
@@ -840,7 +846,7 @@ const badges = css`
840
846
 
841
847
  --badge-webhook-text-color: var(--color-warm-grey-1); // @presenter Color
842
848
  --badge-webhook-bg-color: var(--color-purple-7); // @presenter Color
843
- --badge-webhook-border-radius: var(--border-radius); // @presenter BorderRadius
849
+ --badge-webhook-border-radius: var(--border-radius-md); // @presenter BorderRadius
844
850
 
845
851
  /**
846
852
  * @tokens Audience Badge
@@ -1048,11 +1054,6 @@ const pages = css`
1048
1054
  --page-mcp-405-margin-vertical-mobile: var(--spacing-xxl);
1049
1055
  --page-mcp-405-margin-horizontal-mobile: 1rem;
1050
1056
 
1051
- --page-mcp-405-status-text-color: var(--text-color-helper);
1052
- --page-mcp-405-status-font-size: var(--font-size-lg); // @presenter FontSize
1053
- --page-mcp-405-status-font-weight: var(--font-weight-semibold); // @presenter FontWeight
1054
- --page-mcp-405-status-line-height: var(--line-height-lg); // @presenter LineHeight
1055
-
1056
1057
  --page-mcp-405-title-text-color: var(--text-color-primary);
1057
1058
  --page-mcp-405-title-font-size: 42px; // @presenter FontSize
1058
1059
  --page-mcp-405-title-font-weight: var(--font-weight-bold); // @presenter FontWeight
@@ -1269,7 +1270,7 @@ const tree = css`
1269
1270
 
1270
1271
  *::-webkit-scrollbar-thumb {
1271
1272
  background-color: var(--color-warm-grey-2);
1272
- border-radius: var(--border-radius);
1273
+ border-radius: var(--border-radius-full);
1273
1274
  }
1274
1275
 
1275
1276
  *::-webkit-scrollbar-thumb:hover {
@@ -1337,7 +1338,6 @@ export const styles = css<{ palette?: string }>`
1337
1338
  ${breadcrumbs}
1338
1339
  ${button}
1339
1340
  ${aiAssistantButton}
1340
- ${connectMCPButton}
1341
1341
  ${cards}
1342
1342
  ${catalog}
1343
1343
  ${catalogClassic}
@@ -244,4 +244,6 @@ function brandPaletteLight(palette: string | undefined): RuleSet<object> {
244
244
  */
245
245
  export const activeBrandPaletteLight = css<{ palette?: string }>`
246
246
  ${({ palette }) => brandPaletteLight(palette)}
247
+
248
+ // @tokens End
247
249
  `;
@@ -0,0 +1,2 @@
1
+ export type ButtonGroupVariant = 'primary' | 'secondary' | 'outlined';
2
+ export type ButtonGroupSize = 'small' | 'medium' | 'large';
@@ -212,13 +212,8 @@ export type BffCatalogEntityList = BffCatalogList<BffCatalogEntity>;
212
212
  export type BffCatalogRelatedEntityList = BffCatalogList<BffCatalogRelatedEntity>;
213
213
 
214
214
  export type Page = {
215
- // Optional so existing code that builds a Page keeps compiling; the catalog BFF always emits both.
216
- nextPage?: string | null;
217
- previousPage?: string | null;
218
- endCursor: string | null;
219
- startCursor: string | null;
220
- hasNextPage: boolean;
221
- hasPrevPage: boolean;
215
+ nextPage: string | null;
216
+ previousPage: string | null;
222
217
  limit: number;
223
218
  total: number;
224
219
  };
@@ -1,5 +1,8 @@
1
+ import type React from 'react';
1
2
  import { DEFAULT_COLOR_MODES } from '../constants';
2
3
 
3
4
  export type Plural<T extends string> = `${T}s`;
4
5
 
5
6
  export type ColorMode = (typeof DEFAULT_COLOR_MODES)[keyof typeof DEFAULT_COLOR_MODES];
7
+
8
+ export type RenderableChildren<Context> = React.ReactNode | ((context: Context) => React.ReactNode);
@@ -143,6 +143,7 @@ export type ThemeHooks = {
143
143
  docs: {
144
144
  enabled: boolean;
145
145
  name?: string;
146
+ publicEndpoint?: boolean;
146
147
  };
147
148
  };
148
149
  useSidebarItems: (activeVersion?: Version | null) => {
@@ -22,3 +22,4 @@ export type * from './segmented';
22
22
  export type * from './tooltip';
23
23
  export type * from './toast';
24
24
  export type * from './link';
25
+ export type * from './button-group';
@@ -136,6 +136,9 @@ export type TranslationKey =
136
136
  | 'page.notFound.description'
137
137
  | 'page.mcpNotAllowed.title'
138
138
  | 'page.mcpNotAllowed.description'
139
+ | 'page.mcpNotAllowed.publicNote'
140
+ | 'page.mcpNotAllowed.publicEndpointHint'
141
+ | 'page.mcpNotAllowed.mainEndpointHint'
139
142
  | 'page.mcpNotAllowed.snippets.terminal.hint'
140
143
  | 'page.mcpNotAllowed.snippets.claudeCode.headline'
141
144
  | 'page.mcpNotAllowed.snippets.claudeDesktop.headline'
@@ -290,6 +293,8 @@ export type TranslationKey =
290
293
  | 'page.actions.connectMcp.codexDescription'
291
294
  | 'page.actions.connectMcp.copyConfig'
292
295
  | 'page.actions.connectMcp.copyConfigDescription'
296
+ | 'page.actions.connectMcp.moreOptions'
297
+ | 'page.actions.moreActions'
293
298
  | 'openapi.download.description.title'
294
299
  | 'openapi.info.title'
295
300
  | 'openapi.info.contact.url'
@@ -297,6 +302,7 @@ export type TranslationKey =
297
302
  | 'openapi.info.license'
298
303
  | 'openapi.info.termsOfService'
299
304
  | 'openapi.info.metadata.title'
305
+ | 'graphql.info.metadata.title'
300
306
  | 'openapi.key'
301
307
  | 'openapi.value'
302
308
  | 'openapi.enum'
@@ -386,6 +392,8 @@ export type TranslationKey =
386
392
  | 'openapi.mcp.inputExample'
387
393
  | 'openapi.mcp.outputSchema'
388
394
  | 'openapi.mcp.outputExample'
395
+ | 'openapi.mcp.exampleTitle'
396
+ | 'openapi.mcp.argumentsExample'
389
397
  | 'asyncapi.download.description.title'
390
398
  | 'asyncapi.info.title'
391
399
  | 'asyncapi.info.contact.url'
@@ -466,7 +474,6 @@ export type TranslationKey =
466
474
  | 'graphql.sample'
467
475
  | 'graphql.referenced'
468
476
  | 'graphql.content.fragment'
469
- | 'button.copy.tooltipText'
470
477
  | 'button.download.tooltipText'
471
478
  | 'button.externalLink.tooltipText'
472
479
  | 'button.email.tooltipText'
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+
3
+ import type { JSX } from 'react';
4
+
5
+ // Splits a translated sentence on <link>...</link> markers and renders the
6
+ // marked phrase as an anchor, so each locale keeps its own word order.
7
+ export function renderWithLink(text: string, href: string): JSX.Element {
8
+ const [before, label, after] = text.split(/<link>|<\/link>/);
9
+ if (label === undefined) {
10
+ return <>{text}</>;
11
+ }
12
+ return (
13
+ <>
14
+ {before}
15
+ <a href={href}>{label}</a>
16
+ {after}
17
+ </>
18
+ );
19
+ }
@@ -48,3 +48,4 @@ export * from './get-auto-dismiss-duration';
48
48
  export * from './tooltip-placement';
49
49
  export * from './telemetry/get-base-data-attributes';
50
50
  export * from './telemetry/generate-before-after-context';
51
+ export * from './RenderWithLink';
@@ -15,7 +15,7 @@ const Icon = (props: IconProps) => (
15
15
  {...props}
16
16
  >
17
17
  <path
18
- d="M0 4C0 1.79086 1.79086 0 4 0H16C18.2091 0 20 1.79086 20 4V16C20 18.2091 18.2091 20 16 20H4C1.79086 20 0 18.2091 0 16V4Z"
18
+ d="M0 6C0 2.68629 2.68629 0 6 0H14C17.3137 0 20 2.68629 20 6V14C20 17.3137 17.3137 20 14 20H6C2.68629 20 0 17.3137 0 14V6Z"
19
19
  fill="var(--layer-color)"
20
20
  />
21
21
  <path
package/src/index.ts CHANGED
@@ -15,6 +15,8 @@ export * from '@redocly/theme/components/Badge/Badge';
15
15
  export * from '@redocly/theme/components/Dropdown/Dropdown';
16
16
  export * from '@redocly/theme/components/Dropdown/DropdownMenu';
17
17
  export * from '@redocly/theme/components/Dropdown/DropdownMenuItem';
18
+ export * from '@redocly/theme/components/Dropdown/DropdownMenuItemContent';
19
+ export * from '@redocly/theme/components/SplitButton/SplitButton';
18
20
  export * from '@redocly/theme/components/Loaders/Loading';
19
21
  export * from '@redocly/theme/components/LoadMore/LoadMore';
20
22
  export * from '@redocly/theme/components/Link/Link';
@@ -3,17 +3,18 @@ import styled from 'styled-components';
3
3
 
4
4
  import type { JSX } from 'react';
5
5
 
6
- import { useThemeHooks } from '@redocly/theme/core/hooks';
6
+ import { useThemeHooks, useMCPConfig } from '@redocly/theme/core/hooks';
7
+ import { renderWithLink } from '@redocly/theme/core/utils';
7
8
  import { ConnectMCPButton } from '@redocly/theme/components/Buttons/ConnectMCPButton';
8
9
  import { McpConnectionTabs } from '@redocly/theme/components/MCP/McpConnectionTabs';
9
10
 
10
11
  export default function McpNotAllowed(): JSX.Element {
11
12
  const { useTranslate } = useThemeHooks();
12
13
  const { translate } = useTranslate();
14
+ const { isPublicEndpointPage, alternateServerUrl } = useMCPConfig();
13
15
 
14
16
  return (
15
17
  <NotAllowedWrapper data-component-name="layouts/McpNotAllowed">
16
- <StatusText>405</StatusText>
17
18
  <Title data-translation-key="page.mcpNotAllowed.title">
18
19
  {translate('page.mcpNotAllowed.title', 'Connect to the MCP server')}
19
20
  </Title>
@@ -23,6 +24,36 @@ export default function McpNotAllowed(): JSX.Element {
23
24
  'To use this MCP server, register it in your MCP client (for example: VS Code, Cursor, or Claude Code).',
24
25
  )}
25
26
  </Description>
27
+ {isPublicEndpointPage && (
28
+ <Description data-translation-key="page.mcpNotAllowed.publicNote">
29
+ {translate(
30
+ 'page.mcpNotAllowed.publicNote',
31
+ 'This endpoint serves publicly available content only and requires no login.',
32
+ )}
33
+ </Description>
34
+ )}
35
+ {isPublicEndpointPage && alternateServerUrl && (
36
+ <Description data-translation-key="page.mcpNotAllowed.mainEndpointHint">
37
+ {renderWithLink(
38
+ translate(
39
+ 'page.mcpNotAllowed.mainEndpointHint',
40
+ 'To access content available to your account, use the <link>main MCP endpoint</link>.',
41
+ ),
42
+ alternateServerUrl,
43
+ )}
44
+ </Description>
45
+ )}
46
+ {!isPublicEndpointPage && alternateServerUrl && (
47
+ <Description data-translation-key="page.mcpNotAllowed.publicEndpointHint">
48
+ {renderWithLink(
49
+ translate(
50
+ 'page.mcpNotAllowed.publicEndpointHint',
51
+ 'To connect anonymously without an account, use the <link>public endpoint</link>.',
52
+ ),
53
+ alternateServerUrl,
54
+ )}
55
+ </Description>
56
+ )}
26
57
  <ButtonWrapper>
27
58
  <ConnectMCPButton alignment="start" />
28
59
  </ButtonWrapper>
@@ -46,13 +77,6 @@ const NotAllowedWrapper = styled.div`
46
77
  }
47
78
  `;
48
79
 
49
- const StatusText = styled.div`
50
- color: var(--page-mcp-405-status-text-color);
51
- font-size: var(--page-mcp-405-status-font-size);
52
- line-height: var(--page-mcp-405-status-line-height);
53
- font-weight: var(--page-mcp-405-status-font-weight);
54
- `;
55
-
56
80
  const Title = styled.div`
57
81
  font-size: var(--page-mcp-405-title-font-size);
58
82
  line-height: var(--page-mcp-405-title-line-height);
@@ -24,9 +24,9 @@ export const cards = css`
24
24
  --card-link-icon-width: 14px;
25
25
  --card-link-icon-height: 14px;
26
26
  --card-border-width: 1px;
27
- --card-image-border-radius: var(--border-radius-md);
27
+ --card-image-border-radius: var(--border-radius-xl);
28
28
  --card-image-aspect-ratio: 16 / 9;
29
- --card-icon-border-radius: var(--border-radius-md);
29
+ --card-icon-border-radius: var(--border-radius-lg);
30
30
  --card-icon-border: var(--card-border-width) var(--border-style) var(--card-icon-border-color);
31
31
  --card-icon-padding: var(--spacing-sm);
32
32
  --card-icon-size: 24px;
@@ -49,7 +49,7 @@ export const cards = css`
49
49
  --card-cta-icon-height: 14px;
50
50
  --card-badge-margin: 0 var(--spacing-xxs) 0 0 ;
51
51
  --card-badge-padding: 0 var(--spacing-xxs);
52
- --card-badge-border-radius: var(--border-radius);
52
+ --card-badge-border-radius: var(--badge-border-radius);
53
53
  --card-badge-font-size: var(--font-size-sm);
54
54
  --card-badge-font-weight: var(--font-weight-regular);
55
55
  --card-badge-line-height: var(--line-height-sm);
@@ -88,7 +88,7 @@ export const cards = css`
88
88
  --card-bg-color: transparent;
89
89
  --card-bg-color-hover: var(--layer-color);
90
90
  --card-border-width: 0;
91
- --card-border-radius: var(--border-radius-md);
91
+ --card-border-radius: var(--border-radius-xl);
92
92
  --card-padding: var(--spacing-xs) 0;
93
93
  --card-icon-border-color-hover: var(--card-icon-border-color);
94
94
  --card-icon-bg-color-hover: var(--card-icon-bg-color);
@@ -154,5 +154,7 @@ export const cards = css`
154
154
  .card-icon-color-blueberry {
155
155
  --card-icon-color: var(--color-blueberry-7);
156
156
  }
157
+
158
+ // @tokens End
157
159
  `;
158
160
  /* eslint-enable theme/no-raw-colors-in-styles */
@@ -63,6 +63,7 @@ const CodePanelWrapper = styled.div`
63
63
  background-color: var(--code-panel-bg-color);
64
64
  border: 1px solid var(--code-panel-border-color);
65
65
  border-radius: var(--code-panel-border-radius);
66
+ overflow: clip;
66
67
  --code-block-max-height: calc(100vh - var(--navbar-height) - 2 * var(--spacing-xl));
67
68
  height: calc(100vh - var(--navbar-height) - 2 * var(--spacing-xl));
68
69
  position: sticky;
@@ -153,7 +153,7 @@ const StepContent = styled.div.withConfig({
153
153
  margin: var(--spacing-xs) 0px var(--spacing-xs) calc(var(--spacing-unit) * 3.5);
154
154
  padding: var(--spacing-md) var(--spacing-lg);
155
155
  background: ${({ isActive }) => (isActive ? 'var(--layer-color)' : 'none')};
156
- border-radius: var(--border-radius);
156
+ border-radius: var(--code-step-border-radius);
157
157
 
158
158
  &:hover {
159
159
  background-color: ${({ isActive }) =>
@@ -7,10 +7,11 @@ export const codeWalkthrough = css`
7
7
  --code-step-bg-active: var(--layer-color);
8
8
  --code-step-bg-hover: var(--color-hover-base);
9
9
  --code-step-bg-active-hover: var(--layer-color-hover);
10
+ --code-step-border-radius: var(--border-radius-lg);
10
11
 
11
12
  --code-panel-bg-color: var(--layer-color);
12
13
  --code-panel-line-numbering-color: var(--text-color-disabled);
13
14
  --code-panel-header-height: var(--spacing-lg);
14
15
  --code-panel-border-color: var(--border-color-secondary);
15
- --code-panel-border-radius: var(--border-radius);
16
+ --code-panel-border-radius: var(--border-radius-xl);
16
17
  `;
@@ -173,6 +173,7 @@ export function TabList({
173
173
  });
174
174
 
175
175
  useEffect(() => {
176
+ // oxlint-disable-next-line react-you-might-not-need-an-effect/no-pass-data-to-parent
176
177
  onReadyChange?.(isReady);
177
178
  }, [isReady, onReadyChange]);
178
179
 
@@ -281,6 +282,7 @@ const useHighlightBarAnimation = (props: UseHighlightBarAnimationProps) => {
281
282
  });
282
283
 
283
284
  useEffect(() => {
285
+ // oxlint-disable-next-line react-you-might-not-need-an-effect/no-pass-data-to-parent
284
286
  const activeIndex = childrenArray.findIndex((child) => child.props.label === activeTab);
285
287
  const container = tabsContainerRef.current;
286
288
 
@@ -302,6 +304,7 @@ const useHighlightBarAnimation = (props: UseHighlightBarAnimationProps) => {
302
304
  const moreButtonRect = moreButton.getBoundingClientRect();
303
305
  const containerRect = container.getBoundingClientRect();
304
306
 
307
+ // oxlint-disable-next-line react-you-might-not-need-an-effect/no-derived-state
305
308
  setHighlightStyle({
306
309
  left: moreButtonRect.left - containerRect.left,
307
310
  width: moreButtonRect.width,
@@ -319,6 +322,7 @@ const useHighlightBarAnimation = (props: UseHighlightBarAnimationProps) => {
319
322
 
320
323
  if (visibleTabs.includes(activeIndex)) {
321
324
  activeTabElement.classList.add('active');
325
+ // oxlint-disable-next-line react-you-might-not-need-an-effect/no-derived-state
322
326
  setHighlightStyle({ left: offsetLeft, width: offsetWidth });
323
327
  return;
324
328
  }
@@ -400,8 +404,8 @@ export const TabItem = styled.li.withConfig({
400
404
  right: -4px;
401
405
  bottom: -2px;
402
406
  left: -4px;
403
- border: 1px solid var(--button-border-color-focused);
404
- border-radius: 6px;
407
+ border: var(--border-width) var(--border-style) var(--button-border-color-focused);
408
+ border-radius: var(--border-radius-md);
405
409
  pointer-events: none;
406
410
  }
407
411
  }
@@ -144,7 +144,9 @@ function useValidateActiveTab(
144
144
  initialTab: string,
145
145
  ) {
146
146
  useEffect(() => {
147
+ // oxlint-disable-next-line react-you-might-not-need-an-effect/no-pass-data-to-parent
147
148
  const availableLabels = childrenArray.map((child) => child.props.label);
149
+ // oxlint-disable-next-line react-you-might-not-need-an-effect/no-pass-data-to-parent
148
150
  if (activeTab && !availableLabels.includes(activeTab) && availableLabels.length > 0) {
149
151
  setActiveTab(initialTab);
150
152
  }
@@ -221,8 +223,8 @@ export const TabContent = styled.div`
221
223
  right: -4px;
222
224
  bottom: -2px;
223
225
  left: -4px;
224
- border: 1px solid var(--button-border-color-focused);
225
- border-radius: 6px;
226
+ border: var(--border-width) var(--border-style) var(--button-border-color-focused);
227
+ border-radius: var(--border-radius-md);
226
228
  pointer-events: none;
227
229
  }
228
230
  }