@redocly/theme 0.65.0-next.1 → 0.65.0-next.3

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 (53) hide show
  1. package/lib/components/Banner/Banner.js +10 -2
  2. package/lib/components/Banner/variables.js +8 -1
  3. package/lib/components/Button/variables.js +3 -3
  4. package/lib/components/CodeBlock/CodeBlockContainer.js +12 -7
  5. package/lib/components/CodeBlock/variables.dark.d.ts +1 -0
  6. package/lib/components/CodeBlock/variables.dark.js +8 -0
  7. package/lib/components/CodeBlock/variables.js +3 -1
  8. package/lib/components/Markdown/styles/links.js +2 -1
  9. package/lib/components/Menu/MenuItem.js +15 -26
  10. package/lib/components/Menu/variables.dark.js +2 -0
  11. package/lib/components/Menu/variables.js +3 -1
  12. package/lib/components/PageActions/PageActions.js +1 -0
  13. package/lib/components/PageNavigation/NavigationButton.js +19 -11
  14. package/lib/components/PageNavigation/PageNavigation.js +6 -0
  15. package/lib/components/PageNavigation/variables.d.ts +1 -0
  16. package/lib/components/PageNavigation/variables.js +27 -0
  17. package/lib/components/Search/variables.js +2 -2
  18. package/lib/core/hooks/use-modal-scroll-lock.js +21 -10
  19. package/lib/core/hooks/use-page-actions.js +43 -24
  20. package/lib/core/styles/dark.js +5 -3
  21. package/lib/core/styles/global.js +18 -13
  22. package/lib/core/styles/palette.dark.js +6 -0
  23. package/lib/core/styles/palette.js +39 -0
  24. package/lib/core/types/catalog.d.ts +1 -1
  25. package/lib/icons/LinkIcon/LinkIcon.js +6 -6
  26. package/lib/markdoc/components/Cards/Card.js +1 -0
  27. package/lib/markdoc/components/Heading/Heading.js +7 -1
  28. package/package.json +2 -2
  29. package/src/components/Banner/Banner.tsx +11 -3
  30. package/src/components/Banner/variables.ts +8 -1
  31. package/src/components/Button/variables.ts +3 -3
  32. package/src/components/CodeBlock/CodeBlockContainer.tsx +12 -7
  33. package/src/components/CodeBlock/variables.dark.ts +5 -0
  34. package/src/components/CodeBlock/variables.ts +3 -1
  35. package/src/components/Markdown/styles/links.ts +2 -1
  36. package/src/components/Menu/MenuItem.tsx +15 -26
  37. package/src/components/Menu/variables.dark.ts +2 -0
  38. package/src/components/Menu/variables.ts +3 -1
  39. package/src/components/PageActions/PageActions.tsx +1 -0
  40. package/src/components/PageNavigation/NavigationButton.tsx +24 -22
  41. package/src/components/PageNavigation/PageNavigation.tsx +6 -0
  42. package/src/components/PageNavigation/variables.ts +24 -0
  43. package/src/components/Search/variables.ts +2 -2
  44. package/src/core/hooks/use-modal-scroll-lock.ts +30 -14
  45. package/src/core/hooks/use-page-actions.ts +70 -33
  46. package/src/core/styles/dark.ts +5 -3
  47. package/src/core/styles/global.ts +18 -13
  48. package/src/core/styles/palette.dark.ts +6 -0
  49. package/src/core/styles/palette.ts +39 -0
  50. package/src/core/types/catalog.ts +1 -1
  51. package/src/icons/LinkIcon/LinkIcon.tsx +19 -6
  52. package/src/markdoc/components/Cards/Card.tsx +1 -0
  53. package/src/markdoc/components/Heading/Heading.tsx +7 -1
@@ -4,6 +4,7 @@ import styled from 'styled-components';
4
4
  import type { JSX } from 'react';
5
5
  import type { ResolvedNavItemWithLink } from '@redocly/config';
6
6
 
7
+ import { breakpoints } from '@redocly/theme/core/utils';
7
8
  import { useThemeConfig } from '@redocly/theme/core/hooks';
8
9
  import { NextButton } from '@redocly/theme/components/PageNavigation/NextButton';
9
10
  import { PreviousButton } from '@redocly/theme/components/PageNavigation/PreviousButton';
@@ -41,8 +42,13 @@ const PageNavigationWrapper = styled.div`
41
42
  justify-content: space-between;
42
43
  margin: 25px 0;
43
44
  width: 100%;
45
+ gap: var(--page-navigations-wrapper-gap);
44
46
 
45
47
  @media print {
46
48
  display: none;
47
49
  }
50
+
51
+ @media screen and (max-width: ${breakpoints.small}) {
52
+ flex-direction: column;
53
+ }
48
54
  `;
