@redocly/theme 0.19.7 → 0.19.9

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.
@@ -19,6 +19,8 @@ function FilterContent({ setFilterTerm, filters, filterTerm, isMobile, filterVal
19
19
  clearAll: 'theme.catalog.filters.clearAll',
20
20
  };
21
21
  const hasActiveFilters = filters.some((filter) => {
22
+ if (filterTerm)
23
+ return true;
22
24
  if (filter.selectedOptions && filter.selectedOptions instanceof Set) {
23
25
  return filter.selectedOptions.size;
24
26
  }
@@ -28,12 +30,14 @@ function FilterContent({ setFilterTerm, filters, filterTerm, isMobile, filterVal
28
30
  });
29
31
  const handleClearAll = () => {
30
32
  filters.forEach((filter) => filter.selectOption(''));
33
+ setFilterTerm('');
31
34
  };
32
35
  return (react_1.default.createElement(FilterContentWrapper, { isMobile: isMobile },
33
36
  react_1.default.createElement(Catalog_1.FilterControls, null,
34
37
  react_1.default.createElement(FilterPopover_1.StyledInput, { placeholder: translate(translationKeys.placeholder, 'Type to filter...'), value: filterTerm, onChange: (e) => setFilterTerm(e.target.value) })),
35
38
  react_1.default.createElement(exports.FilterItems, null, filters.map((filter, idx) => (react_1.default.createElement(Filter_1.Filter, { filter: filter, key: filter.property + '-' + idx, filterValuesCasing: filterValuesCasing })))),
36
- hasActiveFilters && (react_1.default.createElement(Button_1.Button, { size: "small", onClick: handleClearAll }, translate(translationKeys.placeholder, 'Clear all filters')))));
39
+ hasActiveFilters && (react_1.default.createElement(ActionsContainer, null,
40
+ react_1.default.createElement(ClearAllButton, { size: "default", variant: "outlined", onClick: handleClearAll }, translate(translationKeys.placeholder, 'Clear all filters'))))));
37
41
  }
38
42
  exports.FilterContent = FilterContent;
39
43
  const FilterContentWrapper = (0, styled_components_1.default)(Sidebar_1.Sidebar) `
@@ -42,11 +46,10 @@ const FilterContentWrapper = (0, styled_components_1.default)(Sidebar_1.Sidebar)
42
46
 
43
47
  ${Button_1.Button} {
44
48
  width: var(--filter-content-clear-button-width);
45
- margin: var(--filter-content-clear-button-margin);
46
49
  }
47
50
 
48
51
  ${({ theme, isMobile }) => !isMobile && theme.mediaQueries.medium} {
49
- display: block;
52
+ display: flex;
50
53
  border-right: 1px solid var(--filter-content-border-color);
51
54
 
52
55
  ${Catalog_1.FilterControls} {
@@ -55,6 +58,16 @@ const FilterContentWrapper = (0, styled_components_1.default)(Sidebar_1.Sidebar)
55
58
  }
56
59
  `;
57
60
  exports.FilterItems = styled_components_1.default.div `
61
+ overflow: scroll;
58
62
  padding: var(--filter-content-items-padding);
59
63
  `;
64
+ const ActionsContainer = styled_components_1.default.div `
65
+ display: flex;
66
+ align-items: center;
67
+ padding: var(--spacing-base) var(--spacing-lg);
68
+ margin-top: auto;
69
+ `;
70
+ const ClearAllButton = (0, styled_components_1.default)(Button_1.Button) `
71
+ width: var(--filter-content-clear-button-width);
72
+ `;
60
73
  //# sourceMappingURL=FilterContent.js.map
