@redocly/theme 0.19.6 → 0.19.8

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.
@@ -51,7 +51,7 @@ const getSize = (size = 'default') => (0, styled_components_1.css) `
51
51
  min-width: var(--button-${size}-min-width);
52
52
  `;
53
53
  exports.baseButtonStyles = (0, styled_components_1.css) `
54
- display: flex;
54
+ display: inline-flex;
55
55
  align-items: center;
56
56
  justify-content: center;
57
57
  gap: var(--spacing-xs);
@@ -74,6 +74,7 @@ exports.baseButtonStyles = (0, styled_components_1.css) `
74
74
  &:hover {
75
75
  box-shadow: var(--button-hover-box-shadow);
76
76
  background-color: var(--button-hover-background-color);
77
+ color: var(--button-hover-color, var(--button-color));
77
78
  border: var(--button-border-width) var(--button-border-style) var(--button-hover-border-color);
78
79
  }
79
80
 
@@ -52,12 +52,16 @@ exports.button = (0, styled_components_1.css) `
52
52
  --button-color: var(--text-primary); // @presenter Color
53
53
  --button-background-color: var(--bg-overlay); // @presenter Color
54
54
  --button-border-color: var(--bg-overlay);
55
+ --button-outlined-color: var(--text-primary);
56
+
55
57
 
56
58
  --button-hover-background-color: var(--bg-overlay); // @presenter Color
57
59
  --button-hover-border-color: var(--border-primary); // @presenter Color
60
+ --button-outlined-hover-color: var(--text-primary); // @presenter Color
58
61
 
59
62
  --button-active-background-color: var(--bg-overlay); // @presenter Color
60
63
  --button-active-border-color: var(--button-color); // @presenter Color
64
+ --button-outlined-active-color: var(--bg-overlay); // @presenter Color
61
65
 
62
66
  --button-disabled-color: var(--text-placeholder); // @presenter Color
63
67
  --button-disabled-background-color: var(--bg-raised); // @presenter Color
@@ -72,12 +76,15 @@ exports.button = (0, styled_components_1.css) `
72
76
  --button-background-color: var(--color-primary); // @presenter Color
73
77
  --button-border-color: var(--color-primary); // @presenter Color
74
78
  --button-border: 1px solid var(--button-border-color);
79
+ --button-outlined-color: var(--color-primary);
75
80
 
76
81
  --button-hover-background-color: var(--color-primary-hover); // @presenter Color
77
82
  --button-hover-border-color: var(--color-primary-hover); // @presenter Color
83
+ --button-outlined-hover-color: var(--color-primary-hover);
78
84
 
79
85
  --button-active-background-color: var(--color-primary-active); // @presenter Color
80
86
  --button-active-border-color: var(--color-primary-active); // @presenter Color
87
+ --button-outlined-active-color: var(--color-primary-active); // @presenter Color
81
88
 
82
89
  --button-disabled-color: var(--text-placeholder); // @presenter Color
83
90
  --button-disabled-background-color: var(--bg-raised); // @presenter Color
