@redocly/theme 0.63.0-next.2 → 0.63.0-next.4

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 (36) hide show
  1. package/lib/components/Buttons/CopyButton.d.ts +1 -1
  2. package/lib/components/Buttons/CopyButton.js +1 -1
  3. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.js +2 -2
  4. package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.js +6 -13
  5. package/lib/components/CodeBlock/CodeBlockControls.js +3 -3
  6. package/lib/components/PageActions/PageActions.js +1 -1
  7. package/lib/components/SidebarActions/styled.d.ts +1 -1
  8. package/lib/components/Tooltip/AnchorTooltip.d.ts +7 -0
  9. package/lib/components/Tooltip/AnchorTooltip.js +230 -0
  10. package/lib/components/Tooltip/JsTooltip.d.ts +3 -0
  11. package/lib/components/Tooltip/JsTooltip.js +274 -0
  12. package/lib/components/Tooltip/Tooltip.d.ts +2 -13
  13. package/lib/components/Tooltip/Tooltip.js +14 -190
  14. package/lib/core/hooks/use-page-actions.js +16 -9
  15. package/lib/core/hooks/use-theme-hooks.js +1 -0
  16. package/lib/core/types/hooks.d.ts +3 -0
  17. package/lib/core/types/index.d.ts +1 -0
  18. package/lib/core/types/tooltip.d.ts +13 -0
  19. package/lib/core/types/tooltip.js +3 -0
  20. package/lib/core/utils/transform-revisions-to-version-history.js +13 -20
  21. package/package.json +3 -3
  22. package/src/components/Buttons/CopyButton.tsx +2 -1
  23. package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.tsx +2 -2
  24. package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem.tsx +5 -21
  25. package/src/components/CodeBlock/CodeBlockControls.tsx +3 -0
  26. package/src/components/PageActions/PageActions.tsx +6 -1
  27. package/src/components/Tooltip/AnchorTooltip.tsx +255 -0
  28. package/src/components/Tooltip/JsTooltip.tsx +292 -0
  29. package/src/components/Tooltip/Tooltip.tsx +18 -257
  30. package/src/core/hooks/__mocks__/use-theme-hooks.ts +3 -0
  31. package/src/core/hooks/use-page-actions.ts +17 -6
  32. package/src/core/hooks/use-theme-hooks.ts +1 -0
  33. package/src/core/types/hooks.ts +1 -0
  34. package/src/core/types/index.ts +1 -0
  35. package/src/core/types/tooltip.ts +14 -0
  36. package/src/core/utils/transform-revisions-to-version-history.ts +13 -21
@@ -35,198 +35,22 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Tooltip = void 0;
37
37
  const react_1 = __importStar(require("react"));
38
- const styled_components_1 = __importStar(require("styled-components"));
38
+ const AnchorTooltip_1 = require("../../components/Tooltip/AnchorTooltip");
39
+ const JsTooltip_1 = require("../../components/Tooltip/JsTooltip");
39
40
  const hooks_1 = require("../../core/hooks");