@@ -33,8 +33,7 @@ exports.filter = (0, styled_components_1.css) `
33
33
 
34
34
  --filter-content-border-color: var(--border-secondary);
35
35
  --filter-content-items-padding: 0 var(--spacing-lg);
36
- --filter-content-clear-button-margin: var(--spacing-base) auto 0 auto;
37
- --filter-content-clear-button-width: calc(var(--spacing-unit) * 40);
36
+ --filter-content-clear-button-width: 100%;
38
37
  --filter-controls-background-color: var(--bg-base);
39
38
 
40
39
  --filter-popover-background-color: var(--bg-base);
@@ -16,9 +16,12 @@ export interface SelectProps<T = any> {
16
16
  icon?: React.ReactNode;
17
17
  onlyIcon?: boolean;
18
18
  placeholder?: string;
19
+ disabled?: boolean;
19
20
  }
20
- export declare function Select<T>({ className, value, options, dataAttributes, withArrow, triggerEvent, onChange, placement, alignment, icon, onlyIcon, placeholder, }: SelectProps<T>): JSX.Element;
21
- export declare const SelectContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
21
+ export declare function Select<T>({ className, value, options, dataAttributes, withArrow, triggerEvent, onChange, placement, alignment, icon, onlyIcon, disabled, placeholder, }: SelectProps<T>): JSX.Element;
22
+ export declare const SelectContainer: import("styled-components").StyledComponent<"div", any, {
23
+ disabled?: boolean | undefined;
24
+ }, never>;
22
25
  export declare const SelectInput: import("styled-components").StyledComponent<"div", any, {}, never>;
23
26
  export declare const SelectInputValue: import("styled-components").StyledComponent<"div", any, {}, never>;
24
27
  export declare const SelectList: import("styled-components").StyledComponent<"ul", any, {
@@ -31,7 +31,7 @@ const react_1 = __importStar(require("react"));
31
31
  const styled_components_1 = __importDefault(require("styled-components"));
32
32
  const icons_1 = require("../../icons");
33
33
  const hooks_1 = require("../../hooks");
34
- function Select({ className, value, options, dataAttributes, withArrow = true, triggerEvent = 'click', onChange, placement, alignment, icon, onlyIcon, placeholder, }) {
34
+ function Select({ className, value, options, dataAttributes, withArrow = true, triggerEvent = 'click', onChange, placement, alignment, icon, onlyIcon, disabled, placeholder, }) {
35
35
  const containerRef = (0, react_1.useRef)(null);
36
36
  const [isOpen, setIsOpen] = (0, react_1.useState)(false);
37
37
  // const [selectedIdx, setSelectedIdx] = useState<React.ReactNode | string>(selected);
@@ -55,7 +55,7 @@ function Select({ className, value, options, dataAttributes, withArrow = true, t
55
55
  // // eslint-disable-next-line react-hooks/exhaustive-deps
56
56
  // }, [selected]);
57
57
  const selectedOption = options.find((option) => option.value === value);
58
- return (react_1.default.createElement(exports.SelectContainer, Object.assign({}, dataAttributes, { "data-testid": "select", className: className, ref: containerRef, onPointerEnter: triggerEvent === 'hover' ? handleOpen : undefined, onPointerLeave: triggerEvent === 'hover' ? handleClose : undefined, onClick: triggerEvent === 'click' ? handleToggle : undefined }),
58
+ return (react_1.default.createElement(exports.SelectContainer, Object.assign({}, dataAttributes, { disabled: disabled, "data-testid": "select", className: className, ref: containerRef, onPointerEnter: triggerEvent === 'hover' ? handleOpen : undefined, onPointerLeave: triggerEvent === 'hover' ? handleClose : undefined, onClick: triggerEvent === 'click' ? handleToggle : undefined }),
59
59
  react_1.default.createElement(exports.SelectInput, null,
60
60
  !onlyIcon && (react_1.default.createElement(exports.SelectInputValue, null, (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.label) || (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.element) || placeholder)),
61
61
  icon,
@@ -70,6 +70,13 @@ exports.SelectContainer = styled_components_1.default.div `
70
70
  line-height: var(--select-line-height);
71
71
  border-radius: var(--select-border-radius);
72
72
  color: var(--select-text-color);