@@ -88,7 +95,9 @@ exports.button = (0, styled_components_1.css) `
88
95
  * @tokens Button outline
89
96
  */
90
97
  .button-outlined {
91
- --button-background-color: transparent; // @presenter Color
98
+ background-color: transparent;
99
+ --button-color: var(--button-outlined-color); // @presenter Color
100
+ --button-hover-color: var(--button-outlined-hover-color); // @presenter Color
92
101
  }
93
102
 
94
103
  /**
@@ -1,4 +1,4 @@
1
1
  /// <reference types="react" />
2
2
  import type { MobileMenuProps } from '../../components/Menu/types';
3
- export declare function MobileMenu({ className }: MobileMenuProps): JSX.Element | null;
3
+ export declare function MobileMenu({ className, hideUserProfile }: MobileMenuProps): JSX.Element | null;
4
4
  export declare const ControlButton: import("styled-components").StyledComponent<"li", any, {}, never>;
@@ -38,7 +38,7 @@ const icons_1 = require("../../icons");
38
38
  const Product_1 = require("../../components/Product/Product");
39
39
  const use_mobile_menu_levels_1 = require("../../components/Menu/hooks/use-mobile-menu-levels");
40
40
  const use_mobile_menu_items_1 = require("../../components/Menu/hooks/use-mobile-menu-items");
41
- function MobileMenu({ className }) {
41
+ function MobileMenu({ className, hideUserProfile }) {
42
42
  var _a, _b, _c;
43
43
  const location = (0, react_router_dom_1.useLocation)();
44
44
  const product = (0, hooks_1.useCurrentProduct)();
@@ -65,7 +65,7 @@ function MobileMenu({ className }) {
65
65
  react_1.default.createElement(Product_1.Product, { product: product }))) : null,
66
66
  react_1.default.createElement(MenuWrapper, null,
67
67
  react_1.default.createElement(index_1.Menu, { items: menuItems, isMobile: true }))),
68
- react_1.default.createElement(MobileUserProfile_1.MobileUserProfile, null)));
68
+ hideUserProfile ? null : react_1.default.createElement(MobileUserProfile_1.MobileUserProfile, null)));
69
69
  }
70
70
  exports.MobileMenu = MobileMenu;
71
71
  const MobileMenuWrapper = styled_components_1.default.div `
@@ -1,3 +1,4 @@
1
1
  export interface MobileMenuProps {
2
2
  className?: string;
3
+ hideUserProfile?: boolean;
3
4
  }