40
- const Portal_1 = require("../../components/Portal/Portal");
41
- function TooltipComponent({ children, isOpen, tip, withArrow = true, placement = 'top', className = 'default', width, dataTestId, disabled = false, arrowPosition = 'center', }) {
42
- const tooltipWrapperRef = (0, react_1.useRef)(null);
43
- const tooltipBodyRef = (0, react_1.useRef)(null);
44
- const { isOpened, handleOpen, handleClose } = (0, hooks_1.useControl)(isOpen);
45
- const anchorName = `--tooltip${(0, react_1.useId)().replace(/:/g, '')}`;
46
- (0, hooks_1.useOutsideClick)(isOpened ? [tooltipWrapperRef, tooltipBodyRef] : tooltipWrapperRef, handleClose);
47
- const isControlled = isOpen !== undefined;
48
- (0, react_1.useEffect)(() => {
49
- if (!isControlled)
50
- return;
51
- if (isOpen && !disabled) {
52
- handleOpen();
53
- }
54
- else {
55
- handleClose();
56
- }
57
- }, [isOpen, disabled, isControlled, handleOpen, handleClose]);
58
- const controllers = !isControlled && !disabled
59
- ? {
60
- onMouseEnter: handleOpen,
61
- onMouseLeave: handleClose,
62
- onClick: handleClose,
63
- onFocus: handleOpen,
64
- onBlur: handleClose,
65
- }
66
- : {};
67
- return (react_1.default.createElement(TooltipWrapper, Object.assign({ ref: tooltipWrapperRef }, controllers, { className: `tooltip-${className}`, "data-component-name": "Tooltip/Tooltip", anchorName: anchorName }),
68
- children,
69
- isOpened && !disabled && (react_1.default.createElement(Portal_1.Portal, null,
70
- react_1.default.createElement(TooltipBody, { ref: tooltipBodyRef, "data-testid": dataTestId || (typeof tip === 'string' ? tip : ''), placement: placement, width: width, withArrow: withArrow, arrowPosition: arrowPosition, anchorName: anchorName }, tip)))));
41
+ function TooltipComponent(props) {
42
+ const { useAnchorPositioning } = (0, hooks_1.useThemeHooks)();
43
+ const { isSupported } = useAnchorPositioning();
44
+ if (isSupported) {
45
+ return react_1.default.createElement(AnchorTooltip_1.Tooltip, Object.assign({}, props, { arrowPosition: prepareArrowPosition(props.arrowPosition) }));
46
+ }
47
+ return react_1.default.createElement(JsTooltip_1.Tooltip, Object.assign({}, props));
71
48
  }
72
49
  exports.Tooltip = (0, react_1.memo)(TooltipComponent);
73
- const PLACEMENTS = {
74
- top: (0, styled_components_1.css) `
75
- bottom: anchor(top);
76
- ${({ withArrow, arrowPosition }) => withArrow && arrowPosition === 'left'
77
- ? (0, styled_components_1.css) `
78
- transform: translate(-32px, -6px);
79
- left: anchor(center);
80
- `
81
- : arrowPosition === 'right'
82
- ? (0, styled_components_1.css) `
83
- transform: translate(32px, -6px);
84
- right: anchor(center);
85
- `
86
- : (0, styled_components_1.css) `
87
- transform: translate(-50%, -6px);
88
- left: anchor(center);
89
- `}
90
-
91
- ${({ withArrow, arrowPosition }) => withArrow &&
92
- (0, styled_components_1.css) `
93
- &::after {
94
- border-left: 14px solid transparent;
95
- border-right: 14px solid transparent;
96
- border-top-width: 8px;
97
- border-top-style: solid;
98
- border-radius: 2px;
99
- bottom: 0;
100
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(100%);'}
101
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 100%);'}
102
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(100%);'}
103
- }
104
- `}
105
- `,
106
- bottom: (0, styled_components_1.css) `
107
- top: anchor(bottom);
108
- ${({ withArrow, arrowPosition }) => withArrow && arrowPosition === 'left'
109
- ? (0, styled_components_1.css) `
110
- transform: translate(-32px, 6px);
111
- left: anchor(center);
112
- `
113
- : arrowPosition === 'right'
114
- ? (0, styled_components_1.css) `
115
- transform: translate(32px, 6px);
116
- right: anchor(center);
117
- `
118
- : (0, styled_components_1.css) `
119
- transform: translate(-50%, 6px);
120
- left: anchor(center);
121
- `}
122
-
123
- ${({ withArrow, arrowPosition }) => withArrow &&
124
- (0, styled_components_1.css) `
125
- &::after {
126
- border-left: 14px solid transparent;
127
- border-right: 14px solid transparent;
128
- border-bottom-width: 8px;
129
- border-bottom-style: solid;
130
- border-radius: 0 0 2px 2px;
131
- top: 0;
132
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(-100%);'}
133
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -100%);'}
134
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(-100%);'}
135
- }
136
- `}
137
- `,
138
- left: (0, styled_components_1.css) `
139
- transform: translate(-100%, -50%);
140
- margin-left: -7px;
141
- top: anchor(center);
142
- left: anchor(left);
143
-
144
- ${({ withArrow }) => withArrow &&
145
- (0, styled_components_1.css) `
146
- &::after {
147
- border-top: 14px solid transparent;
148
- border-bottom: 14px solid transparent;
149
- border-left-width: 8px;
150
- border-left-style: solid;
151
- border-radius: 2px 0 0 2px;
152
- right: -9px;
153
- top: 50%;
154
- transform: translateY(-50%);
155
- }
156
- `}
157
- `,
158
- right: (0, styled_components_1.css) `
159
- transform: translate(0, -50%);
160
- margin-left: 7px;
161
- top: anchor(center);
162
- left: anchor(right);
163
-
164
- ${({ withArrow }) => withArrow &&
165
- (0, styled_components_1.css) `
166
- &::after {
167
- border-top: 14px solid transparent;
168
- border-bottom: 14px solid transparent;
169
- border-right-width: 8px;
170
- border-right-style: solid;
171
- border-radius: 0 2px 2px 0;
172
- left: -9px;
173
- top: 50%;
174
- transform: translateY(-50%);
175
- }
176
- `}
177
- `,
50
+ const prepareArrowPosition = (arrowPosition) => {
51
+ if (arrowPosition === 'bottom' || arrowPosition === 'top') {
52
+ return 'center';
53
+ }
54
+ return arrowPosition;
178
55
  };
