@redocly/theme 0.71.0-next.3 → 0.71.0-next.5

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 (34) hide show
  1. package/lib/components/Buttons/MobileMenuButton.d.ts +8 -0
  2. package/lib/components/Buttons/MobileMenuButton.js +58 -0
  3. package/lib/components/Catalog/CatalogFilter/CatalogFilter.js +1 -1
  4. package/lib/components/Navbar/Navbar.js +10 -18
  5. package/lib/core/hooks/use-focus-trap.js +6 -5
  6. package/lib/core/hooks/use-page-actions.d.ts +1 -1
  7. package/lib/core/hooks/use-page-actions.js +29 -33
  8. package/lib/core/styles/dark.js +0 -1
  9. package/lib/core/types/l10n.d.ts +1 -1
  10. package/lib/core/utils/get-ai-prompt-link.d.ts +3 -1
  11. package/lib/core/utils/get-ai-prompt-link.js +1 -0
  12. package/lib/icons/GrokIcon/GrokIcon.d.ts +25 -0
  13. package/lib/icons/GrokIcon/GrokIcon.js +23 -0
  14. package/lib/index.d.ts +1 -0
  15. package/lib/index.js +1 -0
  16. package/lib/markdoc/components/NumberedList/NumberedItem.js +15 -23
  17. package/lib/markdoc/components/NumberedList/variables.js +4 -3
  18. package/lib/markdoc/default.d.ts +2 -0
  19. package/lib/markdoc/default.js +2 -0
  20. package/package.json +3 -2
  21. package/src/components/Buttons/MobileMenuButton.tsx +45 -0
  22. package/src/components/Catalog/CatalogFilter/CatalogFilter.tsx +2 -2
  23. package/src/components/Feedback/Feedback.tsx +1 -3
  24. package/src/components/Navbar/Navbar.tsx +15 -30
  25. package/src/core/hooks/use-focus-trap.ts +8 -7
  26. package/src/core/hooks/use-page-actions.ts +46 -39
  27. package/src/core/styles/dark.ts +0 -1
  28. package/src/core/types/l10n.ts +3 -0
  29. package/src/core/utils/get-ai-prompt-link.ts +5 -2
  30. package/src/icons/GrokIcon/GrokIcon.tsx +24 -0
  31. package/src/index.ts +1 -0
  32. package/src/markdoc/components/NumberedList/NumberedItem.tsx +17 -26
  33. package/src/markdoc/components/NumberedList/variables.ts +4 -3
  34. package/src/markdoc/default.ts +2 -0
@@ -0,0 +1,8 @@
1
+ import type { JSX } from 'react';
2
+ export type MobileMenuButtonProps = {
3
+ isOpen: boolean;
4
+ /** Called inside a transition; the button shows the requested state until it commits. */
5
+ onOpenChange: (isOpen: boolean) => void;
6
+ className?: string;
7
+ };
8
+ export declare function MobileMenuButton({ isOpen, onOpenChange, className, }: MobileMenuButtonProps): JSX.Element;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.MobileMenuButton = MobileMenuButton;
40
+ const react_1 = __importStar(require("react"));
41
+ const styled_components_1 = __importDefault(require("styled-components"));
42
+ const utils_1 = require("../../core/utils");
43
+ const Button_1 = require("../../components/Button/Button");
44
+ const MenuIcon_1 = require("../../icons/MenuIcon/MenuIcon");
45
+ const CloseIcon_1 = require("../../icons/CloseIcon/CloseIcon");
46
+ function MobileMenuButton({ isOpen, onOpenChange, className, }) {
47
+ const [isToggling, startToggle] = (0, react_1.useTransition)();
48
+ const showClose = isToggling ? !isOpen : isOpen;
49
+ return (react_1.default.createElement(MobileMenuButtonWrapper, { "data-component-name": "Buttons/MobileMenuButton", className: className, variant: "text", "data-testid": "mobile-menu-button", onClick: () => startToggle(() => onOpenChange(!showClose)), icon: showClose ? react_1.default.createElement(CloseIcon_1.CloseIcon, null) : react_1.default.createElement(MenuIcon_1.MenuIcon, null), "aria-label": showClose ? 'Close menu button' : 'Open menu button' }));
50
+ }
51
+ const MobileMenuButtonWrapper = (0, styled_components_1.default)(Button_1.Button) `
52
+ margin-left: 0px !important;
53
+
54
+ @media screen and (min-width: ${utils_1.breakpoints.medium}) {
55
+ display: none;
56
+ }
57
+ `;
58
+ //# sourceMappingURL=MobileMenuButton.js.map
@@ -21,7 +21,7 @@ function CatalogFilter({ filter, filterValuesCasing, showCounter = true, classNa
21
21
  if (!filteredOptions || filteredOptions.length === 0) {
22
22
  return null;
23
23
  }
24
- const FilterComponent = filterComponents[(filter.type || 'checkboxes')];
24
+ const FilterComponent = filterComponents[filter.type || 'checkboxes'];
25
25
  return (react_1.default.createElement(CatalogFilterGroup, { className: className, "data-component-name": "Catalog/CatalogFilter", key: filter.property + filter.title },
26
26
  react_1.default.createElement(FilterComponent, { filter: filter, filterValuesCasing: filterValuesCasing, showCounter: showCounter })));
27
27
  }
@@ -50,9 +50,7 @@ const Search_1 = require("../../components/Search/Search");
50
50
  const UserMenu_1 = require("../../components/UserMenu/UserMenu");
51
51
  const LanguagePicker_1 = require("../../components/LanguagePicker/LanguagePicker");
52
52
  const ProductPicker_1 = require("../../components/Product/ProductPicker");
53
- const Button_1 = require("../../components/Button/Button");
54
- const MenuIcon_1 = require("../../icons/MenuIcon/MenuIcon");
55
- const CloseIcon_1 = require("../../icons/CloseIcon/CloseIcon");
53
+ const MobileMenuButton_1 = require("../../components/Buttons/MobileMenuButton");
56
54
  const Banner_1 = require("../../components/Banner/Banner");
57
55
  function Navbar({ className }) {
58
56
  var _a;
@@ -81,19 +79,20 @@ function Navbar({ className }) {
81
79
  hideSearch ? null : react_1.default.createElement(Search_1.Search, null),
82
80
  react_1.default.createElement(LanguagePicker_1.LanguagePicker, { onChangeLanguage: changeLanguage, onlyIcon: true, alignment: "end" }),
83
81
  react_1.default.createElement(ColorModeSwitcher_1.ColorModeSwitcher, null),
84
- react_1.default.createElement(MobileMenuButton, { variant: "text", "data-testid": "mobile-menu-button", onClick: isOpen
85
- ? () => {
82
+ react_1.default.createElement(MobileMenuButton_1.MobileMenuButton, { isOpen: isOpen, onOpenChange: (open) => {
83
+ if (open) {
84
+ openMobileMenu();
85
+ telemetry.sendMobileMenuOpenedMessage([
86
+ (0, utils_1.getBaseDataAttributes)('mobileMenuOpen', 'button'),
87
+ ]);
88
+ }
89
+ else {
86
90
  closeMobileMenu();
87
91
  telemetry.sendMobileMenuClosedMessage([
88
92
  (0, utils_1.getBaseDataAttributes)('mobileMenuClose', 'button'),
89
93
  ]);
90
94
  }
91
- : () => {
92
- openMobileMenu();
93
- telemetry.sendMobileMenuOpenedMessage([
94
- (0, utils_1.getBaseDataAttributes)('mobileMenuOpen', 'button'),
95
- ]);
96
- }, icon: isOpen ? react_1.default.createElement(CloseIcon_1.CloseIcon, null) : react_1.default.createElement(MenuIcon_1.MenuIcon, null), "aria-label": isOpen ? 'Close menu button' : 'Open menu button' }),
95
+ } }),
97
96
  hideUserMenu ? null : react_1.default.createElement(UserMenu_1.UserMenu, null)),
98
97
  navigationTabsConfig && react_1.default.createElement(NavigationTabs_1.NavigationTabs, { config: navigationTabsConfig })));
99
98
  }
@@ -147,11 +146,4 @@ const NavbarRow = styled_components_1.default.div `
147
146
  margin-right: auto;
148
147
  }
149
148
  `;
150
- const MobileMenuButton = (0, styled_components_1.default)(Button_1.Button) `
151
- margin-left: 0px !important;
152
-
153
- @media screen and (min-width: ${utils_1.breakpoints.medium}) {
154
- display: none;
155
- }
156
- `;
157
149
  //# sourceMappingURL=Navbar.js.map
@@ -2,15 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useFocusTrap = useFocusTrap;
4
4
  const react_1 = require("react");