@@ -81,7 +81,7 @@ function NavbarPresentational(props) {
81
81
  const themeConfig = (0, useThemeConfig_1.useThemeConfig)();
82
82
  const menu = (_a = themeConfig.navbar) === null || _a === void 0 ? void 0 : _a.items;
83
83
  return (react_1.default.createElement(exports.NavbarContainer, { "data-component-name": "Navbar/Navbar", className: className },
84
- isOpen && react_1.default.createElement(MobileMenu_1.MobileMenu, null),
84
+ isOpen && react_1.default.createElement(MobileMenu_1.MobileMenu, { hideUserProfile: !!hideUserProfile }),
85
85
  react_1.default.createElement(exports.NavbarRow, null,
86
86
  react_1.default.createElement(BurgerButton_1.BurgerButton, { onClick: isOpen ? closeMobileMenu : openMobileMenu, isOpen: isOpen }),
87
87
  react_1.default.createElement(NavbarLogo_1.NavbarLogo, { logo: logo }),
@@ -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.6",
3
+ "version": "0.19.8",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -47,7 +47,7 @@ const getSize = (size: ButtonSize = 'default'): FlattenSimpleInterpolation => cs
47
47
  `;
48
48
 
49
49
  export const baseButtonStyles = css`
50
- display: flex;
50
+ display: inline-flex;
51
51
  align-items: center;
52
52
  justify-content: center;
53
53
  gap: var(--spacing-xs);
@@ -70,6 +70,7 @@ export const baseButtonStyles = css`
70
70
  &:hover {
71
71
  box-shadow: var(--button-hover-box-shadow);
72
72
  background-color: var(--button-hover-background-color);
73
+ color: var(--button-hover-color, var(--button-color));
73
74
  border: var(--button-border-width) var(--button-border-style) var(--button-hover-border-color);
74
75
  }
75
76
 
@@ -50,12 +50,16 @@ export const button = css`
50
50
  --button-color: var(--text-primary); // @presenter Color
51
51
  --button-background-color: var(--bg-overlay); // @presenter Color
52
52
  --button-border-color: var(--bg-overlay);
53
+ --button-outlined-color: var(--text-primary);
54
+
53
55
 
54
56
  --button-hover-background-color: var(--bg-overlay); // @presenter Color
55
57
  --button-hover-border-color: var(--border-primary); // @presenter Color
58
+ --button-outlined-hover-color: var(--text-primary); // @presenter Color
56
59
 
57
60
  --button-active-background-color: var(--bg-overlay); // @presenter Color
58
61
  --button-active-border-color: var(--button-color); // @presenter Color
62
+ --button-outlined-active-color: var(--bg-overlay); // @presenter Color
59
63
 
60
64
  --button-disabled-color: var(--text-placeholder); // @presenter Color
61
65
  --button-disabled-background-color: var(--bg-raised); // @presenter Color
@@ -70,12 +74,15 @@ export const button = css`
70
74
  --button-background-color: var(--color-primary); // @presenter Color
71
75
  --button-border-color: var(--color-primary); // @presenter Color
72
76
  --button-border: 1px solid var(--button-border-color);
77
+ --button-outlined-color: var(--color-primary);
73
78
 
74
79
  --button-hover-background-color: var(--color-primary-hover); // @presenter Color
75
80
  --button-hover-border-color: var(--color-primary-hover); // @presenter Color
81
+ --button-outlined-hover-color: var(--color-primary-hover);
76
82
 
77
83
  --button-active-background-color: var(--color-primary-active); // @presenter Color
78
84
  --button-active-border-color: var(--color-primary-active); // @presenter Color
85
+ --button-outlined-active-color: var(--color-primary-active); // @presenter Color
79
86
 
80
87
  --button-disabled-color: var(--text-placeholder); // @presenter Color
81
88
  --button-disabled-background-color: var(--bg-raised); // @presenter Color
@@ -86,7 +93,9 @@ export const button = css`
86
93
  * @tokens Button outline
87
94
  */
88
95
  .button-outlined {
89
- --button-background-color: transparent; // @presenter Color
96
+ background-color: transparent;
97
+ --button-color: var(--button-outlined-color); // @presenter Color
98
+ --button-hover-color: var(--button-outlined-hover-color); // @presenter Color
90
99
  }
91
100
 
92
101
  /**
@@ -12,7 +12,7 @@ import { Product } from '@theme/components/Product/Product';
12
12
  import { useMobileMenuLevels } from '@theme/components/Menu/hooks/use-mobile-menu-levels';
13
13
  import { useMobileMenuItems } from '@theme/components/Menu/hooks/use-mobile-menu-items';
14
14
 
15
- export function MobileMenu({ className }: MobileMenuProps): JSX.Element | null {
15
+ export function MobileMenu({ className, hideUserProfile }: MobileMenuProps): JSX.Element | null {
16
16
  const location = useLocation();
17
17
  const product = useCurrentProduct();
18
18
 
@@ -66,7 +66,7 @@ export function MobileMenu({ className }: MobileMenuProps): JSX.Element | null {
66
66
  <Menu items={menuItems} isMobile />
67
67
  </MenuWrapper>
68
68
  </ScrollableArea>
69
- <MobileUserProfile />
69
+ {hideUserProfile ? null : <MobileUserProfile />}
70
70
  </MobileMenuWrapper>
71
71
  );
72
72
  }
@@ -1,3 +1,4 @@
1
1
  export interface MobileMenuProps {
2
2
  className?: string;
3
+ hideUserProfile?: boolean;
3
4
  }
@@ -89,7 +89,7 @@ export function NavbarPresentational(props: NavbarPresentationalProps): JSX.Elem
89
89
 
90
90
  return (
91
91
  <NavbarContainer data-component-name="Navbar/Navbar" className={className}>
92
- {isOpen && <MobileMenu />}
92
+ {isOpen && <MobileMenu hideUserProfile={!!hideUserProfile} />}
93
93
  <NavbarRow>
94
94
  <BurgerButton onClick={isOpen ? closeMobileMenu : openMobileMenu} isOpen={isOpen} />
95
95
  <NavbarLogo logo={logo} />
@@ -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: {