179
- const TooltipWrapper = styled_components_1.default.div.attrs(({ anchorName }) => ({
180
- style: {
181
- anchorName: anchorName,
182
- },
183
- })) `
184
- display: flex;
185
- `;
186
- const TooltipBody = styled_components_1.default.span.attrs(({ anchorName }) => ({
187
- style: {
188
- positionAnchor: anchorName,
189
- },
190
- })) `
191
- position: fixed;
192
- min-width: 64px;
193
- padding: var(--tooltip-padding);
194
- max-width: var(--tooltip-max-width);
195
- white-space: normal;
196
- word-break: normal;
197
- overflow-wrap: break-word;
198
- text-align: left;
199
-
200
- border-radius: var(--border-radius-md);
201
- transition: opacity 0.3s ease-out;
202
-
203
- font-size: var(--font-size-base);
204
- line-height: var(--line-height-base);
205
-
206
- z-index: var(--z-index-overlay);
207
-
208
- &::after {
209
- position: absolute;
210
-
211
- content: ' ';
212
- display: inline-block;
213
- width: 0;
214
- height: 0;
215
- border-color: var(--tooltip-arrow-color, var(--tooltip-bg-color));
216
- }
217
-
218
- background: var(--tooltip-bg-color);
219
- color: var(--tooltip-text-color);
220
- border: var(--tooltip-border-width, 0) var(--tooltip-border-style, solid)
221
- var(--tooltip-border-color, transparent);
222
- box-shadow:
223
- 0px 8px 24px 8px #0000000a,
224
- 0px 4px 12px 0px #00000014;
225
-
226
- width: ${({ width }) => width || 'max-content'};
227
-
228
- ${({ placement }) => (0, styled_components_1.css) `
229
- ${PLACEMENTS[placement]};
230
- `}
231
- `;
232
56
  //# sourceMappingURL=Tooltip.js.map
@@ -23,6 +23,7 @@ const use_mcp_config_1 = require("./use-mcp-config");
23
23
  const clipboard_service_1 = require("../utils/clipboard-service");
24
24
  const dom_1 = require("../utils/dom");
25
25
  const mcp_1 = require("../utils/mcp");
