1
Fork 0

typescript(og-website): basic projects page

Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
Matei Adriel 2019-10-20 14:20:54 +03:00 committed by prescientmoon
parent 4b9d6c80ad
commit 79fea699a7
Signed by: prescientmoon
SSH key fingerprint: SHA256:UUF9JT2s8Xfyv76b8ZuVL7XrmimH4o49p4b+iexbVH4
15 changed files with 165 additions and 36 deletions

View file

@ -3,8 +3,9 @@ import { withCss } from '../helpers/withCss'
import { Nav } from './Nav'
import { buttons } from '../constants/navButtons'
import { LayoutOptions } from '../types/LayoutOptions'
import { ServiceWorker } from './ServiceWorker'
export const Layout = ({ title, body }: LayoutOptions) => html`
export const Layout = ({ title, body, url }: LayoutOptions) => html`
<!DOCTYPE html>
<html lang="en">
<head>
@ -14,8 +15,10 @@ export const Layout = ({ title, body }: LayoutOptions) => html`
${withCss('layout', 'config')}
</head>
<body class="background">
${Nav(buttons)}
${Nav(buttons, url)}
<div id="page-content">${body}</div>
${ServiceWorker('/static/js/service-worker.js')}
</body>
</html>
`

View file

@ -2,17 +2,23 @@ import { TemplateResult, html } from '@popeindustries/lit-html-server'
import { withCss } from '../helpers/withCss'
import { UrlConfig } from '../types/UrlConfig'
export const NavButtons = (config: UrlConfig) => html`
<a class="nav-button" href=${config.url}>${config.name}</a>
`
export const NavButtons = (config: UrlConfig, url: string) => {
const className = ['nav-button', config.url === url && 'glow']
.filter(Boolean)
.join(' ')
export const Nav = (buttons: UrlConfig[]) =>
return html`
<a class=${className} href=${config.url}>${config.name}</a>
`
}
export const Nav = (buttons: UrlConfig[], url: string) =>
html`
${withCss('nav')}
<div id="nav">
<div id="nav-buttons">
${buttons.map(NavButtons)}
${buttons.map(button => NavButtons(button, url))}
</div>
</div>
`

View file