@@ -0,0 +1,24 @@
1
+ import { css } from 'styled-components';
2
+
3
+ export const pageNavigation = css`
4
+ /**
5
+ * @tokens Page Navigation
6
+ */
7
+
8
+ --page-navigations-wrapper-gap: var(--spacing-base); // @presenter Spacing
9
+
10
+ --page-navigation-button-width: var(--container-max-width); // @presenter Width
11
+ --page-navigation-button-padding: var(--spacing-sm) var(--spacing-base); // @presenter Spacing
12
+ --page-navigation-button-title-font-size: var(--font-size-lg); // @presenter FontSize
13
+ --page-navigation-button-title-font-weight: var(--font-weight-medium); // @presenter FontWeight
14
+ --page-navigation-button-title-line-height: var(--line-height-lg); // @presenter LineHeight
15
+ --page-navigation-button-title-color: var(--text-color-primary); // @presenter Color
16
+ --page-navigation-button-gap: var(--spacing-xxs); // @presenter Spacing
17
+ --page-navigation-button-border-radius: var(--border-radius-xl); // @presenter BorderRadius
18
+ --page-navigation-button-border-color: var(--border-color-secondary); // @presenter Color
19
+ --page-navigation-button-border: var(--border-width) var(--border-style) var(--page-navigation-button-border-color); // @presenter Border
20
+ --page-navigation-button-border-color-hover: var(--color-primary-base, var(--color-warm-grey-11)); // @presenter Color
21
+ --page-navigation-button-border-hover: var(--border-width) var(--border-style) var(--page-navigation-button-border-color-hover); // @presenter Border
22
+ --page-navigation-button-min-width: 220px; // @presenter Width
23
+ // @tokens End
24
+ `;
@@ -164,7 +164,7 @@ export const search = css`
164
164
  --search-ai-text-line-height: var(--line-height-lg);
165
165
  --search-ai-thinking-text-margin: var(--md-pre-margin) 0;
166
166
 
167
- --search-ai-user-bg-color: var(--color-blue-6);
167
+ --search-ai-user-bg-color: var(--color-primary-base, var(--search-ai-user-bg-color-legacy));
168
168
  --search-ai-user-text-color: var(--color-static-white);
169
169
  --search-ai-assistant-bg-color: var(--layer-color);
170
170
  --search-ai-assistant-text-color: var(--text-color-primary);
@@ -247,7 +247,7 @@ export const search = css`
247
247
  --search-ai-conversation-input-border-radius: var(--border-radius-lg);
248
248
  --search-ai-conversation-input-font-size: var(--font-size-base);
249
249
  --search-ai-conversation-input-placeholder-color: var(--search-input-placeholder-color);
250
- --search-ai-conversation-input-border-color-focus: var(--color-blue-6);
250
+ --search-ai-conversation-input-border-color-focus: var(--color-primary-base, var(--search-ai-conversation-input-border-color-focus-legacy));
251
251
  --search-ai-conversation-input-border-color-disabled: var(--border-color-secondary);
252
252
 
253
253
  --search-ai-conversation-input-send-button-right: 12px;
@@ -1,40 +1,56 @@
1
- import { useEffect } from 'react';
1
+ import { useEffect, useRef } from 'react';
2
2
 
