@redocly/theme 0.12.4 → 0.13.1
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.
- package/lib/I18n/LanguagePicker.js +5 -1
- package/lib/components/Footer/FooterColumn.d.ts +4 -0
- package/lib/components/Footer/FooterColumn.js +53 -4
- package/lib/components/Markdown/MarkdownWrapper.js +1 -1
- package/lib/components/Navbar/NavbarItem.d.ts +3 -0
- package/lib/components/Navbar/NavbarItem.js +41 -2
- package/lib/globalStyle.js +7 -0
- package/lib/types/portal/src/shared/types/nav.d.ts +4 -0
- package/package.json +1 -22
- package/src/I18n/LanguagePicker.tsx +6 -1
- package/src/components/Footer/FooterColumn.tsx +35 -3
- package/src/components/Markdown/MarkdownWrapper.tsx +1 -1
- package/src/components/Navbar/Navbar.tsx +1 -2
- package/src/components/Navbar/NavbarItem.tsx +19 -1
- package/src/globalStyle.ts +7 -0
- package/src/types/portal/src/shared/types/nav.ts +4 -0
|
@@ -44,8 +44,12 @@ const LanguagePicker = (props) => {
|
|
|
44
44
|
if (locales.length < 2) {
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
47
|
+
const locale = locales.find((l) => l.code === currentLocale);
|
|
48
|
+
if (!locale) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
47
51
|
return (react_1.default.createElement(Dropdown, { "data-component-name": "I18n/LanguagePicker", ref: dropdownRef, isOpen: isOpen, onClick: () => setIsOpen(!isOpen), onBlur: () => setIsOpen(false) },
|
|
48
|
-
react_1.default.createElement(DropdownValue, { role: "link" },
|
|
52
|
+
react_1.default.createElement(DropdownValue, { role: "link" }, locale.name || locale.code),
|
|
49
53
|
react_1.default.createElement(DropdownMenu, null, locales.map((locale) => (react_1.default.createElement(MenuItem, { onClick: () => {
|
|
50
54
|
const newLangPathname = (0, utils_1.withPathPrefix)((0, utils_1.getPathnameForLocale)(location.pathname, defaultLocale, locale.code, locales));
|
|
51
55
|
const newUrlWithLanguage = `${newLangPathname}${location.search}${location.hash}`;
|
|
@@ -4,4 +4,8 @@ interface FooterColumnProps {
|
|
|
4
4
|
column: ResolvedNavItem;
|
|
5
5
|
}
|
|
6
6
|
export declare function FooterColumn({ column }: FooterColumnProps): JSX.Element;
|
|
7
|
+
export declare const FooterLinkIcon: import("styled-components").StyledComponent<"i", any, {
|
|
8
|
+
url?: string | undefined;
|
|
9
|
+
withIconPadding: boolean;
|
|
10
|
+
}, never>;
|
|
7
11
|
export {};
|
|
@@ -1,23 +1,49 @@
|
|
|
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.FooterColumn = void 0;
|
|
29
|
+
exports.FooterLinkIcon = exports.FooterColumn = void 0;
|
|
7
30
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const styled_components_1 =
|
|
31
|
+
const styled_components_1 = __importStar(require("styled-components"));
|
|
9
32
|
const Link_1 = require("../../mocks/Link");
|
|
10
33
|
const hooks_1 = require("../../mocks/hooks");
|
|
11
34
|
function FooterColumn({ column }) {
|
|
12
35
|
var _a;
|
|
13
36
|
const { translate } = (0, hooks_1.useTranslate)();
|
|
37
|
+
const hasIcon = column.items ? column.items.some((item) => !!item.icon) : false;
|
|
14
38
|
return (react_1.default.createElement(FooterColumnContainer, { "data-component-name": "Footer/FooterColumn" },
|
|
15
|
-
react_1.default.createElement(FooterColumnTitle,
|
|
39
|
+
react_1.default.createElement(FooterColumnTitle, { withIconPadding: hasIcon }, translate(column.labelTranslationKey, column.label)), (_a = column === null || column === void 0 ? void 0 : column.items) === null || _a === void 0 ? void 0 :
|
|
16
40
|
_a.map((columnItem, columnItemIndex) => {
|
|
17
41
|
if (columnItem.type === 'error') {
|
|
18
42
|
return null;
|
|
19
43
|
}
|
|
20
|
-
return columnItem.type === 'separator' ? (react_1.default.createElement(FooterSeparator, { key: columnItem.label + '_' + columnItemIndex }, translate(columnItem.labelTranslationKey, columnItem.label))) : (react_1.default.createElement(FooterLink, { key: columnItemIndex, to: columnItem.link, external: columnItem.external, target: columnItem.target, "data-cy": columnItem.label },
|
|
44
|
+
return columnItem.type === 'separator' ? (react_1.default.createElement(FooterSeparator, { key: columnItem.label + '_' + columnItemIndex }, translate(columnItem.labelTranslationKey, columnItem.label))) : (react_1.default.createElement(FooterLink, { key: columnItemIndex, to: columnItem.link, external: columnItem.external, target: columnItem.target, "data-cy": columnItem.label },
|
|
45
|
+
react_1.default.createElement(exports.FooterLinkIcon, { url: columnItem.icon, withIconPadding: hasIcon }),
|
|
46
|
+
translate(columnItem.labelTranslationKey, columnItem.label)));
|
|
21
47
|
})));
|
|
22
48
|
}
|
|
23
49
|
exports.FooterColumn = FooterColumn;
|
|
@@ -26,6 +52,10 @@ const FooterColumnTitle = styled_components_1.default.p `
|
|
|
26
52
|
font-weight: var(--footer-title-font-weight);
|
|
27
53
|
font-size: var(--footer-title-font-size);
|
|
28
54
|
margin-bottom: var(--footer-title-margin-vertical);
|
|
55
|
+
${({ withIconPadding }) => withIconPadding &&
|
|
56
|
+
(0, styled_components_1.css) `
|
|
57
|
+
padding-left: calc(var(--footer-item-icon-width) + var(--footer-item-icon-margin-right));
|
|
58
|
+
`}
|
|
29
59
|
font-family: var(--footer-font-family);
|
|
30
60
|
color: var(--footer-title-text-color);
|
|
31
61
|
`;
|
|
@@ -53,4 +83,23 @@ const FooterLink = (0, styled_components_1.default)(Link_1.Link) `
|
|
|
53
83
|
color: var(--footer-link-hover-color);
|
|
54
84
|
}
|
|
55
85
|
`;
|
|
86
|
+
exports.FooterLinkIcon = styled_components_1.default.i `
|
|
87
|
+
${({ withIconPadding, url }) => withIconPadding &&
|
|
88
|
+
!url &&
|
|
89
|
+
(0, styled_components_1.css) `
|
|
90
|
+
padding-left: calc(var(--footer-item-icon-width) + var(--footer-item-icon-margin-right));
|
|
91
|
+
`}
|
|
92
|
+
${({ url }) => url &&
|
|
93
|
+
(0, styled_components_1.css) `
|
|
94
|
+
background-image: url('${url}');
|
|
95
|
+
background-size: contain;
|
|
96
|
+
background-position: center;
|
|
97
|
+
background-repeat: no-repeat;
|
|
98
|
+
width: var(--footer-item-icon-width);
|
|
99
|
+
height: var(--footer-item-icon-height);
|
|
100
|
+
display: inline-block;
|
|
101
|
+
margin-right: var(--footer-item-icon-margin-right);
|
|
102
|
+
vertical-align: middle;
|
|
103
|
+
`}
|
|
104
|
+
`;
|
|
56
105
|
//# sourceMappingURL=FooterColumn.js.map
|
|
@@ -11,3 +11,6 @@ export declare const NavbarLink: import("styled-components").StyledComponent<typ
|
|
|
11
11
|
export declare const NavbarMenuItem: import("styled-components").StyledComponent<"li", any, {
|
|
12
12
|
active?: boolean | undefined;
|
|
13
13
|
}, never>;
|
|
14
|
+
export declare const NavbarIcon: import("styled-components").StyledComponent<"i", any, {
|
|
15
|
+
url?: string | undefined;
|
|
16
|
+
}, never>;
|
|
@@ -1,11 +1,34 @@
|
|
|
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.NavbarMenuItem = exports.NavbarLink = exports.NavbarMenuItemWithDropdownWrapper = exports.NavbarItem = void 0;
|
|
29
|
+
exports.NavbarIcon = exports.NavbarMenuItem = exports.NavbarLink = exports.NavbarMenuItemWithDropdownWrapper = exports.NavbarItem = void 0;
|
|
7
30
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const styled_components_1 =
|
|
31
|
+
const styled_components_1 = __importStar(require("styled-components"));
|
|
9
32
|
const react_router_dom_1 = require("react-router-dom");
|
|
10
33
|
const Link_1 = require("../../mocks/Link");
|
|
11
34
|
const utils_1 = require("../../mocks/utils");
|
|
@@ -22,12 +45,14 @@ function NavbarItem({ navItem, className }) {
|
|
|
22
45
|
(0, utils_2.withPathPrefix)((0, utils_1.getPathnameForLocale)(item.link, defaultLocale, currentLocale, locales));
|
|
23
46
|
return (react_1.default.createElement(exports.NavbarMenuItem, { active: isActive, "data-component-name": "Navbar/NavbarItem", className: className },
|
|
24
47
|
react_1.default.createElement(exports.NavbarLink, { to: item.link, external: item.external, target: item.target, active: isActive },
|
|
48
|
+
item.icon ? react_1.default.createElement(exports.NavbarIcon, { url: item.icon }) : null,
|
|
25
49
|
react_1.default.createElement(NavbarLabel, null, translate(item.labelTranslationKey, item.label)))));
|
|
26
50
|
}
|
|
27
51
|
if (navItem.items) {
|
|
28
52
|
const item = navItem;
|
|
29
53
|
return (react_1.default.createElement(exports.NavbarMenuItemWithDropdownWrapper, null,
|
|
30
54
|
react_1.default.createElement(exports.NavbarMenuItem, { active: false, "data-component-name": "Navbar/NavbarItem", className: className },
|
|
55
|
+
react_1.default.createElement(exports.NavbarIcon, { url: item.icon }),
|
|
31
56
|
react_1.default.createElement(NavbarLabel, null, translate(item.labelTranslationKey, item.label))),
|
|
32
57
|
react_1.default.createElement(NavbarDropdown_1.NavbarDropdown, { items: item.items })));
|
|
33
58
|
}
|
|
@@ -74,4 +99,18 @@ const NavbarLabel = styled_components_1.default.span `
|
|
|
74
99
|
cursor: pointer;
|
|
75
100
|
vertical-align: middle;
|
|
76
101
|
`;
|
|
102
|
+
exports.NavbarIcon = styled_components_1.default.i `
|
|
103
|
+
${({ url }) => url &&
|
|
104
|
+
(0, styled_components_1.css) `
|
|
105
|
+
background-image: url('${url}');
|
|
106
|
+
width: var(--navbar-item-icon-width);
|
|
107
|
+
height: var(--navbar-item-icon-height);
|
|
108
|
+
display: inline-block;
|
|
109
|
+
background-size: contain;
|
|
110
|
+
margin-right: var(--navbar-item-icon-margin-right);
|
|
111
|
+
vertical-align: middle;
|
|
112
|
+
background-position: center;
|
|
113
|
+
background-repeat: no-repeat;
|
|
114
|
+
`}
|
|
115
|
+
`;
|
|
77
116
|
//# sourceMappingURL=NavbarItem.js.map
|
package/lib/globalStyle.js
CHANGED
|
@@ -1530,6 +1530,10 @@ const footer = (0, styled_components_1.css) `
|
|
|
1530
1530
|
--footer-item-padding-vertical: 0.5em; // @presenter Spacingv
|
|
1531
1531
|
--footer-item-padding-horizontal: 0;
|
|
1532
1532
|
|
|
1533
|
+
--footer-item-icon-width: 24px; // @presenter Spacing
|
|
1534
|
+
--footer-item-icon-height: 24px; // @presenter Spacing
|
|
1535
|
+
--footer-item-icon-margin-right: 12px; // @presenter Spacing
|
|
1536
|
+
|
|
1533
1537
|
--footer-column-width: 20%; // @presenter Spacing
|
|
1534
1538
|
--footer-column-margin-vertical: 20px; // @presenter Spacing
|
|
1535
1539
|
--footer-column-margin-horizontal: 0; // @presenter Spacing
|
|
@@ -1577,6 +1581,9 @@ const navbar = (0, styled_components_1.css) `
|
|
|
1577
1581
|
--navbar-item-active-text-color: var(--navbar-text-color); // @presenter Color
|
|
1578
1582
|
--navbar-item-active-text-decoration: none;
|
|
1579
1583
|
--navbar-item-separator-line-color: var(--border-color); // @presenter Color
|
|
1584
|
+
--navbar-item-icon-width: 1.5em; // @presenter Spacing
|
|
1585
|
+
--navbar-item-icon-height: 1.5em; // @presenter Spacing
|
|
1586
|
+
--navbar-item-icon-margin-right: 0.5em; // @presenter Spacing
|
|
1580
1587
|
|
|
1581
1588
|
/**
|
|
1582
1589
|
* @tokens Navbar dropdown
|
|
@@ -17,6 +17,7 @@ export type ResolvedNavLinkItem = {
|
|
|
17
17
|
separatorLine?: boolean;
|
|
18
18
|
routeSlug?: string;
|
|
19
19
|
active?: boolean;
|
|
20
|
+
icon?: string;
|
|
20
21
|
[REDOCLY_TEAMS_RBAC]?: Rbac;
|
|
21
22
|
};
|
|
22
23
|
export type ResolvedNavGroupItem = {
|
|
@@ -38,6 +39,7 @@ export type ResolvedNavGroupItem = {
|
|
|
38
39
|
separatorLine?: boolean;
|
|
39
40
|
routeSlug?: string;
|
|
40
41
|
active?: boolean;
|
|
42
|
+
icon?: string;
|
|
41
43
|
[REDOCLY_TEAMS_RBAC]?: Rbac;
|
|
42
44
|
};
|
|
43
45
|
export type ResolvedNavItem = ResolvedNavLinkItem | ResolvedNavGroupItem | {
|
|
@@ -53,6 +55,7 @@ export type ResolvedNavItem = ResolvedNavLinkItem | ResolvedNavGroupItem | {
|
|
|
53
55
|
link?: undefined;
|
|
54
56
|
items?: ResolvedNavItem[];
|
|
55
57
|
sidebar?: ResolvedNavItem[];
|
|
58
|
+
icon?: string;
|
|
56
59
|
[REDOCLY_TEAMS_RBAC]?: Rbac;
|
|
57
60
|
} | {
|
|
58
61
|
type: 'error';
|
|
@@ -66,6 +69,7 @@ export type ResolvedNavItem = ResolvedNavLinkItem | ResolvedNavGroupItem | {
|
|
|
66
69
|
link?: undefined;
|
|
67
70
|
items?: ResolvedNavItem[];
|
|
68
71
|
sidebar?: ResolvedNavItem[];
|
|
72
|
+
icon?: string;
|
|
69
73
|
[REDOCLY_TEAMS_RBAC]?: Rbac;
|
|
70
74
|
};
|
|
71
75
|
export type ResolvedNavItemWithLink = (ResolvedNavLinkItem | ResolvedNavGroupItem) & {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.1",
|
|
4
4
|
"description": "Shared UI components library",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "team@redocly.com",
|
|
@@ -87,27 +87,6 @@
|
|
|
87
87
|
"hotkeys-js": "^3.10.1",
|
|
88
88
|
"timeago.js": "^4.0.2"
|
|
89
89
|
},
|
|
90
|
-
"nx": {
|
|
91
|
-
"namedInputs": {
|
|
92
|
-
"prod": [
|
|
93
|
-
"!{projectRoot}/**/__tests__/**",
|
|
94
|
-
"!{projectRoot}/**/*.stories.{ts,tsx}"
|
|
95
|
-
]
|
|
96
|
-
},
|
|
97
|
-
"targets": {
|
|
98
|
-
"build": {
|
|
99
|
-
"outputs": [
|
|
100
|
-
"{projectRoot}/lib"
|
|
101
|
-
]
|
|
102
|
-
},
|
|
103
|
-
"test": {
|
|
104
|
-
"outputs": [
|
|
105
|
-
"{projectRoot}/coverage",
|
|
106
|
-
"{projectRoot}/report.json"
|
|
107
|
-
]
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
90
|
"scripts": {
|
|
112
91
|
"start": "npm-run-all --parallel storybook storybook:tokens:watch",
|
|
113
92
|
"watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
|
|
@@ -23,6 +23,11 @@ export const LanguagePicker = (props: { onChangeLanguage: (newLang: string) => v
|
|
|
23
23
|
return null;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
const locale = locales.find((l) => l.code === currentLocale);
|
|
27
|
+
if (!locale) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
26
31
|
return (
|
|
27
32
|
<Dropdown
|
|
28
33
|
data-component-name="I18n/LanguagePicker"
|
|
@@ -31,7 +36,7 @@ export const LanguagePicker = (props: { onChangeLanguage: (newLang: string) => v
|
|
|
31
36
|
onClick={() => setIsOpen(!isOpen)}
|
|
32
37
|
onBlur={() => setIsOpen(false)}
|
|
33
38
|
>
|
|
34
|
-
<DropdownValue role="link">{
|
|
39
|
+
<DropdownValue role="link">{locale.name || locale.code}</DropdownValue>
|
|
35
40
|
<DropdownMenu>
|
|
36
41
|
{locales.map((locale) => (
|
|
37
42
|
<MenuItem
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import styled from 'styled-components';
|
|
2
|
+
import styled, { css } from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import { Link } from '@portal/Link';
|
|
5
5
|
import type { ResolvedNavItem } from '@theme/types/portal';
|
|
@@ -11,9 +11,13 @@ interface FooterColumnProps {
|
|
|
11
11
|
|
|
12
12
|
export function FooterColumn({ column }: FooterColumnProps): JSX.Element {
|
|
13
13
|
const { translate } = useTranslate();
|
|
14
|
+
const hasIcon = column.items ? column.items.some((item) => !!item.icon) : false;
|
|
15
|
+
|
|
14
16
|
return (
|
|
15
17
|
<FooterColumnContainer data-component-name="Footer/FooterColumn">
|
|
16
|
-
<FooterColumnTitle
|
|
18
|
+
<FooterColumnTitle withIconPadding={hasIcon}>
|
|
19
|
+
{translate(column.labelTranslationKey, column.label)}
|
|
20
|
+
</FooterColumnTitle>
|
|
17
21
|
{column?.items?.map((columnItem, columnItemIndex) => {
|
|
18
22
|
if (columnItem.type === 'error') {
|
|
19
23
|
return null;
|
|
@@ -31,6 +35,7 @@ export function FooterColumn({ column }: FooterColumnProps): JSX.Element {
|
|
|
31
35
|
target={columnItem.target}
|
|
32
36
|
data-cy={columnItem.label}
|
|
33
37
|
>
|
|
38
|
+
<FooterLinkIcon url={columnItem.icon} withIconPadding={hasIcon} />
|
|
34
39
|
{translate(columnItem.labelTranslationKey, columnItem.label)}
|
|
35
40
|
</FooterLink>
|
|
36
41
|
);
|
|
@@ -39,11 +44,16 @@ export function FooterColumn({ column }: FooterColumnProps): JSX.Element {
|
|
|
39
44
|
);
|
|
40
45
|
}
|
|
41
46
|
|
|
42
|
-
const FooterColumnTitle = styled.p
|
|
47
|
+
const FooterColumnTitle = styled.p<{ withIconPadding: boolean }>`
|
|
43
48
|
display: inline-block;
|
|
44
49
|
font-weight: var(--footer-title-font-weight);
|
|
45
50
|
font-size: var(--footer-title-font-size);
|
|
46
51
|
margin-bottom: var(--footer-title-margin-vertical);
|
|
52
|
+
${({ withIconPadding }) =>
|
|
53
|
+
withIconPadding &&
|
|
54
|
+
css`
|
|
55
|
+
padding-left: calc(var(--footer-item-icon-width) + var(--footer-item-icon-margin-right));
|
|
56
|
+
`}
|
|
47
57
|
font-family: var(--footer-font-family);
|
|
48
58
|
color: var(--footer-title-text-color);
|
|
49
59
|
`;
|
|
@@ -74,3 +84,25 @@ const FooterLink = styled(Link)`
|
|
|
74
84
|
color: var(--footer-link-hover-color);
|
|
75
85
|
}
|
|
76
86
|
`;
|
|
87
|
+
|
|
88
|
+
export const FooterLinkIcon = styled.i<{ url?: string; withIconPadding: boolean }>`
|
|
89
|
+
${({ withIconPadding, url }) =>
|
|
90
|
+
withIconPadding &&
|
|
91
|
+
!url &&
|
|
92
|
+
css`
|
|
93
|
+
padding-left: calc(var(--footer-item-icon-width) + var(--footer-item-icon-margin-right));
|
|
94
|
+
`}
|
|
95
|
+
${({ url }) =>
|
|
96
|
+
url &&
|
|
97
|
+
css`
|
|
98
|
+
background-image: url('${url}');
|
|
99
|
+
background-size: contain;
|
|
100
|
+
background-position: center;
|
|
101
|
+
background-repeat: no-repeat;
|
|
102
|
+
width: var(--footer-item-icon-width);
|
|
103
|
+
height: var(--footer-item-icon-height);
|
|
104
|
+
display: inline-block;
|
|
105
|
+
margin-right: var(--footer-item-icon-margin-right);
|
|
106
|
+
vertical-align: middle;
|
|
107
|
+
`}
|
|
108
|
+
`;
|
|
@@ -14,8 +14,7 @@ import { Search } from '@theme/components/Search/Search';
|
|
|
14
14
|
import { AuthUserProfile } from '@theme/components/Profile/AuthUserProfile';
|
|
15
15
|
import type { LogoConfig, ResolvedConfigLinks } from '@theme/types/portal';
|
|
16
16
|
import { useI18n } from '@portal/hooks';
|
|
17
|
-
|
|
18
|
-
import { LanguagePicker } from '../../I18n/LanguagePicker';
|
|
17
|
+
import { LanguagePicker } from '@theme/I18n/LanguagePicker';
|
|
19
18
|
|
|
20
19
|
const EmptyNavbarHack = createGlobalStyle`
|
|
21
20
|
#redocly_root {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import styled from 'styled-components';
|
|
2
|
+
import styled, { css } from 'styled-components';
|
|
3
3
|
import { useLocation } from 'react-router-dom';
|
|
4
4
|
|
|
5
5
|
import { Link } from '@portal/Link';
|
|
@@ -36,6 +36,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
|
|
|
36
36
|
className={className}
|
|
37
37
|
>
|
|
38
38
|
<NavbarLink to={item.link} external={item.external} target={item.target} active={isActive}>
|
|
39
|
+
{item.icon ? <NavbarIcon url={item.icon} /> : null}
|
|
39
40
|
<NavbarLabel>{translate(item.labelTranslationKey, item.label)}</NavbarLabel>
|
|
40
41
|
</NavbarLink>
|
|
41
42
|
</NavbarMenuItem>
|
|
@@ -51,6 +52,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
|
|
|
51
52
|
data-component-name="Navbar/NavbarItem"
|
|
52
53
|
className={className}
|
|
53
54
|
>
|
|
55
|
+
<NavbarIcon url={item.icon} />
|
|
54
56
|
<NavbarLabel>{translate(item.labelTranslationKey, item.label)}</NavbarLabel>
|
|
55
57
|
</NavbarMenuItem>
|
|
56
58
|
<NavbarDropdown items={item.items as ResolvedNavLinkItem[]} />
|
|
@@ -106,3 +108,19 @@ const NavbarLabel = styled.span`
|
|
|
106
108
|
cursor: pointer;
|
|
107
109
|
vertical-align: middle;
|
|
108
110
|
`;
|
|
111
|
+
|
|
112
|
+
export const NavbarIcon = styled.i<{ url?: string }>`
|
|
113
|
+
${({ url }) =>
|
|
114
|
+
url &&
|
|
115
|
+
css`
|
|
116
|
+
background-image: url('${url}');
|
|
117
|
+
width: var(--navbar-item-icon-width);
|
|
118
|
+
height: var(--navbar-item-icon-height);
|
|
119
|
+
display: inline-block;
|
|
120
|
+
background-size: contain;
|
|
121
|
+
margin-right: var(--navbar-item-icon-margin-right);
|
|
122
|
+
vertical-align: middle;
|
|
123
|
+
background-position: center;
|
|
124
|
+
background-repeat: no-repeat;
|
|
125
|
+
`}
|
|
126
|
+
`;
|
package/src/globalStyle.ts
CHANGED
|
@@ -1544,6 +1544,10 @@ const footer = css`
|
|
|
1544
1544
|
--footer-item-padding-vertical: 0.5em; // @presenter Spacingv
|
|
1545
1545
|
--footer-item-padding-horizontal: 0;
|
|
1546
1546
|
|
|
1547
|
+
--footer-item-icon-width: 24px; // @presenter Spacing
|
|
1548
|
+
--footer-item-icon-height: 24px; // @presenter Spacing
|
|
1549
|
+
--footer-item-icon-margin-right: 12px; // @presenter Spacing
|
|
1550
|
+
|
|
1547
1551
|
--footer-column-width: 20%; // @presenter Spacing
|
|
1548
1552
|
--footer-column-margin-vertical: 20px; // @presenter Spacing
|
|
1549
1553
|
--footer-column-margin-horizontal: 0; // @presenter Spacing
|
|
@@ -1593,6 +1597,9 @@ const navbar = css`
|
|
|
1593
1597
|
--navbar-item-active-text-color: var(--navbar-text-color); // @presenter Color
|
|
1594
1598
|
--navbar-item-active-text-decoration: none;
|
|
1595
1599
|
--navbar-item-separator-line-color: var(--border-color); // @presenter Color
|
|
1600
|
+
--navbar-item-icon-width: 1.5em; // @presenter Spacing
|
|
1601
|
+
--navbar-item-icon-height: 1.5em; // @presenter Spacing
|
|
1602
|
+
--navbar-item-icon-margin-right: 0.5em; // @presenter Spacing
|
|
1596
1603
|
|
|
1597
1604
|
/**
|
|
1598
1605
|
* @tokens Navbar dropdown
|
|
@@ -20,6 +20,7 @@ export type ResolvedNavLinkItem = {
|
|
|
20
20
|
separatorLine?: boolean;
|
|
21
21
|
routeSlug?: string;
|
|
22
22
|
active?: boolean;
|
|
23
|
+
icon?: string;
|
|
23
24
|
[REDOCLY_TEAMS_RBAC]?: Rbac;
|
|
24
25
|
};
|
|
25
26
|
|
|
@@ -44,6 +45,7 @@ export type ResolvedNavGroupItem = {
|
|
|
44
45
|
separatorLine?: boolean;
|
|
45
46
|
routeSlug?: string;
|
|
46
47
|
active?: boolean;
|
|
48
|
+
icon?: string;
|
|
47
49
|
[REDOCLY_TEAMS_RBAC]?: Rbac;
|
|
48
50
|
};
|
|
49
51
|
|
|
@@ -65,6 +67,7 @@ export type ResolvedNavItem =
|
|
|
65
67
|
link?: undefined;
|
|
66
68
|
items?: ResolvedNavItem[]; // for typescript
|
|
67
69
|
sidebar?: ResolvedNavItem[]; // for typescript
|
|
70
|
+
icon?: string;
|
|
68
71
|
[REDOCLY_TEAMS_RBAC]?: Rbac;
|
|
69
72
|
}
|
|
70
73
|
| {
|
|
@@ -81,6 +84,7 @@ export type ResolvedNavItem =
|
|
|
81
84
|
link?: undefined;
|
|
82
85
|
items?: ResolvedNavItem[]; // for typescript
|
|
83
86
|
sidebar?: ResolvedNavItem[]; // for typescript
|
|
87
|
+
icon?: string; // for typescript
|
|
84
88
|
[REDOCLY_TEAMS_RBAC]?: Rbac;
|
|
85
89
|
};
|
|
86
90
|
|