Skip to content

Commit

Permalink
Improve example app layout and loading experience
Browse files Browse the repository at this point in the history
- Improved the layout by making the content fill enough space so footer
appears at the bottom.
- Improved the loading experience by reading the signed in user resource
  inside a component that is deeper in the header so that it can be
  wrapped in a suspense boundary and we can render the header as soon as
  the code loads even though the signed in user might still be loading.
  • Loading branch information
kyarik committed Dec 27, 2020
1 parent 8de1b56 commit 51e046d
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 29 deletions.
7 changes: 7 additions & 0 deletions example/src/Root/Content/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from 'styled-components';

export const Content = styled.main`
min-height: calc(100vh - 192px);
padding-bottom: 32px;
overflow: hidden;
`;
6 changes: 4 additions & 2 deletions example/src/Root/Footer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import * as React from 'react';
import styled from 'styled-components';

const Container = styled.footer`
padding: 64px;
height: 128px;
display: flex;
align-items: center;
padding: 0 32px;
background-color: lightcoral;
margin-top: 96px;
`;

export const Footer: React.VFC = () => <Container>Example App</Container>;
16 changes: 16 additions & 0 deletions example/src/Root/Header/HeaderLink/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NavLink } from 'pre-router';
import styled from 'styled-components';

export const HeaderLink = styled(NavLink)`
color: black;
font-size: 20px;
text-decoration: none;
&.active {
color: indigo;
}
& ~ & {
padding-left: 16px;
}
`;
22 changes: 22 additions & 0 deletions example/src/Root/Header/HeaderUser/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as React from 'react';
import { Resource } from 'suspendable';
import { SignedInUser } from '~/types';
import { HeaderLink } from '../HeaderLink';

interface Props {
signedInUserResource: Resource<SignedInUser>;
}

export const HeaderUser: React.VFC<Props> = ({ signedInUserResource }) => {
const signedInUser = signedInUserResource.read();

return (
<div>
{signedInUser ? (
<span>Welcome {signedInUser.name}</span>
) : (
<HeaderLink to="/sign-in">Sign in</HeaderLink>
)}
</div>
);
};
32 changes: 8 additions & 24 deletions example/src/Root/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as React from 'react';
import styled from 'styled-components';
import { NavLink } from 'pre-router';
import { Resource } from 'suspendable';
import { SignedInUser } from '~/types';
import { HeaderLink } from './HeaderLink';
import { HeaderUser } from './HeaderUser';

const Container = styled.header`
display: flex;
Expand All @@ -12,37 +14,19 @@ const Container = styled.header`
padding: 0 32px;
`;

const HeaderLink = styled(NavLink)`
color: black;
font-size: 20px;
text-decoration: none;
&.active {
color: indigo;
}
& ~ & {
padding-left: 16px;
}
`;

interface Props {
signedInUser: SignedInUser;
signedInUserResource: Resource<SignedInUser>;
}

export const Header: React.VFC<Props> = ({ signedInUser }) => (
export const Header: React.VFC<Props> = ({ signedInUserResource }) => (
<Container>
<nav>
<HeaderLink to="/">Home</HeaderLink>
<HeaderLink to="/profile">Profile</HeaderLink>
</nav>

<div>
{signedInUser ? (
<span>Welcome {signedInUser.name}</span>
) : (
<HeaderLink to="/sign-in">Sign in</HeaderLink>
)}
</div>
<React.Suspense fallback="Loading user...">
<HeaderUser signedInUserResource={signedInUserResource} />
</React.Suspense>
</Container>
);
7 changes: 4 additions & 3 deletions example/src/Root/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { RouteComponent } from 'pre-router';
import * as React from 'react';
import { Content } from './Content';
import { PreloadedRootData } from './data';
import { Footer } from './Footer';
import { Header } from './Header';

const Root: RouteComponent<PreloadedRootData> = ({ preloadedData, children }) => {
const signedInUser = preloadedData.signedInUserResource.read();
const { signedInUserResource } = preloadedData;

return (
<>
<Header signedInUser={signedInUser} />
{children}
<Header signedInUserResource={signedInUserResource} />
<Content>{children}</Content>
<Footer />
</>
);
Expand Down

0 comments on commit 51e046d

Please sign in to comment.