From 4ce68de7c59e42c67754e42ef7b6d7b2038f2393 Mon Sep 17 00:00:00 2001 From: Rowan Hogan Date: Sat, 8 Sep 2018 17:13:55 +1000 Subject: [PATCH] Add table of contents --- src/components/Loading/index.js | 2 +- src/components/page/index.js | 15 ++-- src/components/search/index.js | 3 +- src/components/sections/index.js | 48 ++++++++++++ src/lib/api/index.js | 7 +- src/routes/home/index.js | 17 ++-- src/routes/media/index.js | 51 ++++++++---- src/styles/_layout.scss | 128 ++++++++++++++++++++++++++++--- src/styles/_loading.scss | 4 +- src/styles/_page.scss | 24 ++++-- src/styles/_thumbs.scss | 5 +- src/styles/_typography.scss | 19 ++++- 12 files changed, 269 insertions(+), 54 deletions(-) create mode 100644 src/components/sections/index.js diff --git a/src/components/Loading/index.js b/src/components/Loading/index.js index 18be486..e92f5a1 100644 --- a/src/components/Loading/index.js +++ b/src/components/Loading/index.js @@ -1,6 +1,6 @@ import React from 'react' -export default ({ title }) => ( +export default ({ title = '' }) => (

{title.replace(/_/g, ' ')}

diff --git a/src/components/page/index.js b/src/components/page/index.js index de2cc16..978bd40 100644 --- a/src/components/page/index.js +++ b/src/components/page/index.js @@ -1,7 +1,9 @@ import React, { Component } from 'react' import { withRouter } from 'react-router-dom' import { fetchPage } from '../../lib/api' -import Loading from '../../components/loading' + +import Loading from '../loading' +import Sections from '../sections' class Page extends Component { constructor(props) { @@ -11,7 +13,7 @@ class Page extends Component { loading: false, title: '', content: undefined, - sections: undefined + sections: [] } } @@ -52,10 +54,11 @@ class Page extends Component { } render() { - const { loading, title, content, error } = this.state + const { content, error, loading, sections, title } = this.state return (
+ {sections.length ? : null} {loading && } {content ? (
@@ -67,12 +70,10 @@ class Page extends Component {
) : error ? (
-

Error

+

Error

{error}
- ) : ( -

{title}

- )} + ) : null}
) } diff --git a/src/components/search/index.js b/src/components/search/index.js index 3782609..abdafa8 100644 --- a/src/components/search/index.js +++ b/src/components/search/index.js @@ -105,8 +105,7 @@ class Search extends Component { 'search-result', selected === index ? 'active' : undefined ].join(' ')} - key={index} - onClick={() => this.setState({ open: false })}> + key={index}>

{result.title}

{result.description} diff --git a/src/components/sections/index.js b/src/components/sections/index.js new file mode 100644 index 0000000..b7c7a60 --- /dev/null +++ b/src/components/sections/index.js @@ -0,0 +1,48 @@ +import React, { Component } from 'react' +import OutsideClickHandler from 'react-outside-click-handler' + +class Sections extends Component { + constructor(props) { + super(props) + + this.state = { + open: false + } + } + + render() { + const { sections } = this.props + const { open } = this.state + + return ( + this.setState({ open: false })}> +

+ + {open && ( + + )} +
+ + ) + } +} + +export default Sections diff --git a/src/lib/api/index.js b/src/lib/api/index.js index cb90c7a..18a9906 100644 --- a/src/lib/api/index.js +++ b/src/lib/api/index.js @@ -38,7 +38,12 @@ export const fetchMedia = title => if (error) { return reject(error) } else { - return resolve(query.pages[-1]) + const data = lodashGet(query, 'pages[-1]') + + return resolve({ + title: data.title, + content: lodashGet(data, 'imageinfo[0]') + }) } }) ) diff --git a/src/routes/home/index.js b/src/routes/home/index.js index 1170240..1b9bba1 100644 --- a/src/routes/home/index.js +++ b/src/routes/home/index.js @@ -2,14 +2,15 @@ import React from 'react' import Page from '../../components/page' export default () => ( -
-

Wikipadia

- -
-

- WikiPadia is a beautiful, customisable Wikipedia reader. It was - specifically built for leisurely reading on an iPad. -

+
+
+

Wikipadia

+
+

+ WikiPadia is a beautiful, customisable Wikipedia reader. It + was specifically built for leisurely reading on an iPad. +

+
diff --git a/src/routes/media/index.js b/src/routes/media/index.js index 6aa5587..3ee5592 100644 --- a/src/routes/media/index.js +++ b/src/routes/media/index.js @@ -1,24 +1,25 @@ import React, { Component } from 'react' +import keys from 'lodash/keys' import { fetchMedia } from '../../lib/api' +import Loading from '../../components/loading' + export default class extends Component { constructor(props) { super(props) + const { match: { params: { title } } } = props this.state = { loading: false, - title: props.title, - content: undefined, - sections: undefined + title } } componentDidMount() { - const { match: { params: { title } } } = this.props - return this.fetchPage(title) + return this.fetchPage(this.state.title) } - fetchPage = title => { + fetchPage(title) { this.setState({ loading: true }) return fetchMedia(`File:${decodeURIComponent(title)}`) @@ -42,22 +43,42 @@ export default class extends Component { render() { const { loading, title, content, error } = this.state + console.log(content) + return ( -
- {loading &&

Loading…

} - {content ? ( -
-

{title}

-
+
+ {loading ? ( + + ) : content ? ( +
+

{title}

+ +
+ + {title} + +
+ {keys(content.extmetadata).map(key => { + return ( +
+
{key}
+
+
+ ) + })} +
+
) : error ? (

Error

{error}
- ) : ( -

{title}

- )} + ) : null}
) } diff --git a/src/styles/_layout.scss b/src/styles/_layout.scss index 24839cb..104fb5b 100644 --- a/src/styles/_layout.scss +++ b/src/styles/_layout.scss @@ -19,6 +19,7 @@ display: flex; justify-content: space-between; z-index: 5; + padding-right: $header-height - 0.5rem; &.hidden { transform: translateY(-100%); @@ -35,7 +36,7 @@ height: $header-height; text-indent: -9999px; overflow: hidden; - color: $color-dark; + color: currentColor; &:before { content: 'W'; @@ -78,12 +79,6 @@ outline: 0; } } - - button { - position: absolute; - top: 0; - right: 0; - } } .search-results { @@ -104,7 +99,6 @@ display: block; padding: 1rem; line-height: 1; - font-size: 0.75rem; border-top: thin solid rgba(black, 0.1); color: inherit; text-decoration: none; @@ -131,7 +125,7 @@ } .search-result-title { - font-size: inherit; + font-size: 0.9rem; font-family: $title-stack; margin: 0; } @@ -139,6 +133,7 @@ .search-result-description { margin: 0.5rem 0 0; opacity: 0.5; + font-size: 0.75rem; &:first-letter { text-transform: capitalize; @@ -150,3 +145,118 @@ padding: 3rem 1rem; opacity: 0.5; } + +.page-sections { + position: fixed; + top: 0; + right: 0; + z-index: 10; +} + +$bar-height: 0.166rem; + +.page-sections-button { + position: relative; + width: $header-height; + height: $header-height; + background-color: transparent; + padding: 0; + border: 0; + text-indent: -9999px; + text-align: left; + overflow: hidden; + outline: 0; + opacity: 0.75; + cursor: pointer; + color: currentColor; + + &:before, + &:after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: $header-height / 2.5; + height: $bar-height; + background: currentColor; + border-radius: 1rem; + transition: all 100ms ease; + } + + &:before { + transform: translate(-50%, -275%); + box-shadow: 0 ($bar-height * 4.5); + } + + &:after { + transform: translate(-50%, -50%); + } +} + +.page-sections.active { + .page-sections-button { + &:before { + transform: translate(-50%, -50%) rotate(-45deg); + box-shadow: none; + } + + &:after { + transform: translate(-50%, -50%) rotate(45deg); + } + } +} + +.page-sections-nav { + position: absolute; + top: 85%; + right: 0.75rem; + background-color: white; + width: 16rem; + max-width: calc(100vw - 1.5rem); + max-height: calc(95vh - #{$header-height}); + overflow: auto; + box-shadow: 0 0.25rem 2rem rgba(black, 0.125); + border-radius: 0.25rem; + + a { + display: block; + padding: 0.666rem 1rem; + font-size: 0.8rem; + color: currentColor; + text-decoration: none; + border-top: thin solid rgba(black, 0.1); + + &:first-child { + border-top-width: 0; + } + + &:visited { + color: currentColor; + } + + &:hover, + &:active { + background-color: rgba(black, 0.075); + } + + span { + opacity: 0.5; + font-size: 80%; + } + + .section-level-2 { + margin-left: 0.5rem; + } + + .section-level-3, + .section-level-4, + .section-level-5 { + margin-left: 1rem; + } + + label { + font-family: $title-stack; + margin-left: 0.5rem; + } + } +} diff --git a/src/styles/_loading.scss b/src/styles/_loading.scss index b7549c2..c47f575 100644 --- a/src/styles/_loading.scss +++ b/src/styles/_loading.scss @@ -10,8 +10,8 @@ content: ''; position: absolute; top: 5rem; - left: 10%; - right: 10%; + left: 5%; + right: 5%; height: 40vh; } diff --git a/src/styles/_page.scss b/src/styles/_page.scss index eb5ef6d..d20202f 100644 --- a/src/styles/_page.scss +++ b/src/styles/_page.scss @@ -5,10 +5,6 @@ $sidebar-width: 20rem; .root { counter-reset: section; - // table.vertical-navbox { - // display: none; - // } - p:first-of-type { b { font-family: 'Playfair Display', 'PT Serif', 'Lora', Georgia, serif; @@ -58,8 +54,8 @@ $sidebar-width: 20rem; > .hatnote:first-child + div.hatnote { text-align: center; font-size: 0.75em; - margin-top: -1rem; - margin-bottom: 2rem; + margin: -1rem auto 2rem; + max-width: 32rem; opacity: 0.75; } @@ -147,10 +143,21 @@ table { max-width: 100%; } + th[colspan='2'], .adr, .fn { font-weight: bold; text-align: center; + padding: 1rem; + } + + td[colspan='2'] { + text-align: center; + } + + th[scope='row'] { + text-align: right; + padding-right: 1.5rem; } th, @@ -332,5 +339,8 @@ pre { .reflist { font-size: 75%; - column-count: 2; + + @media (min-width: 48rem) { + column-count: 2; + } } diff --git a/src/styles/_thumbs.scss b/src/styles/_thumbs.scss index 098f0e3..06336a4 100644 --- a/src/styles/_thumbs.scss +++ b/src/styles/_thumbs.scss @@ -9,11 +9,14 @@ .thumbcaption { font-size: 75%; + margin: 1rem auto; line-height: 1.5em; + max-width: 32rem; + opacity: 0.75; } } -.infobox .image, +.infobox :only-child > .image, .thumb { display: block; diff --git a/src/styles/_typography.scss b/src/styles/_typography.scss index 81f1fc1..052ee80 100644 --- a/src/styles/_typography.scss +++ b/src/styles/_typography.scss @@ -48,6 +48,23 @@ h6 { } h1, -h2 { +h2, +.center { text-align: center; } + +dt, +dd { + display: block; + padding: 0; + margin: 1rem 0; +} + +dt { + font-weight: bold; + font-family: $title-stack; +} + +sup.reference { + font-size: x-small; +}