This commit is contained in:
Arwed Mett 2018-02-16 20:52:28 +01:00
parent fdac043d4b
commit d8d75ab752
10 changed files with 143 additions and 48 deletions

View File

@ -1,22 +1,27 @@
//@flow
import React from "react"
import { Header, Projects, Contact } from "./components"
import { Body, Section, Content } from "./elements"
import { Body, Section, content } from "./elements"
import NoscriptWarning from "./noscript"
import { ThemeProvider } from "styled-components"
import { Dark } from "./themes"
const projects = {
title: "My Projects",
body: () => <Projects />
}
const contact = {
title: "Contact",
body: () => <Contact />
}
export default () => <ThemeProvider theme={ Dark }>
<Body>
<NoscriptWarning />
<Header />
<Content>
<Section title="My Projects">
<Projects />
</Section>
<Section title="Contact">
<Contact />
</Section>
</Content>
{ content([
projects,
contact
]) }
</Body>
</ThemeProvider>

View File

@ -1,39 +1,90 @@
//@flow
import React, { Component, Node } from "react"
import React, { Component } from "react"
import type { Node } from "react"
import { Section } from "."
import type { SectionDescription } from "."
import styled from "styled-components"
import Observer from "@researchgate/react-intersection-observer"
type LinkProps = {
title: String,
target: Node
}
const Link = styled.a`
text-decoration: inherit;
color: white;
min-height: 40px;
display: flex;
align-items: center;
padding: 0 20px;
type LinkState = {
target: Node
}
transition: 0.3s ease;
:hover {
background-color: #777;
class Link extends Component<LinkProps, LinkState> {
constructor(props) {
super(props)
const { target } = props
this.setState({ target })
}
}
`
type ContentProps = {
children: React.Node
}
const Header = styled.header.attrs({
backgroundcolor: props => props.theme.backgroundcolor || "#111111"
})`
position: sticky;
top: 0;
display: flex;
justify-content: left;
align-items: center;
width: 60%;
z-index: 5;
margin: 20px auto;
min-height: 40px;
border-bottom: solid white;
background-color: ${ props => props.backgroundcolor };
`
type ContentState = {
/**
* create a hash based on the section title
*/
const get_hash = (section: SectionDescription, key: number) =>
key + "-" + section.title.toLocaleLowerCase().split(" ").join("-")
}
/**
* create a link to the section, according to the name and key.
*/
const create_link = (section: SectionDescription, key: number) =>
<Link href={ "#" + get_hash(section, key) } key={ key }>{ section.title }</Link>
class Content extends Component<ContentProps, ContentState> {
render() {
const { children } = this.props
return <div>
{ children }
</div>
}
}
/**
* create a link for every section.
*/
const generate_links = (sections: Array<SectionDescription>) => sections.map(create_link)
export default Content
/**
* transform a section description intto a section.
*/
const create_section = (description: SectionDescription, key: number) =>
<Section
description={ description }
hash={ get_hash(description, key) }
key={ key }
/>
/**
* create a list of sections from their description.
*/
const generate_sections = (descriptions: Array<SectionDescription>) =>
descriptions.map(create_section)
const Sentinel = styled.div`
width: 100%;
height: 1px;
`
const test = () => alert("test")
export default (sections: Array<SectionDescription>) => <div>
<Observer onChange={ test } root="body" rootMargin="0% 0% 0% 0%">
<Sentinel />
</Observer>
<Header onWheel={ test }>
{ generate_links(sections) }
</Header>
{ generate_sections(sections) }
</div>

View File

@ -6,13 +6,10 @@ export {
Name as HeaderName
} from "./header"
export {
Body
} from "./body"
export { Body } from "./body"
export {
default as Section
} from "./section"
export { default as Section } from "./section"
export type { SectionDescription } from "./section"
export {
default as Project,
@ -23,4 +20,5 @@ export {
H1, H2, Title, P
} from "./text"
export { default as Content } from "./content"
export { default as content } from "./content"

View File

@ -18,8 +18,13 @@ const Style = styled.section`
const Title = H1
export default (props: { title: string, children?: Node }) => <Style>
<Title>{ props.title }</Title>
export type SectionDescription = {
title: string,
body: () => Node
}
export default (props: { description: SectionDescription, hash: string }) => <Style>
<Title id={ props.hash || "" }>{ props.description.title }</Title>
<br />
<div>{ props.children }</div>
<div>{ props.description.body() }</div>
</Style>

3
src/util/index.js Normal file
View File

@ -0,0 +1,3 @@
//@flow
export { default as map } from "./map"

4
src/util/map.js Normal file
View File

@ -0,0 +1,4 @@
//@flow
export default <A, B>(f: (A, number) => B) => (elements: Array<A>) => elements.map(f)

View File

@ -0,0 +1,7 @@
//@flow
import util from "./util"
describe("homepage", () => {
util()
})

9
test/util/index.js Normal file
View File

@ -0,0 +1,9 @@
//@flow
import map from "./map"
export default () => {
describe("util", () => {
map()
})
}

13
test/util/map.js Normal file
View File

@ -0,0 +1,13 @@
//@flow
import { map } from "../../src/util"
import assert from "assert"
export default () => {
describe("map", () => {
const numbers = [1, 2, 3, 4, 5, 6, 7]
const numbers_plus_1 = map(x => x + 1)(numbers)
it("add one to all members", () => {
assert.deepEqual(numbers_plus_1, [2, 3, 4, 5, 6, 7, 8])
})
})
}

View File

@ -102,7 +102,7 @@ const development = config => Object.assign({ }, config(), {
stats: 'errors-only',
host: process.env.HOST,
port: 3000,
port: 5000,
compress: true,
overlay: true,
hot: true,