5
+ const FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
5
6
  function useFocusTrap(containerRef) {
6
7
  (0, react_1.useEffect)(() => {
8
+ var _a;
7
9
  const trapElement = containerRef.current;
8
10
  if (!trapElement)
9
11
  return;
10
- const focusableElements = trapElement.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
11
- const firstElement = focusableElements[0];
12
+ const getFocusableElements = () => trapElement.querySelectorAll(FOCUSABLE_SELECTOR);
12
13
  const handleKeyDown = (event) => {
13
14
  if (event.key === 'Tab') {
15
+ const focusableElements = getFocusableElements();
16
+ const firstElement = focusableElements[0];
14
17
  const lastElement = focusableElements[focusableElements.length - 1];
15
18
  if (event.shiftKey && document.activeElement === firstElement) {
16
19
  lastElement === null || lastElement === void 0 ? void 0 : lastElement.focus();
@@ -23,9 +26,7 @@ function useFocusTrap(containerRef) {
23
26
  }
24
27
  };
25
28
  trapElement.addEventListener('keydown', handleKeyDown);
26
- if (firstElement) {
27
- firstElement.focus();
28
- }
29
+ (_a = getFocusableElements()[0]) === null || _a === void 0 ? void 0 : _a.focus();
29
30
  return () => {
30
31
  trapElement.removeEventListener('keydown', handleKeyDown);
31
32
  };
@@ -1,3 +1,3 @@
1
1
  import type { PageAction } from '../types';
2
- export type PageActionType = 'copy' | 'view' | 'chatgpt' | 'claude' | 'docs-mcp-cursor' | 'docs-mcp-vscode' | 'docs-mcp-claude' | 'mcp-cursor' | 'mcp-vscode';
2
+ export type PageActionType = 'copy' | 'view' | 'chatgpt' | 'claude' | 'grok' | 'docs-mcp-cursor' | 'docs-mcp-vscode' | 'docs-mcp-claude' | 'mcp-cursor' | 'mcp-vscode';
3
3
  export declare function usePageActions(pageSlug: string, mcpUrl?: string, actions?: PageActionType[]): PageAction[];
@@ -14,6 +14,7 @@ const react_1 = require("react");
14
14
  const CopyIcon_1 = require("../../icons/CopyIcon/CopyIcon");
15
15
  const ChatGptIcon_1 = require("../../icons/ChatGptIcon/ChatGptIcon");
16
16
  const ClaudeIcon_1 = require("../../icons/ClaudeIcon/ClaudeIcon");
17
+ const GrokIcon_1 = require("../../icons/GrokIcon/GrokIcon");
17
18
  const MarkdownFullIcon_1 = require("../../icons/MarkdownFullIcon/MarkdownFullIcon");
18
19
  const VSCodeIcon_1 = require("../../icons/VSCodeIcon/VSCodeIcon");
19
20
  const CursorIcon_1 = require("../../icons/CursorIcon/CursorIcon");
@@ -31,6 +32,7 @@ const DEFAULT_ENABLED_ACTIONS = [
31
32
  'view',
32
33
  'chatgpt',
33
34
  'claude',
35
+ 'grok',
34
36
  'docs-mcp-cursor',
35
37
  'docs-mcp-vscode',
36
38
  'docs-mcp-claude',
@@ -84,6 +86,16 @@ function usePageActions(pageSlug, mcpUrl, actions) {
84
86
  ? (0, urls_1.combineUrls)(origin, pathname, 'index.html.md')
85
87
  : (0, urls_1.combineUrls)(origin, (0, urls_1.removeTrailingSlash)(pathname) + '.md');
86
88
  const externalAiPrompt = `Read ${mdPageUrl} and answer questions based on the content.`;
89
+ const createAiPromptAction = (target, iconComponent, texts) => () => {
90
+ const link = (0, get_ai_prompt_link_1.getAiPromptLink)(target, externalAiPrompt);
91
+ return Object.assign(Object.assign({}, texts), { iconComponent,
92
+ link, onClick: () => {
93
+ telemetry.sendPageActionsClickedMessage([
94
+ Object.assign(Object.assign({}, (0, get_base_data_attributes_1.getBaseDataAttributes)('pageActions', 'button')), { actionType: target }),
95
+ ]);
96
+ window.location.href = link;
97
+ } });
98
+ };
87
99
  const actionHandlers = {
88
100
  'docs-mcp-cursor': createMCPHandler('cursor', false),
89
101
  'docs-mcp-vscode': createMCPHandler('vscode', false),
@@ -124,38 +136,21 @@ function usePageActions(pageSlug, mcpUrl, actions) {
124
136
  ]);
125
137
  },
126
138
  }),
127
- chatgpt: () => {
128
- const link = (0, get_ai_prompt_link_1.getAiPromptLink)('chatgpt', externalAiPrompt);
129
- return {
130
- buttonText: translate('page.actions.chatGptButtonText', 'Open in ChatGPT'),
131
- title: translate('page.actions.chatGptTitle', 'Open in ChatGPT'),
132
- description: translate('page.actions.chatGptDescription', 'Get insights from ChatGPT'),
133
- iconComponent: ChatGptIcon_1.ChatGptIcon,
134
- link,
135
- onClick: () => {
136
- telemetry.sendPageActionsClickedMessage([
137
- Object.assign(Object.assign({}, (0, get_base_data_attributes_1.getBaseDataAttributes)('pageActions', 'button')), { actionType: 'chatgpt' }),
138
- ]);
139
- window.location.href = link;
140
- },
141
- };
142
- },
143
- claude: () => {
144
- const link = (0, get_ai_prompt_link_1.getAiPromptLink)('claude', externalAiPrompt);
145
- return {
146
- buttonText: translate('page.actions.claudeButtonText', 'Open in Claude'),
147
- title: translate('page.actions.claudeTitle', 'Open in Claude'),
148
- description: translate('page.actions.claudeDescription', 'Get insights from Claude'),
149
- iconComponent: ClaudeIcon_1.ClaudeIcon,
150
- link,
151
- onClick: () => {
152
- telemetry.sendPageActionsClickedMessage([
153
- Object.assign(Object.assign({}, (0, get_base_data_attributes_1.getBaseDataAttributes)('pageActions', 'button')), { actionType: 'claude' }),
154
- ]);
155
- window.location.href = link;
156
- },
157
- };
158
- },
139
+ chatgpt: createAiPromptAction('chatgpt', ChatGptIcon_1.ChatGptIcon, {
140
+ buttonText: translate('page.actions.chatGptButtonText', 'Open in ChatGPT'),
141
+ title: translate('page.actions.chatGptTitle', 'Open in ChatGPT'),
142
+ description: translate('page.actions.chatGptDescription', 'Get insights from ChatGPT'),
143
+ }),
144
+ claude: createAiPromptAction('claude', ClaudeIcon_1.ClaudeIcon, {
145
+ buttonText: translate('page.actions.claudeButtonText', 'Open in Claude'),
146
+ title: translate('page.actions.claudeTitle', 'Open in Claude'),
147
+ description: translate('page.actions.claudeDescription', 'Get insights from Claude'),
148
+ }),
149
+ grok: createAiPromptAction('grok', GrokIcon_1.GrokIcon, {
150
+ buttonText: translate('page.actions.grokButtonText', 'Open in Grok'),
151
+ title: translate('page.actions.grokTitle', 'Open in Grok'),
152
+ description: translate('page.actions.grokDescription', 'Get insights from Grok'),
153
+ }),
159
154
  };
160
155
  return (((_b = (_a = themeConfig.navigation) === null || _a === void 0 ? void 0 : _a.actions) === null || _b === void 0 ? void 0 : _b.items) || actions || DEFAULT_ENABLED_ACTIONS)
161
156
  .filter((action) => !shouldHideAction(action, hideActionContext))
@@ -198,7 +193,7 @@ function shouldHideAction(action, { pageProps, themeConfig, apiDocsExcludeFromSe
198
193
  if ((_b = (_a = themeConfig.navigation) === null || _a === void 0 ? void 0 : _a.actions) === null || _b === void 0 ? void 0 : _b.hide) {
199
194
  return true;
200
195
  }
201
- const actionDependsOnLlmsTxt = ['view', 'copy', 'chatgpt', 'claude'].includes(action);
196
+ const actionDependsOnLlmsTxt = ['view', 'copy', 'chatgpt', 'claude', 'grok'].includes(action);
202
197
  if (actionDependsOnLlmsTxt) {
203
198
  // Can't use any actions if search is globally disabled (markdown files are not generated)
204
199
  if ((_c = themeConfig.search) === null || _c === void 0 ? void 0 : _c.hide) {
@@ -219,6 +214,7 @@ function shouldHideActionByType(action, { isPublic, mcpUrl, isMcpDisabled, }) {
219
214
  switch (action) {
220
215
  case 'chatgpt':
221
216
  case 'claude':
217
+ case 'grok':
222
218
  return !isPublic;
223
219
  case 'docs-mcp-cursor':
224
220
  case 'docs-mcp-vscode':
@@ -65,7 +65,6 @@ const numberedListDarkMode = (0, styled_components_1.css) `
65
65
  */
66
66
 
67
67
  --md-numbered-list-marker-bg-color: var(--color-warm-grey-3); // @presenter Color
68
- --md-numbered-list-marker-bg-color-hover: var(--color-warm-grey-4); // @presenter Color
69
68
 
70
69
  // @tokens End
71
70
  `;
@@ -1,5 +1,5 @@
1
1
  import type { TOptions } from 'i18next';
2
- export type TranslationKey = 'dev.newApp' | 'dev.newApp.text' | 'dev.sidebar.header' | 'dev.sidebar.footer.text' | 'dev.create.app.dialog.appName.placeholder' | 'dev.create.app.dialog.appName.error' | 'dev.create.app.dialog.selectAPIs' | 'dev.create.app.dialog.description' | 'dev.create.app.dialog.description.placeholder' | 'dev.create.app.dialog.create' | 'dev.create.app.dialog.cancel' | 'dev.main.tab.appKeys' | 'dev.main.tab.logs' | 'dev.app.description.title' | 'dev.edit.description.dialog.title' | 'dev.edit.description.dialog.save' | 'dev.edit.description.dialog.cancel' | 'dev.create.app.dialog.callbackUrls' | 'dev.create.app.dialog.callbackUrls.placeholder' | 'dev.create.app.dialog.callbackUrls.hint' | 'dev.app.callbackUrls.title' | 'dev.edit.callbackUrls.dialog.title' | 'dev.edit.callbackUrls.dialog.placeholder' | 'dev.edit.callbackUrls.dialog.hint' | 'dev.edit.callbackUrls.dialog.save' | 'dev.edit.callbackUrls.dialog.cancel' | 'dev.edit.apis.dialog.selectedAPIs' | 'dev.app.key.create' | 'dev.create.key.dialog.title' | 'dev.create.key.dialog.create' | 'dev.create.key.dialog.cancel' | 'dev.app.edit' | 'dev.app.delete' | 'dev.edit.app.dialog.title' | 'dev.edit.app.dialog.save' | 'dev.edit.app.dialog.cancel' | 'dev.delete.app.dialog.title' | 'dev.delete.app.dialog.confirmation' | 'dev.delete.app.dialog.delete' | 'dev.delete.app.dialog.cancel' | 'dev.app.key.roll' | 'dev.roll.key.dialog.title' | 'dev.roll.key.dialog.apiKey' | 'dev.roll.key.dialog.expires' | 'dev.roll.key.dialog.confirmation' | 'dev.roll.key.dialog.cancel' | 'dev.roll.key.dialog.roll' | 'dev.update.key.dialog.title' | 'dev.update.key.dialog.update' | 'dev.update.key.dialog.cancel' | 'dev.app.key.api.name' | 'dev.app.key.api.status' | 'dev.app.key.api.edit' | 'dev.edit.apis.dialog.title' | 'dev.edit.apis.dialog.apiKey' | 'dev.edit.apis.dialog.save' | 'dev.edit.apis.dialog.cancel' | 'dev.select.placeholder' | 'dev.app.overview.status.pending' | 'dev.app.overview.status.approved' | 'dev.app.overview.status.revoked' | 'dev.app.overview.status' | 'dev.app.overview.non-production' | 'dev.app.overview.production' | 'dev.app.overview.clientId' | 'dev.app.overview.apiKey' | 'dev.app.key.revoke' | 'dev.revoke.key.dialog.title' | 'dev.revoke.key.dialog.apiKey' | 'dev.revoke.key.dialog.expires' | 'dev.revoke.key.dialog.confirmation' | 'dev.revoke.key.dialog.revoke' | 'dev.revoke.key.dialog.cancel' | 'dev.app.overview.expires' | 'dev.app.overview.created' | 'dev.app.overview.visibilityToggle.hide' | 'dev.app.overview.visibilityToggle.show' | 'search.loading' | 'search.noResults.title' | 'search.keys.navigate' | 'search.keys.select' | 'search.keys.exit' | 'search.label' | 'search.cancel' | 'search.recent' | 'search.navbar.label' | 'search.suggested' | 'search.showMore' | 'search.error.title' | 'search.error.button' | 'search.filter.title' | 'search.filter.reset' | 'search.filter.field.reset' | 'search.ai.welcomeText' | 'search.ai.newConversation' | 'search.ai.backToSearch' | 'search.ai.back' | 'search.ai.assistant' | 'search.ai.placeholder' | 'search.ai.generatingResponse' | 'search.ai.followUpQuestion' | 'search.ai.send' | 'search.ai.suggestionsTitle' | 'search.ai.thinkingText' | 'search.ai.resourcesFound' | 'search.ai.resourcesFound.basedOn' | 'search.ai.resourcesFound.resources' | 'search.ai.feedback.title' | 'search.ai.feedback.detailsPlaceholder' | 'search.ai.feedback.thanks' | 'search.ai.toolCall.executed' | 'search.ai.toolCall.executing' | 'search.ai.toolCall.usedTools' | 'search.ai.button' | 'search.ai.label' | 'search.ai.disclaimer' | 'search.ai.error.description' | 'search.ai.error.description.forbidden' | 'search.ai.error.description.unauthorized' | 'search.ai.error.header' | 'search.ai.error.header.forbidden' | 'search.ai.error.header.unauthorized' | 'search.ai.feedback.more' | 'search.ai.actions.copy' | 'search.ai.actions.like' | 'search.ai.actions.dislike' | 'search.searchItem.deprecated' | 'search.searchItem.enum' | 'search.searchItem.example' | 'search.groups.all' | 'search.filter.field.footer' | 'aiAssistant.trigger' | 'toc.header' | 'footer.copyrightText' | 'page.homeButton' | 'page.forbidden.title' | 'page.forbidden.description' | 'page.notFound.title' | 'page.notFound.description' | 'page.apiNotFound.title' | 'page.apiNotFound.description' | 'page.apiNotFound.hint' | 'page.apiNotFound.backButton' | 'page.mcpNotAllowed.title' | 'page.mcpNotAllowed.description' | 'page.mcpNotAllowed.publicNote' | 'page.mcpNotAllowed.publicEndpointHint' | 'page.mcpNotAllowed.mainEndpointHint' | 'page.mcpNotAllowed.snippets.terminal.hint' | 'page.mcpNotAllowed.snippets.claudeCode.headline' | 'page.mcpNotAllowed.snippets.claudeDesktop.headline' | 'page.mcpNotAllowed.snippets.claudeDesktop.accountHint' | 'page.mcpNotAllowed.snippets.claudeDesktop.instruction' | 'page.mcpNotAllowed.snippets.chatgptApp.headline' | 'page.mcpNotAllowed.snippets.chatgptApp.instruction' | 'page.mcpNotAllowed.snippets.codexCli.headline' | 'page.mcpNotAllowed.snippets.prompt.headline' | 'page.mcpNotAllowed.snippets.prompt.hint' | 'page.mcpNotAllowed.snippets.json.hint' | 'page.mcpNotAllowed.tabs.claude' | 'page.mcpNotAllowed.tabs.chatgpt' | 'page.mcpNotAllowed.tabs.json' | 'page.lastUpdated.timeago' | 'page.lastUpdated.on' | 'catalog.filters.placeholder' | 'catalog.filters.title' | 'catalog.filters.add' | 'catalog.filters.clearAll' | 'catalog.filters.select.addFilter' | 'catalog.filters.select.all' | 'catalog.filters.done' | 'catalog.catalogs.all.title' | 'catalog.catalogs.all.description' | 'catalog.catalogs.all.switcherLabel' | 'catalog.catalogs.service.title' | 'catalog.catalogs.service.description' | 'catalog.catalogs.service.switcherLabel' | 'catalog.catalogs.user.title' | 'catalog.catalogs.user.description' | 'catalog.catalogs.user.switcherLabel' | 'catalog.catalogs.team.title' | 'catalog.catalogs.team.description' | 'catalog.catalogs.team.switcherLabel' | 'catalog.catalogs.domain.title' | 'catalog.catalogs.domain.description' | 'catalog.catalogs.domain.switcherLabel' | 'catalog.catalogs.apiDescription.title' | 'catalog.catalogs.apiDescription.description' | 'catalog.catalogs.apiDescription.switcherLabel' | 'catalog.catalogs.dataSchema.title' | 'catalog.catalogs.dataSchema.description' | 'catalog.catalogs.dataSchema.switcherLabel' | 'catalog.catalogs.apiOperation.title' | 'catalog.catalogs.apiOperation.description' | 'catalog.catalogs.apiOperation.switcherLabel' | 'catalog.entity.metadata.title' | 'catalog.entity.schema.title' | 'catalog.entity.properties.apiDescription.title' | 'catalog.backToAllLabel' | 'catalog.notConnected' | 'catalog.tags.label' | 'catalog.sort' | 'catalog.catalogs.label' | 'catalog.owners.label' | 'catalog.repositories.label' | 'catalog.email.label' | 'catalog.format.label' | 'catalog.entityType.label' | 'catalog.domains.label' | 'catalog.contact.label' | 'catalog.methodAndPath.label' | 'catalog.links.label' | 'catalog.metadata.domains' | 'catalog.metadata.owners' | 'catalog.history.button.label' | 'catalog.history.sidebar.title' | 'catalog.history.sidebar.close' | 'catalog.history.version.label' | 'catalog.filters.close' | 'catalog.history.version.notSpecified' | 'catalog.history.version.default' | 'catalog.history.revisions.limitMessage' | 'catalog.history.revision.current' | 'catalog.history.revisions.showLess' | 'catalog.history.revisions.showMore' | 'navigationTabs.label' | 'sidebar.menu.backLabel' | 'sidebar.menu.backToLabel' | 'sidebar.actions.show' | 'sidebar.actions.hide' | 'sidebar.actions.changeToSingleColumn' | 'sidebar.actions.changeToTwoColumns' | 'sidebar.actions.singleColumn' | 'sidebar.actions.twoColumns' | 'versionPicker.label' | 'versionPicker.unversioned' | 'codeSnippet.copy.buttonText' | 'codeSnippet.copy.tooltipText' | 'codeSnippet.copy.toasterText' | 'markdown.editPage.text' | 'feedback.settings.comment.submitText' | 'feedback.settings.comment.label' | 'feedback.settings.comment.send' | 'feedback.settings.comment.cancel' | 'feedback.settings.comment.maxLength' | 'feedback.settings.comment.satisfiedLabel' | 'feedback.settings.comment.neutralLabel' | 'feedback.settings.comment.dissatisfiedLabel' | 'feedback.settings.submitText' | 'feedback.settings.label' | 'feedback.settings.reasons.label' | 'feedback.submit' | 'feedback.cancel' | 'feedback.settings.comment.likeLabel' | 'feedback.settings.comment.dislikeLabel' | 'feedback.sentiment.thumbUp' | 'feedback.sentiment.thumbDown' | 'feedback.settings.leftScaleLabel' | 'feedback.settings.rightScaleLabel' | 'feedback.settings.optionalEmail.placeholder' | 'feedback.settings.optionalEmail.label' | 'codeSnippet.report.buttonText' | 'codeSnippet.report.tooltipText' | 'codeSnippet.report.label' | 'codeSnippet.expand.tooltipText' | 'codeSnippet.collapse.tooltipText' | 'jsonViewer.showMore' | 'jsonViewer.showLess' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'mobileMenu.version' | 'navbar.label' | 'navbar.products' | 'page.nextButton' | 'page.previousButton' | 'page.actions.copyButtonText' | 'page.actions.copyTitle' | 'page.actions.copyDescription' | 'page.actions.viewAsMdTitle' | 'page.actions.viewAsMdButtonText' | 'page.actions.viewAsMdDescription' | 'page.actions.chatGptTitle' | 'page.actions.chatGptButtonText' | 'page.actions.chatGptDescription' | 'page.actions.claudeTitle' | 'page.actions.claudeButtonText' | 'page.actions.claudeDescription' | 'page.actions.cursorMcpButtonText' | 'page.actions.cursorMcpTitle' | 'page.actions.cursorMcpDescription' | 'page.actions.connectMcp' | 'page.actions.connectMcp.cursor' | 'page.actions.connectMcp.cursorDescription' | 'page.actions.connectMcp.vscode' | 'page.actions.connectMcp.vscodeDescription' | 'page.actions.connectMcp.claude' | 'page.actions.connectMcp.claudeDescription' | 'page.actions.connectMcp.claudeCode' | 'page.actions.connectMcp.claudeCodeDescription' | 'page.actions.connectMcp.codex' | 'page.actions.connectMcp.codexDescription' | 'page.actions.connectMcp.copyConfig' | 'page.actions.connectMcp.copyConfigDescription' | 'page.actions.connectMcp.moreOptions' | 'page.actions.moreActions' | 'promptTag.copy.buttonText' | 'promptTag.showPrompt' | 'promptTag.hidePrompt' | 'promptTag.showFullPrompt' | 'promptTag.showLess' | 'promptTag.openIn.cursor' | 'promptTag.openIn.cursorDescription' | 'promptTag.openIn.claude' | 'promptTag.openIn.claudeDescription' | 'promptTag.openIn.chatgpt' | 'promptTag.openIn.chatgptDescription' | 'openapi.download.description.title' | 'openapi.info.title' | 'openapi.info.contact.url' | 'openapi.info.contact.name' | 'openapi.info.license' | 'openapi.info.termsOfService' | 'openapi.info.metadata.title' | 'graphql.info.metadata.title' | 'openapi.key' | 'openapi.value' | 'openapi.enum' | 'openapi.items' | 'openapi.default' | 'openapi.variable' | 'openapi.variables' | 'openapi.actions.show' | 'openapi.actions.hide' | 'openapi.actions.more' | 'openapi.languages.title' | 'openapi.languages.moreButton.tooltipText' | 'openapi.servers.title' | 'openapi.operations' | 'openapi.schemas' | 'openapi.webhooks' | 'openapi.description' | 'openapi.badges.deprecated' | 'openapi.badges.required' | 'openapi.badges.webhook' | 'openapi.request' | 'openapi.path' | 'openapi.query' | 'openapi.querystring' | 'openapi.cookie' | 'openapi.header' | 'openapi.body' | 'openapi.responses' | 'openapi.response' | 'openapi.callbacks' | 'openapi.callbackRequest' | 'openapi.callbackResponse' | 'openapi.payload' | 'openapi.discriminator' | 'openapi.contentType' | 'openapi.tryIt' | 'openapi.loading' | 'openapi.example' | 'openapi.examples' | 'openapi.additionalProperties' | 'openapi.patternProperties' | 'openapi.required' | 'openapi.recursive' | 'openapi.complex' | 'openapi.property' | 'openapi.properties' | 'openapi.details' | 'openapi.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.deepLink.tooltip' | 'openapi.collapseAll' | 'openapi.viewSecurityDetails' | 'openapi.noResponseExample' | 'openapi.discriminator.searchPlaceholder' | 'openapi.discriminator.searchNoResults' | 'openapi.discriminator.defaultMapping' | 'openapi.discriminator.defaultMappingTooltip' | 'openapi.noResponseContent' | 'openapi.noRequestPayload' | 'openapi.noRequestData' | 'openapi.hidePattern' | 'openapi.showPattern' | 'openapi.authorizationUrl' | 'openapi.tokenUrl' | 'openapi.refreshUrl' | 'openapi.showOptionalScopes' | 'openapi.hideOptionalScopes' | 'openapi.security' | 'openapi.httpAuthorizationScheme' | 'openapi.bearerFormat' | 'openapi.parameterName' | 'openapi.flowType' | 'openapi.connectUrl' | 'openapi.requiredScopes' | 'openapi.unsupportedLanguage' | 'openapi.failedToGenerateCodeSample' | 'openapi.schemaCatalogLink.title' | 'openapi.schemaCatalogLink.copyButtonTooltip' | 'openapi.schemaCatalogLink.copiedTooltip' | 'openapi.mcp.title' | 'openapi.mcp.endpoint' | 'openapi.mcp.tools' | 'openapi.mcp.protocolVersion' | 'openapi.mcp.capabilities' | 'openapi.mcp.experimentalCapabilities' | 'openapi.mcp.inputSchema' | 'openapi.mcp.inputExample' | 'openapi.mcp.outputSchema' | 'openapi.mcp.outputExample' | 'openapi.mcp.exampleTitle' | 'openapi.mcp.argumentsExample' | 'asyncapi.download.description.title' | 'asyncapi.info.title' | 'asyncapi.info.contact.url' | 'asyncapi.info.contact.name' | 'asyncapi.info.license' | 'asyncapi.info.termsOfService' | 'asyncapi.key' | 'asyncapi.value' | 'asyncapi.variables' | 'asyncapi.required' | 'asyncapi.requiredScopes' | 'asyncapi.viewSecurityDetails' | 'graphql.download.description.title' | 'graphql.info.title' | 'graphql.info.contact.url' | 'graphql.info.contact.name' | 'graphql.info.license' | 'graphql.info.termsOfService' | 'graphql.overview' | 'graphql.metadata' | 'graphql.key' | 'graphql.value' | 'graphql.queries' | 'graphql.mutations' | 'graphql.subscriptions' | 'graphql.directives' | 'graphql.objects' | 'graphql.interfaces' | 'graphql.unions' | 'graphql.enums' | 'graphql.inputs' | 'graphql.scalars' | 'graphql.actions.show' | 'graphql.actions.hide' | 'graphql.actions.more' | 'graphql.fields' | 'graphql.inputFields' | 'graphql.values' | 'graphql.arguments.label' | 'graphql.arguments.show' | 'graphql.arguments.hide' | 'graphql.arguments.here' | 'graphql.returnTypes.label' | 'graphql.returnTypes.show' | 'graphql.returnTypes.hide' | 'graphql.possibleTypes' | 'graphql.defaultValue' | 'graphql.deprecationReason' | 'graphql.requiredScopes' | 'graphql.viewSecurityDetails' | 'graphql.objectScopes' | 'graphql.fieldScopes' | 'graphql.implementedInterfaces' | 'graphql.implementedBy' | 'graphql.nonNull' | 'graphql.required' | 'asyncapi.badges.deprecated' | 'graphql.badges.deprecated' | 'asyncapi.actions.show' | 'asyncapi.actions.hide' | 'asyncapi.actions.more' | 'asyncapi.payload' | 'asyncapi.parameters' | 'asyncapi.messages' | 'asyncapi.contentType' | 'asyncapi.moreDetails' | 'asyncapi.property' | 'asyncapi.properties' | 'asyncapi.details' | 'asyncapi.reply' | 'asyncapi.servers.title' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'graphql.content.fragment' | 'graphql.tryIt' | 'graphql.loading' | 'button.download.tooltipText' | 'button.externalLink.tooltipText' | 'button.email.tooltipText' | 'codeWalkthrough.download' | 'codeWalkthrough.preview' | 'time.justNow' | 'time.past.second' | 'time.past.seconds' | 'time.past.minute' | 'time.past.minutes' | 'time.past.hour' | 'time.past.hours' | 'time.past.day' | 'time.past.days' | 'time.past.week' | 'time.past.weeks' | 'time.past.month' | 'time.past.months' | 'time.past.year' | 'time.past.years' | 'page.internalServerError.title' | 'page.internalServerError.description' | 'page.skipToContent.label' | 'select.noResults' | 'loaders.loading' | 'filter.dateRange.from' | 'filter.dateRange.to' | 'diagram.openFullscreen' | 'diagram.zoomIn' | 'diagram.zoomOut' | 'diagram.reset' | 'diagram.close' | 'diagram.viewer' | 'consent.title' | 'consent.message' | 'consent.privacyPolicy' | 'consent.customize' | 'consent.rejectAll' | 'consent.acceptAll' | 'consent.acceptAllCookies' | 'consent.savePreferences' | 'consent.dialog.title' | 'consent.dialog.description' | 'consent.dialog.close' | 'consent.alwaysOn' | 'consent.alwaysOff' | 'consent.gpcNotice' | 'consent.category.necessary.title' | 'consent.category.necessary.description' | 'consent.category.analytics.title' | 'consent.category.analytics.description' | 'consent.category.marketing.title' | 'consent.category.marketing.description' | 'consent.settingsLink';
2
+ export type TranslationKey = 'dev.newApp' | 'dev.newApp.text' | 'dev.sidebar.header' | 'dev.sidebar.footer.text' | 'dev.create.app.dialog.appName.placeholder' | 'dev.create.app.dialog.appName.error' | 'dev.create.app.dialog.selectAPIs' | 'dev.create.app.dialog.description' | 'dev.create.app.dialog.description.placeholder' | 'dev.create.app.dialog.create' | 'dev.create.app.dialog.cancel' | 'dev.main.tab.appKeys' | 'dev.main.tab.logs' | 'dev.app.description.title' | 'dev.edit.description.dialog.title' | 'dev.edit.description.dialog.save' | 'dev.edit.description.dialog.cancel' | 'dev.create.app.dialog.callbackUrls' | 'dev.create.app.dialog.callbackUrls.placeholder' | 'dev.create.app.dialog.callbackUrls.hint' | 'dev.app.callbackUrls.title' | 'dev.edit.callbackUrls.dialog.title' | 'dev.edit.callbackUrls.dialog.placeholder' | 'dev.edit.callbackUrls.dialog.hint' | 'dev.edit.callbackUrls.dialog.save' | 'dev.edit.callbackUrls.dialog.cancel' | 'dev.edit.apis.dialog.selectedAPIs' | 'dev.app.key.create' | 'dev.create.key.dialog.title' | 'dev.create.key.dialog.create' | 'dev.create.key.dialog.cancel' | 'dev.app.edit' | 'dev.app.delete' | 'dev.edit.app.dialog.title' | 'dev.edit.app.dialog.save' | 'dev.edit.app.dialog.cancel' | 'dev.delete.app.dialog.title' | 'dev.delete.app.dialog.confirmation' | 'dev.delete.app.dialog.delete' | 'dev.delete.app.dialog.cancel' | 'dev.app.key.roll' | 'dev.roll.key.dialog.title' | 'dev.roll.key.dialog.apiKey' | 'dev.roll.key.dialog.expires' | 'dev.roll.key.dialog.confirmation' | 'dev.roll.key.dialog.cancel' | 'dev.roll.key.dialog.roll' | 'dev.update.key.dialog.title' | 'dev.update.key.dialog.update' | 'dev.update.key.dialog.cancel' | 'dev.app.key.api.name' | 'dev.app.key.api.status' | 'dev.app.key.api.edit' | 'dev.edit.apis.dialog.title' | 'dev.edit.apis.dialog.apiKey' | 'dev.edit.apis.dialog.save' | 'dev.edit.apis.dialog.cancel' | 'dev.select.placeholder' | 'dev.app.overview.status.pending' | 'dev.app.overview.status.approved' | 'dev.app.overview.status.revoked' | 'dev.app.overview.status' | 'dev.app.overview.non-production' | 'dev.app.overview.production' | 'dev.app.overview.clientId' | 'dev.app.overview.apiKey' | 'dev.app.key.revoke' | 'dev.revoke.key.dialog.title' | 'dev.revoke.key.dialog.apiKey' | 'dev.revoke.key.dialog.expires' | 'dev.revoke.key.dialog.confirmation' | 'dev.revoke.key.dialog.revoke' | 'dev.revoke.key.dialog.cancel' | 'dev.app.overview.expires' | 'dev.app.overview.created' | 'dev.app.overview.visibilityToggle.hide' | 'dev.app.overview.visibilityToggle.show' | 'search.loading' | 'search.noResults.title' | 'search.keys.navigate' | 'search.keys.select' | 'search.keys.exit' | 'search.label' | 'search.cancel' | 'search.recent' | 'search.navbar.label' | 'search.suggested' | 'search.showMore' | 'search.error.title' | 'search.error.button' | 'search.filter.title' | 'search.filter.reset' | 'search.filter.field.reset' | 'search.ai.welcomeText' | 'search.ai.newConversation' | 'search.ai.backToSearch' | 'search.ai.back' | 'search.ai.assistant' | 'search.ai.placeholder' | 'search.ai.generatingResponse' | 'search.ai.followUpQuestion' | 'search.ai.send' | 'search.ai.suggestionsTitle' | 'search.ai.thinkingText' | 'search.ai.resourcesFound' | 'search.ai.resourcesFound.basedOn' | 'search.ai.resourcesFound.resources' | 'search.ai.feedback.title' | 'search.ai.feedback.detailsPlaceholder' | 'search.ai.feedback.thanks' | 'search.ai.toolCall.executed' | 'search.ai.toolCall.executing' | 'search.ai.toolCall.usedTools' | 'search.ai.button' | 'search.ai.label' | 'search.ai.disclaimer' | 'search.ai.error.description' | 'search.ai.error.description.forbidden' | 'search.ai.error.description.unauthorized' | 'search.ai.error.header' | 'search.ai.error.header.forbidden' | 'search.ai.error.header.unauthorized' | 'search.ai.feedback.more' | 'search.ai.actions.copy' | 'search.ai.actions.like' | 'search.ai.actions.dislike' | 'search.searchItem.deprecated' | 'search.searchItem.enum' | 'search.searchItem.example' | 'search.groups.all' | 'search.filter.field.footer' | 'aiAssistant.trigger' | 'toc.header' | 'footer.copyrightText' | 'page.homeButton' | 'page.forbidden.title' | 'page.forbidden.description' | 'page.notFound.title' | 'page.notFound.description' | 'page.apiNotFound.title' | 'page.apiNotFound.description' | 'page.apiNotFound.hint' | 'page.apiNotFound.backButton' | 'page.mcpNotAllowed.title' | 'page.mcpNotAllowed.description' | 'page.mcpNotAllowed.publicNote' | 'page.mcpNotAllowed.publicEndpointHint' | 'page.mcpNotAllowed.mainEndpointHint' | 'page.mcpNotAllowed.snippets.terminal.hint' | 'page.mcpNotAllowed.snippets.claudeCode.headline' | 'page.mcpNotAllowed.snippets.claudeDesktop.headline' | 'page.mcpNotAllowed.snippets.claudeDesktop.accountHint' | 'page.mcpNotAllowed.snippets.claudeDesktop.instruction' | 'page.mcpNotAllowed.snippets.chatgptApp.headline' | 'page.mcpNotAllowed.snippets.chatgptApp.instruction' | 'page.mcpNotAllowed.snippets.codexCli.headline' | 'page.mcpNotAllowed.snippets.prompt.headline' | 'page.mcpNotAllowed.snippets.prompt.hint' | 'page.mcpNotAllowed.snippets.json.hint' | 'page.mcpNotAllowed.tabs.claude' | 'page.mcpNotAllowed.tabs.chatgpt' | 'page.mcpNotAllowed.tabs.json' | 'page.lastUpdated.timeago' | 'page.lastUpdated.on' | 'catalog.filters.placeholder' | 'catalog.filters.title' | 'catalog.filters.add' | 'catalog.filters.clearAll' | 'catalog.filters.select.addFilter' | 'catalog.filters.select.all' | 'catalog.filters.done' | 'catalog.catalogs.all.title' | 'catalog.catalogs.all.description' | 'catalog.catalogs.all.switcherLabel' | 'catalog.catalogs.service.title' | 'catalog.catalogs.service.description' | 'catalog.catalogs.service.switcherLabel' | 'catalog.catalogs.user.title' | 'catalog.catalogs.user.description' | 'catalog.catalogs.user.switcherLabel' | 'catalog.catalogs.team.title' | 'catalog.catalogs.team.description' | 'catalog.catalogs.team.switcherLabel' | 'catalog.catalogs.domain.title' | 'catalog.catalogs.domain.description' | 'catalog.catalogs.domain.switcherLabel' | 'catalog.catalogs.apiDescription.title' | 'catalog.catalogs.apiDescription.description' | 'catalog.catalogs.apiDescription.switcherLabel' | 'catalog.catalogs.dataSchema.title' | 'catalog.catalogs.dataSchema.description' | 'catalog.catalogs.dataSchema.switcherLabel' | 'catalog.catalogs.apiOperation.title' | 'catalog.catalogs.apiOperation.description' | 'catalog.catalogs.apiOperation.switcherLabel' | 'catalog.entity.metadata.title' | 'catalog.entity.schema.title' | 'catalog.entity.properties.apiDescription.title' | 'catalog.backToAllLabel' | 'catalog.notConnected' | 'catalog.tags.label' | 'catalog.sort' | 'catalog.catalogs.label' | 'catalog.owners.label' | 'catalog.repositories.label' | 'catalog.email.label' | 'catalog.format.label' | 'catalog.entityType.label' | 'catalog.domains.label' | 'catalog.contact.label' | 'catalog.methodAndPath.label' | 'catalog.links.label' | 'catalog.metadata.domains' | 'catalog.metadata.owners' | 'catalog.history.button.label' | 'catalog.history.sidebar.title' | 'catalog.history.sidebar.close' | 'catalog.history.version.label' | 'catalog.filters.close' | 'catalog.history.version.notSpecified' | 'catalog.history.version.default' | 'catalog.history.revisions.limitMessage' | 'catalog.history.revision.current' | 'catalog.history.revisions.showLess' | 'catalog.history.revisions.showMore' | 'navigationTabs.label' | 'sidebar.menu.backLabel' | 'sidebar.menu.backToLabel' | 'sidebar.actions.show' | 'sidebar.actions.hide' | 'sidebar.actions.changeToSingleColumn' | 'sidebar.actions.changeToTwoColumns' | 'sidebar.actions.singleColumn' | 'sidebar.actions.twoColumns' | 'versionPicker.label' | 'versionPicker.unversioned' | 'codeSnippet.copy.buttonText' | 'codeSnippet.copy.tooltipText' | 'codeSnippet.copy.toasterText' | 'markdown.editPage.text' | 'feedback.settings.comment.submitText' | 'feedback.settings.comment.label' | 'feedback.settings.comment.send' | 'feedback.settings.comment.cancel' | 'feedback.settings.comment.maxLength' | 'feedback.settings.comment.satisfiedLabel' | 'feedback.settings.comment.neutralLabel' | 'feedback.settings.comment.dissatisfiedLabel' | 'feedback.settings.submitText' | 'feedback.settings.label' | 'feedback.settings.reasons.label' | 'feedback.submit' | 'feedback.cancel' | 'feedback.settings.comment.likeLabel' | 'feedback.settings.comment.dislikeLabel' | 'feedback.sentiment.thumbUp' | 'feedback.sentiment.thumbDown' | 'feedback.settings.leftScaleLabel' | 'feedback.settings.rightScaleLabel' | 'feedback.settings.optionalEmail.placeholder' | 'feedback.settings.optionalEmail.label' | 'codeSnippet.report.buttonText' | 'codeSnippet.report.tooltipText' | 'codeSnippet.report.label' | 'codeSnippet.expand.tooltipText' | 'codeSnippet.collapse.tooltipText' | 'jsonViewer.showMore' | 'jsonViewer.showLess' | 'userMenu.login' | 'userMenu.logout' | 'userMenu.devOnboardingLabel' | 'mobileMenu.mainMenu' | 'mobileMenu.previous' | 'mobileMenu.products' | 'mobileMenu.version' | 'navbar.label' | 'navbar.products' | 'page.nextButton' | 'page.previousButton' | 'page.actions.copyButtonText' | 'page.actions.copyTitle' | 'page.actions.copyDescription' | 'page.actions.viewAsMdTitle' | 'page.actions.viewAsMdButtonText' | 'page.actions.viewAsMdDescription' | 'page.actions.chatGptTitle' | 'page.actions.chatGptButtonText' | 'page.actions.chatGptDescription' | 'page.actions.claudeTitle' | 'page.actions.claudeButtonText' | 'page.actions.claudeDescription' | 'page.actions.grokTitle' | 'page.actions.grokButtonText' | 'page.actions.grokDescription' | 'page.actions.cursorMcpButtonText' | 'page.actions.cursorMcpTitle' | 'page.actions.cursorMcpDescription' | 'page.actions.connectMcp' | 'page.actions.connectMcp.cursor' | 'page.actions.connectMcp.cursorDescription' | 'page.actions.connectMcp.vscode' | 'page.actions.connectMcp.vscodeDescription' | 'page.actions.connectMcp.claude' | 'page.actions.connectMcp.claudeDescription' | 'page.actions.connectMcp.claudeCode' | 'page.actions.connectMcp.claudeCodeDescription' | 'page.actions.connectMcp.codex' | 'page.actions.connectMcp.codexDescription' | 'page.actions.connectMcp.copyConfig' | 'page.actions.connectMcp.copyConfigDescription' | 'page.actions.connectMcp.moreOptions' | 'page.actions.moreActions' | 'promptTag.copy.buttonText' | 'promptTag.showPrompt' | 'promptTag.hidePrompt' | 'promptTag.showFullPrompt' | 'promptTag.showLess' | 'promptTag.openIn.cursor' | 'promptTag.openIn.cursorDescription' | 'promptTag.openIn.claude' | 'promptTag.openIn.claudeDescription' | 'promptTag.openIn.chatgpt' | 'promptTag.openIn.chatgptDescription' | 'openapi.download.description.title' | 'openapi.info.title' | 'openapi.info.contact.url' | 'openapi.info.contact.name' | 'openapi.info.license' | 'openapi.info.termsOfService' | 'openapi.info.metadata.title' | 'graphql.info.metadata.title' | 'openapi.key' | 'openapi.value' | 'openapi.enum' | 'openapi.items' | 'openapi.default' | 'openapi.variable' | 'openapi.variables' | 'openapi.actions.show' | 'openapi.actions.hide' | 'openapi.actions.more' | 'openapi.languages.title' | 'openapi.languages.moreButton.tooltipText' | 'openapi.servers.title' | 'openapi.operations' | 'openapi.schemas' | 'openapi.webhooks' | 'openapi.description' | 'openapi.badges.deprecated' | 'openapi.badges.required' | 'openapi.badges.webhook' | 'openapi.request' | 'openapi.path' | 'openapi.query' | 'openapi.querystring' | 'openapi.cookie' | 'openapi.header' | 'openapi.body' | 'openapi.responses' | 'openapi.response' | 'openapi.callbacks' | 'openapi.callbackRequest' | 'openapi.callbackResponse' | 'openapi.payload' | 'openapi.discriminator' | 'openapi.contentType' | 'openapi.tryIt' | 'openapi.loading' | 'openapi.example' | 'openapi.examples' | 'openapi.additionalProperties' | 'openapi.patternProperties' | 'openapi.required' | 'openapi.recursive' | 'openapi.complex' | 'openapi.property' | 'openapi.properties' | 'openapi.details' | 'openapi.hideExample' | 'openapi.showExample' | 'openapi.expandAll' | 'openapi.deepLink.tooltip' | 'openapi.collapseAll' | 'openapi.viewSecurityDetails' | 'openapi.noResponseExample' | 'openapi.discriminator.searchPlaceholder' | 'openapi.discriminator.searchNoResults' | 'openapi.discriminator.defaultMapping' | 'openapi.discriminator.defaultMappingTooltip' | 'openapi.noResponseContent' | 'openapi.noRequestPayload' | 'openapi.noRequestData' | 'openapi.hidePattern' | 'openapi.showPattern' | 'openapi.authorizationUrl' | 'openapi.tokenUrl' | 'openapi.refreshUrl' | 'openapi.showOptionalScopes' | 'openapi.hideOptionalScopes' | 'openapi.security' | 'openapi.httpAuthorizationScheme' | 'openapi.bearerFormat' | 'openapi.parameterName' | 'openapi.flowType' | 'openapi.connectUrl' | 'openapi.requiredScopes' | 'openapi.unsupportedLanguage' | 'openapi.failedToGenerateCodeSample' | 'openapi.schemaCatalogLink.title' | 'openapi.schemaCatalogLink.copyButtonTooltip' | 'openapi.schemaCatalogLink.copiedTooltip' | 'openapi.mcp.title' | 'openapi.mcp.endpoint' | 'openapi.mcp.tools' | 'openapi.mcp.protocolVersion' | 'openapi.mcp.capabilities' | 'openapi.mcp.experimentalCapabilities' | 'openapi.mcp.inputSchema' | 'openapi.mcp.inputExample' | 'openapi.mcp.outputSchema' | 'openapi.mcp.outputExample' | 'openapi.mcp.exampleTitle' | 'openapi.mcp.argumentsExample' | 'asyncapi.download.description.title' | 'asyncapi.info.title' | 'asyncapi.info.contact.url' | 'asyncapi.info.contact.name' | 'asyncapi.info.license' | 'asyncapi.info.termsOfService' | 'asyncapi.key' | 'asyncapi.value' | 'asyncapi.variables' | 'asyncapi.required' | 'asyncapi.requiredScopes' | 'asyncapi.viewSecurityDetails' | 'graphql.download.description.title' | 'graphql.info.title' | 'graphql.info.contact.url' | 'graphql.info.contact.name' | 'graphql.info.license' | 'graphql.info.termsOfService' | 'graphql.overview' | 'graphql.metadata' | 'graphql.key' | 'graphql.value' | 'graphql.queries' | 'graphql.mutations' | 'graphql.subscriptions' | 'graphql.directives' | 'graphql.objects' | 'graphql.interfaces' | 'graphql.unions' | 'graphql.enums' | 'graphql.inputs' | 'graphql.scalars' | 'graphql.actions.show' | 'graphql.actions.hide' | 'graphql.actions.more' | 'graphql.fields' | 'graphql.inputFields' | 'graphql.values' | 'graphql.arguments.label' | 'graphql.arguments.show' | 'graphql.arguments.hide' | 'graphql.arguments.here' | 'graphql.returnTypes.label' | 'graphql.returnTypes.show' | 'graphql.returnTypes.hide' | 'graphql.possibleTypes' | 'graphql.defaultValue' | 'graphql.deprecationReason' | 'graphql.requiredScopes' | 'graphql.viewSecurityDetails' | 'graphql.objectScopes' | 'graphql.fieldScopes' | 'graphql.implementedInterfaces' | 'graphql.implementedBy' | 'graphql.nonNull' | 'graphql.required' | 'asyncapi.badges.deprecated' | 'graphql.badges.deprecated' | 'asyncapi.actions.show' | 'asyncapi.actions.hide' | 'asyncapi.actions.more' | 'asyncapi.payload' | 'asyncapi.parameters' | 'asyncapi.messages' | 'asyncapi.contentType' | 'asyncapi.moreDetails' | 'asyncapi.property' | 'asyncapi.properties' | 'asyncapi.details' | 'asyncapi.reply' | 'asyncapi.servers.title' | 'graphql.variables' | 'graphql.querySample' | 'graphql.mutationSample' | 'graphql.subscriptionSample' | 'graphql.responseSample' | 'graphql.locations' | 'graphql.sample' | 'graphql.referenced' | 'graphql.content.fragment' | 'graphql.tryIt' | 'graphql.loading' | 'button.download.tooltipText' | 'button.externalLink.tooltipText' | 'button.email.tooltipText' | 'codeWalkthrough.download' | 'codeWalkthrough.preview' | 'time.justNow' | 'time.past.second' | 'time.past.seconds' | 'time.past.minute' | 'time.past.minutes' | 'time.past.hour' | 'time.past.hours' | 'time.past.day' | 'time.past.days' | 'time.past.week' | 'time.past.weeks' | 'time.past.month' | 'time.past.months' | 'time.past.year' | 'time.past.years' | 'page.internalServerError.title' | 'page.internalServerError.description' | 'page.skipToContent.label' | 'select.noResults' | 'loaders.loading' | 'filter.dateRange.from' | 'filter.dateRange.to' | 'diagram.openFullscreen' | 'diagram.zoomIn' | 'diagram.zoomOut' | 'diagram.reset' | 'diagram.close' | 'diagram.viewer' | 'consent.title' | 'consent.message' | 'consent.privacyPolicy' | 'consent.customize' | 'consent.rejectAll' | 'consent.acceptAll' | 'consent.acceptAllCookies' | 'consent.savePreferences' | 'consent.dialog.title' | 'consent.dialog.description' | 'consent.dialog.close' | 'consent.alwaysOn' | 'consent.alwaysOff' | 'consent.gpcNotice' | 'consent.category.necessary.title' | 'consent.category.necessary.description' | 'consent.category.analytics.title' | 'consent.category.analytics.description' | 'consent.category.marketing.title' | 'consent.category.marketing.description' | 'consent.settingsLink';
3
3
  export type Locale = {
4
4
  code: string;
5
5
  name: string;
@@ -1,4 +1,5 @@
1
1
  import type { AiPromptTarget } from '../types/prompt';
2
+ type AiPromptLinkTarget = AiPromptTarget | 'grok';
2
3
  /**
3
4
  * Builds a link that opens an AI tool with the prompt prefilled.
4
5
  *
@@ -12,4 +13,5 @@ import type { AiPromptTarget } from '../types/prompt';
12
13
  * // 'https://claude.ai/new?q=Summarize+this+page'
13
14
  * ```
14
15
  */
15
- export declare function getAiPromptLink(target: AiPromptTarget, prompt: string): string;
16
+ export declare function getAiPromptLink(target: AiPromptLinkTarget, prompt: string): string;
17
+ export {};
@@ -4,6 +4,7 @@ exports.getAiPromptLink = getAiPromptLink;
4
4
  const AI_PROMPT_ENDPOINTS = {
5
5
  chatgpt: { baseUrl: 'https://chat.openai.com', queryParam: 'q' },
6
6
  claude: { baseUrl: 'https://claude.ai/new', queryParam: 'q' },
7
+ grok: { baseUrl: 'https://grok.com/', queryParam: 'q' },
7
8
  // Encoding: https://cursor.com/docs/integrations/deeplinks
8
9
  cursor: { baseUrl: 'https://cursor.com/link/prompt', queryParam: 'text' },
9
10
  };
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import type { IconProps } from '../../icons/types';
3
+ declare const Icon: (props: IconProps) => React.JSX.Element;
4
+ export declare const GrokIcon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<{
5
+ color?: string;
6
+ size?: string;
7
+ className?: string;
8
+ 'data-component-name'?: string;
9
+ } & React.SVGProps<SVGSVGElement>, "data-component-name" | "size" | keyof React.SVGProps<SVGSVGElement>> & {
10
+ color?: string;
11
+ size?: string;
12
+ className?: string;
13
+ 'data-component-name'?: string;
14
+ } & React.SVGProps<SVGSVGElement>, "data-component-name"> & Partial<Pick<import("styled-components").FastOmit<{
15
+ color?: string;
16
+ size?: string;
17
+ className?: string;
18
+ 'data-component-name'?: string;
19
+ } & React.SVGProps<SVGSVGElement>, "data-component-name" | "size" | keyof React.SVGProps<SVGSVGElement>> & {
20
+ color?: string;
21
+ size?: string;
22
+ className?: string;
23
+ 'data-component-name'?: string;
24
+ } & React.SVGProps<SVGSVGElement>, "data-component-name">>> & string & Omit<typeof Icon, keyof React.Component<any, {}, any>>;
25
+ export {};
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.GrokIcon = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const styled_components_1 = __importDefault(require("styled-components"));
9
+ const utils_1 = require("../../core/utils");
10
+ const Icon = (props) => (react_1.default.createElement("svg", Object.assign({ viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, props),
11
+ react_1.default.createElement("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" }),
12
+ react_1.default.createElement("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" })));
13
+ exports.GrokIcon = (0, styled_components_1.default)(Icon).attrs({
14
+ 'data-component-name': 'icons/GrokIcon/GrokIcon',
15
+ }) `
16
+ path {
17
+ fill: ${({ color }) => (0, utils_1.getCssColorVariable)(color)};
18
+ }
19
+
20
+ height: ${({ size }) => size || '16px'};
21
+ width: ${({ size }) => size || '16px'};
22
+ `;
23
+ //# sourceMappingURL=GrokIcon.js.map
package/lib/index.d.ts CHANGED
@@ -165,6 +165,7 @@ export * from './icons/SpinnerIcon/SpinnerIcon';
165
165
  export * from './icons/ChatGptIcon/ChatGptIcon';
166
166
  export * from './icons/CopyIcon/CopyIcon';
167
167
  export * from './icons/ClaudeIcon/ClaudeIcon';
168
+ export * from './icons/GrokIcon/GrokIcon';
168
169
  export * from './icons/CleanIcon/CleanIcon';
169
170
  export * from './icons/GraphqlIcon/GraphqlIcon';
170
171
  export * from './icons/DeselectIcon/DeselectIcon';
package/lib/index.js CHANGED
@@ -229,6 +229,7 @@ __exportStar(require("./icons/SpinnerIcon/SpinnerIcon"), exports);
229
229
  __exportStar(require("./icons/ChatGptIcon/ChatGptIcon"), exports);
230
230
  __exportStar(require("./icons/CopyIcon/CopyIcon"), exports);
231
231
  __exportStar(require("./icons/ClaudeIcon/ClaudeIcon"), exports);
232
+ __exportStar(require("./icons/GrokIcon/GrokIcon"), exports);
232
233
  __exportStar(require("./icons/CleanIcon/CleanIcon"), exports);
233
234
  __exportStar(require("./icons/GraphqlIcon/GraphqlIcon"), exports);
234
235
  __exportStar(require("./icons/DeselectIcon/DeselectIcon"), exports);
@@ -55,8 +55,8 @@ function NumberedItem({ headline, anchorId, headlineLevel, icon, iconRawContent,
55
55
  type === exports.NumberedListType.ICON && (react_1.default.createElement(MarkerContent, { className: "numbered-item-marker-content" },
56
56
  react_1.default.createElement(GenericIcon_1.GenericIcon, { icon: icon, rawContent: iconRawContent }))),
57
57
  type === exports.NumberedListType.NUMBER && (react_1.default.createElement(MarkerContent, { className: "numbered-item-marker-content" }, index)),
58
- anchorId && (react_1.default.createElement(MarkerLink, { className: "numbered-item-marker-link", $isDot: isDot },
59
- react_1.default.createElement(MarkerLinkIcon, { "aria-hidden": "true", focusable: "false", color: "--md-numbered-list-marker-text-color" })))));
58
+ anchorId && (react_1.default.createElement(MarkerLink, { className: "numbered-item-marker-link", "aria-hidden": "true" },
59
+ react_1.default.createElement(MarkerLinkIcon, { "aria-hidden": "true", focusable: "false", size: "var(--md-numbered-list-marker-link-size)", color: "--md-numbered-list-marker-link-icon-color" })))));
60
60
  return (react_1.default.createElement(NumberedItemWrapper, { "data-component-name": "Markdoc/NumberedList/NumberedItem", className: className, id: anchorId, $size: size, $isDot: isDot },
61
61
  react_1.default.createElement(MarkerRail, null,
62
62
  anchorId ? (react_1.default.createElement("a", Object.assign({ href: `#${anchorId}` }, (headline
@@ -110,24 +110,23 @@ const MarkerContent = styled_components_1.default.span `
110
110
  justify-content: center;
111
111
  `;
112
112
  const MarkerLink = styled_components_1.default.span `
113
+ position: absolute;
114
+ inset-inline-end: calc(100% + var(--md-numbered-list-marker-link-gap));
113
115
  display: none;
114
116
  align-items: center;
115
117
  justify-content: center;
116
118
 
117
- svg {
118
- width: var(--icon-width, 16px);
119
- height: var(--icon-height, 16px);
119
+ &::before {
120
+ content: '';
121
+ position: absolute;
122
+ inset-block: 0;
123
+ inset-inline-start: 100%;
124
+ width: var(--md-numbered-list-marker-link-gap);
120
125
  }
121
-
122
- ${({ $isDot }) => $isDot &&
123
- (0, styled_components_1.css) `
124
- position: absolute;
125
- inset-inline-end: calc(100% + var(--md-numbered-list-dot-link-gap));
126
- `}
127
126
  `;
128
127
  const MarkerLinkIcon = (0, styled_components_1.default)(LinkIcon_1.LinkIcon) `
129
128
  path:first-of-type {
130
- fill: var(--md-numbered-list-marker-icon-bg-color);
129
+ fill: var(--md-numbered-list-marker-link-bg-color);
131
130
  }
132
131
  `;
133
132
  const MarkerRail = styled_components_1.default.span `
@@ -199,17 +198,10 @@ const NumberedItemWrapper = styled_components_1.default.li `
199
198
  padding-bottom: 0;
200
199
  }
201
200
 
202
- &:hover,
203
- &:focus-within {
204
- ${Marker} {
205
- background-color: ${({ $isDot }) => $isDot ? 'var(--text-color-primary)' : 'var(--md-numbered-list-marker-bg-color-hover)'};
206
- }
207
-
208
- a ${Marker}:not([data-dot]) .numbered-item-marker-content {
209
- display: none;
210
- }
211
-
212
- a ${Marker} .numbered-item-marker-link {
201
+ &:has(${MarkerRail} a:hover),
202
+ &:has(${MarkerRail} a:focus-visible),
203
+ &:has(${NumberedItemHeadline}:hover) {
204
+ .numbered-item-marker-link {
213
205
  display: flex;
214
206
  }
215
207
  }
@@ -11,8 +11,6 @@ exports.markdownNumberedList = (0, styled_components_1.css) `
11
11
  --md-numbered-list-gap: var(--spacing-base); // @presenter Spacing
12
12
 
13
13
  --md-numbered-list-marker-bg-color: var(--color-warm-grey-2); // @presenter Color
14
- --md-numbered-list-marker-bg-color-hover: var(--color-warm-grey-3); // @presenter Color
15
- --md-numbered-list-marker-icon-bg-color: transparent; // @presenter Color
16
14
  --md-numbered-list-marker-text-color: var(--text-color-primary); // @presenter Color
17
15
  --md-numbered-list-marker-font-size: var(--font-size-base); // @presenter FontSize
18
16
 
@@ -23,7 +21,10 @@ exports.markdownNumberedList = (0, styled_components_1.css) `
23
21
  --md-numbered-list-icon-small-size: 12px; // @presenter Spacing
24
22
  --md-numbered-list-dot-size: 10px; // @presenter Spacing
25
23
  --md-numbered-list-dot-rail-padding-top: 7px; // @presenter Spacing
26
- --md-numbered-list-dot-link-gap: 6px; // @presenter Spacing
24
+ --md-numbered-list-marker-link-gap: 10px; // @presenter Spacing
25
+ --md-numbered-list-marker-link-size: 20px; // @presenter Spacing
26
+ --md-numbered-list-marker-link-icon-color: var(--md-numbered-list-marker-text-color); // @presenter Color
27
+ --md-numbered-list-marker-link-bg-color: var(--bg-color-tonal); // @presenter Color
27
28
 
28
29
  --md-numbered-list-tail-bg-color: var(--md-numbered-list-marker-bg-color); // @presenter Color
29
30
  --md-numbered-list-tail-fade-gradient: linear-gradient(to bottom, var(--md-numbered-list-tail-bg-color), transparent); // @presenter Color
@@ -30,6 +30,7 @@ import { icon } from '../markdoc/tags/icon';
30
30
  import { connectMcp } from '../markdoc/tags/connect-mcp';
31
31
  import { loginButton } from '../markdoc/tags/login-button';
32
32
  import { diagram } from '../markdoc/tags/diagram';
33
+ import { visibility } from '../markdoc/tags/visibility';
33
34
  import { prompt } from '../markdoc/tags/prompt';
34
35
  export declare const tags: {
35
36
  [accordion.tagName]: import("./tags/types").MarkdocTagSchema;
@@ -57,5 +58,6 @@ export declare const tags: {
57
58
  [connectMcp.tagName]: import("./tags/types").MarkdocTagSchema;
58
59
  [loginButton.tagName]: import("./tags/types").MarkdocTagSchema;
59
60
  [diagram.tagName]: import("./tags/types").MarkdocTagSchema;
61
+ [visibility.tagName]: import("./tags/types").MarkdocTagSchema;
60
62
  [prompt.tagName]: import("./tags/types").MarkdocTagSchema;
61
63
  };
@@ -72,6 +72,7 @@ const icon_1 = require("../markdoc/tags/icon");
72
72
  const connect_mcp_1 = require("../markdoc/tags/connect-mcp");
73
73
  const login_button_1 = require("../markdoc/tags/login-button");
74
74
  const diagram_1 = require("../markdoc/tags/diagram");
75
+ const visibility_1 = require("../markdoc/tags/visibility");
75
76
  const prompt_1 = require("../markdoc/tags/prompt");
76
77
  exports.tags = {
77
78
  [accordion_1.accordion.tagName]: accordion_1.accordion.schema,
@@ -99,6 +100,7 @@ exports.tags = {
99
100
  [connect_mcp_1.connectMcp.tagName]: connect_mcp_1.connectMcp.schema,
100
101
  [login_button_1.loginButton.tagName]: login_button_1.loginButton.schema,
101
102
  [diagram_1.diagram.tagName]: diagram_1.diagram.schema,
103
+ [visibility_1.visibility.tagName]: visibility_1.visibility.schema,
102
104
  [prompt_1.prompt.tagName]: prompt_1.prompt.schema,
103
105
  };
104
106
  //# sourceMappingURL=default.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.71.0-next.3",
3
+ "version": "0.71.0-next.5",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -43,7 +43,7 @@
43
43
  "devDependencies": {
44
44
  "@babel/core": "7.29.7",
45
45
  "@markdoc/markdoc": "0.5.2",
46
- "@redocly/realm-asyncapi-sdk": "0.16.0",
46
+ "@redocly/realm-asyncapi-sdk": "0.17.0-next.0",
47
47
  "@redocly/tooling-test-utils": "0.0.0",
48
48
  "@shikijs/types": "3.21.0",
49
49
  "@testing-library/react": "16.3.0",
@@ -58,6 +58,7 @@
58
58
  "@vitest/coverage-v8": "4.1.11",
59
59
  "@vitest/ui": "4.1.11",
60
60
  "concurrently": "7.6.0",
61
+ "jest-styled-components": "7.4.0",
61
62
  "react-router": "^8.3.0",
62
63
  "resize-observer-polyfill": "1.5.1",
63
64
  "rimraf": "5.0.7",
@@ -0,0 +1,45 @@
1
+ import React, { useTransition } from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { JSX } from 'react';
5
+
6
+ import { breakpoints } from '@redocly/theme/core/utils';
7
+ import { Button } from '@redocly/theme/components/Button/Button';
8
+ import { MenuIcon } from '@redocly/theme/icons/MenuIcon/MenuIcon';
9
+ import { CloseIcon } from '@redocly/theme/icons/CloseIcon/CloseIcon';
10
+
11
+ export type MobileMenuButtonProps = {
12
+ isOpen: boolean;
13
+ /** Called inside a transition; the button shows the requested state until it commits. */
14
+ onOpenChange: (isOpen: boolean) => void;
15
+ className?: string;
16
+ };
17
+
18
+ export function MobileMenuButton({
19
+ isOpen,
20
+ onOpenChange,
21
+ className,
22
+ }: MobileMenuButtonProps): JSX.Element {
23
+ const [isToggling, startToggle] = useTransition();
24
+ const showClose = isToggling ? !isOpen : isOpen;
25
+
26
+ return (
27
+ <MobileMenuButtonWrapper
28
+ data-component-name="Buttons/MobileMenuButton"
29
+ className={className}
30
+ variant="text"
31
+ data-testid="mobile-menu-button"
32
+ onClick={() => startToggle(() => onOpenChange(!showClose))}
33
+ icon={showClose ? <CloseIcon /> : <MenuIcon />}
34
+ aria-label={showClose ? 'Close menu button' : 'Open menu button'}
35
+ />
36
+ );
37
+ }
38
+
39
+ const MobileMenuButtonWrapper = styled(Button)`
40
+ margin-left: 0px !important;
41
+
42
+ @media screen and (min-width: ${breakpoints.medium}) {
43
+ display: none;
44
+ }
45
+ `;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import styled from 'styled-components';
3
3
 
4
4
  import type { JSX } from 'react';
5
- import type { FilterProps, FilterTypes } from '@redocly/theme/core/types';
5
+ import type { FilterProps } from '@redocly/theme/core/types';
6
6
 
7
7
  import { CatalogFilterSelect } from '@redocly/theme/components/Catalog/CatalogFilter/CatalogFilterSelect';
8
8
  import { CatalogFilterCheckboxes } from '@redocly/theme/components/Catalog/CatalogFilter/CatalogFilterCheckboxes';
@@ -31,7 +31,7 @@ export function CatalogFilter({
31
31
  return null;
32
32
  }
33
33
 
34
- const FilterComponent = filterComponents[(filter.type || 'checkboxes') as FilterTypes];
34
+ const FilterComponent = filterComponents[filter.type || 'checkboxes'];
35
35
 
36
36
  return (
37
37
  <CatalogFilterGroup
@@ -43,9 +43,7 @@ export function Feedback(props: FeedbackProps & { path?: string }) {
43
43
  const renderFeedbackComponent = () => {
44
44
  const { type, settings, path } = feedbackConf;
45
45
 
46
- const FeedbackComponent = feedbackComponents[
47
- type as FeedbackComponentsKeys
48
- ] as FeedbackComponents[FeedbackComponentsKeys];
46
+ const FeedbackComponent = feedbackComponents[type as FeedbackComponentsKeys];
49
47
 
50
48
  if (!FeedbackComponent) {
51
49
  return null;
@@ -19,9 +19,7 @@ import { Search } from '@redocly/theme/components/Search/Search';
19
19
  import { UserMenu } from '@redocly/theme/components/UserMenu/UserMenu';
20
20
  import { LanguagePicker } from '@redocly/theme/components/LanguagePicker/LanguagePicker';
21
21
  import { ProductPicker } from '@redocly/theme/components/Product/ProductPicker';
22
- import { Button } from '@redocly/theme/components/Button/Button';
23
- import { MenuIcon } from '@redocly/theme/icons/MenuIcon/MenuIcon';
24
- import { CloseIcon } from '@redocly/theme/icons/CloseIcon/CloseIcon';
22
+ import { MobileMenuButton } from '@redocly/theme/components/Buttons/MobileMenuButton';
25
23
  import { Banner } from '@redocly/theme/components/Banner/Banner';
26
24
 
27
25
  export type NavbarProps = {
@@ -69,25 +67,20 @@ export function Navbar({ className }: NavbarProps): JSX.Element | null {
69
67
  <LanguagePicker onChangeLanguage={changeLanguage} onlyIcon alignment="end" />
70
68
  <ColorModeSwitcher />
71
69
  <MobileMenuButton
72
- variant="text"
73
- data-testid="mobile-menu-button"
74
- onClick={
75
- isOpen
76
- ? () => {
77
- closeMobileMenu();
78
- telemetry.sendMobileMenuClosedMessage([
79
- getBaseDataAttributes('mobileMenuClose', 'button'),
80
- ]);
81
- }
82
- : () => {
83
- openMobileMenu();
84
- telemetry.sendMobileMenuOpenedMessage([
85
- getBaseDataAttributes('mobileMenuOpen', 'button'),
86
- ]);
87
- }
88
- }
89
- icon={isOpen ? <CloseIcon /> : <MenuIcon />}
90
- aria-label={isOpen ? 'Close menu button' : 'Open menu button'}
70
+ isOpen={isOpen}
71
+ onOpenChange={(open) => {
72
+ if (open) {
73
+ openMobileMenu();
74
+ telemetry.sendMobileMenuOpenedMessage([
75
+ getBaseDataAttributes('mobileMenuOpen', 'button'),
76
+ ]);
77
+ } else {
78
+ closeMobileMenu();
79
+ telemetry.sendMobileMenuClosedMessage([
80
+ getBaseDataAttributes('mobileMenuClose', 'button'),
81
+ ]);
82
+ }
83
+ }}
91
84
  />
92
85
  {hideUserMenu ? null : <UserMenu />}
93
86
  </NavbarRow>
@@ -147,11 +140,3 @@ const NavbarRow = styled.div`
147
140
  margin-right: auto;
148
141
  }
149
142
  `;
150
-
151
- const MobileMenuButton = styled(Button)`
152
- margin-left: 0px !important;
153
-
154
- @media screen and (min-width: ${breakpoints.medium}) {
155
- display: none;
156
- }
157
- `;
@@ -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 focusableElements = trapElement.querySelectorAll<HTMLElement>(
12
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
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
- if (firstElement) {
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,7 @@ 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';
9
11
  import { MarkdownFullIcon } from '@redocly/theme/icons/MarkdownFullIcon/MarkdownFullIcon';
10
12
  import { VSCodeIcon } from '@redocly/theme/icons/VSCodeIcon/VSCodeIcon';
11
13
  import { CursorIcon } from '@redocly/theme/icons/CursorIcon/CursorIcon';
@@ -30,6 +32,7 @@ const DEFAULT_ENABLED_ACTIONS = [
30
32
  'view',
31
33
  'chatgpt',
32
34
  'claude',
35
+ 'grok',
33
36
  'docs-mcp-cursor',
34
37
  'docs-mcp-vscode',
35
38
  'docs-mcp-claude',
@@ -40,6 +43,7 @@ export type PageActionType =
40
43
  | 'view'
41
44
  | 'chatgpt'
42
45
  | 'claude'
46
+ | 'grok'
43
47
  | 'docs-mcp-cursor'
44
48
  | 'docs-mcp-vscode'
45
49
  | 'docs-mcp-claude'
@@ -115,6 +119,30 @@ export function usePageActions(
115
119
  : combineUrls(origin, removeTrailingSlash(pathname) + '.md');
116
120
  const externalAiPrompt = `Read ${mdPageUrl} and answer questions based on the content.`;
117
121
 
122
+ const createAiPromptAction =
123
+ (
124
+ target: 'chatgpt' | 'claude' | 'grok',
125
+ iconComponent: ComponentType,
126
+ texts: Pick<PageAction, 'buttonText' | 'title' | 'description'>,
127
+ ) =>
128
+ (): PageAction => {
129
+ const link = getAiPromptLink(target, externalAiPrompt);
130
+ return {
131
+ ...texts,
132
+ iconComponent,
133
+ link,
134
+ onClick: () => {
135
+ telemetry.sendPageActionsClickedMessage([
136
+ {
137
+ ...getBaseDataAttributes('pageActions', 'button'),
138
+ actionType: target,
139
+ },
140
+ ]);
141
+ window.location.href = link;
142
+ },
143
+ };
144
+ };
145
+
118
146
  const actionHandlers: Record<PageActionType, () => PageAction> = {
119
147
  'docs-mcp-cursor': createMCPHandler('cursor', false),
120
148
  'docs-mcp-vscode': createMCPHandler('vscode', false),
@@ -163,45 +191,23 @@ export function usePageActions(
163
191
  },
164
192
  }),
165
193
 
166
- chatgpt: () => {
167
- const link = getAiPromptLink('chatgpt', externalAiPrompt);
168
- return {
169
- buttonText: translate('page.actions.chatGptButtonText', 'Open in ChatGPT'),
170
- title: translate('page.actions.chatGptTitle', 'Open in ChatGPT'),
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
- },
194
+ chatgpt: createAiPromptAction('chatgpt', ChatGptIcon, {
195
+ buttonText: translate('page.actions.chatGptButtonText', 'Open in ChatGPT'),
196
+ title: translate('page.actions.chatGptTitle', 'Open in ChatGPT'),
197
+ description: translate('page.actions.chatGptDescription', 'Get insights from ChatGPT'),
198
+ }),
185
199
 
186
- claude: () => {
187
- const link = getAiPromptLink('claude', externalAiPrompt);
188
- return {
189
- buttonText: translate('page.actions.claudeButtonText', 'Open in Claude'),
190
- title: translate('page.actions.claudeTitle', 'Open in Claude'),
191
- description: translate('page.actions.claudeDescription', 'Get insights from Claude'),
192
- iconComponent: ClaudeIcon,
193
- link,
194
- onClick: () => {
195
- telemetry.sendPageActionsClickedMessage([
196
- {
197
- ...getBaseDataAttributes('pageActions', 'button'),
198
- actionType: 'claude',
199
- },
200
- ]);
201
- window.location.href = link;
202
- },
203
- };
204
- },
200
+ claude: createAiPromptAction('claude', ClaudeIcon, {
201
+ buttonText: translate('page.actions.claudeButtonText', 'Open in Claude'),
202
+ title: translate('page.actions.claudeTitle', 'Open in Claude'),
203
+ description: translate('page.actions.claudeDescription', 'Get insights from Claude'),
204
+ }),
205
+
206
+ grok: createAiPromptAction('grok', GrokIcon, {
207
+ buttonText: translate('page.actions.grokButtonText', 'Open in Grok'),
208
+ title: translate('page.actions.grokTitle', 'Open in Grok'),
209
+ description: translate('page.actions.grokDescription', 'Get insights from Grok'),
210
+ }),
205
211
  };
206
212
 
207
213
  return (themeConfig.navigation?.actions?.items || actions || DEFAULT_ENABLED_ACTIONS)
@@ -311,7 +317,7 @@ function shouldHideAction(
311
317
  return true;
312
318
  }
313
319
 
314
- const actionDependsOnLlmsTxt = ['view', 'copy', 'chatgpt', 'claude'].includes(action);
320
+ const actionDependsOnLlmsTxt = ['view', 'copy', 'chatgpt', 'claude', 'grok'].includes(action);
315
321
 
316
322
  if (actionDependsOnLlmsTxt) {
317
323
  // Can't use any actions if search is globally disabled (markdown files are not generated)
@@ -345,6 +351,7 @@ function shouldHideActionByType(
345
351
  switch (action) {
346
352
  case 'chatgpt':
347
353
  case 'claude':
354
+ case 'grok':
348
355
  return !isPublic;
349
356
  case 'docs-mcp-cursor':
350
357
  case 'docs-mcp-vscode':
@@ -67,7 +67,6 @@ const numberedListDarkMode = css`
67
67
  */
68
68
 
69
69
  --md-numbered-list-marker-bg-color: var(--color-warm-grey-3); // @presenter Color
70
- --md-numbered-list-marker-bg-color-hover: var(--color-warm-grey-4); // @presenter Color
71
70
 
72
71
  // @tokens End
73
72
  `
@@ -292,6 +292,9 @@ export type TranslationKey =
292
292
  | 'page.actions.claudeTitle'
293
293
  | 'page.actions.claudeButtonText'
294
294
  | 'page.actions.claudeDescription'
295
+ | 'page.actions.grokTitle'
296
+ | 'page.actions.grokButtonText'
297
+ | 'page.actions.grokDescription'
295
298
  | 'page.actions.cursorMcpButtonText'
296
299
  | 'page.actions.cursorMcpTitle'
297
300
  | 'page.actions.cursorMcpDescription'
@@ -2,9 +2,12 @@ import type { AiPromptTarget } from '../types/prompt';
2
2
 
3
3
  type AiPromptEndpoint = { baseUrl: string; queryParam: string };
4
4
 
5
- const AI_PROMPT_ENDPOINTS: Record<AiPromptTarget, AiPromptEndpoint> = {
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: AiPromptTarget, prompt: string): string {
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);
@@ -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
+ `;
package/src/index.ts CHANGED
@@ -193,6 +193,7 @@ export * from '@redocly/theme/icons/SpinnerIcon/SpinnerIcon';
193
193
  export * from '@redocly/theme/icons/ChatGptIcon/ChatGptIcon';
194
194
  export * from '@redocly/theme/icons/CopyIcon/CopyIcon';
195
195
  export * from '@redocly/theme/icons/ClaudeIcon/ClaudeIcon';
196
+ export * from '@redocly/theme/icons/GrokIcon/GrokIcon';
196
197
  export * from '@redocly/theme/icons/CleanIcon/CleanIcon';
197
198
  export * from '@redocly/theme/icons/GraphqlIcon/GraphqlIcon';
198
199
  export * from '@redocly/theme/icons/DeselectIcon/DeselectIcon';
@@ -63,11 +63,12 @@ export function NumberedItem({
63
63
  <MarkerContent className="numbered-item-marker-content">{index}</MarkerContent>
64
64
  )}
65
65
  {anchorId && (
66
- <MarkerLink className="numbered-item-marker-link" $isDot={isDot}>
66
+ <MarkerLink className="numbered-item-marker-link" aria-hidden="true">
67
67
  <MarkerLinkIcon
68
68
  aria-hidden="true"
69
69
  focusable="false"
70
- color="--md-numbered-list-marker-text-color"
70
+ size="var(--md-numbered-list-marker-link-size)"
71
+ color="--md-numbered-list-marker-link-icon-color"
71
72
  />
72
73
  </MarkerLink>
73
74
  )}
@@ -156,27 +157,25 @@ const MarkerContent = styled.span`
156
157
  justify-content: center;
157
158
  `;
158
159
 
159
- const MarkerLink = styled.span<{ $isDot?: boolean }>`
160
+ const MarkerLink = styled.span`
161
+ position: absolute;
162
+ inset-inline-end: calc(100% + var(--md-numbered-list-marker-link-gap));
160
163
  display: none;
161
164
  align-items: center;
162
165
  justify-content: center;
163
166
 
164
- svg {
165
- width: var(--icon-width, 16px);
166
- height: var(--icon-height, 16px);
167
+ &::before {
168
+ content: '';
169
+ position: absolute;
170
+ inset-block: 0;
171
+ inset-inline-start: 100%;
172
+ width: var(--md-numbered-list-marker-link-gap);
167
173
  }
168
-
169
- ${({ $isDot }) =>
170
- $isDot &&
171
- css`
172
- position: absolute;
173
- inset-inline-end: calc(100% + var(--md-numbered-list-dot-link-gap));
174
- `}
175
174
  `;
176
175
 
177
176
  const MarkerLinkIcon = styled(LinkIcon)`
178
177
  path:first-of-type {
179
- fill: var(--md-numbered-list-marker-icon-bg-color);
178
+ fill: var(--md-numbered-list-marker-link-bg-color);
180
179
  }
181
180
  `;
182
181
 
@@ -256,18 +255,10 @@ const NumberedItemWrapper = styled.li<{ $size?: string; $isDot?: boolean }>`
256
255
  padding-bottom: 0;
257
256
  }
258
257
 
259
- &:hover,
260
- &:focus-within {
261
- ${Marker} {
262
- background-color: ${({ $isDot }) =>
263
- $isDot ? 'var(--text-color-primary)' : 'var(--md-numbered-list-marker-bg-color-hover)'};
264
- }
265
-
266
- a ${Marker}:not([data-dot]) .numbered-item-marker-content {
267
- display: none;
268
- }
269
-
270
- a ${Marker} .numbered-item-marker-link {
258
+ &:has(${MarkerRail} a:hover),
259
+ &:has(${MarkerRail} a:focus-visible),
260
+ &:has(${NumberedItemHeadline}:hover) {
261
+ .numbered-item-marker-link {
271
262
  display: flex;
272
263
  }
273
264
  }
@@ -9,8 +9,6 @@ export const markdownNumberedList = css`
9
9
  --md-numbered-list-gap: var(--spacing-base); // @presenter Spacing
10
10
 
11
11
  --md-numbered-list-marker-bg-color: var(--color-warm-grey-2); // @presenter Color
12
- --md-numbered-list-marker-bg-color-hover: var(--color-warm-grey-3); // @presenter Color
13
- --md-numbered-list-marker-icon-bg-color: transparent; // @presenter Color
14
12
  --md-numbered-list-marker-text-color: var(--text-color-primary); // @presenter Color
15
13
  --md-numbered-list-marker-font-size: var(--font-size-base); // @presenter FontSize
16
14
 
@@ -21,7 +19,10 @@ export const markdownNumberedList = css`
21
19
  --md-numbered-list-icon-small-size: 12px; // @presenter Spacing
22
20
  --md-numbered-list-dot-size: 10px; // @presenter Spacing
23
21
  --md-numbered-list-dot-rail-padding-top: 7px; // @presenter Spacing
24
- --md-numbered-list-dot-link-gap: 6px; // @presenter Spacing
22
+ --md-numbered-list-marker-link-gap: 10px; // @presenter Spacing
23
+ --md-numbered-list-marker-link-size: 20px; // @presenter Spacing
24
+ --md-numbered-list-marker-link-icon-color: var(--md-numbered-list-marker-text-color); // @presenter Color
25
+ --md-numbered-list-marker-link-bg-color: var(--bg-color-tonal); // @presenter Color
25
26
 
26
27
  --md-numbered-list-tail-bg-color: var(--md-numbered-list-marker-bg-color); // @presenter Color
27
28
  --md-numbered-list-tail-fade-gradient: linear-gradient(to bottom, var(--md-numbered-list-tail-bg-color), transparent); // @presenter Color
@@ -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
  };