mirror of
https://github.com/nickzuber/meteorite.git
synced 2024-09-11 11:36:03 +03:00
Pricing page
This commit is contained in:
parent
1cd8d240c3
commit
52e12bedac
@ -5,6 +5,7 @@ import { AuthProvider } from './providers/Auth';
|
||||
import {
|
||||
Home,
|
||||
Login,
|
||||
Pricing,
|
||||
Notifications,
|
||||
NotificationsRedesign,
|
||||
} from './pages';
|
||||
@ -16,6 +17,7 @@ class App extends Component {
|
||||
<Router>
|
||||
<Home path={routes.HOME} />
|
||||
<Login path={routes.LOGIN} />
|
||||
<Pricing path={routes.PRICING} />
|
||||
<Notifications path={routes.NOTIFICATIONS} />
|
||||
<NotificationsRedesign path={routes.REDESIGN_NOTIFICATIONS} />
|
||||
</Router>
|
||||
|
@ -1,6 +1,7 @@
|
||||
export default {
|
||||
HOME: '/',
|
||||
NOTIFICATIONS: '/notifications',
|
||||
PRICING: '/pricing',
|
||||
REDESIGN_NOTIFICATIONS: '/notifications-redesign',
|
||||
LOGIN: '/login'
|
||||
};
|
||||
|
@ -5,7 +5,12 @@ import styled from '@emotion/styled';
|
||||
import {css, jsx} from '@emotion/core';
|
||||
import {Link as RouterLink} from '@reach/router';
|
||||
import {routes} from '../../constants';
|
||||
import Logo from '../../components/Logo';
|
||||
import {
|
||||
BasicPageWrapper,
|
||||
forSmallScreens,
|
||||
forMobile
|
||||
} from '../common';
|
||||
import WorkflowToggle from './WorkflowToggle';
|
||||
|
||||
import {ReactComponent as CloudOffSvg} from '../../images/svg/icons/cloud_off.svg'
|
||||
import {ReactComponent as NotificationsActiveSvg} from '../../images/svg/icons/notifications_active.svg'
|
||||
@ -32,9 +37,6 @@ import '../../styles/font.css';
|
||||
const themeColor = '#27B768';
|
||||
const ALT_BACKGROUND_COLOR = '#f6f2ed';
|
||||
|
||||
const hash = process.env.GIT_HASH ? `#${process.env.GIT_HASH}` : '';
|
||||
const version = require('../../../package.json').version + hash;
|
||||
|
||||
const ProductHuntButton = () => (
|
||||
<a href="https://www.producthunt.com/posts/meteorite?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-meteorite" target="_blank">
|
||||
<img
|
||||
@ -46,26 +48,6 @@ const ProductHuntButton = () => (
|
||||
</a>
|
||||
);
|
||||
|
||||
const forSmallScreens = rules => `
|
||||
@media (max-width: 1100px) {
|
||||
${rules}
|
||||
}
|
||||
`;
|
||||
|
||||
const forMobile = rules => `
|
||||
@media (max-width: 800px) {
|
||||
${rules}
|
||||
}
|
||||
`;
|
||||
|
||||
const DefaultContainer = styled('div')`
|
||||
overflow-x: hidden;
|
||||
* {
|
||||
font-family: medium-content-sans-serif-font, "Inter UI", system-ui, sans-serif;
|
||||
font-size: 15px;
|
||||
}
|
||||
`;
|
||||
|
||||
const Outer = styled('div')`
|
||||
background: ${p => p.alt ? ALT_BACKGROUND_COLOR : 'none'};
|
||||
`;
|
||||
@ -96,37 +78,6 @@ const FlexItem = styled('div')`
|
||||
flex-wrap: wrap;
|
||||
`;
|
||||
|
||||
const ButtonLink = styled('a')`
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background-color: transparent;
|
||||
border: 0px solid transparent;
|
||||
padding: 0.125rem 0.75rem;
|
||||
font-size: 18px;
|
||||
line-height: 1.75;
|
||||
border-radius: 5px;
|
||||
transition: all 0.15s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #f4f4f4;
|
||||
border-color: #f4f4f4;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #eee;
|
||||
border-color: #eee;
|
||||
}
|
||||
`;
|
||||
|
||||
const Button = styled(RouterLink)`
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
@ -185,41 +136,6 @@ const HeroButton = styled(MainButton)`
|
||||
margin-left: 0;
|
||||
`;
|
||||
|
||||
const LogoTitle = styled('span')`
|
||||
display: inline-block;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
color: #333333;
|
||||
font-size: 22px;
|
||||
font-weight: 800;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
${forMobile(`
|
||||
display: none;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const LogoSection = () => (
|
||||
<div css={css`
|
||||
display: inline-flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 125px;
|
||||
${forMobile(`
|
||||
width: 36px;
|
||||
`)}
|
||||
div {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
}
|
||||
`}>
|
||||
<Logo white size={26} style={{filter: 'invert(0.8)'}} />
|
||||
<LogoTitle>Meteorite</LogoTitle>
|
||||
</div>
|
||||
);
|
||||
|
||||
const LoginContainer = styled('div')``;
|
||||
|
||||
const FlexBreak = styled('div')`
|
||||
flex-basis: 100%;
|
||||
height: 0;
|
||||
@ -431,145 +347,7 @@ const CompanyPerson = styled('div')`
|
||||
}
|
||||
`;
|
||||
|
||||
const GroupedLinks = styled(`div`)`
|
||||
text-align: center;
|
||||
margin: 8px auto 0;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-size: 17px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: 0.75rem 2.25rem;
|
||||
border: 1px solid #EAEDF3;
|
||||
margin-left: -1px;
|
||||
margin-top: 8px;
|
||||
transition: all 75ms ease-in-out;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #EAEDF366;
|
||||
}
|
||||
|
||||
a:active {
|
||||
background-color: #EAEDF3;
|
||||
}
|
||||
|
||||
a:first-of-type {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
a:last-of-type {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
`;
|
||||
|
||||
const FooterSubtleText = styled('p')`
|
||||
margin: 24px auto;
|
||||
color: #6c757d;
|
||||
`;
|
||||
|
||||
const WorkflowToggle = () => {
|
||||
const [state, setState] = React.useState(0);
|
||||
const [imageOpacity, setImageOpacity] = React.useState(1);
|
||||
const timer = React.useRef();
|
||||
const easeTimingMs = 200;
|
||||
|
||||
const items = [
|
||||
{
|
||||
id: 0,
|
||||
title: 'Filter The Noise',
|
||||
description: 'Stay focused on the important things. We\'ll only show the notifications that matter to you.',
|
||||
image: ScreenshotPng
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Highlight The Callouts',
|
||||
description: 'When things stand out, you shouldn\'t miss it. We mark notifications when there\'s something interesting going down.',
|
||||
image: ReasonsPng
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Sort By Importance',
|
||||
description: 'Don\'t get lost at sea – the most important notifications stay at the top of the list.',
|
||||
image: ScoresPng
|
||||
},
|
||||
];
|
||||
|
||||
const activeItem = items[state];
|
||||
|
||||
return (
|
||||
<div css={css`
|
||||
margin-top: 32px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
${forSmallScreens(`
|
||||
flex-direction: column;
|
||||
`)}
|
||||
`}>
|
||||
<div css={css`
|
||||
flex: 1;
|
||||
${forSmallScreens(`
|
||||
margin-bottom: 24px;
|
||||
`)}
|
||||
`}>
|
||||
{items.map((item, xid) => (
|
||||
<div
|
||||
key={xid}
|
||||
onClick={() => {
|
||||
if (xid === state) return;
|
||||
clearTimeout(timer.current);
|
||||
setImageOpacity(0);
|
||||
timer.current = setTimeout(() => {
|
||||
setState(xid);
|
||||
setImageOpacity(1);
|
||||
}, easeTimingMs);
|
||||
}}
|
||||
css={css`
|
||||
border-radius: 8px;
|
||||
padding: 18px 20px;
|
||||
margin: 0 32px 8px 0;
|
||||
cursor: pointer;
|
||||
background: ${state === xid ? '#ffffff' : 'none'};
|
||||
transition: all 0.15s ease-in-out;
|
||||
`}>
|
||||
<h3 css={css`
|
||||
font-size: 22px;
|
||||
line-height: 26px;
|
||||
margin: 0 auto 4px;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
font-weight: 500;
|
||||
`}>{item.title}</h3>
|
||||
<p css={css`
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
`}>{item.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div css={css`
|
||||
position: relative;
|
||||
flex: 3;
|
||||
`}>
|
||||
<img
|
||||
src={activeItem.image}
|
||||
css={css`
|
||||
max-width: 100%;
|
||||
opacity: ${imageOpacity};
|
||||
will-change: opacity;
|
||||
box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.175);
|
||||
transition: opacity ${easeTimingMs}ms linear;
|
||||
border-radius: 4px;
|
||||
`} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Scene ({loggedIn, onLogout, ...props}) {
|
||||
export default function Scene (props) {
|
||||
const baseItemOffset = {
|
||||
scale: 0.1,
|
||||
top: -185,
|
||||
@ -577,37 +355,7 @@ export default function Scene ({loggedIn, onLogout, ...props}) {
|
||||
};
|
||||
|
||||
return (
|
||||
<DefaultContainer>
|
||||
{/* Header */}
|
||||
<Container>
|
||||
<FlexItem css={css`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`}>
|
||||
<LogoSection />
|
||||
{loggedIn ? (
|
||||
<LoginContainer>
|
||||
<Button to={routes.REDESIGN_NOTIFICATIONS} css={css`
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: #E91E63;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
border-radius: 100%;
|
||||
}`}>{'Notifications'}</Button>
|
||||
<ButtonLink href="#" onClick={onLogout}>{'Logout'}</ButtonLink>
|
||||
</LoginContainer>
|
||||
) : (
|
||||
<LoginContainer>
|
||||
<MainButton to={routes.LOGIN}>{'Login / Sign up'}</MainButton>
|
||||
</LoginContainer>
|
||||
)}
|
||||
</FlexItem>
|
||||
</Container>
|
||||
<BasicPageWrapper {...props}>
|
||||
|
||||
{/* Hero */}
|
||||
<Container css={css`
|
||||
@ -627,6 +375,7 @@ export default function Scene ({loggedIn, onLogout, ...props}) {
|
||||
${forMobile(`
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 300px;
|
||||
`)}
|
||||
`}>
|
||||
<HeroButton css={css`${forMobile(`margin-bottom: 12px;`)}`} to={routes.LOGIN}>{'Login / Sign up'}</HeroButton>
|
||||
@ -744,7 +493,7 @@ export default function Scene ({loggedIn, onLogout, ...props}) {
|
||||
<FeatureItem color={'#fd9446'}>
|
||||
<WbIridescentSvg />
|
||||
<h3>{'Reasoning'}</h3>
|
||||
<p>{'We\ll also tell you why you\'re getting each notification.'}</p>
|
||||
<p>{'We\'ll also tell you why you\'re getting each notification.'}</p>
|
||||
</FeatureItem>
|
||||
<FeatureItem color={'#fc46fd'}>
|
||||
<TimelineSvg />
|
||||
@ -776,26 +525,6 @@ export default function Scene ({loggedIn, onLogout, ...props}) {
|
||||
<FlexBreak height={40} />
|
||||
</Container>
|
||||
</Outer>
|
||||
|
||||
{/* Footer */}
|
||||
<Container column>
|
||||
<Logo white size={42} style={{filter: 'invert(0.8)', margin: '0 auto'}} />
|
||||
<Title css={css`font-size: 26px; margin: 12px auto;`}>{'Manage your notifications.'}</Title>
|
||||
<FlexBreak height={20} />
|
||||
<GroupedLinks>
|
||||
<a target="_blank" href="https://github.com/nickzuber/meteorite/issues">Donate</a>
|
||||
<a target="_blank" href="https://github.com/nickzuber/meteorite/issues">Feedback</a>
|
||||
<a target="_blank" href="https://github.com/nickzuber/meteorite/commits/master">Changelog</a>
|
||||
</GroupedLinks>
|
||||
<GroupedLinks>
|
||||
<a target="_blank" href="https://github.com/nickzuber/meteorite">GitHub</a>
|
||||
<a target="_blank" href="https://twitter.com/nick_zuber">Twitter</a>
|
||||
</GroupedLinks>
|
||||
<FlexBreak height={20} />
|
||||
<FooterSubtleText>
|
||||
{`© 2019 Nick Zuber – Meteorite v${version}`}
|
||||
</FooterSubtleText>
|
||||
</Container>
|
||||
</DefaultContainer>
|
||||
</BasicPageWrapper>
|
||||
);
|
||||
};
|
||||
|
131
src/pages/Home/WorkflowToggle.js
Normal file
131
src/pages/Home/WorkflowToggle.js
Normal file
@ -0,0 +1,131 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import {css, jsx} from '@emotion/core';
|
||||
import {Link as RouterLink} from '@reach/router';
|
||||
import {routes} from '../../constants';
|
||||
import {
|
||||
BasicPageWrapper,
|
||||
forSmallScreens,
|
||||
forMobile
|
||||
} from '../common';
|
||||
|
||||
import {ReactComponent as CloudOffSvg} from '../../images/svg/icons/cloud_off.svg'
|
||||
import {ReactComponent as NotificationsActiveSvg} from '../../images/svg/icons/notifications_active.svg'
|
||||
import {ReactComponent as PriorityHighSvg} from '../../images/svg/icons/priority_high.svg'
|
||||
import {ReactComponent as TuneSvg} from '../../images/svg/icons/tune.svg'
|
||||
import {ReactComponent as SpeedSvg} from '../../images/svg/icons/speed.svg'
|
||||
import {ReactComponent as GpsFixedSvg} from '../../images/svg/icons/gps_fixed.svg'
|
||||
import {ReactComponent as WbIridescentSvg} from '../../images/svg/icons/wb_iridescent.svg'
|
||||
import {ReactComponent as TimelineSvg} from '../../images/svg/icons/timeline.svg'
|
||||
|
||||
import ItemPng from '../../images/screenshots/item.png';
|
||||
import ItemTwoPng from '../../images/screenshots/item-2.png';
|
||||
import ScreenshotPng from '../../images/screenshots/new/dashboard.png';
|
||||
import ScoresPng from '../../images/screenshots/new/scores.png';
|
||||
import ReasonsPng from '../../images/screenshots/new/reasons.png';
|
||||
|
||||
import RobinLogo from '../../images/logos/robin-logo.png';
|
||||
import ForwardLogo from '../../images/logos/forward-logo.png';
|
||||
import FacebookLogo from '../../images/logos/facebook-logo.png';
|
||||
|
||||
const WorkflowToggle = () => {
|
||||
const [state, setState] = React.useState(0);
|
||||
const [imageOpacity, setImageOpacity] = React.useState(1);
|
||||
const timer = React.useRef();
|
||||
const easeTimingMs = 200;
|
||||
|
||||
const items = [
|
||||
{
|
||||
id: 0,
|
||||
title: 'Filter The Noise',
|
||||
description: 'Stay focused on the important things. We\'ll only show the notifications that matter to you.',
|
||||
image: ScreenshotPng
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Highlight The Callouts',
|
||||
description: 'When things stand out, you shouldn\'t miss it. We mark notifications when there\'s something interesting going down.',
|
||||
image: ReasonsPng
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Sort By Importance',
|
||||
description: 'Don\'t get lost at sea – the most important notifications stay at the top of the list.',
|
||||
image: ScoresPng
|
||||
},
|
||||
];
|
||||
|
||||
const activeItem = items[state];
|
||||
|
||||
return (
|
||||
<div css={css`
|
||||
margin-top: 32px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
${forSmallScreens(`
|
||||
flex-direction: column;
|
||||
`)}
|
||||
`}>
|
||||
<div css={css`
|
||||
flex: 1;
|
||||
${forSmallScreens(`
|
||||
margin-bottom: 24px;
|
||||
`)}
|
||||
`}>
|
||||
{items.map((item, xid) => (
|
||||
<div
|
||||
key={xid}
|
||||
onClick={() => {
|
||||
if (xid === state) return;
|
||||
clearTimeout(timer.current);
|
||||
setImageOpacity(0);
|
||||
timer.current = setTimeout(() => {
|
||||
setState(xid);
|
||||
setImageOpacity(1);
|
||||
}, easeTimingMs);
|
||||
}}
|
||||
css={css`
|
||||
border-radius: 8px;
|
||||
padding: 18px 20px;
|
||||
margin: 0 32px 8px 0;
|
||||
cursor: pointer;
|
||||
background: ${state === xid ? '#ffffff' : 'none'};
|
||||
transition: all 0.15s ease-in-out;
|
||||
`}>
|
||||
<h3 css={css`
|
||||
font-size: 22px;
|
||||
line-height: 26px;
|
||||
margin: 0 auto 4px;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
font-weight: 500;
|
||||
`}>{item.title}</h3>
|
||||
<p css={css`
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
`}>{item.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div css={css`
|
||||
position: relative;
|
||||
flex: 3;
|
||||
`}>
|
||||
<img
|
||||
src={activeItem.image}
|
||||
css={css`
|
||||
max-width: 100%;
|
||||
opacity: ${imageOpacity};
|
||||
will-change: opacity;
|
||||
box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.175);
|
||||
transition: opacity ${easeTimingMs}ms linear;
|
||||
border-radius: 4px;
|
||||
`} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WorkflowToggle;
|
@ -345,12 +345,9 @@ export default function Scene ({
|
||||
prev: readTodayLastWeekCount
|
||||
});
|
||||
|
||||
readStatistics = readStatistics.map(n => parseInt(n, 10) || 0);
|
||||
// const lastWeekStats = readStatistics.slice(0, 7);
|
||||
// const thisWeekStats = readStatistics.slice(7);
|
||||
|
||||
const lastWeekStats = [0, 3, 7, 2, 4, 5, 0];
|
||||
const thisWeekStats = [0, 2, 8, 4, 5, null, null];
|
||||
readStatistics = readStatistics.map(n => parseInt(n, 10));
|
||||
const lastWeekStats = readStatistics.slice(0, 7);
|
||||
const thisWeekStats = readStatistics.slice(7);
|
||||
|
||||
const percentageDeltaToday = getPercentageDelta(counts.cur, counts.prev);
|
||||
const highestRepoReadCount = Object.values(reposReadCounts).reduce((h, c) => Math.max(h, c), 0);
|
||||
|
@ -711,7 +711,7 @@ export function ProfileSection ({user, onLogout}) {
|
||||
onLogout();
|
||||
setMenuShow(false);
|
||||
}}>
|
||||
<h2>Sign out</h2>
|
||||
<h2>Logout</h2>
|
||||
<p>Log off your account and return to home page</p>
|
||||
</optimized.div>
|
||||
</InteractionMenu>
|
||||
|
443
src/pages/Pricing/Scene.js
Normal file
443
src/pages/Pricing/Scene.js
Normal file
@ -0,0 +1,443 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import {css, jsx} from '@emotion/core';
|
||||
import {Link as RouterLink} from '@reach/router';
|
||||
import {routes} from '../../constants';
|
||||
import {
|
||||
BasicPageWrapper,
|
||||
forSmallScreens,
|
||||
forMobile
|
||||
} from '../common';
|
||||
|
||||
import ItemPng from '../../images/screenshots/item.png';
|
||||
import ItemTwoPng from '../../images/screenshots/item-2.png';
|
||||
|
||||
import '../../styles/gradient.css';
|
||||
import '../../styles/font.css';
|
||||
|
||||
const themeColor = '#27B768';
|
||||
const ALT_BACKGROUND_COLOR = '#f6f2ed';
|
||||
|
||||
const ProductHuntButton = () => (
|
||||
<a href="https://www.producthunt.com/posts/meteorite?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-meteorite" target="_blank">
|
||||
<img
|
||||
src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=145651&theme=dark"
|
||||
alt="Meteorite - Smarter GitHub notifications. | Product Hunt Embed"
|
||||
style={{width: 200, height: 43}}
|
||||
width="200px"
|
||||
height="43px" />
|
||||
</a>
|
||||
);
|
||||
|
||||
const Container = styled('div')`
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: ${p => p.column ? 'column' : 'row'};
|
||||
max-width: 1080px;
|
||||
min-height: 100px;
|
||||
margin: 0 auto;
|
||||
padding: 1rem 0;
|
||||
margin-bottom: 4rem;
|
||||
${forSmallScreens(`
|
||||
padding-left: 2.5rem;
|
||||
padding-right: 2.5rem;
|
||||
`)}
|
||||
${forMobile(`
|
||||
margin-bottom: 2.5rem;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const LightContainer = styled(Container)`
|
||||
${forSmallScreens(`
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
`)}
|
||||
${forMobile(`
|
||||
margin-bottom: 2.5rem;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const FlexItem = styled('div')`
|
||||
flex: ${(({flex = 1}) => flex)};
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
`;
|
||||
|
||||
const Button = styled(RouterLink)`
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background-color: transparent;
|
||||
border: 0px solid transparent;
|
||||
margin: 0rem 0.25rem;
|
||||
width: max-content;
|
||||
padding: 0.125rem 1rem;
|
||||
font-size: 18px;
|
||||
line-height: 1.75;
|
||||
border-radius: 5px;
|
||||
-webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #f4f4f4;
|
||||
border-color: #f4f4f4;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #eee;
|
||||
border-color: #eee;
|
||||
}
|
||||
`;
|
||||
|
||||
const MainButton = styled(Button)`
|
||||
background-color: ${themeColor};
|
||||
border-color: ${themeColor};
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
|
||||
&:hover {
|
||||
background-color: #249959;
|
||||
border-color: #249959;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #20894f;
|
||||
border-color: #20894f;
|
||||
}
|
||||
`;
|
||||
|
||||
const HeroButton = styled(MainButton)`
|
||||
font-size: 22px;
|
||||
margin: -4px 8px 0;
|
||||
margin-left: 0;
|
||||
`;
|
||||
|
||||
const FlexBreak = styled('div')`
|
||||
flex-basis: 100%;
|
||||
height: 0;
|
||||
min-height: ${p => p.height || 0}px;
|
||||
`;
|
||||
|
||||
const HeroTitle = styled('h1')`
|
||||
font-size: 68px;
|
||||
line-height: 68px;
|
||||
margin: 0 auto 6px 0;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
font-weight: 500;
|
||||
|
||||
${forMobile(`
|
||||
font-size: 46px;
|
||||
line-height: 54px;
|
||||
margin: 0 auto 6px;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const HeroSubtitle = styled('h1')`
|
||||
color: #6c757d;
|
||||
font-size: 24px;
|
||||
line-height: 28px;
|
||||
margin: 0 auto 16px;
|
||||
width: 80%;
|
||||
margin-left: 0;
|
||||
font-family: medium-content-sans-serif-font, Inter UI, system-ui, sans-serif;
|
||||
font-weight: 500;
|
||||
|
||||
${forMobile(`
|
||||
margin: 0 auto 32px;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const Title = styled('h1')`
|
||||
font-size: 38px;
|
||||
line-height: 38px;
|
||||
margin: 0 auto 12px;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const Subtitle = styled('h1')`
|
||||
color: #6c757d;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
margin: 0 auto 16px;
|
||||
font-family: medium-content-sans-serif-font, Inter UI, system-ui, sans-serif;
|
||||
font-weight: 500;
|
||||
max-width: 540px;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const LeftTitle = styled(Title)`
|
||||
margin: 0 0 4px;
|
||||
text-align: left;
|
||||
font-size: 34px;
|
||||
line-height: 34px;
|
||||
`;
|
||||
|
||||
const LeftSubtitle = styled(Subtitle)`
|
||||
margin: 0 0 12px;
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
line-height: 23px;
|
||||
`;
|
||||
|
||||
const HeroLeft = styled(FlexItem)`
|
||||
z-index: 1;
|
||||
flex-grow: 1;
|
||||
width: 50%;
|
||||
${forMobile(`
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const HeroRight = styled(FlexItem)`
|
||||
flex-grow: 1;
|
||||
width: 50%;
|
||||
${forMobile(`
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const PricingContainer = styled('div')`
|
||||
position: relative;
|
||||
background: ${ALT_BACKGROUND_COLOR};
|
||||
width: 70%;
|
||||
margin-right: 0;
|
||||
margin-left: auto;
|
||||
min-height: 100px;
|
||||
border-radius: 4px;
|
||||
padding: 28px 24px;
|
||||
text-align: left;
|
||||
${forMobile(`
|
||||
width: 100%;
|
||||
`)}
|
||||
|
||||
h4 {
|
||||
margin: -2px 0 0;
|
||||
font-size: 20px;
|
||||
color: #26b768;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
margin: 8px auto 0;
|
||||
color: #6c757d;
|
||||
}
|
||||
`;
|
||||
|
||||
const Price = styled(Title)(p => `
|
||||
font-size: ${p.crossed ? 32 : 52}px;
|
||||
line-height: ${p.crossed ? 32 : 54}px;
|
||||
text-decoration: ${p.crossed ? 'line-through' : 'unset'};
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
text-align: left;
|
||||
`);
|
||||
|
||||
const Badge = styled('span')`
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
text-align: left;
|
||||
background: #26b768;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
vertical-align: super;
|
||||
display: inline-block;
|
||||
`;
|
||||
|
||||
const FloatingLinkBox = styled('div')`
|
||||
background: rgb(255, 254, 253);
|
||||
flex: 1;
|
||||
position: relative;
|
||||
box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075);
|
||||
border-radius: 4px;
|
||||
padding: 16px 24px;
|
||||
margin: 0 24px 0 0;
|
||||
${forMobile(`
|
||||
margin: 0 0 24px 0;
|
||||
`)}
|
||||
|
||||
h4 {
|
||||
margin: 0;
|
||||
color: #47494b;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
margin: 6px auto;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-size: 16px;
|
||||
color: #00A0F5;
|
||||
transition: all 200ms ease;
|
||||
}
|
||||
a:hover {
|
||||
color: #0886c9;
|
||||
}
|
||||
a::after {
|
||||
content: " →"
|
||||
}
|
||||
`;
|
||||
|
||||
const HorizontalFlexContainer = styled('div')`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
margin-top: 1rem;
|
||||
`;
|
||||
|
||||
const FAQItem = styled('div')`
|
||||
flex: 1 0 34%;
|
||||
${forMobile(`
|
||||
flex: 1 0 51%;
|
||||
`)}
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
align-items: left;
|
||||
justify-content: center;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0 12px;
|
||||
|
||||
h3 {
|
||||
font-size: 21px;
|
||||
justify-content: center;
|
||||
line-height: 25px;
|
||||
margin: 18px 0 8px;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.7px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 18px;
|
||||
justify-content: center;
|
||||
line-height: 22px;
|
||||
margin: 0 0 12px;
|
||||
color: #6c757d;
|
||||
|
||||
a {
|
||||
font-size: 18px;
|
||||
justify-content: center;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function Scene (props) {
|
||||
return (
|
||||
<BasicPageWrapper {...props}>
|
||||
{/* Pricing */}
|
||||
<Container css={css`
|
||||
${forMobile(`
|
||||
flex-direction: column;
|
||||
`)}
|
||||
`}>
|
||||
<HeroLeft>
|
||||
<HeroTitle>
|
||||
{'Simple pricing.'}<br />
|
||||
{'Great value.'}</HeroTitle>
|
||||
<HeroSubtitle>{'Get started for absolutely free. No trials needed.'}</HeroSubtitle>
|
||||
<FlexBreak />
|
||||
</HeroLeft>
|
||||
<HeroRight>
|
||||
<PricingContainer>
|
||||
<Price>{'$0/mo'}</Price>
|
||||
<Badge>{'Great deal'}</Badge>
|
||||
<h4>{'Unlimited everything'}</h4>
|
||||
<p>{'A simple and better way to manage GitHub notifications for more \
|
||||
engineers who want to be more productive.'}</p>
|
||||
</PricingContainer>
|
||||
</HeroRight>
|
||||
</Container>
|
||||
|
||||
<Container css={css`${forMobile(`flex-direction: column;`)}`}>
|
||||
<FloatingLinkBox>
|
||||
<h4>{'Pay what you want.'}</h4>
|
||||
<p>{'Donate to the engineers working on this project.'}</p>
|
||||
<a target="_blank" href="https://donorbox.org/meteorite">{'Visit now'}</a>
|
||||
</FloatingLinkBox>
|
||||
<FloatingLinkBox>
|
||||
<h4>{'Want to contribute?'}</h4>
|
||||
<p>{'All of the code is open sourced and free to edit.'}</p>
|
||||
<a target="_blank" href="https://github.com/nickzuber/meteorite">{'Check it out'}</a>
|
||||
</FloatingLinkBox>
|
||||
</Container>
|
||||
|
||||
{/* FAQ */}
|
||||
<Container column>
|
||||
<LeftTitle css={css`padding-left: 12px;`}>{'Still have questions?'}</LeftTitle>
|
||||
<LeftSubtitle css={css`padding-left: 12px;`}>{'Here are some commonly asked questions.'}</LeftSubtitle>
|
||||
|
||||
<LightContainer column>
|
||||
<HorizontalFlexContainer>
|
||||
<FAQItem>
|
||||
<h3>{'What exactly is Meteorite?'}</h3>
|
||||
<p>{'Meteorite is an app designed around prioritizing and organizing your \
|
||||
GitHub notifications. It has a variety of features to help keep you \
|
||||
focused on the notifications that matter to you, and see the most important \
|
||||
updates at the top of your list by keeping track of the thread context.'}</p>
|
||||
<p>{'Basically, Meteorite is the GitHub notifications of your dreams.'}</p>
|
||||
</FAQItem>
|
||||
<FAQItem>
|
||||
<h3>{'Why does this exist?'}</h3>
|
||||
<p>{'GitHub notifications right now can be chaotic and noisy, which end up\
|
||||
making them pretty useless. Meteorite solves this problem by filtering, \
|
||||
sorting, and adding context to the notifications you would normally get.'}</p>
|
||||
<p>{'This project originated from me personally getting sick and tired of the current\
|
||||
GitHub notifications system, so I took a crack and making it better.'}</p>
|
||||
</FAQItem>
|
||||
<FAQItem>
|
||||
<h3>{'Can I try it for free?'}</h3>
|
||||
<p>{'Absolutely – Meteorite is completely free and open source.'}</p>
|
||||
</FAQItem>
|
||||
<FAQItem>
|
||||
<h3>{'Can I host an instance of Meteorite myself?'}</h3>
|
||||
<p>{'Sure – feel free to fork/contribute/self-host anything with this project. Since this project\
|
||||
is completely serverless, you can host your own instance for free using platforms like '}
|
||||
<a href="https://zeit.co/">{'Zeit'}</a>{', '}<a href="https://surge.sh/">{'Surge'}</a>{', \
|
||||
or anything in between.'}</p>
|
||||
</FAQItem>
|
||||
<FAQItem>
|
||||
<h3>{'I like this project. How can I contribute?'}</h3>
|
||||
<p>{'You can contribute by submitting bug reports, feature requests, code that implements any \
|
||||
of those things, or you can help by '}<a href="https://donorbox.org/meteorite">{'donating'}</a>{' to the project itself.'}</p>
|
||||
</FAQItem>
|
||||
<FAQItem>
|
||||
<h3>{'Where can I ask more questions?'}</h3>
|
||||
<p>{'You can either personally reach out to me on '}<a href="https://twitter.com/nick_zuber">{'Twitter'}</a>{' or \
|
||||
leave your question on the official '}<a href="https://github.com/nickzuber/meteorite">{'GitHub repository'}</a>{' as an issue.'}</p>
|
||||
</FAQItem>
|
||||
</HorizontalFlexContainer>
|
||||
</LightContainer>
|
||||
</Container>
|
||||
</BasicPageWrapper>
|
||||
);
|
||||
};
|
30
src/pages/Pricing/index.js
Normal file
30
src/pages/Pricing/index.js
Normal file
@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import { compose } from 'recompose';
|
||||
import { withAuthProvider } from '../../providers/Auth';
|
||||
import { withCookiesProvider } from '../../providers/Cookies';
|
||||
import { OAUTH_TOKEN_COOKIE } from '../../constants/cookies';
|
||||
import Scene from './Scene';
|
||||
|
||||
class PricingPage extends React.Component {
|
||||
onLogout = () => {
|
||||
// Remove cookie and invalidate token on client.
|
||||
this.props.cookiesApi.removeCookie(OAUTH_TOKEN_COOKIE);
|
||||
this.props.authApi.invalidateToken();
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Scene
|
||||
loggedIn={!!this.props.authApi.token}
|
||||
onLogout={this.onLogout}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const enhance = compose(
|
||||
withAuthProvider,
|
||||
withCookiesProvider
|
||||
);
|
||||
|
||||
export default enhance(PricingPage);
|
297
src/pages/common/index.js
Normal file
297
src/pages/common/index.js
Normal file
@ -0,0 +1,297 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import {css, jsx} from '@emotion/core';
|
||||
import {navigate, Link as RouterLink} from '@reach/router';
|
||||
import {routes} from '../../constants';
|
||||
import Logo from '../../components/Logo';
|
||||
|
||||
import '../../styles/gradient.css';
|
||||
import '../../styles/font.css';
|
||||
|
||||
const themeColor = '#27B768';
|
||||
|
||||
const hash = process.env.GIT_HASH ? `#${process.env.GIT_HASH}` : '';
|
||||
const version = require('../../../package.json').version + hash;
|
||||
|
||||
export const forSmallScreens = rules => `
|
||||
@media (max-width: 1100px) {
|
||||
${rules}
|
||||
}
|
||||
`;
|
||||
|
||||
export const forMobile = rules => `
|
||||
@media (max-width: 800px) {
|
||||
${rules}
|
||||
}
|
||||
`;
|
||||
|
||||
const DefaultContainer = styled('div')`
|
||||
overflow-x: hidden;
|
||||
* {
|
||||
font-family: medium-content-sans-serif-font, "Inter UI", system-ui, sans-serif;
|
||||
font-size: 15px;
|
||||
}
|
||||
`;
|
||||
|
||||
const Container = styled('div')`
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: ${p => p.column ? 'column' : 'row'};
|
||||
max-width: 1080px;
|
||||
min-height: 100px;
|
||||
margin: 0 auto;
|
||||
padding: 1rem 0;
|
||||
margin-bottom: 5rem;
|
||||
${forSmallScreens(`
|
||||
padding-left: 2.0rem;
|
||||
padding-right: 2.0rem;
|
||||
`)}
|
||||
${forMobile(`
|
||||
margin-bottom: 2.5rem;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const FlexItem = styled('div')`
|
||||
flex: ${(({flex = 1}) => flex)};
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
`;
|
||||
|
||||
const ButtonLink = styled('a')`
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background-color: transparent;
|
||||
border: 0px solid transparent;
|
||||
padding: 0.125rem 0.75rem;
|
||||
font-size: 18px;
|
||||
line-height: 1.75;
|
||||
border-radius: 5px;
|
||||
transition: all 0.15s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #f4f4f4;
|
||||
border-color: #f4f4f4;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #eee;
|
||||
border-color: #eee;
|
||||
}
|
||||
`;
|
||||
|
||||
const Button = styled(RouterLink)`
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background-color: transparent;
|
||||
border: 0px solid transparent;
|
||||
margin: 0rem 0.25rem;
|
||||
width: max-content;
|
||||
padding: 0.125rem 1rem;
|
||||
font-size: 18px;
|
||||
line-height: 1.75;
|
||||
border-radius: 5px;
|
||||
-webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #f4f4f4;
|
||||
border-color: #f4f4f4;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #eee;
|
||||
border-color: #eee;
|
||||
}
|
||||
`;
|
||||
|
||||
const MainButton = styled(Button)`
|
||||
background-color: ${themeColor};
|
||||
border-color: ${themeColor};
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
|
||||
&:hover {
|
||||
background-color: #249959;
|
||||
border-color: #249959;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #20894f;
|
||||
border-color: #20894f;
|
||||
}
|
||||
`;
|
||||
|
||||
const LogoTitle = styled('span')`
|
||||
display: inline-block;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
color: #333333;
|
||||
font-size: 22px;
|
||||
font-weight: 800;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
margin-top: 4px;
|
||||
|
||||
${forMobile(`
|
||||
display: none;
|
||||
`)}
|
||||
`;
|
||||
|
||||
const LogoSection = () => (
|
||||
<div onClick={() => navigate(routes.HOME)} css={css`
|
||||
display: inline-flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 125px;
|
||||
${forMobile(`
|
||||
width: 36px;
|
||||
`)}
|
||||
div {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
}
|
||||
`}>
|
||||
<Logo white size={26} style={{filter: 'invert(0.8)'}} />
|
||||
<LogoTitle>Meteorite</LogoTitle>
|
||||
</div>
|
||||
);
|
||||
|
||||
const LoginContainer = styled('div')``;
|
||||
|
||||
const FlexBreak = styled('div')`
|
||||
flex-basis: 100%;
|
||||
height: 0;
|
||||
min-height: ${p => p.height || 0}px;
|
||||
`;
|
||||
|
||||
const Title = styled('h1')`
|
||||
font-size: 38px;
|
||||
line-height: 38px;
|
||||
margin: 0 auto 12px;
|
||||
font-family: medium-marketing-display-font,Georgia,Cambria,Times New Roman,Times,serif;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const GroupedLinks = styled(`div`)`
|
||||
text-align: center;
|
||||
margin: 8px auto 0;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-size: 17px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: 0.75rem 2.25rem;
|
||||
border: 1px solid #EAEDF3;
|
||||
margin-left: -1px;
|
||||
margin-top: 8px;
|
||||
transition: all 75ms ease-in-out;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #EAEDF366;
|
||||
}
|
||||
|
||||
a:active {
|
||||
background-color: #EAEDF3;
|
||||
}
|
||||
|
||||
a:first-of-type {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
a:last-of-type {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
`;
|
||||
|
||||
const FooterSubtleText = styled('p')`
|
||||
margin: 24px auto;
|
||||
color: #6c757d;
|
||||
`;
|
||||
|
||||
export function BasicPageWrapper ({loggedIn, onLogout, children}) {
|
||||
return (
|
||||
<DefaultContainer>
|
||||
{/* Header */}
|
||||
<Container>
|
||||
<FlexItem css={css`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`}>
|
||||
<LogoSection />
|
||||
{loggedIn ? (
|
||||
<LoginContainer>
|
||||
<Button to={routes.PRICING}>{'Pricing'}</Button>
|
||||
<Button to={routes.REDESIGN_NOTIFICATIONS} css={css`
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: #E91E63;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
border-radius: 100%;
|
||||
}`}>{'Notifications'}</Button>
|
||||
<ButtonLink href="#" onClick={onLogout}>{'Logout'}</ButtonLink>
|
||||
</LoginContainer>
|
||||
) : (
|
||||
<LoginContainer>
|
||||
<Button to={routes.PRICING}>{'Pricing'}</Button>
|
||||
<MainButton to={routes.LOGIN}>{'Login / Sign up'}</MainButton>
|
||||
</LoginContainer>
|
||||
)}
|
||||
</FlexItem>
|
||||
</Container>
|
||||
|
||||
{children}
|
||||
|
||||
{/* Footer */}
|
||||
<Container column>
|
||||
<Logo white size={42} style={{filter: 'invert(0.8)', margin: '0 auto'}} />
|
||||
<Title css={css`font-size: 26px; margin: 12px auto;`}>{'Manage your notifications.'}</Title>
|
||||
<FlexBreak height={20} />
|
||||
<GroupedLinks>
|
||||
<a target="_blank" href="https://donorbox.org/meteorite">Donate</a>
|
||||
<a target="_blank" href="https://github.com/nickzuber/meteorite/issues">Feedback</a>
|
||||
<a target="_blank" href="https://github.com/nickzuber/meteorite/commits/master">Changelog</a>
|
||||
</GroupedLinks>
|
||||
<GroupedLinks>
|
||||
<a target="_blank" href="https://github.com/nickzuber/meteorite">GitHub</a>
|
||||
<a target="_blank" href="https://twitter.com/nick_zuber">Twitter</a>
|
||||
</GroupedLinks>
|
||||
<FlexBreak height={20} />
|
||||
<FooterSubtleText>
|
||||
{`© 2019 Nick Zuber – Meteorite v${version}`}
|
||||
</FooterSubtleText>
|
||||
</Container>
|
||||
</DefaultContainer>
|
||||
);
|
||||
};
|
@ -2,3 +2,4 @@ export {default as Home} from './Home';
|
||||
export {default as Notifications} from './Notifications';
|
||||
export {default as NotificationsRedesign} from './NotificationsRedesign';
|
||||
export {default as Login} from './Login';
|
||||
export {default as Pricing} from './Pricing';
|
||||
|
@ -6,7 +6,7 @@ const {Provider, Consumer} = React.createContext();
|
||||
|
||||
class AuthProvider extends React.Component {
|
||||
state = {
|
||||
token: this.props.cookiesApi.getCookie(OAUTH_TOKEN_COOKIE) || 'TOKEN'
|
||||
token: this.props.cookiesApi.getCookie(OAUTH_TOKEN_COOKIE)
|
||||
}
|
||||
|
||||
setToken = token => {
|
||||
|
@ -84,6 +84,7 @@ line[stroke="#666"] {
|
||||
|
||||
a {
|
||||
text-underline-position: under;
|
||||
transition: all 200ms ease;
|
||||
}
|
||||
|
||||
.react-tooltip {
|
||||
|
Loading…
Reference in New Issue
Block a user