Skip to content
This repository was archived by the owner on Aug 18, 2023. It is now read-only.

Commit f84a200

Browse files
committed
add custom overrides
1 parent 3d1253b commit f84a200

File tree

8 files changed

+498
-18
lines changed

8 files changed

+498
-18
lines changed

_override/App.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as React from 'react';
2+
import type { Location } from 'history';
3+
4+
export function App({ children, location }: React.PropsWithChildren<{ location: Location }>) {
5+
return (
6+
<>
7+
<header style={{background: 'yellow', textAlign: 'center', padding: '20px 0', fontSize: '24px'}}>
8+
Header
9+
</header>
10+
{children}
11+
</>
12+
);
13+
}

_override/Footer.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import * as React from 'react';
2+
import styled from 'styled-components';
3+
4+
import { Flex, Link } from '@redocly/developer-portal/ui';
5+
6+
7+
export default function Footer(props) {
8+
const { columns, copyrightText } = props.footer;
9+
console.log(columns)
10+
return (
11+
<FooterWrapper>
12+
<Flex py="60px" px="60px">
13+
<FooterItems>
14+
{
15+
columns.map((col, index) => {
16+
return <li key={index}>
17+
{col.group}
18+
<FooterItems>
19+
{
20+
col.items.map((item, index) => {
21+
return <li key={index}>
22+
<Link to={item.link}>{item.label}</Link>
23+
</li>
24+
})
25+
}
26+
</FooterItems>
27+
</li>
28+
})
29+
}
30+
</FooterItems>
31+
</Flex>
32+
</FooterWrapper>
33+
)
34+
}
35+
36+
const FooterWrapper = styled.div`
37+
background: rgba(34,122,136,0.9);
38+
`;
39+
40+
const FooterItems = styled.ul`
41+
margin: 0;
42+
padding: 0;
43+
display: flex;
44+
align-items: center;
45+
color: #ffffff;
46+
justify-content: start;
47+
& li {
48+
list-style: none;
49+
margin-right: 20px;
50+
& a {
51+
color: #ffffff;
52+
}
53+
}
54+
`;

_override/MenuItem.tsx

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import * as React from 'react';
2+
import styled from 'styled-components';
3+
import { lighten } from 'polished';
4+
5+
import { MenuItemProps, Link, Arrow, OperationBadge } from '@redocly/developer-portal/ui';
6+
import { theme } from '../theme';
7+
8+
export default function MenuItem(props: MenuItemProps) {
9+
const {
10+
item: { active, expanded, items, link, label, type, httpVerb, external, target },
11+
depth,
12+
isExpanded,
13+
isAlwaysExpanded,
14+
} = props;
15+
16+
const hasChildren = items && items.length > 0;
17+
const ItemTitleComponent = depth === 0 ? HeaderItem : NestedItem;
18+
const arrowDirection = isExpanded ? 'down' : 'right';
19+
20+
const element =
21+
type === 'separator' ? (
22+
<Separator depth={depth}>{label}</Separator>
23+
) : (
24+
<ItemTitleComponent
25+
expanded={!!expanded && hasChildren}
26+
active={active}
27+
depth={depth}
28+
onClick={props.onClick}
29+
isAlwaysExpanded={!!isAlwaysExpanded}
30+
data-cy={`sidebar-item-${label}`}
31+
>
32+
{hasChildren && (
33+
<ArrowWrapper>
34+
{(props.item.menuStyle === 'drilldown' || !isAlwaysExpanded) && (
35+
<Arrow
36+
width="10px"
37+
height="10px"
38+
color={theme.colors.text.primary}
39+
direction={arrowDirection}
40+
data-cy="arrow"
41+
/>
42+
)}
43+
</ArrowWrapper>
44+
)}
45+
{httpVerb && (
46+
<div>
47+
<OperationBadge type={httpVerb}>{httpVerb}</OperationBadge>
48+
</div>
49+
)}
50+
<MenuLabel>{label}</MenuLabel>
51+
52+
</ItemTitleComponent>
53+
);
54+
55+
return link ? (
56+
<Link to={link} target={target || undefined}>
57+
{element}
58+
</Link>
59+
) : (
60+
element
61+
);
62+
}
63+
64+
const MenuItemTitle = styled.div<{
65+
expanded: boolean;
66+
active: boolean;
67+
isAlwaysExpanded: boolean;
68+
}>`
69+
position: relative;
70+
display: flex;
71+
justify-content: space-between;
72+
font-family: ${({ theme }) => theme.typography.headings.fontFamily};
73+
border-left: ${({active}) => active ? '4px solid #DC1928' : '4px solid transparent'};
74+
color: ${props => (props.active ? props.theme.sidebar.activeTextColor : 'inherit')};
75+
background-color: ${props => (props.active ? props.theme.sidebar.activeBgColor : 'inherit')};
76+
cursor: ${({ isAlwaysExpanded }) => (isAlwaysExpanded ? 'default' : 'pointer')};
77+
opacity: 1;
78+
font-size: 0.929em;
79+
padding: 12.5px 20px;
80+
transition: background-color 0.3s, color 0.3s;
81+
:hover {
82+
color: ${({ isAlwaysExpanded, theme }) =>
83+
isAlwaysExpanded ? 'inherit' : theme.sidebar.activeTextColor};
84+
background-color: ${({ isAlwaysExpanded, theme }) =>
85+
isAlwaysExpanded ? 'inherit' : lighten(0.04, theme.sidebar.activeBgColor)};
86+
}
87+
:empty {
88+
padding: 0;
89+
}
90+
`;
91+
92+
const NestedItem = styled(MenuItemTitle)<{ depth: number }>`
93+
color: inherit;
94+
padding-left: ${({ depth }) => `${(depth + 1) * 20}px`};
95+
:hover {
96+
color: inherit;
97+
}
98+
`;
99+
100+
const HeaderItem = styled(MenuItemTitle)<{ depth: number }>`
101+
position: relative;
102+
`;
103+
104+
const Separator = styled.span<{ depth?: number }>`
105+
display: block;
106+
padding: 12.5px 20px;
107+
padding-left: ${({ depth = 0 }) => `${(depth + 1) * 20}px`};
108+
padding-bottom: 2px;
109+
position: relative;
110+
cursor: default;
111+
font-family: ${({ theme }) => theme.typography.headings.fontFamily};
112+
font-size: 0.8em;
113+
text-transform: uppercase;
114+
opacity: 0.8;
115+
&:before {
116+
content: '';
117+
border-left: 3px solid ${({ theme }) => theme.colors.border.light};
118+
position: absolute;
119+
top: -50%;
120+
bottom: -50%;
121+
left: -12px;
122+
z-index: 1;
123+
}
124+
&:empty {
125+
padding: 0.1em 0;
126+
}
127+
&:empty:before {
128+
top: -1.5em;
129+
bottom: -1.5em;
130+
}
131+
`;
132+
133+
const MenuLabel = styled.span`
134+
width: 100%;
135+
`;
136+
137+
const ArrowWrapper = styled.div`
138+
margin-right: 5px;
139+
`;