@ -8,7 +8,8 @@ export const Project = (project: ProjectConfig) => {
return html`
<div class="project">
<div class="project-thumbail background" style=${style}></div>
<div class="project-icons">
<div class="project-name">${project.name}</div>
<div class="project-links">
<a class="project-source" href=${project.source}>Source</a>
<a class="project-demo" href=${project.demo}>Demo</a>
</div>

View file

@ -0,0 +1,11 @@
import { html } from '@popeindustries/lit-html-server'
export const ServiceWorker = (url: string) => html`
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('${url}')
})
}
</script>
`

View file

@ -1,16 +1,22 @@
import { UrlConfig } from '../types/UrlConfig'
import { Home } from '../components/Home'
import { Projects } from '../components/Projects'
import { html } from '@popeindustries/lit-html-server'
export const buttons: UrlConfig[] = [
{
url: '/',
name: 'Home'
name: 'Home',
component: Home
},
{
url: '/projects',
name: 'Projects'
name: 'Projects',
component: Projects
},
{
url: '/blog',
name: 'Blog'
name: 'Blog',
component: () => html``
}
]

View file

@ -5,10 +5,11 @@ import { Response } from 'express'
export const createComponentRenderer = (
layout: (options: LayoutOptions) => TemplateResult,
name: string
) => (res: Response, { body, title }: LayoutOptions) => {
) => (res: Response, { body, title, url }: LayoutOptions) => {
renderToStream(
layout({
body,
url,
title: `${name} | ${title}`
})
).pipe(res)

View file

@ -2,8 +2,7 @@ import express from 'express'
import { Layout } from './components/Layout'
import { resolve } from 'path'
import { createPageMiddlewareFactory } from './middleware/servePage'
import { Home } from './components/Home'
import { Projects } from './components/Projects'
import { buttons } from './constants/navButtons'
const port = process.env.PORT || 8080
const app = express()
@ -12,21 +11,16 @@ const renderComponent = createPageMiddlewareFactory(Layout, 'Matei Adriel')
app.use('/static', express.static(resolve(__dirname, 'static')))
app.get(
'/',
renderComponent({
body: Home(),
title: 'Home'
})
)
app.get(
'/projects',
renderComponent({
body: Projects(),
title: 'Projects'
})
)
for (const button of buttons) {
app.get(
button.url,
renderComponent({
body: button.component(),
title: button.name,
url: button.url
})
)
}
app.listen(port, () => {
console.log(`Listening on port ${port}`)

View file

@ -6,4 +6,8 @@
--on-bg: white;
--title-font: 'Permanent Marker', cursive;
--home-bg: url(https://cdn.discordapp.com/attachments/485859146558865408/635409620537442325/Wallpaper_space_galaxy_planet_4k_Space_8652415352.jpg);
--glow-color-1: white;
--glow-color-2: cyan;
--glow-color-3: blue;
--glow-duration: 2s;
}

View file

@ -1,7 +1,3 @@
div#nav {
position: absolute;
}
div#home-title {
max-width: 80%;
font-size: 3em;

View file

@ -1,6 +1,7 @@
div#nav {
width: 100%;
padding: var(--spacing, 1rem);
position: absolute;
}
div#nav-buttons {
@ -11,3 +12,8 @@ a.nav-button {
margin: var(--spacing, 1rem);
font-family: var(--title-font);
}
a.nav-button:hover {
animation: glow var(--glow-duration, 1s) ease-in-out infinite alternate;
--glow-color-3: red;
}

View file

@ -1,11 +1,38 @@
div.project-thumbail {
width: 100px;
height: 100px;
width: 200px;
height: 200px;
display: block;
margin: var(--spacing, 1rem);
}
div.project {
background-color: var(--bg-raised, black);
margin: var(--spacing, 1rem);
border-radius: var(--spacing, 1rem);
}
div.project > div {
margin: var(--spacing, 1rem);
text-align: center;
box-sizing: border-box;
}
div.project-name {
border-bottom: 1px solid #777777;
padding-bottom: var(--spacing, 1rem);
}
div.project-links {
display: flex;
flex-direction: row;
justify-content: space-evenly;
}
div#projects {
flex-direction: row;
flex-wrap: wrap;
font-family: var(--title-font);
}
div.project-links *:hover {
animation: glow var(--glow-duration, 1s) ease-in-out infinite alternate;
}

View file

@ -15,3 +15,28 @@
justify-content: center;
align-items: center;
}
.glow {
animation: glow var(--glow-duration, 1s) ease-in-out infinite alternate;
}
@keyframes glow {
from {
text-shadow: 0 0 10px var(--glow-color-1, white),
0 0 20px var(--glow-color-1, white),
0 0 30px var(--glow-color-2, white),
0 0 40px var(--glow-color-2, white),
0 0 50px var(--glow-color-2, white),
0 0 60px var(--glow-color-2, white),
0 0 70px var(--glow-color-2, white);
}
to {
text-shadow: 0 0 20px var(--glow-color-1, white),
0 0 30px var(--glow-color-3, white),
0 0 40px var(--glow-color-3, white),
0 0 50px var(--glow-color-3, white),
0 0 60px var(--glow-color-3, white),
0 0 70px var(--glow-color-3, white),
0 0 80px var(--glow-color-3, white);
}
}

View file

@ -0,0 +1,45 @@
importScripts(
'https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js'
)
if (workbox) {
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
workbox.routing.registerRoute(
/^https:\/\/fonts\.googleapis\.com/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'google-fonts-stylesheets'
})
)
// Cache the underlying font files with a cache-first strategy for 1 year.
workbox.routing.registerRoute(
/^https:\/\/fonts\.gstatic\.com/,
new workbox.strategies.CacheFirst({
cacheName: 'google-fonts-webfonts',
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200]
}),
new workbox.expiration.Plugin({
maxAgeSeconds: 60 * 60 * 24 * 365,
maxEntries: 30
})
]
})
)
workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|webp|svg)$/,
new workbox.strategies.CacheFirst({
cacheName: 'images',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60 // 30 Days
})
]
})
)
} else {
console.log(`Boo! Workbox didn't load 😬`)
}

View file

@ -2,5 +2,6 @@ import { TemplateResult } from '@popeindustries/lit-html-server'
export interface LayoutOptions {
title: string
url: string
body: TemplateResult | string
}

View file

@ -1,4 +1,7 @@
import { TemplateResult } from '@popeindustries/lit-html-server'
export interface UrlConfig {
url: string
name: string
component: () => TemplateResult
}