more semantic class names, option to globalize CSS

This commit is contained in:
Nolan Lawson 2018-01-20 12:35:38 -08:00
parent 9bb9632913
commit 692bfa8660
12 changed files with 95 additions and 46 deletions

46
bin/globalize-css.js Executable file
View file

@ -0,0 +1,46 @@
#!/usr/bin/env node
// Change all the Svelte CSS to just use globals everywhere,
// to reduce CSS size and complexity.
const argv = require('yargs').argv
const path = require('path')
const fs = require('fs')
const pify = require('pify')
const writeFile = pify(fs.writeFile.bind(fs))
const readFile = pify(fs.readFile.bind(fs))
const glob = pify(require('glob'))
const rimraf = pify(require('rimraf'))
const selectorRegex = /\n[ \t]*([0-9\w\- \t\.:#,]+?)[ \t]*\{/g
const styleRegex = /<style>[\s\S]+?<\/style>/
async function main() {
if (argv.reverse) { // reverse the operation we just did
let tmpComponents = await glob('./routes/**/.tmp-*.html')
for (let filename of tmpComponents) {
let text = await readFile(filename, 'utf8')
await rimraf(filename)
let originalFilename = path.join(path.dirname(filename), path.basename(filename).substring(5))
await writeFile(originalFilename, text, 'utf8')
}
} else { // read all files, copy to tmp files, rewrite files to include global CSS everywhere
let components = await glob('./routes/**/*.html')
for (let filename of components) {
let text = await readFile(filename, 'utf8')
let newText = text.replace(styleRegex, style => {
return style.replace(selectorRegex, selectorMatch => {
return selectorMatch.replace(/\S[^\{]+/, selector => `:global(${selector})`)
})
})
let newFilename = path.join(path.dirname(filename), '.tmp-' + path.basename(filename))
await writeFile(newFilename, text, 'utf8')
await writeFile(filename, newText, 'utf8')
}
}
}
Promise.resolve().then(main).catch(err => {
console.error(err)
process.exit(1)
})

View file

@ -10,7 +10,9 @@
"build-sass-watch": "node ./bin/build-sass --watch", "build-sass-watch": "node ./bin/build-sass --watch",
"cy:run": "cypress run", "cy:run": "cypress run",
"cy:open": "cypress open", "cy:open": "cypress open",
"test": "run-p --race dev cy:run" "test": "run-p --race dev cy:run",
"globalize-css": "node ./bin/globalize-css.js",
"deglobalize-css": "node ./bin/globalize-css.js --reverse"
}, },
"dependencies": { "dependencies": {
"chokidar": "^2.0.0", "chokidar": "^2.0.0",
@ -36,6 +38,7 @@
"performance-now": "^2.1.0", "performance-now": "^2.1.0",
"pify": "^3.0.0", "pify": "^3.0.0",
"requestidlecallback": "^0.3.0", "requestidlecallback": "^0.3.0",
"rimraf": "^2.6.2",
"sapper": "^0.3.2", "sapper": "^0.3.2",
"serve-static": "^1.13.1", "serve-static": "^1.13.1",
"style-loader": "^0.19.1", "style-loader": "^0.19.1",

View file

@ -1,15 +1,15 @@
<svg class="{{maskStyle ? 'mask-style' : ''}}"> <svg class="loading-spinner-icon {{maskStyle ? 'mask-style' : ''}}">
<use xlink:href="#fa-spinner" /> <use xlink:href="#fa-spinner" />
</svg> </svg>
<style> <style>
svg { .loading-spinner-icon {
width: 64px; width: 64px;
height: 64px; height: 64px;
fill: var(--svg-fill); fill: var(--svg-fill);
animation: spin 2s infinite linear; animation: spin 2s infinite linear;
} }
svg.mask-style { .loading-spinner-icon.mask-style {
fill: var(--mask-svg-fill); fill: var(--mask-svg-fill);
} }

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 600 B

View file

@ -1,4 +1,4 @@
<nav> <nav class="main-nav">
<ul> <ul>
<li> <li>
<NavItem :page name="home" href="/" svg="#pinafore-logo" label="Home" /> <NavItem :page name="home" href="/" svg="#pinafore-logo" label="Home" />
@ -19,7 +19,7 @@
</nav> </nav>
<style> <style>
nav { .main-nav {
border-bottom: 1px solid var(--nav-border); border-bottom: 1px solid var(--nav-border);
background: var(--nav-bg); background: var(--nav-bg);
position: fixed; position: fixed;
@ -29,7 +29,7 @@
z-index: 10; z-index: 10;
} }
ul { .main-nav ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
@ -38,7 +38,7 @@
} }
@media (max-width: 767px) { @media (max-width: 767px) {
li { .main-nav li {
flex-basis: 100%; flex-basis: 100%;
} }
} }

View file

@ -1,4 +1,4 @@
<a class='{{page === name ? "selected" : ""}}' <a class='main-nav-link {{page === name ? "selected" : ""}}'
aria-label='{{page === name ? `${label} (current page)` : label}}' aria-label='{{page === name ? `${label} (current page)` : label}}'
aria-current="{{page === name}}" aria-current="{{page === name}}"
href='{{href}}'> href='{{href}}'>
@ -8,7 +8,7 @@
<span>{{label}}</span> <span>{{label}}</span>
</a> </a>
<style> <style>
a { .main-nav-link {
border-bottom: 1px solid var(--nav-a-border); border-bottom: 1px solid var(--nav-a-border);
text-decoration: none; text-decoration: none;
padding: 25px 20px; padding: 25px 20px;
@ -17,46 +17,46 @@
align-items: center; align-items: center;
} }
a.selected { .main-nav-link.selected {
border-bottom: 1px solid var(--nav-a-selected-border); border-bottom: 1px solid var(--nav-a-selected-border);
background: var(--nav-a-selected-bg); background: var(--nav-a-selected-bg);
} }
a.selected:hover { .main-nav-link.selected:hover {
border-bottom: 1px solid var(--nav-a-selected-border-hover); border-bottom: 1px solid var(--nav-a-selected-border-hover);
background: var(--nav-a-selected-bg-hover); background: var(--nav-a-selected-bg-hover);
} }
a:hover { .main-nav-link:hover {
background-color: var(--nav-a-bg-hover); background-color: var(--nav-a-bg-hover);
border-bottom: 1px solid var(--nav-a-border-hover); border-bottom: 1px solid var(--nav-a-border-hover);
} }
a:hover span { .main-nav-link:hover span {
color: var(--nav-text-color-hover); color: var(--nav-text-color-hover);
} }
a:hover svg { .main-nav-link:hover svg {
fill: var(--nav-svg-fill-hover); fill: var(--nav-svg-fill-hover);
} }
svg { .main-nav-link svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
display: inline-block; display: inline-block;
fill: var(--nav-svg-fill); fill: var(--nav-svg-fill);
} }
span { .main-nav-link span {
font-size: 16px; font-size: 16px;
color: var(--nav-text-color); color: var(--nav-text-color);
padding-left: 10px; padding-left: 10px;
} }
@media (max-width: 767px) { @media (max-width: 767px) {
span { .main-nav-link span {
display: none; display: none;
} }
svg { .main-nav-link svg {
width: 25px; width: 25px;
height: 25px; height: 25px;
} }

View file

@ -17,18 +17,18 @@
.not-logged-in-home { .not-logged-in-home {
margin: 10px; margin: 10px;
} }
.banner { .not-logged-in-home .banner {
display: flex; display: flex;
align-items: center; align-items: center;
margin: 0 0 30px; margin: 0 0 30px;
} }
svg { .not-logged-in-home svg {
width: 70px; width: 70px;
height: 70px; height: 70px;
fill: royalblue; fill: royalblue;
display: inline-block; display: inline-block;
} }
h1 { .not-logged-in-home h1 {
color: royalblue; color: royalblue;
display: inline-block; display: inline-block;
font-size: 3em; font-size: 3em;
@ -36,7 +36,7 @@
} }
@media (max-width: 767px) { @media (max-width: 767px) {
h1 { .not-logged-in-home h1 {
font-size: 2.7em; font-size: 2.7em;
} }
} }

View file

@ -13,7 +13,7 @@
pointer-events: none; pointer-events: none;
/* will-change: transform; */ /* causes jank in mobile Firefox */ /* will-change: transform; */ /* causes jank in mobile Firefox */
} }
.shown { .virtual-list-item.shown {
opacity: 1; opacity: 1;
pointer-events: auto; pointer-events: auto;
} }

View file

@ -1,8 +1,8 @@
<ul> <ul class="settings-list">
<slot></slot> <slot></slot>
</ul> </ul>
<style> <style>
ul { ul.settings-list {
list-style: none; list-style: none;
width: 100%; width: 100%;
border: 1px solid var(--settings-list-item-border); border: 1px solid var(--settings-list-item-border);
@ -10,7 +10,7 @@
} }
@media (min-width: 768px) { @media (min-width: 768px) {
ul { ul.settings-list {
max-width: 80%; max-width: 80%;
} }
} }

View file

@ -1,4 +1,4 @@
<li> <li class="settings-list-item">
<a :href> <a :href>
{{#if icon}} {{#if icon}}
<svg> <svg>
@ -11,36 +11,36 @@
</a> </a>
</li> </li>
<style> <style>
li { li.settings-list-item {
border: 1px solid var(--settings-list-item-border); border: 1px solid var(--settings-list-item-border);
font-size: 1.3em; font-size: 1.3em;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
a { .settings-list-item a {
display: flex; display: flex;
padding: 20px; padding: 20px;
background: var(--settings-list-item-bg); background: var(--settings-list-item-bg);
} }
a, a:visited { .settings-list-item a, .settings-list-item a:visited {
color: var(--settings-list-item-text); color: var(--settings-list-item-text);
} }
a:hover { .settings-list-item a:hover {
text-decoration: none; text-decoration: none;
background: var(--settings-list-item-bg-hover); background: var(--settings-list-item-bg-hover);
color: var(--settings-list-item-text-hover); color: var(--settings-list-item-text-hover);
} }
a:active { .settings-list-item a:active {
background: var(--settings-list-item-bg-active); background: var(--settings-list-item-bg-active);
} }
svg { .settings-list-item svg {
width: 24px; width: 24px;
height: 24px; height: 24px;
display: inline-block; display: inline-block;
margin-right: 20px; margin-right: 20px;
fill: var(--svg-fill); fill: var(--svg-fill);
} }
.offset-for-icon { .settings-list-item .offset-for-icon {
margin-left: 44px; margin-left: 44px;
} }

View file

@ -1,4 +1,4 @@
<nav> <nav class="settings-nav">
<ul> <ul>
{{#each navItems as navItem}} {{#each navItems as navItem}}
<li> <li>
@ -12,25 +12,25 @@
</nav> </nav>
<style> <style>
ul { .settings-nav ul {
margin: 5px 20px; margin: 5px 20px;
padding: 0; padding: 0;
list-style: none; list-style: none;
} }
li { .settings-nav li {
margin: 5px 0; margin: 5px 0;
font-size: 1em; font-size: 1em;
display: inline-block; display: inline-block;
} }
li::after { .settings-nav li::after {
content: '>'; content: '>';
margin: 0 15px; margin: 0 15px;
color: var(--anchor-text); color: var(--anchor-text);
} }
li:last-child::after { .settings-nav li:last-child::after {
content: ''; content: '';
margin-left: 0; margin-left: 0;
font-size: 1em; font-size: 1em;

View file

@ -1,12 +1,12 @@
<a class='{{getCurrentClass(page, name)}}' aria-label='{{getAriaLabel(page, name, label)}}' href='{{href}}'> <a class='settings-nav-item {{getCurrentClass(page, name)}}' aria-label='{{getAriaLabel(page, name, label)}}' href='{{href}}'>
{{label}} {{label}}
</a> </a>
<style> <style>
a { a.settings-nav-item {
font-size: 1.2em; font-size: 1.2em;
} }
a.selected { a.settings-nav-item.selected {
font-weight: 600; font-weight: 600;
} }
</style> </style>

View file

@ -16,7 +16,7 @@
<form class="add-new-instance" on:submit='onSubmit(event)' aria-labelledby="add-an-instance-h1"> <form class="add-new-instance" on:submit='onSubmit(event)' aria-labelledby="add-an-instance-h1">
<label for="instanceInput">Instance:</label> <label for="instanceInput">Instance:</label>
<input type="text" id="instanceInput" bind:value='$instanceNameInSearch' placeholder=''> <input class="new-instance-input" type="text" id="instanceInput" bind:value='$instanceNameInSearch' placeholder=''>
<button class="primary" type="submit" id="submitButton" disabled="{{!$instanceNameInSearch}}">Add instance</button> <button class="primary" type="submit" id="submitButton" disabled="{{!$instanceNameInSearch}}">Add instance</button>
</form> </form>
@ -27,12 +27,12 @@
</Layout> </Layout>
<style> <style>
@media (max-width: 767px) { @media (max-width: 767px) {
input { input.new-instance-input {
max-width: 90%; max-width: 90%;
} }
} }
input { input.new-instance-input {
min-width: 50%; min-width: 50%;
max-width: 100%; max-width: 100%;
} }