_override/NavBar.tsx

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import * as React from 'react';
2+
import styled from 'styled-components';
3+
4+
import { Flex, Link, SearchBox } from '@redocly/developer-portal/ui';
5+
6+
export default function NavBar(props) {
7+
const { items, logo } = props;
8+
9+
const [isMobileMenuOpened, setMobileMenuOpened] = React.useState(false);
10+
const [pageIsScrolled, setPageIsScrolled] = React.useState(false);
11+
const toggleMobileMenu = () => setMobileMenuOpened(!isMobileMenuOpened);
12+
const hideMobileMenu = () => setMobileMenuOpened(false);
13+
14+
React.useEffect(() => {
15+
const handleScroll = () => setPageIsScrolled(window.scrollY > 10);
16+
17+
document.addEventListener('scroll', handleScroll);
18+
19+
return () => document.removeEventListener('scroll', handleScroll);
20+
}, []);
21+
22+
const navItems = items
23+
.filter(item => item.type !== 'search')
24+
.map((item, index) => {
25+
return (
26+
<NavItem key={index} onClick={hideMobileMenu}>
27+
<Link to={item.link}>{item.label}</Link>
28+
</NavItem>
29+
);
30+
});
31+
32+
return (
33+
<NavWrapper scrolled={pageIsScrolled ? 1 : 0}>
34+
<Flex
35+
maxWidth={{ xs: '100%', large: '1400px' }}
36+
alignItems='center'
37+
justifyContent='space-between'
38+
width='100%'
39+
mx='auto'>
40+
<img src={logo} alt='' height='50' />
41+
<NavItems>
42+
{navItems}
43+
<SearchBox pathPrefix={props.pathPrefix} />
44+
</NavItems>
45+
</Flex>
46+
<NavControls>
47+
<MobileMenuIcon onClick={toggleMobileMenu} />
48+
</NavControls>
49+
<MobileMenu isShown={isMobileMenuOpened}>
50+
<CloseIcon onClick={hideMobileMenu} />
51+
{navItems}
52+
<SearchBox />
53+
</MobileMenu>
54+
</NavWrapper>
55+
);
56+
}
57+
58+
const NavItem = styled.li`
59+
padding: 10px 0;
60+
`;
61+
62+
const NavWrapper = styled.nav<{ scrolled: boolean }>`
63+
padding: 15px 20px;
64+
display: flex;
65+
position: sticky;
66+
z-index: 50;
67+
transition: all 0.25s ease;
68+
background-color: #227a88;
69+
@media only screen and (min-width: ${({ theme }) => theme.breakpoints.large}) {
70+
padding: 10px 15px;
71+
box-shadow: ${({ scrolled }) => (scrolled ? '0px 1px 0px 0px rgba(225,225,225,0.2)' : 'none')};
72+
top: 0;
73+
left: 0;
74+
right: 0;
75+
}
76+
`;
77+
78+
const NavItems = styled.ul`
79+
display: none;
80+
margin: 0 0 0 40px;
81+
padding: 0;
82+
align-items: center;
83+
justify-content: start;
84+
& li {
85+
list-style: none;
86+
margin-right: 20px;
87+
& a {
88+
color: #ffffff;
89+
text-decoration: none;
90+
}
91+
}
92+
@media only screen and (min-width: ${({ theme }) => theme.breakpoints.medium}) {
93+
display: flex;
94+
}
95+
`;
96+
97+
export const MobileMenu = styled.ul<{ isShown: boolean }>`
98+
background: ${props => props.theme.colors.primary.main};
99+
list-style: none;
100+
padding: 50px 40px;
101+
margin: 0;
102+
position: absolute;
103+
border-top: 1px solid transparent;
104+
z-index: 100;
105+
color: ${props => props.theme.colors.primary.contrastText};
106+
top: 0;
107+
right: 0;
108+
left: 0;
109+
bottom: 0;
110+
font-size: 1.1875rem;
111+
box-shadow: 0px 10px 100px 0px rgba(35, 35, 35, 0.1);
112+
text-align: left;
113+
display: none;
114+
@media only screen and (max-width: ${({ theme }) => theme.breakpoints.medium}) {
115+
position: fixed;
116+
display: ${props => (props.isShown ? 'flex' : 'none')};
117+
flex-direction: column;
118+
overflow-y: auto;
119+
}
120+
& li {
121+
list-style: none;
122+
margin-right: 20px;
123+
& a {
124+
color: #ffffff;
125+
text-decoration: none;
126+
}
127+
}
128+
`;
129+
130+
export const NavControls = styled.div`
131+
padding: 10px;
132+
display: flex;
133+
align-items: center;
134+
flex: 1;
135+
justify-content: flex-end;
136+
@media only screen and (min-width: ${({ theme }) => theme.breakpoints.medium}) {
137+
display: none;
138+
}
139+
`;
140+
141+
export const MobileMenuIcon = styled.span`
142+
width: 1.25em;
143+
height: 1.25em;
144+
display: inline-block;
145+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' x='0' y='0' viewBox='0 0 396.7 396.7' xml:space='preserve'%3E%3Cpath fill='white' d='M17 87.8h362.7c9.4 0 17-7.6 17-17s-7.6-17-17-17H17c-9.3 0-17 7.7-17 17C0 80.2 7.7 87.8 17 87.8zM17 215.3h362.7c9.4 0 17-7.6 17-17s-7.6-17-17-17H17c-9.3 0-17 7.7-17 17S7.7 215.3 17 215.3zM17 342.8h362.7c9.4 0 17-7.6 17-17s-7.6-17-17-17H17c-9.3 0-17 7.7-17 17S7.7 342.8 17 342.8z'/%3E%3C/svg%3E");
146+
cursor: pointer;
147+
@media only screen and (min-width: ${({ theme }) => theme.breakpoints.medium}) {
148+
display: none;
149+
}
150+
`;
151+
152+
export const CloseIcon = styled.i`
153+
cursor: pointer;
154+
position: absolute;
155+
right: 20px;
156+
top: 25px;
157+
width: 15px;
158+
height: 15px;
159+
background-repeat: no-repeat;
160+
background-size: 15px 15px;
161+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' viewBox='0 0 15.6 15.6' enable-background='new 0 0 15.642 15.642'%3E%3Cpath fill-rule='evenodd' fill='white' d='M8.9 7.8l6.5-6.5c0.3-0.3 0.3-0.8 0-1.1 -0.3-0.3-0.8-0.3-1.1 0L7.8 6.8 1.3 0.2c-0.3-0.3-0.8-0.3-1.1 0 -0.3 0.3-0.3 0.8 0 1.1l6.5 6.5L0.2 14.4c-0.3 0.3-0.3 0.8 0 1.1 0.1 0.1 0.3 0.2 0.5 0.2s0.4-0.1 0.5-0.2l6.5-6.5 6.5 6.5c0.1 0.1 0.3 0.2 0.5 0.2 0.2 0 0.4-0.1 0.5-0.2 0.3-0.3 0.3-0.8 0-1.1L8.9 7.8z'/%3E%3C/svg%3E");
162+
`;

0 commit comments

Comments
 (0)