diff --git a/README.md b/README.md index e0f5ad3..3b32b6a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # FWDekker Template The base template for pages on fwdekker.com. -This module contains templating functions (e.g. `header`, `footer`), CSS libraries, and some common utility methods that +This module contains templating functions (e.g. `nav`, `footer`), CSS libraries, and some common utility methods that are used on nearly all pages anyway. The main functionality is provided in `template.js` and `template.css`. @@ -22,10 +22,8 @@ $> npm ci ### Building ```shell script -# Build the template in `dist/` for development -$> npm run dev -# Run the `dev` task and automatically rerun it whenever files are changed -$> npm run dev:server # Build the template in `dist/` for deployment $> npm run deploy +# Run the `deploy` task and automatically rerun it whenever files are changed +$> npm run deploy:server ``` diff --git a/package-lock.json b/package-lock.json index 577cc16..5c6e49b 100644 Binary files a/package-lock.json and b/package-lock.json differ diff --git a/package.json b/package.json index da2d3b7..ff24a65 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fwdekker/template", - "version": "2.8.0", + "version": "3.0.0-RC1", "description": "The base template for pages on fwdekker.com.", "author": "Florine W. Dekker", "license": "MIT", @@ -23,8 +23,7 @@ "deploy:server": "grunt deploy:server" }, "dependencies": { - "milligram": "^1.4.1", - "normalize.css": "^8.0.1" + "@picocss/pico": "^1.5.6" }, "devDependencies": { "grunt": "^1.5.3", diff --git a/src/main/css/main.css b/src/main/css/main.css index 6c42610..a6719b3 100644 --- a/src/main/css/main.css +++ b/src/main/css/main.css @@ -1,7 +1,5 @@ -@import "../../../node_modules/normalize.css/normalize.css"; -@import "../../../node_modules/milligram/dist/milligram.css"; +@import "../../../node_modules/@picocss/pico/css/pico.css"; @import "snippets/colors.css"; @import "snippets/common.css"; @import "snippets/nav.css"; -@import "snippets/toc.css"; @import "snippets/overrides.css"; diff --git a/src/main/css/snippets/colors.css b/src/main/css/snippets/colors.css index a005be7..9da50d3 100644 --- a/src/main/css/snippets/colors.css +++ b/src/main/css/snippets/colors.css @@ -1,7 +1,31 @@ +/* Custom main colors */ :root { - --fwdekker-theme-color: #0033cc; - --fwdekker-theme-color-dark: #0029a3; - --fwdekker-theme-color-very-dark: #001f7a; - --fwdekker-theme-color-light: #003df5; - --fwdekker-theme-color-very-light: #1f57ff; + --fwdekker-theme-color-triplet: 0, 51, 204; + --fwdekker-theme-color: rgb(var(--fwdekker-theme-color-triplet)); + + --fwdekker-theme-color-dark-triplet: 0, 41, 163; + --fwdekker-theme-color-dark: rgb(var(--fwdekker-theme-color-dark-triplet)); + + --fwdekker-theme-color-very-dark-triplet: 0, 31, 122; + --fwdekker-theme-color-very-dark: rgb(var(--fwdekker-theme-color-very-dark-triplet)); + + --fwdekker-theme-color-light-triplet: 0, 61, 245; + --fwdekker-theme-color-light: rgb(var(--fwdekker-theme-color-light-triplet)); + + --fwdekker-theme-color-very-light-triplet: 31, 87, 255; + --fwdekker-theme-color-very-light: rgb(var(--fwdekker-theme-color-very-light-triplet)); +} + + +/* pico.css overrides, based on https://picocss.com/docs/customization.html */ +:root { + --primary: var(--fwdekker-theme-color) !important; + --primary-hover: var(--fwdekker-theme-color-light) !important; + --primary-focus: rgba(var(--fwdekker-theme-color-dark-triplet), 0.125) !important; + --primary-inverse: white !important; + + --form-element-active-border-color: var(--primary) !important; + --form-element-focus-color: var(--primary-focus) !important; + --switch-color: var(--primary-inverse) !important; + --switch-checked-background-color: var(--primary) !important; } diff --git a/src/main/css/snippets/common.css b/src/main/css/snippets/common.css index 777c2dd..e185c1f 100644 --- a/src/main/css/snippets/common.css +++ b/src/main/css/snippets/common.css @@ -1,75 +1,88 @@ -/* Base elements */ -html, body { - height: 100%; - margin: 0; - padding: 0; +/* External link icon */ +a[target="_blank"]::after { + display: inline-block; + + width: 0.7em; + height: 0.7em; + margin-left: 0.25rem; + + /* Image from https://icons.getbootstrap.com/icons/box-arrow-up-right/. MIT License. */ + mask-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg fill='currentColor' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z' fill-rule='evenodd'/%3E%3Cpath d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z' fill-rule='evenodd'/%3E%3C/svg%3E%0A"); + mask-size: cover; + background-repeat: no-repeat no-repeat; + background-position: center center; + background-size: cover; + background-color: var(--primary); + + content: ""; } -body { - color: black; + +/* Hide anything */ +.hidden { + display: none !important; } -main { - /* Flex-based footer positioning, taken from https://stackoverflow.com/a/12253099 */ +@media (min-width: 576px) { + .hidden-no-mobile { + display: none; + } +} + +@media (max-width: 576px) { + .hidden-on-mobile { + display: none; + } +} + +/* Input with button next to it */ +.input-with-button { display: flex; - flex-direction: column; - min-height: 100%; } -#contents { - flex: 1; +.input-with-button > *:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} - margin-top: 5rem; - margin-bottom: 5rem; +.input-with-button > *:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +/* Container with table of contents */ +@media (min-width: 576px) { + .container-with-toc { + display: grid; + grid-template-columns: 200px auto; + } +} + +@media (max-width: 576px) { + .container-with-toc aside { + margin-bottom: var(--block-spacing-vertical); + } } /* Noscript */ -noscript img { +noscript.fwd-js-notice img { position: absolute; } -noscript p { +noscript.fwd-js-notice p { font-weight: bold; text-align: center; } -/* Generic classes */ -.hidden { - display: none !important; -} - -.inputWithButton { - display: flex; -} - -.inputWithButton > *:first-child { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.inputWithButton > *:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - - /* Header */ -header .container { - text-align: center; -} - -header h1 > a { +header a[href="."] { color: black; } /* Footer */ -footer { - margin-bottom: 3rem; -} - -#footerVersion { +footer.fwd-footer #fwd-footer-version { float: right; } diff --git a/src/main/css/snippets/nav.css b/src/main/css/snippets/nav.css index 8224a8e..034fc47 100644 --- a/src/main/css/snippets/nav.css +++ b/src/main/css/snippets/nav.css @@ -1,5 +1,6 @@ /* Base elements */ -nav { +nav.fwd-nav { + display: block; z-index: 10; margin: 0; @@ -7,20 +8,29 @@ nav { background-color: var(--fwdekker-theme-color); border-bottom: 1px solid #cccccc; - font-size: 120%; --padding: calc(2em / 3); } -nav * { +nav.fwd-nav * { vertical-align: middle; } -nav a, nav a:link, nav a:visited, nav a:hover, nav a:active { - width: 100%; /* Ensures whole li is clickable */ +nav.fwd-nav a, +nav.fwd-nav a:link, +nav.fwd-nav a:visited, +nav.fwd-nav a:hover, +nav.fwd-nav a:active { + /* Ensures whole li is clickable */ + width: 100%; } -nav a, nav a:link, nav a:visited, nav a:hover, nav a:active, nav #nav-hamburger-label { +nav.fwd-nav a, +nav.fwd-nav a:link, +nav.fwd-nav a:visited, +nav.fwd-nav a:hover, +nav.fwd-nav a:active, +nav.fwd-nav #nav-hamburger-label { display: inline-block; margin: 0; padding: calc(var(--padding)) calc(var(--padding)); @@ -29,15 +39,18 @@ nav a, nav a:link, nav a:visited, nav a:hover, nav a:active, nav #nav-hamburger- color: white; } -nav #nav-hamburger-label { +nav.fwd-nav #nav-hamburger-label { float: right; - font-size: unset; - cursor: pointer; +} + +nav.fwd-nav a[target="_blank"]::after { + margin-bottom: 0.2rem; + background-color: white; } /* Logo */ -nav .logo { +nav.fwd-nav .logo { width: calc(1em + var(--padding)); height: calc(1em + var(--padding)); @@ -45,21 +58,22 @@ nav .logo { filter: brightness(0) invert(1); } -nav div.logo { +nav.fwd-nav div.logo { display: inline-block; margin-right: calc(1em / 3); } /* First level nesting */ -nav ul { +nav.fwd-nav ul { + display: block; margin: 0; padding: 0; list-style: none; } -nav ul li { +nav.fwd-nav ul li { display: inline-block; margin: 0; padding: 0; @@ -68,21 +82,21 @@ nav ul li { background-color: var(--fwdekker-theme-color); } -nav ul li:hover, -nav ul li:focus-within, -nav #nav-hamburger-label:hover, -nav #nav-hamburger-label:focus-within { +nav.fwd-nav ul li:hover, +nav.fwd-nav ul li:focus-within, +nav.fwd-nav #nav-hamburger-label:hover, +nav.fwd-nav #nav-hamburger-label:focus-within { cursor: pointer; background-color: var(--fwdekker-theme-color-very-dark); } -nav li.currentPage { +nav.fwd-nav li.currentPage { background-color: var(--fwdekker-theme-color-dark); } /* Second level nesting */ -nav ul li ul { +nav.fwd-nav ul li ul { z-index: 11; display: none; @@ -90,18 +104,18 @@ nav ul li ul { left: 0; } -nav ul li ul li ul { +nav.fwd-nav ul li ul li ul { left: 100%; top: 0; } -nav ul li:hover > ul, -nav ul li:focus-within > ul, -nav ul li ul:hover { +nav.fwd-nav ul li:hover > ul, +nav.fwd-nav ul li:focus-within > ul, +nav.fwd-nav ul li ul:hover { display: block; } -nav ul li ul li { +nav.fwd-nav ul li ul li { min-width: 7em; width: 100%; white-space: nowrap; @@ -109,18 +123,18 @@ nav ul li ul li { /* Hide hamburger-related elements */ -nav input[type="checkbox"] { +nav.fwd-nav input[type="checkbox"] { display: none; } -@media (min-width: 600px) { - nav #nav-hamburger-label { +@media (min-width: 576px) { + nav.fwd-nav #nav-hamburger-label { display: none; } } -@media (max-width: 600px) { - nav input[type="checkbox"]:not(:checked) ~ ul li:not(:first-child) { +@media (max-width: 576px) { + nav.fwd-nav input[type="checkbox"]:not(:checked) ~ ul li:not(:first-child) { display: none; } } diff --git a/src/main/css/snippets/overrides.css b/src/main/css/snippets/overrides.css index 6e423a3..72d25ee 100644 --- a/src/main/css/snippets/overrides.css +++ b/src/main/css/snippets/overrides.css @@ -4,96 +4,3 @@ select { -moz-appearance: menulist; appearance: auto; } - - -/* Override Milligram color scheme, based on v1.4.1. */ -/* Replaces #9b4dca with `--fwdekker-theme-color`. */ -/* Simply look at latest unminimized Milligram release and Ctrl+F where #9b4dca occurs. */ -.button, -button, -input[type='button'], -input[type='reset'], -input[type='submit'] { - background-color: var(--fwdekker-theme-color); - border: 0.1rem solid var(--fwdekker-theme-color); -} - -.button[disabled]:focus, .button[disabled]:hover, -button[disabled]:focus, -button[disabled]:hover, -input[type='button'][disabled]:focus, -input[type='button'][disabled]:hover, -input[type='reset'][disabled]:focus, -input[type='reset'][disabled]:hover, -input[type='submit'][disabled]:focus, -input[type='submit'][disabled]:hover { - background-color: var(--fwdekker-theme-color); - border-color: var(--fwdekker-theme-color); -} - -.button.button-outline, -button.button-outline, -input[type='button'].button-outline, -input[type='reset'].button-outline, -input[type='submit'].button-outline { - color: var(--fwdekker-theme-color); -} - -.button.button-outline[disabled]:focus, .button.button-outline[disabled]:hover, -button.button-outline[disabled]:focus, -button.button-outline[disabled]:hover, -input[type='button'].button-outline[disabled]:focus, -input[type='button'].button-outline[disabled]:hover, -input[type='reset'].button-outline[disabled]:focus, -input[type='reset'].button-outline[disabled]:hover, -input[type='submit'].button-outline[disabled]:focus, -input[type='submit'].button-outline[disabled]:hover { - color: var(--fwdekker-theme-color); -} - -.button.button-clear, -button.button-clear, -input[type='button'].button-clear, -input[type='reset'].button-clear, -input[type='submit'].button-clear { - color: var(--fwdekker-theme-color); -} - -.button.button-clear[disabled]:focus, .button.button-clear[disabled]:hover, -button.button-clear[disabled]:focus, -button.button-clear[disabled]:hover, -input[type='button'].button-clear[disabled]:focus, -input[type='button'].button-clear[disabled]:hover, -input[type='reset'].button-clear[disabled]:focus, -input[type='reset'].button-clear[disabled]:hover, -input[type='submit'].button-clear[disabled]:focus, -input[type='submit'].button-clear[disabled]:hover { - color: var(--fwdekker-theme-color); -} - -pre { - border-left: 0.3rem solid var(--fwdekker-theme-color); -} - -input[type='color']:focus, -input[type='date']:focus, -input[type='datetime']:focus, -input[type='datetime-local']:focus, -input[type='email']:focus, -input[type='month']:focus, -input[type='number']:focus, -input[type='password']:focus, -input[type='search']:focus, -input[type='tel']:focus, -input[type='text']:focus, -input[type='url']:focus, -input[type='week']:focus, -input:not([type]):focus, -textarea:focus, -select:focus { - border-color: var(--fwdekker-theme-color); -} - -a { - color: var(--fwdekker-theme-color); -} diff --git a/src/main/css/snippets/toc.css b/src/main/css/snippets/toc.css deleted file mode 100644 index afa2214..0000000 --- a/src/main/css/snippets/toc.css +++ /dev/null @@ -1,3 +0,0 @@ -#toc { - position: fixed; -} diff --git a/src/main/js/template.js b/src/main/js/template.js index 26afe16..aecc819 100644 --- a/src/main/js/template.js +++ b/src/main/js/template.js @@ -82,7 +82,7 @@ const nav = function(highlightPath = "", cb = undefined) { }); const nav = stringToHtml( - `