26
+ const urls_1 = require("../utils/urls");
26
27
  function createPageActionResource(pageSlug, pageUrl) {
27
28
  return {
28
29
  id: pageSlug,
@@ -79,9 +80,12 @@ function usePageActions(pageSlug, mcpUrl, actions) {
79
80
  const origin = dom_1.IS_BROWSER
80
81
  ? window.location.origin
81
82
  : ((_a = globalThis['SSR_HOSTNAME']) !== null && _a !== void 0 ? _a : '');
82
- const normalizedSlug = pageSlug.startsWith('/') ? pageSlug : '/' + pageSlug;
83
- const pageUrl = `${origin}${normalizedSlug}`;
84
- const mdPageUrl = new URL(origin + normalizedSlug + (normalizedSlug === '/' ? 'index.html.md' : '.md')).toString();
83
+ const pathname = (0, urls_1.addTrailingSlash)(pageSlug);
84
+ const pageUrl = (0, urls_1.combineUrls)(origin, pathname);
85
+ const isRoot = (0, urls_1.withoutPathPrefix)(pathname) === '/';
86
+ const mdPageUrl = isRoot
87
+ ? (0, urls_1.combineUrls)(origin, pathname, 'index.html.md')
88
+ : (0, urls_1.combineUrls)(origin, (0, urls_1.removeTrailingSlash)(pathname) + '.md');
85
89
  const actionHandlers = {
86
90
  'docs-mcp-cursor': createMCPHandler('cursor', false),
87
91
  'docs-mcp-vscode': createMCPHandler('vscode', false),
@@ -119,7 +123,6 @@ function usePageActions(pageSlug, mcpUrl, actions) {
119
123
  telemetry.sendPageActionsButtonClickedMessage([
120
124
  Object.assign(Object.assign({}, createPageActionResource(pageSlug, pageUrl)), { action_type: 'view' }),
121
125
  ]);
122
- window.location.href = mdPageUrl;
123
126
  },
124
127
  }),
125
128
  chatgpt: () => {
@@ -196,18 +199,22 @@ function createMCPAction({ clientType, mcpConfig, translate, onClickCallback, })
196
199
  return Object.assign(Object.assign({}, sharedProps), { buttonText: translate('page.actions.connectMcp.vscode', 'Connect to VS Code'), title: translate('page.actions.connectMcp.vscode', 'Connect to VS Code'), description: translate('page.actions.connectMcp.vscodeDescription', 'Install MCP server on VS Code'), iconComponent: VSCodeIcon_1.VSCodeIcon });
197
200
  }
198
201
  function shouldHidePageActions(pageProps, themeConfig, openapiExcludeFromSearch) {
199
- var _a, _b, _c, _d, _e, _f, _g;
202
+ var _a, _b, _c, _d, _e, _f, _g, _h;
203
+ // Can't use any actions if search is globally disabled (markdown files are not generated)
204
+ if ((_a = themeConfig.search) === null || _a === void 0 ? void 0 : _a.hide) {
205
+ return true;
206
+ }
200
207
  // Can't use any actions if no markdown files are generated for LLMs
201
- if ((_b = (_a = pageProps === null || pageProps === void 0 ? void 0 : pageProps.seo) === null || _a === void 0 ? void 0 : _a.llmstxt) === null || _b === void 0 ? void 0 : _b.hide) {
208
+ if ((_c = (_b = pageProps === null || pageProps === void 0 ? void 0 : pageProps.seo) === null || _b === void 0 ? void 0 : _b.llmstxt) === null || _c === void 0 ? void 0 : _c.hide) {
202
209
  return true;
203
210
  }
204
211
  // Page actions are explicitly disabled in config
205
- if ((_d = (_c = themeConfig.navigation) === null || _c === void 0 ? void 0 : _c.actions) === null || _d === void 0 ? void 0 : _d.hide) {
212
+ if ((_e = (_d = themeConfig.navigation) === null || _d === void 0 ? void 0 : _d.actions) === null || _e === void 0 ? void 0 : _e.hide) {
206
213
  return true;
207
214
  }
208
215
  // Page is excluded from search
209
- const isOpenApiPage = ((_e = pageProps === null || pageProps === void 0 ? void 0 : pageProps.metadata) === null || _e === void 0 ? void 0 : _e.type) === 'openapi' || ((_f = pageProps === null || pageProps === void 0 ? void 0 : pageProps.metadata) === null || _f === void 0 ? void 0 : _f.subType) === 'openapi-operation';
210
- const isPageExcludedFromSearch = ((_g = pageProps === null || pageProps === void 0 ? void 0 : pageProps.frontmatter) === null || _g === void 0 ? void 0 : _g.excludeFromSearch) || (isOpenApiPage && openapiExcludeFromSearch);
216
+ const isOpenApiPage = ((_f = pageProps === null || pageProps === void 0 ? void 0 : pageProps.metadata) === null || _f === void 0 ? void 0 : _f.type) === 'openapi' || ((_g = pageProps === null || pageProps === void 0 ? void 0 : pageProps.metadata) === null || _g === void 0 ? void 0 : _g.subType) === 'openapi-operation';
217
+ const isPageExcludedFromSearch = ((_h = pageProps === null || pageProps === void 0 ? void 0 : pageProps.frontmatter) === null || _h === void 0 ? void 0 : _h.excludeFromSearch) || (isOpenApiPage && openapiExcludeFromSearch);
211
218
  if (isPageExcludedFromSearch) {
212
219
  return true;
213
220
  }
@@ -5,6 +5,7 @@ const react_1 = require("react");
5
5
  const ThemeDataContext_1 = require("../contexts/ThemeDataContext");
6
6
  const use_telemetry_fallback_1 = require("./use-telemetry-fallback");
7
7
  const fallbacks = {
8
+ useAnchorPositioning: () => ({ isSupported: false }),
8
9
  useTranslate: () => ({
9
10
  translate: (value, options) => (typeof options === 'string' ? options : options === null || options === void 0 ? void 0 : options.defaultValue) || value || '',
10
11
  }),
@@ -16,6 +16,9 @@ import type { DrilldownMenuItemDetails } from './sidebar';
16
16
  import { BffCatalogEntity, BffCatalogEntityList, BffCatalogRelatedEntity, BffCatalogRelatedEntityList, BffCatalogEntityRevision, BffCatalogEntityRevisionList } from './catalog';
17
17
  import { AiSearchError } from '../constants/search';
18
18
  export type ThemeHooks = {
19
+ useAnchorPositioning: () => {
20
+ isSupported: boolean;
21
+ };
19
22
  useTranslate: () => {
20
23
  translate: TFunction;
21
24
  };
@@ -19,3 +19,4 @@ export type * from './code-walkthrough';
19
19
  export type * from './page-actions';
20
20
  export type * from './open-api-info';
21
21
  export type * from './segmented';
22
+ export type * from './tooltip';
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+ export type TooltipProps = {
3
+ children?: ReactNode;
4
+ tip: string | ReactNode;
5
+ isOpen?: boolean;
6
+ withArrow?: boolean;
7
+ placement?: 'top' | 'bottom' | 'left' | 'right';
8
+ className?: string;
9
+ width?: string;
10
+ dataTestId?: string;
11
+ disabled?: boolean;
12
+ arrowPosition?: 'top' | 'bottom' | 'left' | 'right' | 'center';
13
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=tooltip.js.map
@@ -31,26 +31,19 @@ function transformRevisionsToVersionHistory({ revisions, currentRevisionDate, cu
31
31
  }
32
32
  // Check if any revision in this version group is the default version
33
33
  const isDefaultVersion = versionRevisions.some((rev) => rev.isDefaultVersion === true);
34
- const revisions = versionRevisions.length > 1
35
- ? versionRevisions.map((rev, index) => {
36
- var _a;
37
- const revisionMatches = currentRevisionDate
38
- ? rev.revision === currentRevisionDate
39
- : false;
40
- const isActiveRevision = revisionMatches && versionMatches;
41
- const isCurrentByDefault = !currentRevisionDate &&
42
- normalizedCurrentVersion === undefined &&
43
- index === 0 &&
44
- isCurrent;
45
- return {
46
- name: `r.${versionRevisions.length - index}`,
47
- date: (0, date_1.toLocalizedShortDateTime)(rev.revision, locale),
48
- revisionDate: rev.revision,
49
- isActive: isActiveRevision || isCurrentByDefault,
50
- isCurrent: (_a = rev.isCurrent) !== null && _a !== void 0 ? _a : false,
51
- };
52
- })
53
- : undefined;
34
+ const revisions = versionRevisions.map((rev, index) => {
35
+ var _a;
36
+ const revisionMatches = currentRevisionDate ? rev.revision === currentRevisionDate : false;
37
+ const isActiveRevision = revisionMatches && versionMatches;
38
+ const isCurrentByDefault = !currentRevisionDate && normalizedCurrentVersion === undefined && index === 0 && isCurrent;
39
+ return {
40
+ name: `r.${versionRevisions.length - index}`,
41
+ date: (0, date_1.toLocalizedShortDateTime)(rev.revision, locale),
42
+ revisionDate: rev.revision,
43
+ isActive: isActiveRevision || isCurrentByDefault,
44
+ isCurrent: (_a = rev.isCurrent) !== null && _a !== void 0 ? _a : false,
45
+ };
46
+ });
54
47
  return {
55
48
  version,
56
49
  date: (0, date_1.toLocalizedShortDate)((latestRevision === null || latestRevision === void 0 ? void 0 : latestRevision.revision) || null, locale),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.63.0-next.2",
3
+ "version": "0.63.0-next.4",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -63,7 +63,7 @@
63
63
  "vitest": "4.0.10",
64
64
  "vitest-when": "0.6.2",
65
65
  "webpack": "5.105.2",
66
- "@redocly/realm-asyncapi-sdk": "0.9.0-next.1"
66
+ "@redocly/realm-asyncapi-sdk": "0.9.0-next.3"
67
67
  },
68
68
  "dependencies": {
69
69
  "@tanstack/react-query": "5.62.3",
@@ -81,7 +81,7 @@
81
81
  "openapi-sampler": "1.7.0",
82
82
  "react-calendar": "5.1.0",
83
83
  "react-date-picker": "11.0.0",
84
- "@redocly/config": "0.43.0"
84
+ "@redocly/config": "0.44.0"
85
85
  },
86
86
  "scripts": {
87
87
  "watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
@@ -1,7 +1,7 @@
1
1
  import React, { memo } from 'react';
2
2
 
3
3
  import type { JSX } from 'react';
4
- import type { TooltipProps } from '@redocly/theme/components/Tooltip/Tooltip';
4
+ import type { TooltipProps } from '@redocly/theme/core/types';
5
5
  import type { ButtonProps } from '@redocly/theme/components/Button/Button';
6
6
 
7
7
  import { ClipboardService } from '@redocly/theme/core/utils';
@@ -88,6 +88,7 @@ function CopyButtonComponent({
88
88
  tone={tone}
89
89
  extraClass={extraClass}
90
90
  iconPosition={iconPosition}
91
+ aria-label="Copy"
91
92
  >
92
93
  {(type === 'text' || type === 'compound') &&
93
94
  (buttonText || translate('codeSnippet.copy.toasterText', 'Copy'))}
@@ -128,10 +128,10 @@ export function CatalogEntityHistorySidebar({
128
128
 
129
129
  const SidebarOverlay = styled.div`
130
130
  position: fixed;
131
- top: var(--navbar-height);
131
+ top: calc(var(--navbar-height) + var(--banner-height, 0));
132
132
  left: 0;
133
133
  width: var(--sidebar-width);
134
- height: calc(100vh - var(--navbar-height));
134
+ height: calc(100vh - var(--navbar-height) - var(--banner-height, 0));
135
135
  background-color: var(--catalog-history-sidebar-bg-color);
136
136
  border-right: 1px solid var(--catalog-history-sidebar-border-color);
137
137
  display: flex;
@@ -53,9 +53,6 @@ export function CatalogEntityVersionItem({
53
53
 
54
54
  const singleRevisionLink = buildRevisionUrl(basePath, group.singleRevisionDate, group.version);
55
55
 
56
- const isClickable = hasRevisions || Boolean(singleRevisionLink);
57
- const isSingleRevisionActive = Boolean(singleRevisionLink && group.isCurrent);
58
-
59
56
  const versionTitle = isNotSpecifiedVersion
60
57
  ? `${translate('catalog.history.version.label', 'Version')}: ${translate('catalog.history.version.notSpecified', 'not specified')}`
61
58
  : `${translate('catalog.history.version.label', 'Version')}: ${group.version}`;
@@ -64,9 +61,7 @@ export function CatalogEntityVersionItem({
64
61
  <VersionButton
65
62
  type="button"
66
63
  onClick={() => hasRevisions && onToggle(group.version)}
67
- $isClickable={isClickable}
68
64
  $isCurrent={group.isCurrent}
69
- $isActive={isSingleRevisionActive}
70
65
  >
71
66
  <VersionIcon $isCurrent={group.isCurrent}>
72
67
  {group.isCurrent ? (
@@ -155,34 +150,23 @@ export function CatalogEntityVersionItem({
155
150
  }
156
151
 
157
152
  const VersionButton = styled.button<{
158
- $isClickable?: boolean;
159
153
  $isCurrent?: boolean;
160
- $isActive?: boolean;
161
154
  }>`
162
155
  all: unset;
163
156
  display: flex;
164
157
  align-items: center;
165
158
  width: calc(100% - var(--catalog-history-sidebar-version-icon-margin-right));
166
159
  padding: var(--catalog-history-sidebar-version-header-padding);
167
- cursor: ${({ $isClickable }) => ($isClickable ? 'pointer' : 'default')};
160
+ cursor: pointer;
168
161
  border-radius: var(--catalog-history-sidebar-version-header-border-radius);
169
162
  transition: 0.2s ease;
170
163
  text-decoration: none;
171
164
  color: inherit;
172
- background-color: ${({ $isActive }) =>
173
- $isActive ? 'var(--catalog-history-sidebar-revision-item-bg-color-active)' : 'transparent'};
165
+ background-color: 'transparent';
174
166
 
175
- ${({ $isClickable, $isActive }) =>
176
- $isClickable &&
177
- `
178
- &:hover {
179
- background-color: ${
180
- $isActive
181
- ? 'var(--catalog-history-sidebar-revision-item-bg-color-active)'
182
- : 'var(--catalog-history-sidebar-version-header-bg-color-hover)'
183
- };
184
- }
185
- `}
167
+ &:hover {
168
+ background-color: var(--catalog-history-sidebar-version-header-bg-color-hover);
169
+ }
186
170
 
187
171
  ${({ $isCurrent }) =>
188
172
  !$isCurrent &&
@@ -96,6 +96,7 @@ export function CodeBlockControls({
96
96
  size="small"
97
97
  data-testid="report-button"
98
98
  icon={controlsType === 'icon' ? <WarningSquareIcon size="18px" /> : undefined}
99
+ aria-label="Report a problem"
99
100
  {...report.props}
100
101
  >
101
102
  {controlsType != 'icon' && (report.props?.buttonText || 'Report')}
@@ -114,6 +115,7 @@ export function CodeBlockControls({
114
115
  size="small"
115
116
  data-testid="expand-all"
116
117
  icon={controlsType === 'icon' ? <MaximizeIcon /> : undefined}
118
+ aria-label="Expand all"
117
119
  onClick={expand?.onClick}
118
120
  >
119
121
  {controlsType !== 'icon' && (expand?.label || 'Expand all')}
@@ -133,6 +135,7 @@ export function CodeBlockControls({
133
135
  data-testid="collapse-all"
134
136
  icon={controlsType === 'icon' ? <MinimizeIcon /> : undefined}
135
137
  onClick={collapse?.onClick}
138
+ aria-label="Collapse all"
136
139
  >
137
140
  {controlsType !== 'icon' && (expand?.label || 'Collapse all')}
138
141
  </ControlButton>
@@ -83,7 +83,12 @@ export function PageActions(props: PageActionProps): JSX.Element | null {
83
83
  {buttonAction.buttonText}
84
84
  </Button>
85
85
  {actions.length > 1 ? (
86
- <StyledDropdown withArrow trigger={<Button />} placement="bottom" alignment="end">
86
+ <StyledDropdown
87
+ withArrow
88
+ trigger={<Button aria-label="More actions" />}
89
+ placement="bottom"
90
+ alignment="end"
91
+ >
87
92
  <StyledDropdownMenu>{menuItems}</StyledDropdownMenu>
88
93
  </StyledDropdown>
89
94
  ) : null}