3
3
  export function useModalScrollLock(isOpen: boolean): void {
4
+ const originalBodyStylesRef = useRef<{
5
+ overflow: string;
6
+ paddingRight: string;
7
+ scrollbarWidth: string | null;
8
+ } | null>(null);
9
+
4
10
  useEffect(() => {
5
11
  if (typeof window === 'undefined' || typeof document === 'undefined') {
6
12
  return;
7
13
  }
8
14
 
9
15
  const { body, documentElement } = document;
10
- const originalOverflow = body.style.overflow;
11
- const originalPaddingRight = body.style.paddingRight;
12
- const originalScrollbarWidth =
13
- documentElement.style.getPropertyValue('--modal-scrollbar-width');
14
-
15
- const restoreScrollState = () => {
16
- body.style.overflow = originalOverflow;
17
- body.style.paddingRight = originalPaddingRight;
18
- if (originalScrollbarWidth) {
19
- documentElement.style.setProperty('--modal-scrollbar-width', originalScrollbarWidth);
16
+
17
+ const restoreOriginalBodyStyles = () => {
18
+ if (!originalBodyStylesRef.current) return;
19
+
20
+ const { overflow, paddingRight, scrollbarWidth } = originalBodyStylesRef.current;
21
+
22
+ body.style.overflow = overflow;
23
+ body.style.paddingRight = paddingRight;
24
+ if (scrollbarWidth) {
25
+ documentElement.style.setProperty('--modal-scrollbar-width', scrollbarWidth);
20
26
  } else {
21
27
  documentElement.style.removeProperty('--modal-scrollbar-width');
22
28
  }
29
+
30
+ originalBodyStylesRef.current = null;
23
31
  };
24
32
 
25
- if (isOpen) {
26
- const scrollbarWidth = window.innerWidth - documentElement.clientWidth;
33
+ if (isOpen && !originalBodyStylesRef.current) {
34
+ originalBodyStylesRef.current = {
35
+ overflow: body.style.overflow,
36
+ paddingRight: body.style.paddingRight,
37
+ scrollbarWidth: documentElement.style.getPropertyValue('--modal-scrollbar-width') || null,
38
+ };
27
39
 
40
+ const scrollbarWidth = window.innerWidth - documentElement.clientWidth;
28
41
  body.style.overflow = 'hidden';
29
42
 
30
43
  if (scrollbarWidth > 0) {
31
44
  body.style.paddingRight = `${scrollbarWidth}px`;
32
45
  documentElement.style.setProperty('--modal-scrollbar-width', `${scrollbarWidth}px`);
33
46
  }
47
+ } else if (!isOpen && originalBodyStylesRef.current) {
48
+ restoreOriginalBodyStyles();
34
49
  }
35
50
 
51
+ // Cleanup only if component unmounts while modal is open
36
52
  return () => {
37
- restoreScrollState();
53
+ restoreOriginalBodyStyles();
38
54
  };
39
55
  }, [isOpen]);
40
56
  }
@@ -64,21 +64,14 @@ export function usePageActions(
64
64
  const openApiSharedData = usePageSharedData<
65
65
  { options: { excludeFromSearch: boolean } } | undefined
66
66
  >('openAPIDocsStore');
67
+ const openapiExcludeFromSearch = openApiSharedData?.options?.excludeFromSearch;
67
68
  const mcpConfig = useMCPConfig();
68
69
 
69
- const shouldHideAllActions = shouldHidePageActions(
70
- pageProps,
71
- themeConfig,
72
- openApiSharedData?.options?.excludeFromSearch,
73
- );
74
70
  const { isPublic } = usePageData() || {};
75
71
 
76
72
  const createMCPHandler = useCallback(
77
73
  (clientType: MCPClientType, requiresMcpUrl: boolean = false) =>
78
- () => {
79
- if (requiresMcpUrl && !mcpUrl) return null;
80
- if (!requiresMcpUrl && (mcpUrl || mcpConfig.isMcpDisabled)) return null;
81
-
74
+ (): PageAction => {
82
75
  const config = requiresMcpUrl
83
76
  ? { serverName: mcpConfig.serverName, url: mcpUrl || '' }
84
77
  : { serverName: mcpConfig.serverName, url: mcpConfig.serverUrl || '' };
@@ -107,9 +100,14 @@ export function usePageActions(
107
100
  );
108
101
 
109
102
  const result: PageAction[] = useMemo(() => {
110
- if (shouldHideAllActions) {
111
- return [];
112
- }
103
+ const hideActionContext: ShouldHideActionContext = {
104
+ pageProps,
105
+ themeConfig,
106
+ openapiExcludeFromSearch,
107
+ isPublic,
108
+ mcpUrl,
109
+ isMcpDisabled: mcpConfig.isMcpDisabled,
110
+ };
113
111
 
114
112
  const origin = IS_BROWSER
115
113
  ? window.location.origin
@@ -121,7 +119,7 @@ export function usePageActions(
121
119
  ? combineUrls(origin, pathname, 'index.html.md')
122
120
  : combineUrls(origin, removeTrailingSlash(pathname) + '.md');
123
121
 
124
- const actionHandlers: Record<PageActionType, () => PageAction | null> = {
122
+ const actionHandlers: Record<PageActionType, () => PageAction> = {
125
123
  'docs-mcp-cursor': createMCPHandler('cursor', false),
126
124
  'docs-mcp-vscode': createMCPHandler('vscode', false),
127
125
  'mcp-cursor': createMCPHandler('cursor', true),
@@ -169,9 +167,6 @@ export function usePageActions(
169
167
  }),
170
168
 
171
169
  chatgpt: () => {
172
- if (!isPublic) {
173
- return null;
174
- }
175
170
  const link = getExternalAiPromptLink('https://chat.openai.com', mdPageUrl);
176
171
  return {
177
172
  buttonText: translate('page.actions.chatGptButtonText', 'Open in ChatGPT'),
@@ -192,9 +187,6 @@ export function usePageActions(
192
187
  },
193
188
 
194
189
  claude: () => {
195
- if (!isPublic) {
196
- return null;
197
- }
198
190
  const link = getExternalAiPromptLink('https://claude.ai/new', mdPageUrl);
199
191
  return {
200
192
  buttonText: translate('page.actions.claudeButtonText', 'Open in Claude'),
@@ -216,15 +208,18 @@ export function usePageActions(
216
208
  };
217
209
 
218
210
  return (themeConfig.navigation?.actions?.items || actions || DEFAULT_ENABLED_ACTIONS)
219
- .map((action) => actionHandlers[action]?.())
220
- .filter((action): action is PageAction => action !== null);
211
+ .filter((action) => !shouldHideAction(action, hideActionContext))
212
+ .map((action) => actionHandlers[action]());
221
213
  }, [
222
- shouldHideAllActions,
214
+ pageProps,
215
+ themeConfig,
216
+ openapiExcludeFromSearch,
217
+ isPublic,
218
+ mcpUrl,
219
+ mcpConfig.isMcpDisabled,
223
220
  pageSlug,
224
- themeConfig.navigation?.actions?.items,
225
221
  actions,
226
222
  translate,
227
- isPublic,
228
223
  createMCPHandler,
229
224
  telemetry,
230
225
  ]);
@@ -285,35 +280,77 @@ function createMCPAction({
285
280
  };
286
281
  }
287
282
 
288
- function shouldHidePageActions(
289
- pageProps: PageProps,
290
- themeConfig: UiAccessibleConfig,
291
- openapiExcludeFromSearch?: boolean,
283
+ type ShouldHideActionContext = {
284
+ pageProps: PageProps;
285
+ themeConfig: UiAccessibleConfig;
286
+ openapiExcludeFromSearch?: boolean;
287
+ isPublic?: boolean;
288
+ mcpUrl?: string;
289
+ isMcpDisabled: boolean;
290
+ };
291
+
292
+ function shouldHideAction(
293
+ action: PageActionType,
294
+ {
295
+ pageProps,
296
+ themeConfig,
297
+ openapiExcludeFromSearch,
298
+ isPublic,
299
+ mcpUrl,
300
+ isMcpDisabled,
301
+ }: ShouldHideActionContext,
292
302
  ): boolean {
293
303
  // Can't use any actions if search is globally disabled (markdown files are not generated)
294
304
  if (themeConfig.search?.hide) {
295
305
  return true;
296
306
  }
297
-
298
307
  // Can't use any actions if no markdown files are generated for LLMs
299
308
  if (pageProps?.seo?.llmstxt?.hide) {
300
309
  return true;
301
310
  }
302
-
303
311
  // Page actions are explicitly disabled in config
304
312
  if (themeConfig.navigation?.actions?.hide) {
305
313
  return true;
306
314
  }
307
315
 
308
- // Page is excluded from search
309
316
  const isOpenApiPage =
310
317
  pageProps?.metadata?.type === 'openapi' || pageProps?.metadata?.subType === 'openapi-operation';
311
318
  const isPageExcludedFromSearch =
312
319
  pageProps?.frontmatter?.excludeFromSearch || (isOpenApiPage && openapiExcludeFromSearch);
313
320
 
314
- if (isPageExcludedFromSearch) {
321
+ // Page excluded from search: only explicit MCP connect actions remain visible,
322
+ // since they don't depend on the page's markdown.
323
+ if (isPageExcludedFromSearch && action !== 'mcp-cursor' && action !== 'mcp-vscode') {
315
324
  return true;
316
325
  }
317
326
 
318
- return false;
327
+ return shouldHideActionByType(action, { isPublic, mcpUrl, isMcpDisabled });
328
+ }
329
+
330
+ function shouldHideActionByType(
331
+ action: PageActionType,
332
+ {
333
+ isPublic,
334
+ mcpUrl,
335
+ isMcpDisabled,
336
+ }: Pick<ShouldHideActionContext, 'isPublic' | 'mcpUrl' | 'isMcpDisabled'>,
337
+ ): boolean {
338
+ switch (action) {
339
+ case 'chatgpt':
340
+ case 'claude':
341
+ return !isPublic;
342
+ case 'docs-mcp-cursor':
343
+ case 'docs-mcp-vscode':
344
+ return Boolean(mcpUrl) || isMcpDisabled;
345
+ case 'mcp-cursor':
346
+ case 'mcp-vscode':
347
+ return !mcpUrl;
348
+ case 'copy':
349
+ case 'view':
350
+ return false;
351
+ default: {
352
+ action satisfies never;
353
+ return true;
354
+ }
355
+ }
319
356
  }
@@ -15,6 +15,7 @@ import { pageActionsDarkMode } from '@redocly/theme/components/PageActions/varia
15
15
  import { tooltipDarkMode } from '@redocly/theme/components/Tooltip/variables.dark';
16
16
  import { bannerDarkMode } from '@redocly/theme/components/Banner/variables.dark';
17
17
  import { admonitionDarkMode } from '@redocly/theme/components/Admonition/variables.dark';
18
+ import { codeBlockDarkMode } from '@redocly/theme/components/CodeBlock/variables.dark';
18
19
 
19
20
  import { activeBrandPaletteDark } from './palette.dark';
20
21
 
@@ -293,10 +294,10 @@ export const darkMode = css`
293
294
  * @tokens Links
294
295
  */
295
296
 
296
- --link-color-primary: var(--color-blue-7); // @presenter Color
297
- --link-color-primary-hover: var(--color-blue-8); // @presenter Color
297
+ --link-color-primary: var(--link-color-primary-palette, var(--link-color-primary-legacy)); // @presenter Color
298
+ --link-color-primary-hover: var(--link-color-primary-palette, var(--link-color-primary-hover-legacy)); // @presenter Color
298
299
  --link-color-inverse: var(--color-blue-6); // @presenter Color
299
- --link-color-visited: var(--color-purple-8); // @presenter Color
300
+ --link-color-visited: var(--link-color-primary-palette, var(--link-color-visited-legacy)); // @presenter Color
300
301
 
301
302
  /**
302
303
  * @tokens Tab Colors
@@ -352,6 +353,7 @@ export const darkMode = css`
352
353
  ${admonitionDarkMode}
353
354
  ${badgesDarkMode}
354
355
  ${activeBrandPaletteDark}
356
+ ${codeBlockDarkMode}
355
357
  /**
356
358
  * @tokens Dark Theme Scrollbar Config
357
359
  * @presenter Color
@@ -44,6 +44,7 @@ import { skipContent } from '@redocly/theme/components/SkipContent/variables';
44
44
  import { pageActions } from '@redocly/theme/components/PageActions/variables';
45
45
  import { svgViewer } from '@redocly/theme/components/SvgViewer/variables';
46
46
  import { toast } from '@redocly/theme/components/Toast/variables';
47
+ import { pageNavigation } from '@redocly/theme/components/PageNavigation/variables';
47
48
 
48
49
  import { activeBrandPaletteLight } from './palette';
49
50
  import { darkMode } from './dark';
@@ -481,8 +482,8 @@ const headingsTypography = css`
481
482
  * @tokens Typography heading anchor icon
482
483
  */
483
484
 
484
- --heading-anchor-offset-right: 4px; // @presenter Spacing
485
- --heading-anchor-color: var(--button-content-color-primary); // @presenter Color
485
+ --heading-anchor-offset-right: var(--spacing-xs); // @presenter Spacing
486
+ --heading-anchor-color: var(--icon-color-primary); // @presenter Color
486
487
  --heading-anchor-icon: none;
487
488
 
488
489
  /**
@@ -571,18 +572,19 @@ const links = css`
571
572
  * @tokens Links
572
573
  */
573
574
 
574
- --link-color-primary: var(--color-blue-6); // @presenter Color
575
- --link-decoration: none;
576
- --link-font-weight: var(--font-weight-regular); // @presenter FontWeight
575
+ --link-color-primary: var(--link-color-primary-palette, var(--link-color-primary-legacy)); // @presenter Color
576
+ --link-decoration: underline 1px var(--color-primary-base, var(--link-color-primary-legacy));
577
+ --link-underline-offset: 4px;
578
+ --link-font-weight: var(--font-weight-medium); // @presenter FontWeight
577
579
 
578
- --link-color-primary-hover: var(--color-blue-7); // @presenter Color
579
- --link-color-primary-pressed: var(--color-blue-8);
580
- --link-decoration-hover: underline;
580
+ --link-color-primary-hover: var(--link-color-primary-palette, var(--link-color-primary-hover-legacy)); // @presenter Color
581
+ --link-color-primary-pressed: var(--link-color-primary-palette, var(--link-color-primary-pressed-legacy));
582
+ --link-decoration-hover: underline 2px var(--color-primary-base, var(--link-color-primary-hover-legacy));
581
583
 
582
584
  --link-color-inverse: var(--color-blue-5); // @presenter Color
583
585
 
584
- --link-color-visited: var(--color-purple-7); // @presenter Color
585
- --link-visited-decoration: none;
586
+ --link-color-visited: var(--link-color-primary-palette, var(--link-color-visited-legacy)); // @presenter Color
587
+ --link-decoration-visited: underline 1px var(--color-primary-base, var(--link-color-visited-legacy));
586
588
 
587
589
  // @tokens End
588
590
  `;
@@ -706,9 +708,10 @@ const apiReferenceDocs = css`
706
708
  * @tokens API Reference Schema Nested styles
707
709
  */
708
710
 
709
- --schema-nested-offset: calc(var(--spacing-unit) * 2.5); // @presenter Spacing
711
+ --schema-nested-offset: calc(var(--spacing-sm) - 1px); // @presenter Spacing
710
712
  --schema-nested-bg-color: var(--tree-bg-color-active); // @presenter Color
711
-
713
+ --schema-nested-hyperlink-offset: 2px; // @presenter Spacing
714
+
712
715
  /**
713
716
  * @tokens API Reference Schema Required styles
714
717
  */
@@ -740,7 +743,8 @@ const apiReferenceDocs = css`
740
743
  * @tokens API Reference Schema Properties
741
744
  */
742
745
 
743
- --schemas-property-name-text-color: var(--text-color-primary); //@presenter Color
746
+ --schemas-property-name-text-color: var(--color-primary-base, var(--text-color-primary)); //@presenter Color
747
+ --schemas-property-name-box-text-color: var(--text-color-primary); // @presenter Color
744
748
  --schemas-property-name-font-size: var(--font-size-base); // @presenter FontSize
745
749
  --schemas-property-name-font-family: var(--code-font-family); // @presenter FontFamily
746
750
  --schemas-property-name-font-weight: var(--font-weight-regular); // @presenter FontWeight
@@ -1342,6 +1346,7 @@ export const styles = css<{ palette?: string }>`
1342
1346
  ${pageActions}
1343
1347
  ${svgViewer}
1344
1348
  ${toast}
1349
+ ${pageNavigation}
1345
1350
 
1346
1351
  background-color: var(--bg-color);
1347
1352
  color: var(--text-color-primary);
@@ -190,6 +190,12 @@ function brandPaletteDark(palette: string | undefined): FlattenSimpleInterpolati
190
190
 
191
191
  --admonition-default-bg-color-legacy: var(--color-warm-grey-3);
192
192
  --admonition-default-border-color-legacy: var(--color-warm-grey-5);
193
+
194
+ --code-block-highlighted-bg-color-legacy: color-mix(in srgb, var(--color-warm-grey-4) 40%, transparent);
195
+
196
+ --link-color-primary-legacy: var(--color-blue-7);
197
+ --link-color-primary-hover-legacy: var(--color-blue-8);
198
+ --link-color-visited-legacy: var(--color-purple-8);
193
199
  `;
194
200
  }
195
201
  }
@@ -16,6 +16,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
16
16
  --color-brand-10: #555761; // @presenter Color
17
17
  --color-brand-11: #6e6f7a; // @presenter Color
18
18
  --text-color-on-color: #ffffff; // @presenter Color
19
+
20
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
19
21
  `;
20
22
  case 'pink':
21
23
  return css`
@@ -31,6 +33,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
31
33
  --color-brand-10: #6a3055; // @presenter Color
32
34
  --color-brand-11: #4f2841; // @presenter Color
33
35
  --text-color-on-color: #ffffff; // @presenter Color
36
+
37
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
34
38
  `;
35
39
  case 'coral':
36
40
  return css`
@@ -46,6 +50,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
46
50
  --color-brand-10: #6d3338; // @presenter Color
47
51
  --color-brand-11: #4f282b; // @presenter Color
48
52
  --text-color-on-color: #ffffff; // @presenter Color
53
+
54
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
49
55
  `;
50
56
  case 'amber':
51
57
  return css`
@@ -61,6 +67,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
61
67
  --color-brand-10: #71512e; // @presenter Color
62
68
  --color-brand-11: #4f3c28; // @presenter Color
63
69
  --text-color-on-color: #ffffff; // @presenter Color
70
+
71
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
64
72
  `;
65
73
  case 'jade':
66
74
  return css`
@@ -76,6 +84,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
76
84
  --color-brand-10: #2a6052; // @presenter Color
77
85
  --color-brand-11: #284f45; // @presenter Color
78
86
  --text-color-on-color: #ffffff; // @presenter Color
87
+
88
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
79
89
  `;
80
90
  case 'cyan':
81
91
  return css`
@@ -91,6 +101,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
91
101
  --color-brand-10: #285c67; // @presenter Color
92
102
  --color-brand-11: #28484f; // @presenter Color
93
103
  --text-color-on-color: #ffffff; // @presenter Color
104
+
105
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
94
106
  `;
95
107
  case 'ocean':
96
108
  return css`
@@ -106,6 +118,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
106
118
  --color-brand-10: #2d5472; // @presenter Color
107
119
  --color-brand-11: #283e4f; // @presenter Color
108
120
  --text-color-on-color: #ffffff; // @presenter Color
121
+
122
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
109
123
  `;
110
124
  case 'indigo':
111
125
  return css`
@@ -121,6 +135,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
121
135
  --color-brand-10: #303e6b; // @presenter Color
122
136
  --color-brand-11: #28314f; // @presenter Color
123
137
  --text-color-on-color: #ffffff; // @presenter Color
138
+
139
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
124
140
  `;
125
141
  case 'iris':
126
142
  return css`
@@ -136,6 +152,8 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
136
152
  --color-brand-10: #3a3a6a; // @presenter Color
137
153
  --color-brand-11: #2e2e4f; // @presenter Color
138
154
  --text-color-on-color: #ffffff; // @presenter Color
155
+
156
+ --link-color-primary-palette: var(--text-color-primary); // @presenter Color
139
157
  `;
140
158
  default:
141
159
  return css`
@@ -161,6 +179,27 @@ function brandPaletteLight(palette: string | undefined): FlattenSimpleInterpolat
161
179
 
162
180
  --menu-item-bg-color-active-legacy: var(--tree-bg-color-active); // @presenter Color
163
181
  --menu-item-color-active-legacy: var(--tree-content-color-default); // @presenter Color
182
+ --menu-item-color-active-hover-legacy: var(--tree-content-color-hover); // @presenter Color
183
+ --menu-item-bg-color-active-hover-legacy: var(--color-hover-base); // @presenter Color
184
+
185
+ --code-block-highlighted-bg-color-legacy: var(--layer-color-hover); // @presenter Color
186
+ --code-block-tokens-string-color-legacy: var(--color-blue-7); // @presenter Color
187
+
188
+ --security-header-color-legacy: var(--link-color-primary); // @presenter Color
189
+
190
+ --schema-name-color-legacy: var(--text-color-primary); // @presenter Color
191
+
192
+ --search-ai-conversation-input-border-color-focus-legacy: var(--color-blue-6); // @presenter Color
193
+ --search-ai-user-bg-color-legacy: var(--color-blue-6); // @presenter Color
194
+
195
+ --button-content-color-link-legacy: var(--link-color-primary); // @presenter Color
196
+ --button-content-color-link-hover-legacy: var(--link-color-primary-hover); // @presenter Color
197
+ --button-content-color-link-pressed-legacy: var(--link-color-primary-pressed); // @presenter Color
198
+
199
+ --link-color-primary-legacy: var(--color-blue-6); // @presenter Color
200
+ --link-color-primary-hover-legacy: var(--color-blue-7); // @presenter Color
201
+ --link-color-primary-pressed-legacy: var(--color-blue-8); // @presenter Color
202
+ --link-color-visited-legacy: var(--color-purple-7); // @presenter Color
164
203
  `;
165
204
  }
166
205
  }
@@ -171,7 +171,7 @@ export type BffCatalogEntity = {
171
171
  key: string;
172
172
  type: string;
173
173
  title: string;
174
- readonly source: 'api' | 'file';
174
+ readonly source: 'remote' | 'file';
175
175
  domains?: Array<BffCatalogRelatedEntity>;
176
176
  owners?: Array<BffCatalogRelatedEntity>;
177
177
  summary?: string | null;
@@ -6,19 +6,32 @@ import type { IconProps } from '@redocly/theme/icons/types';
6
6
  import { getCssColorVariable } from '@redocly/theme/core/utils';
7
7
 
8
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="M14.625 3.37992C14.3463 3.10024 14.0151 2.87833 13.6505 2.72692C13.2858 2.5755 12.8949 2.49756 12.5 2.49756C12.1052 2.49756 11.7142 2.5755 11.3496 2.72692C10.9849 2.87833 10.6537 3.10024 10.375 3.37992L11.085 4.08992C11.2712 3.90378 11.4922 3.75611 11.7354 3.65537C11.9786 3.55463 12.2393 3.50278 12.5025 3.50278C12.7658 3.50278 13.0264 3.55463 13.2697 3.65537C13.5129 3.75611 13.7339 3.90378 13.92 4.08992C14.1062 4.27607 14.2538 4.49706 14.3546 4.74028C14.4553 4.98349 14.5072 5.24417 14.5072 5.50742C14.5072 5.77068 14.4553 6.03135 14.3546 6.27457C14.2538 6.51778 14.1062 6.73878 13.92 6.92492L9.92002 10.9249C9.54473 11.3009 9.03548 11.5123 8.50428 11.5128C7.97309 11.5133 7.46346 11.3027 7.08752 10.9274C6.71157 10.5521 6.5001 10.0429 6.49964 9.51169C6.49917 8.98049 6.70973 8.47087 7.08502 8.09492L7.79002 7.38492L7.08502 6.67492L6.37502 7.38492C6.09534 7.66363 5.87343 7.99481 5.72201 8.35947C5.57059 8.72412 5.49265 9.11508 5.49265 9.50992C5.49265 9.90477 5.57059 10.2957 5.72201 10.6604C5.87343 11.025 6.09534 11.3562 6.37502 11.6349C6.94076 12.1934 7.70505 12.5045 8.50002 12.4999C8.89637 12.5016 9.28913 12.4246 9.65558 12.2736C10.022 12.1225 10.3549 11.9004 10.635 11.6199L14.635 7.61992C15.1955 7.0561 15.5093 6.29286 15.5074 5.49785C15.5055 4.70285 15.1881 3.9411 14.625 3.37992Z" />
11
- <path d="M2.09502 12.4099C1.90831 12.2241 1.76016 12.0032 1.65907 11.7599C1.55798 11.5167 1.50593 11.2559 1.50593 10.9924C1.50593 10.729 1.55798 10.4682 1.65907 10.2249C1.76016 9.98165 1.90831 9.76076 2.09502 9.57492L6.09502 5.57492C6.28085 5.38822 6.50174 5.24007 6.745 5.13898C6.98826 5.03788 7.24909 4.98584 7.51252 4.98584C7.77594 4.98584 8.03677 5.03788 8.28003 5.13898C8.52329 5.24007 8.74418 5.38822 8.93002 5.57492C9.11554 5.76222 9.26158 5.98486 9.35949 6.22963C9.4574 6.47441 9.50519 6.73634 9.50002 6.99992C9.50154 7.26433 9.45062 7.52641 9.35021 7.771C9.2498 8.0156 9.10188 8.23786 8.91502 8.42492L7.85502 9.49992L8.56501 10.2099L9.62502 9.14992C10.1893 8.58568 10.5063 7.82039 10.5063 7.02242C10.5063 6.22446 10.1893 5.45917 9.62502 4.89492C9.06077 4.33068 8.29548 4.01368 7.49752 4.01368C6.69955 4.01368 5.93426 4.33068 5.37002 4.89492L1.37002 8.89492C1.08958 9.17373 0.867037 9.50522 0.715177 9.87033C0.563316 10.2354 0.485138 10.627 0.485138 11.0224C0.485138 11.4179 0.563316 11.8094 0.715177 12.1745C0.867037 12.5396 1.08958 12.8711 1.37002 13.1499C1.93943 13.7042 2.70546 14.0099 3.50002 13.9999C4.30157 14.0007 5.07087 13.6843 5.64002 13.1199L4.93002 12.4099C4.74418 12.5966 4.52329 12.7448 4.28003 12.8459C4.03677 12.947 3.77594 12.999 3.51252 12.999C3.24909 12.999 2.98826 12.947 2.745 12.8459C2.50174 12.7448 2.28085 12.5966 2.09502 12.4099Z" />
9
+ <svg
10
+ width="20"
11
+ height="20"
12
+ viewBox="0 0 20 20"
13
+ fill="none"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ {...props}
16
+ >
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"
19
+ fill="var(--layer-color)"
20
+ />
21
+ <path
22
+ d="M7.37318 9.56229H12.6232C12.7392 9.56229 12.8505 9.60838 12.9325 9.69043C13.0146 9.77247 13.0607 9.88375 13.0607 9.99979C13.0607 10.1158 13.0146 10.2271 12.9325 10.3091C12.8505 10.3912 12.7392 10.4373 12.6232 10.4373H7.37318C7.25714 10.4373 7.14586 10.3912 7.06382 10.3091C6.98177 10.2271 6.93568 10.1158 6.93568 9.99979C6.93568 9.88375 6.98177 9.77247 7.06382 9.69043C7.14586 9.60838 7.25714 9.56229 7.37318 9.56229ZM8.6853 12.1875H6.4978C5.91764 12.1875 5.36124 11.957 4.95101 11.5468C4.54077 11.1366 4.3103 10.5802 4.3103 10C4.3103 9.41984 4.54077 8.86344 4.95101 8.4532C5.36124 8.04297 5.91764 7.8125 6.4978 7.8125H8.6853C8.80133 7.8125 8.91262 7.76641 8.99466 7.68436C9.07671 7.60231 9.1228 7.49103 9.1228 7.375C9.1228 7.25897 9.07671 7.14769 8.99466 7.06564C8.91262 6.98359 8.80133 6.9375 8.6853 6.9375H6.4978C5.68558 6.9375 4.90662 7.26016 4.33229 7.83449C3.75796 8.40882 3.4353 9.18777 3.4353 10C3.4353 10.8122 3.75796 11.5912 4.33229 12.1655C4.90662 12.7398 5.68558 13.0625 6.4978 13.0625H8.6853C8.80133 13.0625 8.91262 13.0164 8.99466 12.9344C9.07671 12.8523 9.1228 12.741 9.1228 12.625C9.1228 12.509 9.07671 12.3977 8.99466 12.3156C8.91262 12.2336 8.80133 12.1875 8.6853 12.1875ZM13.4982 6.9375H11.3107C11.1946 6.9375 11.0834 6.98359 11.0013 7.06564C10.9193 7.14769 10.8732 7.25897 10.8732 7.375C10.8732 7.49103 10.9193 7.60231 11.0013 7.68436C11.0834 7.76641 11.1946 7.8125 11.3107 7.8125H13.4982C14.0783 7.8125 14.6347 8.04297 15.045 8.4532C15.4552 8.86344 15.6857 9.41984 15.6857 10C15.6857 10.5802 15.4552 11.1366 15.045 11.5468C14.6347 11.957 14.0783 12.1875 13.4982 12.1875H11.3107C11.1946 12.1875 11.0834 12.2336 11.0013 12.3156C10.9193 12.3977 10.8732 12.509 10.8732 12.625C10.8732 12.741 10.9193 12.8523 11.0013 12.9344C11.0834 13.0164 11.1946 13.0625 11.3107 13.0625H13.4982C14.3104 13.0625 15.0894 12.7398 15.6637 12.1655C16.238 11.5912 16.5607 10.8122 16.5607 10C16.5607 9.18777 16.238 8.40882 15.6637 7.83449C15.0894 7.26016 14.3104 6.9375 13.4982 6.9375Z"
23
+ fill="var(--icon-color-primary)"
24
+ />
12
25
  </svg>
13
26
  );
14
27
 
15
28
  export const LinkIcon = styled(Icon).attrs(() => ({
16
29
  'data-component-name': 'icons/LinkIcon/LinkIcon',
17
30
  }))<IconProps>`
18
- path {
31
+ path:last-of-type {
19
32
  fill: ${({ color }) => getCssColorVariable(color)};
20
33
  }
21
34
 
22
- height: ${({ size }) => size || '16px'};
23
- width: ${({ size }) => size || '16px'};
35
+ height: ${({ size }) => size || '20px'};
36
+ width: ${({ size }) => size || '20px'};
24
37
  `;
@@ -170,6 +170,7 @@ const CardWrapper = styled.div.attrs<{
170
170
  text-decoration: none;
171
171
  --md-paragraph-margin: 0;
172
172
  --link-decoration-hover: none;
173
+ --link-decoration: none;
173
174
 
174
175
  background-color: var(--card-bg-color);
175
176
  border-width: var(--card-border-width);
@@ -73,7 +73,7 @@ export function Heading({
73
73
  href={`#${id}`}
74
74
  className={concatClassNames('anchor', 'before')}
75
75
  >
76
- <LinkIcon size="14px" color="--heading-anchor-color" />
76
+ <LinkIcon color="--heading-anchor-color" />
77
77
  </a>
78
78
  );
79
79
 
@@ -98,6 +98,12 @@ const HeadingContentWrapper = styled.div`
98
98
  display: flex;
99
99
  gap: var(--spacing-xs);
100
100
 
101
+ & > .anchor {
102
+ display: flex;
103
+ align-items: center;
104
+ height: 1lh;
105
+ }
106
+
101
107
  & > span {
102
108
  display: flex;
103
109
  align-items: flex-start;