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",
"cy:run": "cypress run",
"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": {
"chokidar": "^2.0.0",
@ -36,6 +38,7 @@
"performance-now": "^2.1.0",
"pify": "^3.0.0",
"requestidlecallback": "^0.3.0",
"rimraf": "^2.6.2",
"sapper": "^0.3.2",
"serve-static": "^1.13.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" />
</svg>
<style>
svg {
.loading-spinner-icon {
width: 64px;
height: 64px;
fill: var(--svg-fill);
animation: spin 2s infinite linear;
}
svg.mask-style {
.loading-spinner-icon.mask-style {
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>
<li>
<NavItem :page name="home" href="/" svg="#pinafore-logo" label="Home" />
@ -19,7 +19,7 @@
</nav>
<style>
nav {
.main-nav {
border-bottom: 1px solid var(--nav-border);
background: var(--nav-bg);
position: fixed;
@ -29,7 +29,7 @@
z-index: 10;
}
ul {
.main-nav ul {
margin: 0;
padding: 0;
list-style: none;
@ -38,7 +38,7 @@
}
@media (max-width: 767px) {
li {
.main-nav li {
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-current="{{page === name}}"
href='{{href}}'>
@ -8,7 +8,7 @@
<span>{{label}}</span>
</a>
<style>
a {
.main-nav-link {
border-bottom: 1px solid var(--nav-a-border);
text-decoration: none;
padding: 25px 20px;
@ -17,46 +17,46 @@
align-items: center;
}
a.selected {
.main-nav-link.selected {
border-bottom: 1px solid var(--nav-a-selected-border);
background: var(--nav-a-selected-bg);
}
a.selected:hover {
.main-nav-link.selected:hover {
border-bottom: 1px solid var(--nav-a-selected-border-hover);
background: var(--nav-a-selected-bg-hover);
}
a:hover {
.main-nav-link:hover {
background-color: var(--nav-a-bg-hover);
border-bottom: 1px solid var(--nav-a-border-hover);
}
a:hover span {
.main-nav-link:hover span {
color: var(--nav-text-color-hover);
}
a:hover svg {
.main-nav-link:hover svg {
fill: var(--nav-svg-fill-hover);
}
svg {
.main-nav-link svg {
width: 20px;
height: 20px;
display: inline-block;
fill: var(--nav-svg-fill);
}
span {
.main-nav-link span {
font-size: 16px;
color: var(--nav-text-color);
padding-left: 10px;
}
@media (max-width: 767px) {
span {
.main-nav-link span {
display: none;
}
svg {
.main-nav-link svg {
width: 25px;
height: 25px;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,7 +16,7 @@
<form class="add-new-instance" on:submit='onSubmit(event)' aria-labelledby="add-an-instance-h1">
<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>
</form>
@ -27,12 +27,12 @@
</Layout>
<style>
@media (max-width: 767px) {
input {
input.new-instance-input {
max-width: 90%;
}
}
input {
input.new-instance-input {
min-width: 50%;
max-width: 100%;
}