Skip to content

Commit e41dc6d

Browse files
committed
🚧 Progress Commit
1 parent fd5c600 commit e41dc6d

File tree

19 files changed

+497
-33
lines changed

19 files changed

+497
-33
lines changed

packages/common/src/components/Layout/Layout.tsx renamed to packages/app/src/app/components/Layout/Layout.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import React from 'react';
2-
import Navigation from '../Navigation';
3-
import { Footer } from '../Footer';
2+
import { Footer } from '@codesandbox/common/lib/components';
3+
import { PageHeader } from '../PageHeader';
44
import { Main, PageContent } from './elements';
55

6-
interface ILayoutProps {}
6+
interface ILayoutProps {
7+
title: string;
8+
}
79

810
// TODO:
911
// - Refactor Navigation
1012
// - Add code to determine Navigation Items / Page Title from Route Info
1113

12-
export const Layout: React.FC<ILayoutProps> = ({ children }) => (
14+
export const Layout: React.FC<ILayoutProps> = ({ title, children }) => (
1315
<Main>
14-
<Navigation />
16+
<PageHeader title={title} />
1517
<PageContent>{children}</PageContent>
1618
<Footer />
1719
</Main>
File renamed without changes.
File renamed without changes.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React from 'react';
2+
import { Helmet } from 'react-helmet';
3+
import { useOvermind } from 'app/overmind';
4+
import { Logo } from '@codesandbox/common/lib/components/Logo';
5+
import { UserMenu } from '../UserMenu';
6+
import {
7+
Container,
8+
Content,
9+
Left,
10+
Home,
11+
Separator,
12+
Right,
13+
Button,
14+
} from './elements';
15+
16+
interface IPageHeaderProps {
17+
title: string;
18+
children: {
19+
left: React.ReactChildren;
20+
right: React.ReactChildren;
21+
};
22+
}
23+
24+
export const PageHeader: React.FC<IPageHeaderProps> = ({
25+
title = '',
26+
children,
27+
}) => {
28+
const {
29+
actions: { signInClicked },
30+
state: {
31+
isLoggedIn,
32+
isAuthenticating,
33+
},
34+
} = useOvermind();
35+
36+
const handleSignIn = async () => {
37+
await signInClicked({ useExtraScopes: false });
38+
};
39+
40+
return (
41+
<Container>
42+
<Helmet>
43+
<title>{title ? `${title} - CodeSandbox` : `CodeSandbox`}</title>
44+
</Helmet>
45+
<Content>
46+
<Left>
47+
<Home to="/">
48+
<Logo width={38} height={38} />
49+
</Home>
50+
<Separator />
51+
{children.left}
52+
</Left>
53+
<Right>
54+
{children.right}
55+
{isLoggedIn ? (
56+
<UserMenu />
57+
) : (
58+
<Button block onClick={handleSignIn}>
59+
Sign In
60+
</Button>
61+
)}
62+
</Right>
63+
</Content>
64+
</Container>
65+
);
66+
};
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import styled, { css } from 'styled-components';
2+
import { Group } from 'reakit/Group';
3+
import {
4+
Link as BaseLink,
5+
Button as BaseButton,
6+
} from '@codesandbox/common/lib/components';
7+
8+
export const Container = styled.header`
9+
display: flex;
10+
justify-content: center;
11+
align-items: center;
12+
width: 100%;
13+
padding: 0px 2rem;
14+
box-sizing: border-box;
15+
`;
16+
17+
export const Content = styled.nav`
18+
display: flex;
19+
align-items: space-between;
20+
width: 100%;
21+
max-width: 1280px;
22+
color: white;
23+
padding: 1rem 0px;
24+
`;
25+
26+
export const Left = styled(Group)`
27+
display: flex;
28+
flex: 1 1 auto;
29+
align-items: center;
30+
`;
31+
32+
export const Home = styled(BaseLink)`
33+
display: inline-flex;
34+
margin-right: 1rem;
35+
color: white;
36+
37+
&:focus {
38+
outline: none;
39+
}
40+
41+
&:hover,
42+
&:focus {
43+
color: rgb(64, 169, 243);
44+
}
45+
`;
46+
47+
export const Separator = styled.hr`
48+
display: inline-flex;
49+
height: 22px;
50+
width: 1px;
51+
margin: 0;
52+
border-style: none solid none none;
53+
border-right: 1px solid rgba(255, 255, 255, 0.4);
54+
`;
55+
56+
export const Link = styled(BaseLink)`
57+
${({ theme }) => css`
58+
display: inline-flex;
59+
align-items: center;
60+
padding: 0 0.5rem;
61+
margin: 0 0.5rem;
62+
color: white;
63+
${theme.fonts.primary.medium};
64+
transition: color 0.2s ease 0s;
65+
text-decoration: none;
66+
67+
&:focus {
68+
outline: none;
69+
}
70+
71+
&:hover,
72+
&:focus {
73+
color: rgb(64, 169, 243);
74+
}
75+
`}
76+
`;
77+
78+
export const MenuLink = styled(Link)`
79+
display: flex;
80+
align-items: center;
81+
padding: 0.5rem 1rem;
82+
margin: 0;
83+
border: none;
84+
border-left: 2px solid transparent;
85+
background: none;
86+
color: rgba(255, 255, 255, 0.8);
87+
text-decoration: none;
88+
transition: all 0.3s ease 0s;
89+
90+
&:focus {
91+
outline: none;
92+
}
93+
94+
&:hover,
95+
&:focus {
96+
border-color: rgb(64, 169, 243);
97+
background-color: rgba(64, 169, 243, 0.098);
98+
color: white;
99+
}
100+
`;
101+
102+
export const Right = styled(Group)`
103+
display: flex;
104+
flex: 0 0 auto;
105+
align-items: center;
106+
`;
107+
108+
export const Button = styled(BaseButton)`
109+
flex: 0 0 auto;
110+
width: initial;
111+
112+
&:not(:first-child) {
113+
margin-left: 1rem;
114+
}
115+
`;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { PageHeader } from "./PageHeader";
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import React from 'react';
2+
import { useOvermind } from 'app/overmind';
3+
import {
4+
ChatIcon,
5+
CogIcon,
6+
CuratorIcon,
7+
DashboardIcon,
8+
DocumentationIcon,
9+
ExitIcon,
10+
FolderIcon,
11+
PatronIcon,
12+
ProIcon,
13+
SearchIcon,
14+
UserIcon,
15+
} from '@codesandbox/common/lib/components/icons';
16+
import { Menu, MenuItem, Separator } from '@codesandbox/common/lib/components/Menu';
17+
import track from '@codesandbox/common/lib/utils/analytics';
18+
import {
19+
profileUrl,
20+
patronUrl,
21+
curatorUrl,
22+
dashboardUrl,
23+
searchUrl,
24+
} from '@codesandbox/common/lib/utils/url-generator';
25+
import { Avatar } from './elements';
26+
27+
interface IUserMenuProps {}
28+
29+
export const UserMenu: React.FC<IUserMenuProps> = () => {
30+
const {
31+
actions: {
32+
modalOpened,
33+
signOutClicked,
34+
files: { gotUploadedFiles },
35+
},
36+
state: { user },
37+
} = useOvermind();
38+
39+
return (
40+
<Avatar
41+
as={Menu}
42+
aria-label="User Menu"
43+
name={user.username}
44+
img={user.avatarUrl}
45+
onOpen={track('User Menu Open')}
46+
>
47+
<MenuItem icon={UserIcon} to={profileUrl(user.username)}>
48+
My Profile
49+
</MenuItem>
50+
<Separator />
51+
<MenuItem icon={DashboardIcon} to={dashboardUrl()}>
52+
Dashboard
53+
</MenuItem>
54+
<MenuItem icon={DocumentationIcon} to="/docs">
55+
Documentation
56+
</MenuItem>
57+
<MenuItem icon={SearchIcon} to={searchUrl()}>
58+
Search Sandboxes
59+
</MenuItem>
60+
{user.curatorAt && (
61+
<MenuItem icon={CuratorIcon} to={curatorUrl()}>
62+
Curator Dashboard
63+
</MenuItem>
64+
)}
65+
{user.subscription && user.subscription.plan === 'patron' && (
66+
<MenuItem icon={PatronIcon} to={patronUrl()}>
67+
Patron Page
68+
</MenuItem>
69+
)}
70+
{!user.subscription && (
71+
<MenuItem icon={ProIcon} to="/pricing">
72+
Upgrade to Pro
73+
</MenuItem>
74+
)}
75+
<Separator />
76+
{user.subscription && user.subscription.plan === 'pro' && (
77+
<MenuItem icon={ProIcon} to="/pro">
78+
Manage Subscription
79+
</MenuItem>
80+
)}
81+
<MenuItem icon={FolderIcon} onClick={() => gotUploadedFiles(null)}>
82+
Storage Management
83+
</MenuItem>
84+
<MenuItem
85+
icon={CogIcon}
86+
onClick={() => modalOpened({ modal: 'preferences' })}
87+
>
88+
Preferences
89+
</MenuItem>
90+
<Separator />
91+
<MenuItem
92+
icon={ChatIcon}
93+
onClick={() => modalOpened({ modal: 'feedback' })}
94+
>
95+
Submit Feedback
96+
</MenuItem>
97+
<Separator />
98+
<MenuItem icon={ExitIcon} onClick={() => signOutClicked()}>
99+
Sign Out
100+
</MenuItem>
101+
</Avatar>
102+
);
103+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import styled, { css } from 'styled-components';
2+
import { Avatar as BaseAvatar } from '@codesandbox/common/lib/components';
3+
4+
export const Avatar = styled(BaseAvatar)(
5+
({ theme }) => css`
6+
margin-left: 1rem;
7+
width: 28px;
8+
height: 28px;
9+
border-radius: 4px;
10+
border: 2px solid ${theme.secondary};
11+
`
12+
);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { UserMenu } from './UserMenu';

0 commit comments

Comments
 (0)