73
+ min-width: 0;
74
+
75
+ ${({ disabled }) => disabled &&
76
+ `
77
+ opacity: 0.59;
78
+ pointer-events: none;
79
+ `}
73
80
 
74
81
  a {
75
82
  display: block;
@@ -89,6 +96,8 @@ exports.SelectInput = styled_components_1.default.div `
89
96
  exports.SelectInputValue = styled_components_1.default.div `
90
97
  pointer-events: none;
91
98
  min-width: 0;
99
+ text-overflow: ellipsis;
100
+ overflow: hidden;
92
101
  `;
93
102
  exports.SelectList = styled_components_1.default.ul `
94
103
  position: absolute;
@@ -114,6 +123,8 @@ exports.SelectListItem = styled_components_1.default.li `
114
123
 
115
124
  & > * {
116
125
  padding: var(--select-list-item-vertical-padding) var(--select-list-item-horizontal-padding);
126
+ overflow: hidden;
127
+ text-overflow: ellipsis;
117
128
  }
118
129
 
119
130
  :hover {
@@ -1,7 +1,11 @@
1
+ /// <reference types="react" />
1
2
  import type { SelectProps } from '../Select';
3
+ import type { Version } from '../../types/portal';
2
4
  import { Select } from '../Select';
3
- export declare const VersionPicker: import("styled-components").StyledComponent<typeof Select, any, {
4
- dataAttributes: {
5
- 'data-component-name': string;
6
- };
7
- } & SelectProps<any>, "dataAttributes">;
5
+ export interface VersionPickerProps extends SelectProps {
6
+ }
7
+ export declare function VersionPicker(props: {
8
+ versions?: Version[];
9
+ onChange: (v: Version) => void;
10
+ }): JSX.Element | null;
11
+ export declare const VersionPickerSelect: import("styled-components").StyledComponent<typeof Select, any, SelectProps<any>, never>;
@@ -1,27 +1,82 @@
1
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 (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.VersionPicker = void 0;
29
+ exports.VersionPickerSelect = exports.VersionPicker = void 0;
30
+ const React = __importStar(require("react"));
7
31
  const styled_components_1 = __importDefault(require("styled-components"));
32
+ const hooks_1 = require("../../hooks");
33
+ const hooks_2 = require("../../mocks/hooks");
8
34
  const Select_1 = require("../Select");
9
- exports.VersionPicker = (0, styled_components_1.default)(Select_1.Select).attrs(() => ({
10
- dataAttributes: {
11
- 'data-component-name': 'Sidebar/VersionPicker',
12
- },
13
- })) `
35
+ function VersionPicker(props) {
36
+ var _a;
37
+ const themeConfig = (0, hooks_1.useThemeConfig)();
38
+ const { versionPicker } = themeConfig;
39
+ const { translate } = (0, hooks_2.useTranslate)();
40
+ const translationKeys = {
41
+ label: 'theme.versionPicker.label',
42
+ unversioned: 'theme.versionPicker.unversioned',
43
+ };
44
+ const { versions = [], onChange } = props;
45
+ const options = versions.map((version) => {
46
+ return {
47
+ element: version.label || version.version,
48
+ value: version,
49
+ active: version.active,
50
+ };
51
+ });
52
+ if (versionPicker === null || versionPicker === void 0 ? void 0 : versionPicker.hide) {
53
+ return null;
54
+ }
55
+ const value = (_a = options.find((item) => item.active)) === null || _a === void 0 ? void 0 : _a.value;
56
+ if (!options.length && !(versionPicker === null || versionPicker === void 0 ? void 0 : versionPicker.showForUnversioned))
57
+ return null;
58
+ return (React.createElement(VersionsPickerWrapper, null,
59
+ React.createElement(VersionPickerLabel, { "data-translation-key": translationKeys.label }, translate(translationKeys.label, 'Version:')),
60
+ React.createElement(exports.VersionPickerSelect, { placeholder: translate(translationKeys.unversioned, 'All versions'), disabled: !options.length, options: options, value: value, onChange: onChange })));
61
+ }
62
+ exports.VersionPicker = VersionPicker;
63
+ const VersionPickerLabel = styled_components_1.default.label `
64
+ font-size: var(--version-picker-label-font-size);
65
+ font-weight: var(--version-picker-label-font-weight);
66
+ `;
67
+ exports.VersionPickerSelect = (0, styled_components_1.default)(Select_1.Select) `
14
68
  --select-list-item-active-background-color: var(
15
69
  --version-picker-list-item-active-background-color
16
70
  );
17
71
  --select-list-item-hover-background-color: var(--version-picker-list-item-hover-background-color);
18
72
 
73
+ flex: 1;
74
+
19
75
  font-size: var(--version-picker-font-size);
20
76
  font-weight: var(--version-picker-font-weight);
21
77
  border-radius: var(--version-picker-border-radius);
22
78
  line-height: var(--version-picker-line-height);
23
79
  color: var(--version-picker-text-color);
24
- margin: var(--version-picker-margin-vertical) var(--version-picker-margin-horizontal);
25
80
 
26
81
  ${Select_1.SelectInput} {
27
82
  border: var(--version-picker-input-border);
@@ -50,4 +105,17 @@ exports.VersionPicker = (0, styled_components_1.default)(Select_1.Select).attrs(
50
105
  }
51
106
  }
52
107
  `;
108
+ const VersionsPickerWrapper = styled_components_1.default.div.attrs(() => ({
109
+ dataAttributes: {
110
+ 'data-component-name': 'Sidebar/VersionPicker',
111
+ },
112
+ })) `
113
+ display: flex;
114
+ gap: 10px;
115
+ flex-direction: row;
116
+ align-items: center;
117
+ justify-content: space-between;
118
+ padding: var(--version-picker-padding-vertical) var(--version-picker-padding-horizontal);
119
+ border-bottom: var(--version-picker-border-bottom);
120
+ `;
53
121
  //# sourceMappingURL=VersionPicker.js.map
@@ -190,8 +190,12 @@ exports.versionPicker = (0, styled_components_1.css) `
190
190
  --version-picker-line-height: var(--select-line-height); // @presenter LineHeight
191
191
  --version-picker-text-color: var(--select-text-color); // @presenter Color
192
192
  --version-picker-border-radius: var(--select-border-radius); // @presenter BorderRadius
193
- --version-picker-margin-vertical: 10px; // @presenter Spacing
194
- --version-picker-margin-horizontal: 15px; // @presenter Spacing
193
+ --version-picker-padding-vertical: 10px; // @presenter Spacing
194
+ --version-picker-padding-horizontal: calc(var(--sidebar-margin-horizontal) + var(--sidebar-item-padding-horizontal)); // @presenter Spacing
195
+ --version-picker-border-bottom: 1px solid var(--border-primary); // @presenter Border
196
+
197
+ --version-picker-label-font-size: var(--font-size-base);
198
+ --version-picker-label-font-weight: var(--font-weight-bold);
195
199
 
196
200
  --version-picker-input-padding-horizontal: var(--select-input-padding-horizontal); // @presenter Spacing
197
201
  --version-picker-input-padding-vertical: var(--select-input-padding-vertical); // @presenter Spacing
package/lib/config.d.ts CHANGED
@@ -1555,6 +1555,17 @@ export declare const themeConfigSchema: {
1555
1555
  readonly additionalProperties: false;
1556
1556
  readonly default: {};
1557
1557
  };
1558
+ readonly versionPicker: {
1559
+ readonly type: "object";
1560
+ readonly properties: {
1561
+ readonly hide: {
1562
+ readonly type: "boolean";
1563
+ };
1564
+ readonly showForUnversioned: {
1565
+ readonly type: "boolean";
1566
+ };
1567
+ };
1568
+ };
1558
1569
  readonly breadcrumbs: {
1559
1570
  readonly type: "object";
1560
1571
  readonly properties: {
package/lib/config.js CHANGED
@@ -535,6 +535,15 @@ exports.themeConfigSchema = {
535
535
  additionalProperties: false,
536
536
  default: {},
537
537
  },
538
+ versionPicker: {
539
+ type: 'object',
540
+ properties: {
541
+ hide: { type: 'boolean' },
542
+ showForUnversioned: {
543
+ type: 'boolean',
544
+ },
545
+ },
546
+ },
538
547
  breadcrumbs: {
539
548
  type: 'object',
540
549
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.19.7",
3
+ "version": "0.19.9",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -32,6 +32,7 @@ export function FilterContent({
32
32
  };
33
33
 
34
34
  const hasActiveFilters = filters.some((filter) => {
35
+ if (filterTerm) return true;
35
36
  if (filter.selectedOptions && filter.selectedOptions instanceof Set) {
36
37
  return filter.selectedOptions.size;
37
38
  } else if (filter.selectedOptions.from && filter.selectedOptions.to) {
@@ -41,6 +42,7 @@ export function FilterContent({
41
42
 
42
43
  const handleClearAll = () => {
43
44
  filters.forEach((filter) => filter.selectOption(''));
45
+ setFilterTerm('');
44
46
  };
45
47
 
46
48
  return (
@@ -62,9 +64,11 @@ export function FilterContent({
62
64
  ))}
63
65
  </FilterItems>
64
66
  {hasActiveFilters && (
65
- <Button size="small" onClick={handleClearAll}>
66
- {translate(translationKeys.placeholder, 'Clear all filters')}
67
- </Button>
67
+ <ActionsContainer>
68
+ <ClearAllButton size="default" variant="outlined" onClick={handleClearAll}>
69
+ {translate(translationKeys.placeholder, 'Clear all filters')}
70
+ </ClearAllButton>
71
+ </ActionsContainer>
68
72
  )}
69
73
  </FilterContentWrapper>
70
74
  );
@@ -76,11 +80,10 @@ const FilterContentWrapper = styled(Sidebar)<{ isMobile?: boolean }>`
76
80
 
77
81
  ${Button} {
78
82
  width: var(--filter-content-clear-button-width);
79
- margin: var(--filter-content-clear-button-margin);
80
83
  }
81
84
 
82
85
  ${({ theme, isMobile }) => !isMobile && theme.mediaQueries.medium} {
83
- display: block;
86
+ display: flex;
84
87
  border-right: 1px solid var(--filter-content-border-color);
85
88
 
86
89
  ${FilterControls} {
@@ -90,5 +93,17 @@ const FilterContentWrapper = styled(Sidebar)<{ isMobile?: boolean }>`
90
93
  `;
91
94
 
92
95
  export const FilterItems = styled.div`
96
+ overflow: scroll;
93
97
  padding: var(--filter-content-items-padding);
94
98
  `;
99
+
100
+ const ActionsContainer = styled.div`
101
+ display: flex;
102
+ align-items: center;
103
+ padding: var(--spacing-base) var(--spacing-lg);
104
+ margin-top: auto;
105
+ `;
106
+
107
+ const ClearAllButton = styled(Button)`
108
+ width: var(--filter-content-clear-button-width);
109
+ `;
@@ -31,8 +31,7 @@ export const filter = css`
31
31
 
32
32
  --filter-content-border-color: var(--border-secondary);
33
33
  --filter-content-items-padding: 0 var(--spacing-lg);
34
- --filter-content-clear-button-margin: var(--spacing-base) auto 0 auto;
35
- --filter-content-clear-button-width: calc(var(--spacing-unit) * 40);
34
+ --filter-content-clear-button-width: 100%;
36
35
  --filter-controls-background-color: var(--bg-base);
37
36
 
38
37
  --filter-popover-background-color: var(--bg-base);
@@ -21,6 +21,7 @@ export interface SelectProps<T = any> {
21
21
  icon?: React.ReactNode;
22
22
  onlyIcon?: boolean;
23
23
  placeholder?: string;
24
+ disabled?: boolean;
24
25
  }
25
26
 
26
27
  export function Select<T>({
@@ -35,6 +36,7 @@ export function Select<T>({
35
36
  alignment,
36
37
  icon,
37
38
  onlyIcon,
39
+ disabled,
38
40
  placeholder,
39
41
  }: SelectProps<T>) {
40
42
  const containerRef = useRef<HTMLDivElement | null>(null);
@@ -72,6 +74,7 @@ export function Select<T>({
72
74
  return (
73
75
  <SelectContainer
74
76
  {...dataAttributes}
77
+ disabled={disabled}
75
78
  data-testid="select"
76
79
  className={className}
77
80
  ref={containerRef}
@@ -105,13 +108,21 @@ export function Select<T>({
105
108
  );
106
109
  }
107
110
 
108
- export const SelectContainer = styled.div`
111
+ export const SelectContainer = styled.div<{ disabled?: boolean }>`
109
112
  position: relative;
110
113
  font-size: var(--select-font-size);
111
114
  font-weight: var(--select-font-weight);
112
115
  line-height: var(--select-line-height);
113
116
  border-radius: var(--select-border-radius);
114
117
  color: var(--select-text-color);
118
+ min-width: 0;
119
+
120
+ ${({ disabled }) =>
121
+ disabled &&
122
+ `
123
+ opacity: 0.59;
124
+ pointer-events: none;
125
+ `}
115
126
 
116
127
  a {
117
128
  display: block;
@@ -133,6 +144,8 @@ export const SelectInput = styled.div`
133
144
  export const SelectInputValue = styled.div`
134
145
  pointer-events: none;
135
146
  min-width: 0;
147
+ text-overflow: ellipsis;
148
+ overflow: hidden;
136
149
  `;
137
150
 
138
151
  export const SelectList = styled.ul<{ placement?: string; alignment?: string }>`
@@ -160,6 +173,8 @@ export const SelectListItem = styled.li<{ selected: boolean }>`
160
173
 
161
174
  & > * {
162
175
  padding: var(--select-list-item-vertical-padding) var(--select-list-item-horizontal-padding);
176
+ overflow: hidden;
177
+ text-overflow: ellipsis;
163
178
  }
164
179
 
165
180
  :hover {
@@ -1,25 +1,77 @@
1
+ import * as React from 'react';
1
2
  import styled from 'styled-components';
2
3
 
3
4
  import type { SelectProps } from '../Select';
4
5
 
6
+ import { useThemeConfig } from '@theme/hooks';
7
+ import { useTranslate } from '@portal/hooks';
8
+ import type { Version } from '@theme/types/portal';
9
+
5
10
  import { Select, SelectInput, SelectList, SelectListItem } from '../Select';
6
11
 
7
- export const VersionPicker = styled(Select).attrs(() => ({
8
- dataAttributes: {
9
- 'data-component-name': 'Sidebar/VersionPicker',
10
- },
11
- }))<SelectProps>`
12
+ export interface VersionPickerProps extends SelectProps {}
13
+
14
+ export function VersionPicker(props: { versions?: Version[]; onChange: (v: Version) => void }) {
15
+ const themeConfig = useThemeConfig();
16
+ const { versionPicker } = themeConfig;
17
+
18
+ const { translate } = useTranslate();
19
+ const translationKeys = {
20
+ label: 'theme.versionPicker.label',
21
+ unversioned: 'theme.versionPicker.unversioned',
22
+ };
23
+
24
+ const { versions = [], onChange } = props;
25
+ const options = versions.map((version) => {
26
+ return {
27
+ element: version.label || version.version,
28
+ value: version,
29
+ active: version.active,
30
+ };
31
+ });
32
+
33
+ if (versionPicker?.hide) {
34
+ return null;
35
+ }
36
+
37
+ const value = options.find((item) => item.active)?.value;
38
+
39
+ if (!options.length && !versionPicker?.showForUnversioned) return null;
40
+
41
+ return (
42
+ <VersionsPickerWrapper>
43
+ <VersionPickerLabel data-translation-key={translationKeys.label}>
44
+ {translate(translationKeys.label, 'Version:')}
45
+ </VersionPickerLabel>
46
+ <VersionPickerSelect
47
+ placeholder={translate(translationKeys.unversioned, 'All versions')}
48
+ disabled={!options.length}
49
+ options={options}
50
+ value={value}
51
+ onChange={onChange}
52
+ />
53
+ </VersionsPickerWrapper>
54
+ );
55
+ }
56
+
57
+ const VersionPickerLabel = styled.label`
58
+ font-size: var(--version-picker-label-font-size);
59
+ font-weight: var(--version-picker-label-font-weight);
60
+ `;
61
+
62
+ export const VersionPickerSelect = styled(Select)<SelectProps>`
12
63
  --select-list-item-active-background-color: var(
13
64
  --version-picker-list-item-active-background-color
14
65
  );
15
66
  --select-list-item-hover-background-color: var(--version-picker-list-item-hover-background-color);
16
67
 
68
+ flex: 1;
69
+
17
70
  font-size: var(--version-picker-font-size);
18
71
  font-weight: var(--version-picker-font-weight);
19
72
  border-radius: var(--version-picker-border-radius);
20
73
  line-height: var(--version-picker-line-height);
21
74
  color: var(--version-picker-text-color);
22
- margin: var(--version-picker-margin-vertical) var(--version-picker-margin-horizontal);
23
75
 
24
76
  ${SelectInput} {
25
77
  border: var(--version-picker-input-border);
@@ -48,3 +100,17 @@ export const VersionPicker = styled(Select).attrs(() => ({
48
100
  }
49
101
  }
50
102
  `;
103
+
104
+ const VersionsPickerWrapper = styled.div.attrs(() => ({
105
+ dataAttributes: {
106
+ 'data-component-name': 'Sidebar/VersionPicker',
107
+ },
108
+ }))`
109
+ display: flex;
110
+ gap: 10px;
111
+ flex-direction: row;
112
+ align-items: center;
113
+ justify-content: space-between;
114
+ padding: var(--version-picker-padding-vertical) var(--version-picker-padding-horizontal);
115
+ border-bottom: var(--version-picker-border-bottom);
116
+ `;
@@ -189,8 +189,12 @@ export const versionPicker = css`
189
189
  --version-picker-line-height: var(--select-line-height); // @presenter LineHeight
190
190
  --version-picker-text-color: var(--select-text-color); // @presenter Color
191
191
  --version-picker-border-radius: var(--select-border-radius); // @presenter BorderRadius
192
- --version-picker-margin-vertical: 10px; // @presenter Spacing
193
- --version-picker-margin-horizontal: 15px; // @presenter Spacing
192
+ --version-picker-padding-vertical: 10px; // @presenter Spacing
193
+ --version-picker-padding-horizontal: calc(var(--sidebar-margin-horizontal) + var(--sidebar-item-padding-horizontal)); // @presenter Spacing
194
+ --version-picker-border-bottom: 1px solid var(--border-primary); // @presenter Border
195
+
196
+ --version-picker-label-font-size: var(--font-size-base);
197
+ --version-picker-label-font-weight: var(--font-weight-bold);
194
198
 
195
199
  --version-picker-input-padding-horizontal: var(--select-input-padding-horizontal); // @presenter Spacing
196
200
  --version-picker-input-padding-vertical: var(--select-input-padding-vertical); // @presenter Spacing
package/src/config.ts CHANGED
@@ -622,6 +622,15 @@ export const themeConfigSchema = {
622
622
  additionalProperties: false,
623
623
  default: {},
624
624
  },
625
+ versionPicker: {
626
+ type: 'object',
627
+ properties: {
628
+ hide: { type: 'boolean' },
629
+ showForUnversioned: {
630
+ type: 'boolean',
631
+ },
632
+ },
633
+ },
625
634
  breadcrumbs: {
626
635
  type: 'object',
627
636
  properties: {