@openstack_dev/gatsby-theme-marketing-oif-core 1.0.12 → 1.0.13
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/package.json +1 -1
- package/src/components/Navbar/AuthUserSubNavBar/index.js +145 -0
- package/src/components/Navbar/LoginButton/index.js +29 -0
- package/src/components/Navbar/MobileMenu/index.js +34 -0
- package/src/components/Navbar/MobileMenu/index.module.scss +9 -0
- package/src/components/Navbar/NavBarDropDown/index.js +47 -0
- package/src/components/Navbar/NavBarHeader/index.js +28 -0
- package/src/components/Navbar/NavBarHeader/index.module.scss +55 -0
- package/src/components/Navbar/NavBarItem/index.js +92 -0
- package/src/components/Navbar/PublicUserSubNavBar/index.js +83 -0
- package/src/components/Navbar/SearchBar/index.js +108 -0
- package/src/components/Navbar/SearchBar/index.module.scss +43 -0
- package/src/components/Navbar/index.js +24 -465
- package/src/components/Navbar/index.module.scss +2 -105
- package/src/components/Navbar/template.js +157 -0
package/package.json
CHANGED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { navigate } from "gatsby";
|
|
4
|
+
import Box from "@mui/material/Box";
|
|
5
|
+
import Button from "@mui/material/Button";
|
|
6
|
+
import AddIcon from "@mui/icons-material/Add";
|
|
7
|
+
import RemoveIcon from "@mui/icons-material/Remove";
|
|
8
|
+
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
|
9
|
+
|
|
10
|
+
import styles from "../index.module.scss";
|
|
11
|
+
|
|
12
|
+
function AuthUserSubNavBar({
|
|
13
|
+
member,
|
|
14
|
+
isMobile,
|
|
15
|
+
navbarMenu,
|
|
16
|
+
setActiveMenu,
|
|
17
|
+
isSearchBarOpen,
|
|
18
|
+
handleNavigation,
|
|
19
|
+
}) {
|
|
20
|
+
const onClickLogout = () => {
|
|
21
|
+
navigate("/auth/logout", {
|
|
22
|
+
state: {
|
|
23
|
+
backUrl: window.location.pathname,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return isMobile ? (
|
|
29
|
+
<>
|
|
30
|
+
<Button
|
|
31
|
+
className={styles.mobileOption}
|
|
32
|
+
onClick={() => setActiveMenu("My Account")}
|
|
33
|
+
disableRipple
|
|
34
|
+
>
|
|
35
|
+
My Account
|
|
36
|
+
{navbarMenu === "My Account" ? (
|
|
37
|
+
<RemoveIcon aria-hidden="true" />
|
|
38
|
+
) : (
|
|
39
|
+
<AddIcon aria-hidden="true" />
|
|
40
|
+
)}
|
|
41
|
+
</Button>
|
|
42
|
+
{navbarMenu === "My Account" && (
|
|
43
|
+
<Box className={styles.mobileDropdownMenu}>
|
|
44
|
+
<Button
|
|
45
|
+
className={styles.mobileDropdownOption}
|
|
46
|
+
onClick={() => handleNavigation("/profile/")}
|
|
47
|
+
sx={{ display: "block" }}
|
|
48
|
+
disableRipple
|
|
49
|
+
>
|
|
50
|
+
Edit Profile
|
|
51
|
+
</Button>
|
|
52
|
+
<Button
|
|
53
|
+
className={styles.mobileDropdownOption}
|
|
54
|
+
onClick={() => handleNavigation(
|
|
55
|
+
`/community/members/profile/${
|
|
56
|
+
member.id
|
|
57
|
+
}/${`${member.first_name.toLowerCase()}-${member.last_name.toLowerCase()}`}`,
|
|
58
|
+
)}
|
|
59
|
+
sx={{ display: "block" }}
|
|
60
|
+
disableRipple
|
|
61
|
+
>
|
|
62
|
+
View Public Profile
|
|
63
|
+
</Button>
|
|
64
|
+
<div className={styles.divider} />
|
|
65
|
+
<Button
|
|
66
|
+
className={styles.mobileDropdownOption}
|
|
67
|
+
sx={{ display: "block" }}
|
|
68
|
+
onClick={onClickLogout}
|
|
69
|
+
disableRipple
|
|
70
|
+
>
|
|
71
|
+
Log out
|
|
72
|
+
</Button>
|
|
73
|
+
</Box>
|
|
74
|
+
)}
|
|
75
|
+
</>
|
|
76
|
+
) : (
|
|
77
|
+
<Box
|
|
78
|
+
maxWidth="15%"
|
|
79
|
+
sx={{
|
|
80
|
+
display: {
|
|
81
|
+
xs: "none",
|
|
82
|
+
md: isSearchBarOpen ? "none" : "flex",
|
|
83
|
+
},
|
|
84
|
+
justifyContent: "flex-end",
|
|
85
|
+
marginLeft: "auto",
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
<Box
|
|
89
|
+
className={`${styles.navbarOption}`}
|
|
90
|
+
sx={{ my: 2, display: "block" }}
|
|
91
|
+
>
|
|
92
|
+
My Account
|
|
93
|
+
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
94
|
+
<Box className={styles.dropDownMenu}>
|
|
95
|
+
<Button
|
|
96
|
+
className={styles.dropdownMenuOption}
|
|
97
|
+
onClick={() => handleNavigation("/profile/")}
|
|
98
|
+
sx={{ display: "block" }}
|
|
99
|
+
disableRipple
|
|
100
|
+
>
|
|
101
|
+
Edit Profile
|
|
102
|
+
</Button>
|
|
103
|
+
<Button
|
|
104
|
+
className={styles.dropdownMenuOption}
|
|
105
|
+
onClick={() => handleNavigation(
|
|
106
|
+
`/community/members/profile/${
|
|
107
|
+
member.id
|
|
108
|
+
}/${`${member.first_name.toLowerCase()}-${member.last_name.toLowerCase()}`}`,
|
|
109
|
+
)}
|
|
110
|
+
sx={{ display: "block" }}
|
|
111
|
+
disableRipple
|
|
112
|
+
>
|
|
113
|
+
View Public Profile
|
|
114
|
+
</Button>
|
|
115
|
+
<div className={styles.divider} />
|
|
116
|
+
<Button
|
|
117
|
+
className={styles.dropdownMenuOption}
|
|
118
|
+
sx={{ display: "block" }}
|
|
119
|
+
onClick={onClickLogout}
|
|
120
|
+
disableRipple
|
|
121
|
+
>
|
|
122
|
+
Log out
|
|
123
|
+
</Button>
|
|
124
|
+
</Box>
|
|
125
|
+
</Box>
|
|
126
|
+
</Box>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
AuthUserSubNavBar.propTypes = {
|
|
131
|
+
member: PropTypes.oneOfType([PropTypes.object, PropTypes.oneOf([null])]),
|
|
132
|
+
isMobile: PropTypes.bool.isRequired,
|
|
133
|
+
navbarMenu: PropTypes.string.isRequired,
|
|
134
|
+
setActiveMenu: PropTypes.func,
|
|
135
|
+
isSearchBarOpen: PropTypes.bool,
|
|
136
|
+
handleNavigation: PropTypes.func.isRequired,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
AuthUserSubNavBar.defaultProps = {
|
|
140
|
+
member: null,
|
|
141
|
+
isSearchBarOpen: false,
|
|
142
|
+
setActiveMenu: (option) => console.log(option),
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default AuthUserSubNavBar;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { doLogin } from "openstack-uicore-foundation/lib/security/methods";
|
|
4
|
+
import Button from "@mui/material/Button";
|
|
5
|
+
|
|
6
|
+
import styles from "../index.module.scss";
|
|
7
|
+
|
|
8
|
+
function LoginButton({ backUrl }) {
|
|
9
|
+
return (
|
|
10
|
+
<Button
|
|
11
|
+
className={`${styles.navbarOption} ${styles.login}`}
|
|
12
|
+
onClick={() => doLogin(backUrl)}
|
|
13
|
+
sx={{ my: 2, display: "block" }}
|
|
14
|
+
disableRipple
|
|
15
|
+
>
|
|
16
|
+
Log in
|
|
17
|
+
</Button>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
LoginButton.propTypes = {
|
|
22
|
+
backUrl: PropTypes.string,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
LoginButton.defaultProps = {
|
|
26
|
+
backUrl: "/",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default LoginButton;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import Box from "@mui/material/Box";
|
|
4
|
+
import IconButton from "@mui/material/IconButton";
|
|
5
|
+
import MenuIcon from "@mui/icons-material/Menu";
|
|
6
|
+
|
|
7
|
+
import styles from "./index.module.scss";
|
|
8
|
+
|
|
9
|
+
function MobileMenu({ handleMobileMenuToggle }) {
|
|
10
|
+
return (
|
|
11
|
+
<Box
|
|
12
|
+
className={styles.mobileMenuWrapper}
|
|
13
|
+
sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}
|
|
14
|
+
>
|
|
15
|
+
<IconButton
|
|
16
|
+
className={styles.toggleIcon}
|
|
17
|
+
size="large"
|
|
18
|
+
aria-label="account of current user"
|
|
19
|
+
aria-controls="menu-appbar"
|
|
20
|
+
aria-haspopup="true"
|
|
21
|
+
onClick={() => handleMobileMenuToggle()}
|
|
22
|
+
color="inherit"
|
|
23
|
+
>
|
|
24
|
+
<MenuIcon />
|
|
25
|
+
</IconButton>
|
|
26
|
+
</Box>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
MobileMenu.propTypes = {
|
|
31
|
+
handleMobileMenuToggle: PropTypes.func.isRequired,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default MobileMenu;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import Box from "@mui/material/Box";
|
|
4
|
+
import Button from "@mui/material/Button";
|
|
5
|
+
|
|
6
|
+
import styles from "../index.module.scss";
|
|
7
|
+
|
|
8
|
+
function NavBarDropDown({ isMobile, items, handleNavigation }) {
|
|
9
|
+
return (
|
|
10
|
+
<Box className={isMobile ? styles.mobileDropdownMenu : styles.dropDownMenu}>
|
|
11
|
+
{items.map((subItem) => (!subItem.title && !subItem.link ? (
|
|
12
|
+
<div className={styles.divider} key={subItem.title} />
|
|
13
|
+
) : (
|
|
14
|
+
<Button
|
|
15
|
+
className={
|
|
16
|
+
isMobile ? styles.mobileDropdownOption : styles.dropdownMenuOption
|
|
17
|
+
}
|
|
18
|
+
key={isMobile ? `${subItem.title}-mobile` : subItem.title}
|
|
19
|
+
onClick={(ev) => handleNavigation(ev, subItem.link)}
|
|
20
|
+
sx={{ display: "block" }}
|
|
21
|
+
disableRipple
|
|
22
|
+
>
|
|
23
|
+
{subItem.title}
|
|
24
|
+
</Button>
|
|
25
|
+
)))}
|
|
26
|
+
</Box>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
NavBarDropDown.propTypes = {
|
|
31
|
+
isMobile: PropTypes.bool,
|
|
32
|
+
items: PropTypes.arrayOf(
|
|
33
|
+
PropTypes.shape({
|
|
34
|
+
link: PropTypes.string,
|
|
35
|
+
title: PropTypes.string,
|
|
36
|
+
display: PropTypes.bool,
|
|
37
|
+
requiresAuth: PropTypes.bool,
|
|
38
|
+
}),
|
|
39
|
+
).isRequired,
|
|
40
|
+
handleNavigation: PropTypes.func.isRequired,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
NavBarDropDown.defaultProps = {
|
|
44
|
+
isMobile: false,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default NavBarDropDown;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import Box from "@mui/material/Box";
|
|
4
|
+
|
|
5
|
+
import styles from "./index.module.scss";
|
|
6
|
+
import SearchBar from "../SearchBar";
|
|
7
|
+
|
|
8
|
+
function NavBarHeader({ setIsSearchBarOpen }) {
|
|
9
|
+
return (
|
|
10
|
+
<Box className={styles.navbarHeader}>
|
|
11
|
+
<div className={styles.brandWrapper}>
|
|
12
|
+
<a
|
|
13
|
+
className={styles.navbarBrand}
|
|
14
|
+
href="/"
|
|
15
|
+
alt="Openstack logo"
|
|
16
|
+
aria-label="Go to homepage"
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
<SearchBar onSearchBarOpen={(value) => setIsSearchBarOpen(value)} />
|
|
20
|
+
</Box>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
NavBarHeader.propTypes = {
|
|
25
|
+
setIsSearchBarOpen: PropTypes.func.isRequired,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default NavBarHeader;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
.navbarHeader {
|
|
2
|
+
.brandWrapper {
|
|
3
|
+
margin: 10px 0;
|
|
4
|
+
padding-right: 20px;
|
|
5
|
+
float: left;
|
|
6
|
+
border-right: 1px solid #eee;
|
|
7
|
+
min-width: 135px;
|
|
8
|
+
a.navbarBrand {
|
|
9
|
+
background: url("../../../images/openstack-logo-full.svg") left no-repeat;
|
|
10
|
+
height: 35px;
|
|
11
|
+
width: 135px;
|
|
12
|
+
color: #777;
|
|
13
|
+
padding: 15px 15px;
|
|
14
|
+
font-size: 18px;
|
|
15
|
+
line-height: 20px;
|
|
16
|
+
display: block;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
.navbarToggle {
|
|
20
|
+
appearance: button;
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
position: relative;
|
|
23
|
+
float: right;
|
|
24
|
+
padding: 9px 10px;
|
|
25
|
+
margin-top: 8px;
|
|
26
|
+
margin-bottom: 8px;
|
|
27
|
+
background: transparent;
|
|
28
|
+
border: none;
|
|
29
|
+
.iconBar {
|
|
30
|
+
background-color: #5a5a5a;
|
|
31
|
+
height: 3px;
|
|
32
|
+
border-radius: 3px;
|
|
33
|
+
display: block;
|
|
34
|
+
width: 22px;
|
|
35
|
+
margin-top: 4px;
|
|
36
|
+
}
|
|
37
|
+
@media (min-width: 768px) {
|
|
38
|
+
display: none;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
@media (min-width: 768px) and (max-width: 1310px) {
|
|
42
|
+
.brandWrapper {
|
|
43
|
+
width: 75px;
|
|
44
|
+
min-width: 75px;
|
|
45
|
+
margin-top: 0;
|
|
46
|
+
a.navbarBrand {
|
|
47
|
+
background: url("../../../images/openstack-logo-vert.svg") left
|
|
48
|
+
no-repeat;
|
|
49
|
+
margin-left: 0px !important;
|
|
50
|
+
height: 54px;
|
|
51
|
+
width: 59px;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import Button from "@mui/material/Button";
|
|
4
|
+
import AddIcon from "@mui/icons-material/Add";
|
|
5
|
+
import RemoveIcon from "@mui/icons-material/Remove";
|
|
6
|
+
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
|
7
|
+
import NavBarDropDown from "../NavBarDropDown";
|
|
8
|
+
import Link from "../../Link";
|
|
9
|
+
|
|
10
|
+
import styles from "../index.module.scss";
|
|
11
|
+
|
|
12
|
+
function NavBarItem({
|
|
13
|
+
isMobile,
|
|
14
|
+
item,
|
|
15
|
+
navbarMenu,
|
|
16
|
+
setActiveMenu,
|
|
17
|
+
handleNavigation,
|
|
18
|
+
}) {
|
|
19
|
+
return isMobile ? (
|
|
20
|
+
<>
|
|
21
|
+
<Button
|
|
22
|
+
disableRipple
|
|
23
|
+
className={styles.mobileOption}
|
|
24
|
+
key={`${item.title}-mobile`}
|
|
25
|
+
onClick={() => setActiveMenu(item.title)}
|
|
26
|
+
>
|
|
27
|
+
{item.title}
|
|
28
|
+
{item.items?.length > 0
|
|
29
|
+
&& (item.title === navbarMenu ? (
|
|
30
|
+
<RemoveIcon aria-hidden="true" />
|
|
31
|
+
) : (
|
|
32
|
+
<AddIcon aria-hidden="true" />
|
|
33
|
+
))}
|
|
34
|
+
</Button>
|
|
35
|
+
{item.items?.length > 0 && item.title === navbarMenu && (
|
|
36
|
+
<NavBarDropDown
|
|
37
|
+
items={item.items}
|
|
38
|
+
handleNavigation={handleNavigation}
|
|
39
|
+
isMobile
|
|
40
|
+
/>
|
|
41
|
+
)}
|
|
42
|
+
</>
|
|
43
|
+
) : (
|
|
44
|
+
<Link
|
|
45
|
+
className={styles.navbarOption}
|
|
46
|
+
key={item.title}
|
|
47
|
+
sx={{ my: 2, display: "block" }}
|
|
48
|
+
href={item.link}
|
|
49
|
+
>
|
|
50
|
+
{item.items?.length > 0 ? (
|
|
51
|
+
<>
|
|
52
|
+
{item.title}
|
|
53
|
+
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
54
|
+
<NavBarDropDown
|
|
55
|
+
items={item.items}
|
|
56
|
+
handleNavigation={handleNavigation}
|
|
57
|
+
/>
|
|
58
|
+
</>
|
|
59
|
+
) : (
|
|
60
|
+
item.title
|
|
61
|
+
)}
|
|
62
|
+
</Link>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
NavBarItem.propTypes = {
|
|
67
|
+
isMobile: PropTypes.bool,
|
|
68
|
+
item: PropTypes.shape({
|
|
69
|
+
title: PropTypes.string,
|
|
70
|
+
link: PropTypes.string,
|
|
71
|
+
display: PropTypes.bool,
|
|
72
|
+
requiresAuth: PropTypes.bool,
|
|
73
|
+
items: PropTypes.arrayOf(
|
|
74
|
+
PropTypes.shape({
|
|
75
|
+
link: PropTypes.string,
|
|
76
|
+
title: PropTypes.string,
|
|
77
|
+
display: PropTypes.bool,
|
|
78
|
+
requiresAuth: PropTypes.bool,
|
|
79
|
+
}),
|
|
80
|
+
),
|
|
81
|
+
}),
|
|
82
|
+
navbarMenu: PropTypes.string.isRequired,
|
|
83
|
+
setActiveMenu: PropTypes.func,
|
|
84
|
+
handleNavigation: PropTypes.func.isRequired,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
NavBarItem.defaultProps = {
|
|
88
|
+
isMobile: false,
|
|
89
|
+
setActiveMenu: (option) => console.log(option),
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default NavBarItem;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import Box from "@mui/material/Box";
|
|
4
|
+
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
|
5
|
+
import LoginButton from "../LoginButton";
|
|
6
|
+
import NavBarDropDown from "../NavBarDropDown";
|
|
7
|
+
|
|
8
|
+
import styles from "../index.module.scss";
|
|
9
|
+
|
|
10
|
+
function PublicUserSubNavBar({ isSearchBarOpen, isDesktop, handleNavigation }) {
|
|
11
|
+
const publicNavbarMenu = [
|
|
12
|
+
{
|
|
13
|
+
link: "https://openinfra.dev/join",
|
|
14
|
+
title: "Sign up for Foundation Membership",
|
|
15
|
+
display: true,
|
|
16
|
+
requiresAuth: false,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
link: "https://openinfra.dev/join",
|
|
20
|
+
title: "Sponsor the Foundation",
|
|
21
|
+
display: true,
|
|
22
|
+
requiresAuth: false,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
link: "https://openinfra.dev",
|
|
26
|
+
title: "More about the Foundation",
|
|
27
|
+
display: true,
|
|
28
|
+
requiresAuth: false,
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const getBackURL = () => {
|
|
33
|
+
let backUrl = "/";
|
|
34
|
+
if (window && typeof window !== "undefined") {
|
|
35
|
+
backUrl = window.location.pathname;
|
|
36
|
+
}
|
|
37
|
+
return backUrl;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Box
|
|
42
|
+
maxWidth={isDesktop ? "15%" : "100px"}
|
|
43
|
+
sx={
|
|
44
|
+
isDesktop
|
|
45
|
+
? {
|
|
46
|
+
display: {
|
|
47
|
+
xs: "none",
|
|
48
|
+
md: isSearchBarOpen ? "none" : "flex",
|
|
49
|
+
},
|
|
50
|
+
justifyContent: "flex-end",
|
|
51
|
+
marginLeft: "auto",
|
|
52
|
+
}
|
|
53
|
+
: {}
|
|
54
|
+
}
|
|
55
|
+
>
|
|
56
|
+
<Box
|
|
57
|
+
className={`${styles.navbarOption} ${styles.join}`}
|
|
58
|
+
sx={{ my: 2, display: "block" }}
|
|
59
|
+
>
|
|
60
|
+
Join
|
|
61
|
+
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
62
|
+
<NavBarDropDown
|
|
63
|
+
items={publicNavbarMenu}
|
|
64
|
+
handleNavigation={handleNavigation}
|
|
65
|
+
/>
|
|
66
|
+
</Box>
|
|
67
|
+
<LoginButton backUrl={getBackURL()} />
|
|
68
|
+
</Box>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
PublicUserSubNavBar.propTypes = {
|
|
73
|
+
isSearchBarOpen: PropTypes.bool,
|
|
74
|
+
isDesktop: PropTypes.bool,
|
|
75
|
+
handleNavigation: PropTypes.func.isRequired,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
PublicUserSubNavBar.defaultProps = {
|
|
79
|
+
isSearchBarOpen: false,
|
|
80
|
+
isDesktop: false,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default PublicUserSubNavBar;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Script } from "gatsby";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import Box from "@mui/material/Box";
|
|
5
|
+
import SearchIcon from "@mui/icons-material/Search";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
SEARCH_WIDGET_BASE_URL,
|
|
9
|
+
getEnvVariable,
|
|
10
|
+
} from "../../../utils/envVariables";
|
|
11
|
+
|
|
12
|
+
import styles from "./index.module.scss";
|
|
13
|
+
|
|
14
|
+
function SearchBar({ isMobile, isMobileMenuOpen, onSearchBarOpen }) {
|
|
15
|
+
const [isSearchBarOpen, setIsSearchBarOpen] = React.useState(false);
|
|
16
|
+
|
|
17
|
+
const handleSearchBarOpenClose = (value) => {
|
|
18
|
+
onSearchBarOpen(value);
|
|
19
|
+
setIsSearchBarOpen(value);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const handleCloseSearchBar = (event) => {
|
|
23
|
+
if (event?.target.matches(".ossw-search-bar-close")) {
|
|
24
|
+
handleSearchBarOpenClose(false);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
React.useEffect(() => {
|
|
29
|
+
document.addEventListener("click", handleCloseSearchBar);
|
|
30
|
+
return () => {
|
|
31
|
+
document.removeEventListener("click", handleCloseSearchBar);
|
|
32
|
+
};
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
if (isSearchBarOpen) {
|
|
37
|
+
const inputElement = document.getElementById("search-bar-input");
|
|
38
|
+
if (inputElement) {
|
|
39
|
+
inputElement.focus();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}, [isSearchBarOpen]);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<>
|
|
46
|
+
<Script
|
|
47
|
+
src={`${getEnvVariable(SEARCH_WIDGET_BASE_URL)}/widget/embed.min.js`}
|
|
48
|
+
/>
|
|
49
|
+
{isMobile ? (
|
|
50
|
+
<Box
|
|
51
|
+
className={`${styles.openstackSearchBarMobile} openstack-search-bar ossw-mobile`}
|
|
52
|
+
sx={{
|
|
53
|
+
visibility: {
|
|
54
|
+
xs: isMobileMenuOpen ? "visible" : "hidden",
|
|
55
|
+
md: "hidden",
|
|
56
|
+
},
|
|
57
|
+
opacity: { xs: isMobileMenuOpen ? "1" : "0", md: "0" },
|
|
58
|
+
height: { xs: isMobileMenuOpen ? "auto" : 0, md: 0 },
|
|
59
|
+
color: "#8a959e",
|
|
60
|
+
}}
|
|
61
|
+
data-baseurl={getEnvVariable(SEARCH_WIDGET_BASE_URL)}
|
|
62
|
+
data-context="www-openstack"
|
|
63
|
+
/>
|
|
64
|
+
) : (
|
|
65
|
+
<Box
|
|
66
|
+
className={styles.searchWrapper}
|
|
67
|
+
sx={{ display: { xs: "none", md: "flex" } }}
|
|
68
|
+
>
|
|
69
|
+
<div
|
|
70
|
+
role="button"
|
|
71
|
+
tabIndex={0}
|
|
72
|
+
onKeyDown={(event) => {
|
|
73
|
+
if (event.key === "Enter" || event.key === " ") handleSearchBarOpenClose(true);
|
|
74
|
+
}}
|
|
75
|
+
onClick={() => handleSearchBarOpenClose(true)}
|
|
76
|
+
className={styles.searchComponent}
|
|
77
|
+
>
|
|
78
|
+
<SearchIcon className={styles.searchIcon} />
|
|
79
|
+
<span className={styles.headerSearchText}>Search</span>
|
|
80
|
+
</div>
|
|
81
|
+
<Box
|
|
82
|
+
className={`openstack-search-bar ${styles.openstackSearchBar}`}
|
|
83
|
+
style={{
|
|
84
|
+
visibility: isSearchBarOpen ? "visible" : "hidden",
|
|
85
|
+
opacity: isSearchBarOpen ? "1" : "0",
|
|
86
|
+
}}
|
|
87
|
+
data-baseurl={getEnvVariable(SEARCH_WIDGET_BASE_URL)}
|
|
88
|
+
data-context="www-openstack"
|
|
89
|
+
/>
|
|
90
|
+
</Box>
|
|
91
|
+
)}
|
|
92
|
+
</>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
SearchBar.propTypes = {
|
|
97
|
+
isMobile: PropTypes.bool,
|
|
98
|
+
isMobileMenuOpen: PropTypes.bool,
|
|
99
|
+
onSearchBarOpen: PropTypes.func,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
SearchBar.defaultProps = {
|
|
103
|
+
isMobile: false,
|
|
104
|
+
isMobileMenuOpen: false,
|
|
105
|
+
onSearchBarOpen: () => null,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export default SearchBar;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.searchWrapper {
|
|
2
|
+
padding: 20px 0px 15px 20px;
|
|
3
|
+
float: left;
|
|
4
|
+
text-transform: uppercase;
|
|
5
|
+
color: #8a959e;
|
|
6
|
+
font-size: 12px;
|
|
7
|
+
font-weight: 400;
|
|
8
|
+
line-height: 17.15px;
|
|
9
|
+
.searchComponent {
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
z-index: 5;
|
|
12
|
+
position: relative;
|
|
13
|
+
.searchIcon {
|
|
14
|
+
width: 12px;
|
|
15
|
+
height: 12px;
|
|
16
|
+
line-height: 12px;
|
|
17
|
+
margin-right: 5px;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
.openstackSearchBar {
|
|
21
|
+
width: 100%;
|
|
22
|
+
position: absolute;
|
|
23
|
+
top: 0;
|
|
24
|
+
z-index: 100;
|
|
25
|
+
height: 70px;
|
|
26
|
+
padding-top: 10px;
|
|
27
|
+
padding-right: 12%;
|
|
28
|
+
background-color: #fff;
|
|
29
|
+
opacity: 0;
|
|
30
|
+
transition: opacity 0.3s ease;
|
|
31
|
+
}
|
|
32
|
+
@media (max-width: 768px) {
|
|
33
|
+
display: none;
|
|
34
|
+
}
|
|
35
|
+
@media (max-width: 1160px) {
|
|
36
|
+
.headerSearchText {
|
|
37
|
+
display: none;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
@media (min-width: 768px) and (max-width: 1310px) {
|
|
41
|
+
padding: 25px 0px 15px 20px;
|
|
42
|
+
}
|
|
43
|
+
}
|