1
0
mirror of https://github.com/locomotivemtl/locomotive-boilerplate.git synced 2026-01-15 00:55:08 +08:00

7 Commits

Author SHA1 Message Date
Jérémy Minié
098019ad5e Use 11ty config to try swup fragments in a more realistic setup 2024-01-18 18:06:53 -05:00
Jérémy Minié
8cde150a3a Use 11ty w/ twig setup instead of hardcoded HTML files 2024-01-18 17:17:11 -05:00
Jérémy Minié
d9c3bd9f92 Add swup & swup fragment plugin to test its implementation w/ the boilerplate 2024-01-18 11:42:17 -05:00
Jérémy Minié
a37c5b047a Fix PurgeCSS safelist regex 2024-01-16 15:07:09 -05:00
Deven Caron
61b6222525 Merge pull request #163 from locomotivemtl/chore/update-node-version
Update node version & bump npm packages version
2024-01-05 15:24:22 -05:00
Deven Caron
5acd27d1b0 Compile assets 2024-01-05 09:06:33 -05:00
Deven Caron
9a5a91b221 Update Node version and npm dependencies 2024-01-05 09:06:24 -05:00
34 changed files with 6051 additions and 1095 deletions

3
.gitignore vendored
View File

@@ -3,4 +3,5 @@ node_modules
Thumbs.db
loconfig.*.json
!loconfig.example.json
.prettierrc
.prettierrc
www/**/*.html

2
.nvmrc
View File

@@ -1 +1 @@
v17.9
v20.10

View File

@@ -1,3 +1,3 @@
{
"version": 1702288850381
"version": 1705619201399
}

View File

@@ -1,3 +1,4 @@
export {default as Example} from './modules/Example';
// export {default as Example} from './modules/Example';
export {default as Dialog} from './modules/Dialog';
export {default as Load} from './modules/Load';
export {default as Scroll} from './modules/Scroll';

View File

@@ -0,0 +1,36 @@
import { module } from 'modujs';
export default class extends module {
constructor(m) {
super(m);
this.$closeBtn = this.$('close')[0]
}
init() {
// Prevent ESC to close dialog
this.onKeyDown = this.onKeyDown.bind(this)
}
onKeyDown(e) {
if(e.key === 'Escape') {
console.log('ESCAPE');
e.preventDefault()
this.$closeBtn.click();
}
}
populate(container) {
this.el.appendChild(container)
}
show() {
this.el.showModal();
window.addEventListener('keydown', this.onKeyDown);
}
close() {
window.removeEventListener('keydown', this.onKeyDown);
this.el.close();
}
}

View File

@@ -1,5 +1,6 @@
import { module } from 'modujs';
import modularLoad from 'modularload';
import Swup from 'swup';
import SwupFragmentPlugin from '@swup/fragment-plugin';
export default class extends module {
constructor(m) {
@@ -7,16 +8,70 @@ export default class extends module {
}
init() {
const load = new modularLoad({
enterDelay: 0,
transitions: {
customTransition: {}
const load = new Swup({
containers: ['[data-load-container]'],
// cache: false,
plugins: [
new SwupFragmentPlugin({
rules: [
{
from: ['/projects/:page?'],
to: ['/projects/:page?'],
containers: ['#paginated']
},
{
from: ['/projects/:page?'],
to: ['/project/:slug'],
containers: ['#modal'],
name: 'open-modal'
},
{
from: ['/project/:slug'],
to: ['/project/:slug'],
containers: ['#modal'],
name: 'modal-update'
},
{
from: ['/project/:slug'],
to: ['/projects/:page?'],
containers: ['#modal', '#paginated'],
name: 'close-modal'
},
]
})
]
});
load.hooks.before('content:replace', async (visit) => {
console.log('before content replace:', visit);
for(let container of visit.containers) {
const oldContainer = this.el.querySelector(container)
console.log('old container: ', oldContainer)
this.call('destroy', oldContainer, 'app');
}
});
load.on('loaded', (transition, oldContainer, newContainer) => {
this.call('destroy', oldContainer, 'app');
this.call('update', newContainer, 'app');
load.hooks.on('content:replace', (visit) => {
console.log('On content replace:', visit);
if(visit.fragmentVisit) {
if(visit.fragmentVisit.name == 'open-modal') {
this.call('populate', document.getElementById('modal'), 'Dialog');
this.call('show', null, 'Dialog')
} else if(visit.fragmentVisit.name == 'close-modal') {
this.call('close', null, 'Dialog')
}
}
for(let container of visit.containers) {
const newContainer = this.el.querySelector(container)
console.log('new container: ', newContainer)
newContainer.classList.add('transition-fade')
this.call('update', newContainer, 'app');
}
});
console.log(this, load);
}
}

View File

@@ -69,3 +69,27 @@ a {
color: $color-link-hover;
}
}
/* Define a transition duration during page visits */
html.is-changing .transition-fade {
transition: opacity 0.1s;
opacity: 1;
}
/* Define the styles for the unloaded pages */
html.is-animating .transition-fade {
opacity: 0;
}
#paginated.is-changing {
transition: opacity 250ms;
}
#paginated.is-animating {
opacity: 0;
}
#modal.is-changing {
transition: opacity 100ms;
}
#modal.is-animating {
opacity: 0;
}

View File

@@ -1,9 +1,11 @@
import buildEleventy from './tasks/eleventy.js';
import concatFiles from './tasks/concats.js';
import compileScripts from './tasks/scripts.js';
import compileStyles from './tasks/styles.js';
import compileSVGs from './tasks/svgs.js';
import bumpVersions from './tasks/versions.js';
buildEleventy();
concatFiles();
compileScripts();
compileStyles();

50
build/tasks/eleventy.js Normal file
View File

@@ -0,0 +1,50 @@
import message from '../helpers/message.js';
import { merge } from '../utils/index.js';
import Eleventy from "@11ty/eleventy";
export const defaultEleventyOptions = {
production: true
}
export const developmentEleventyOptions = {
production: false
}
export const productionEleventyOptions = {
production: true
}
let elev;
export default async function buildEleventy(eleventyOptions = null) {
if (eleventyOptions == null) {
eleventyOptions = productionEleventyOptions;
} else if (
eleventyOptions !== developmentEleventyOptions &&
eleventyOptions !== productionEleventyOptions
) {
eleventyOptions = merge({}, defaultEleventyOptions, eleventyOptions);
}
const { production } = eleventyOptions;
const timeLabel = `11ty compiled in`;
console.time(timeLabel);
try {
if(!elev) {
elev = new Eleventy();
if(!production) {
await elev.watch();
}
}
// Disable caching to ensure a fresh build each time
await elev.write();
message(`11ty compiled`, 'success', timeLabel);
} catch(err) {
console.error(err)
message(err, 'error', timeLabel);
}
}

View File

@@ -236,7 +236,7 @@ async function purgeUnusedCSS(outfile, label) {
keyframes: true,
safelist: {
// Keep all except .u-gc-* | .u-margin-* | .u-padding-*
standard: [ /^(((?!\bu-gc-).)*$ | (((?!\bu-margin-).)*$) | (((?!\bu-padding-).)*$))/ ]
standard: [ /^(?!.*\b(u-gc-|u-margin|u-padding)).*$/ ]
},
variables: true,
})

View File

@@ -2,6 +2,7 @@ import concatFiles, { developmentConcatFilesArgs } from './tasks/concats.js';
import compileScripts, { developmentScriptsArgs } from './tasks/scripts.js';
import compileStyles, { developmentStylesArgs } from './tasks/styles.js' ;
import compileSVGs, { developmentSVGsArgs } from './tasks/svgs.js';
import buildEleventy, { developmentEleventyOptions } from './tasks/eleventy.js';
import loconfig from './helpers/config.js';
import message from './helpers/message.js';
import notification from './helpers/notification.js';
@@ -19,6 +20,7 @@ concatFiles(...developmentConcatFilesArgs);
compileScripts(...developmentScriptsArgs);
compileStyles(...developmentStylesArgs);
compileSVGs(...developmentSVGsArgs);
await buildEleventy(developmentEleventyOptions);
// Create a new BrowserSync instance
const server = browserSync.create();
@@ -53,10 +55,7 @@ function configureServer(server, { paths, tasks }) {
// Reload on any changes to views or processed files
server.watch(
[
...views,
join(paths.scripts.dest, '*.js'),
join(paths.styles.dest, '*.css'),
join(paths.svgs.dest, '*.svg'),
join(paths.dest, '**/*')
]
).on('change', server.reload);

4
data/metadata.json Normal file
View File

@@ -0,0 +1,4 @@
{
"title": "Locomotive Boilerplate",
"description": "Front-end boilerplate for projects by Locomotive."
}

34
data/projects.json Normal file
View File

@@ -0,0 +1,34 @@
[
{
"title": "Lusail Stadium",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Scelerisque viverra mauris in aliquam sem fringilla ut morbi tincidunt. In dictum non consectetur a erat nam at lectus urna. Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue."
},
{
"title": "Tottenham Hotspur Stadium",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing. Eget mi proin sed libero enim sed. Tincidunt id aliquet risus feugiat in ante metus."
},
{
"title": "Narendra Modi Stadium",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae tempus quam pellentesque nec nam aliquam. Velit laoreet id donec ultrices tincidunt. Tincidunt lobortis feugiat vivamus at augue eget arcu."
},
{
"title": "Texas A&M Kyle Field",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Integer malesuada nunc vel risus commodo viverra maecenas accumsan. Dui faucibus in ornare quam viverra orci sagittis."
},
{
"title": "The Cathedral — A New Icon for Milan",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Scelerisque viverra mauris in aliquam sem fringilla ut morbi tincidunt. In dictum non consectetur a erat nam at lectus urna. Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue."
},
{
"title": "Allianz Field",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing. Eget mi proin sed libero enim sed. Tincidunt id aliquet risus feugiat in ante metus."
},
{
"title": "TQL Stadium",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae tempus quam pellentesque nec nam aliquam. Velit laoreet id donec ultrices tincidunt. Tincidunt lobortis feugiat vivamus at augue eget arcu."
},
{
"title": "Groupama Stadium and Training Centre",
"desc": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Integer malesuada nunc vel risus commodo viverra maecenas accumsan. Dui faucibus in ornare quam viverra orci sagittis."
}
]

71
eleventy.config.cjs Normal file
View File

@@ -0,0 +1,71 @@
// Import required modules
const twig = require("twig");
const fs = require('fs')
const eleventyPluginTwig = require("@factorial/eleventy-plugin-twig");
// Export Eleventy configuration
module.exports = function(eleventyConfig) {
// Function to generate a version identifier
function generateVersion() {
// You can use a timestamp, a hash of asset files, or any other method you prefer
return Date.now();
}
eleventyConfig.setServerOptions({
enabled: false,
});
eleventyConfig.addWatchTarget("views/**/*");
// Use twig
eleventyConfig.addPlugin(eleventyPluginTwig, {
twig: {
namespaces: {
layouts: "views/layouts",
partials: "views/partials",
snippets: "views/snippets"
}
},
dir: {
input: 'views/templates',
output: 'www'
}
});
twig.extendFilter("log", function(value) {
return '<pre>'+JSON.stringify(value)+'</pre>';
});
twig.extendFilter("slug", function(str) {
return str
.toLowerCase() // Convert the string to lowercase
.replace(/\s+/g, '-') // Replace spaces with dashes
.replace(/[^\w-]/g, '') // Remove non-word characters
.replace(/--+/g, '-') // Replace consecutive dashes with a single dash
.trim(); // Trim any leading or trailing dashes
})
// // Add a filter to append the version to asset URLs
twig.extendFilter('version', function(url) {
const version = generateVersion();
return `${url}?v=${version}`;
});
twig.extendFunction("critical_css", function() {
try {
return fs.readFileSync('./www/assets/styles/critical.css', 'utf-8')
} catch(error) {
return '';
}
});
// Configure and return Eleventy settings
return {
templateFormats: ['twig'],
dir: {
input: 'views/templates',
output: 'www',
data: '../../data'
}
};
};

View File

@@ -19,7 +19,10 @@
"dest": "./www/assets/images"
},
"views": {
"src": "./www/"
"src": "./views/"
},
"data": {
"src": "./data/"
}
},
"tasks": {

6079
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
"author": "Locomotive <info@locomotive.ca>",
"type": "module",
"engines": {
"node": ">=17.9",
"node": ">=20.1",
"npm": ">=8.0"
},
"scripts": {
@@ -14,15 +14,17 @@
"build": "node --experimental-json-modules --no-warnings build/build.js"
},
"dependencies": {
"@swup/fragment-plugin": "^0.3.7",
"locomotive-scroll": "^5.0.0-beta.9",
"modujs": "^1.4.2",
"modularload": "^1.2.6",
"normalize.css": "^8.0.1",
"svg4everybody": "^2.1.9"
"svg4everybody": "^2.1.9",
"swup": "^4.5.1"
},
"devDependencies": {
"autoprefixer": "^10.4.13",
"browser-sync": "^2.27.11",
"browser-sync": "^3.0.2",
"concat": "^1.0.3",
"esbuild": "^0.17.6",
"kleur": "^4.1.5",
@@ -31,7 +33,10 @@
"purgecss": "^5.0.0",
"sass": "^1.69.5",
"svg-mixer": "~2.3.14",
"tiny-glob": "^0.2.9"
"tiny-glob": "^0.2.9",
"@11ty/eleventy": "^2.0.1",
"@factorial/eleventy-plugin-twig": "^0.1.2",
"twig": "^1.16.0"
},
"overrides": {
"browser-sync": {

48
views/layouts/base.twig Normal file
View File

@@ -0,0 +1,48 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="images">
<head>
<meta charset="utf-8">
<base href="/">
<title>{% if title %}{{ title }} | {% endif %}{{ metadata.title }}</title>
<meta name="description" content="{% if description %}{{description}}{% else %}{{ metadata.description }}{% endif %}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
{% block beforeMain %}
<div data-module-scroll="main">
{% include "@partials/header.twig" %}
{% endblock %}
<main>
{% block content %}{% endblock %}
{% block afterContent %}
{% include "@partials/footer.twig" %}
{% endblock %}
</main>
{% block afterMain %}
</div>
{% endblock %}
</div>
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js" crossorigin="anonymous"></script>
<script nomodule src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController" crossorigin="anonymous"></script>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>

View File

@@ -0,0 +1,3 @@
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>

View File

@@ -0,0 +1,15 @@
{% set _logo_tag = page.url == '/' ? 'h1' : 'span' %}
<header>
<a href="/">
<{{_logo_tag}} style="text-decoration: underline;">Locomotive Boilerplate</{{_logo_tag}}>
</a>
<nav>
<ul>
<li><a href="/images">Images</a></li>
<li><a href="/form" data-load="customTransition">Form</a></li>
<li><a href="/grid">Grid</a></li>
<li><a href="/projects">Projects</a></li>
</ul>
</nav>
</header>

61
views/templates/form.twig Normal file
View File

@@ -0,0 +1,61 @@
{% extends "@layouts/base.twig" %}
{% block content %}
<div class="o-container">
<h1 class="c-heading -h1">Page</h1>
<div class="o-layout">
<div class="o-layout_item u-1/2@from-small">
<form class="c-form">
<div class="c-form_item">
<label class="c-form_label" for="input">Input</label>
<input class="c-form_input" type="text" id="input">
</div>
<div class="c-form_item">
<div class="o-layout -gutter">
<div class="o-layout_item u-1/2">
<input class="c-form_checkbox" type="checkbox" id="checkbox">
<label class="c-form_checkboxLabel" for="checkbox">Checkbox</label>
</div>
<div class="o-layout_item u-1/2">
<input class="c-form_checkbox" type="checkbox" id="checkbox2">
<label class="c-form_checkboxLabel" for="checkbox2">Checkbox 2</label>
</div>
</div>
</div>
<div class="c-form_item">
<div class="o-layout -gutter">
<div class="o-layout_item u-1/2">
<input class="c-form_radio" type="radio" name="radio" id="radio">
<label class="c-form_radioLabel" for="radio">Radio</label>
</div>
<div class="o-layout_item u-1/2">
<input class="c-form_radio" type="radio" name="radio" id="radio2">
<label class="c-form_radioLabel" for="radio2">Radio 2</label>
</div>
</div>
</div>
<div class="c-form_item">
<label class="c-form_label" for="select">Select</label>
<div class="c-form_select">
<select class="c-form_select_input" id="select">
<option value="option">Option</option>
<option value="option2">Option 2</option>
<option value="option3">Option 3</option>
</select>
</div>
</div>
<div class="c-form_item">
<label class="c-form_label" for="textarea">Textarea</label>
<textarea class="c-form_textarea" id="textarea"></textarea>
</div>
<button class="c-button" type="submit">
Submit
</button>
</form>
</div>
</div>
</div>
{% endblock %}

29
views/templates/grid.twig Normal file
View File

@@ -0,0 +1,29 @@
{% extends "@layouts/base.twig" %}
{% block content %}
<div class="o-container">
<h1 class="c-heading -h1">Hello</h1>
<div class="o-grid -col-4 -col-12@from-medium -gutters">
<div class="o-grid_item u-gc-1/8@from-medium" style="background-color: gray;">
<h2 class="c-heading -h2">This grid has 4 columns and 12 columns from `medium` MQ</h2>
</div>
<div class="o-grid_item u-gc-1/5@from-medium" style="background-color: yellow;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-5/9@from-medium" style="background-color: red;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-9/13@from-medium" style="background-color: blue;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-1/3 u-gc-5/13@from-medium" style="background-color: pink;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,69 @@
{% extends "@layouts/base.twig" %}
{% block content %}
<div class="o-container">
<h1 class="c-heading -h1">Images</h1>
<section>
<h3 class="c-heading -h3">Relative to scroll</h3>
<h4 class="c-heading -h3">Using o-ratio & img</h3>
<div style="width: 640px; max-width: 100%;">
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=3" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=4" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=5" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
</div>
<h4 class="c-heading -h3">Using o-ratio & background-image</h3>
<div style="width: 480px; max-width: 100%;">
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=1"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=2"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=3"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=4"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=5"></div>
</div>
<h4 class="c-heading -h3">Using SVG viewport for ratio</h3>
<div style="width: 480px; max-width: 100%;">
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=6"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=7"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=8"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
</div>
</section>
</div>
{% endblock %}

View File

@@ -0,0 +1,11 @@
---
title: Home
---
{% extends "@layouts/base.twig" %}
{% block content %}
<div class="o-container">
<h2 class="c-heading -h2">Hello world!</h2>
</div>
{% endblock %}

View File

@@ -0,0 +1,26 @@
---
pagination:
data: projects
size: 1
alias: project
permalink: "project/{{ project.title | slug }}/index.html"
---
{% extends "@layouts/base.twig" %}
{% block content %}
<div class="o-container">
<main id="modal">
<h1 class="c-heading -h1">{{project.title}}</h1>
<p>{{project.desc}}</p>
{% if pagination.page.previous %}
<a style="float: left;" href="/project/{{pagination.page.previous.title | slug}}">← {{pagination.page.previous.title}}</a>
{% endif %}
{% if pagination.page.next %}
<a style="float: right;" href="/project/{{pagination.page.next.title | slug}}">{{pagination.page.next.title}} →</a>
{% endif %}
<div style="clear: both;"></div>
</main>
</div>
{% endblock %}

View File

@@ -0,0 +1,42 @@
---
pagination:
data: projects
size: 4
---
{% extends "@layouts/base.twig" %}
{% block beforeMain %}
<dialog id="dialog" data-module-dialog>
<a href="/" data-swup-link-to-fragment="#paginated" style="float: right;" data-dialog="close">Close</a>
</dialog>
<div data-module-scroll="main">
{% include "@partials/header.twig" %}
{% endblock %}
{% block content %}
<div class="o-container">
<h1 class="c-heading -h1">Projects</h1>
<div id="paginated">
<ul>
{% for item in pagination.items %}
<li><a href="/project/{{item.title|slug}}">{{ item.title }}</a></li>
{% endfor %}
</ul>
<ol>
{% for pageEntry in pagination.pages %}
{% if page.url == pagination.hrefs[ loop.index0 ] %}
<span aria-current="page">{{ loop.index }}</span>
{% else %}
<a href="{{ pagination.hrefs[ loop.index0 ] }}">{{ loop.index }}</a>
{% endif %}
{% endfor %}
</ol>
</div>
</div>
<template id="modal"></template>
{% endblock %}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,105 +0,0 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="page">
<head>
<meta charset="utf-8">
<title>Form | Locomotive Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
<div data-module-scroll="main">
<header>
<a href="/"><h1>Locomotive Boilerplate</h1></a>
<nav>
<ul>
<li><a href="images.html">Images</a></li>
<li><a href="form.html" data-load="customTransition">Form</a></li>
<li><a href="grid.html">Grid</a></li>
</ul>
</nav>
</header>
<main>
<div class="o-container">
<h1 class="c-heading -h1">Page</h1>
<div class="o-layout">
<div class="o-layout_item u-1/2@from-small">
<form class="c-form">
<div class="c-form_item">
<label class="c-form_label" for="input">Input</label>
<input class="c-form_input" type="text" id="input">
</div>
<div class="c-form_item">
<div class="o-layout -gutter">
<div class="o-layout_item u-1/2">
<input class="c-form_checkbox" type="checkbox" id="checkbox">
<label class="c-form_checkboxLabel" for="checkbox">Checkbox</label>
</div>
<div class="o-layout_item u-1/2">
<input class="c-form_checkbox" type="checkbox" id="checkbox2">
<label class="c-form_checkboxLabel" for="checkbox2">Checkbox 2</label>
</div>
</div>
</div>
<div class="c-form_item">
<div class="o-layout -gutter">
<div class="o-layout_item u-1/2">
<input class="c-form_radio" type="radio" name="radio" id="radio">
<label class="c-form_radioLabel" for="radio">Radio</label>
</div>
<div class="o-layout_item u-1/2">
<input class="c-form_radio" type="radio" name="radio" id="radio2">
<label class="c-form_radioLabel" for="radio2">Radio 2</label>
</div>
</div>
</div>
<div class="c-form_item">
<label class="c-form_label" for="select">Select</label>
<div class="c-form_select">
<select class="c-form_select_input" id="select">
<option value="option">Option</option>
<option value="option2">Option 2</option>
<option value="option3">Option 3</option>
</select>
</div>
</div>
<div class="c-form_item">
<label class="c-form_label" for="textarea">Textarea</label>
<textarea class="c-form_textarea" id="textarea"></textarea>
</div>
<button class="c-button" type="submit">
Submit
</button>
</form>
</div>
</div>
</div>
</main>
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>
</div>
</div>
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js" crossorigin="anonymous"></script>
<script nomodule src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController" crossorigin="anonymous"></script>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>

View File

@@ -1,96 +0,0 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="grid">
<head>
<meta charset="utf-8">
<title>Locomotive Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<!-- For a dark mode managment and svg favicon add this in your favicon.svg -->
<!--
<style>
path {
fill: #000;
}
@media (prefers-color-scheme: dark) {
path {
fill: #fff;
}
}
</style>
-->
<!-- <link rel="icon" href="assets/images/favicons/favicon.svg"> -->
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print"
onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
<div data-module-scroll="main">
<header>
<a href="/">
<h1>Locomotive Boilerplate</h1>
</a>
<nav>
<ul>
<li><a href="images.html">Images</a></li>
<li><a href="form.html" data-load="customTransition">Form</a></li>
<li><a href="grid.html">Grid</a></li>
</ul>
</nav>
</header>
<main>
<div class="o-container">
<h1 class="c-heading -h1">Hello</h1>
<div class="o-grid -col-4 -col-12@from-medium -gutters">
<div class="o-grid_item u-gc-1/8@from-medium" style="background-color: gray;">
<h2 class="c-heading -h2">This grid has 4 columns and 12 columns from `medium` MQ</h2>
</div>
<div class="o-grid_item u-gc-1/5@from-medium" style="background-color: yellow;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-5/9@from-medium" style="background-color: red;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-9/13@from-medium" style="background-color: blue;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
<div class="o-grid_item u-gc-1/3 u-gc-5/13@from-medium" style="background-color: pink;">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita provident distinctio deleniti eaque cumque doloremque aut quo dicta porro commodi, temporibus totam dolor autem tempore quasi ullam sed suscipit vero?</p>
</div>
</div>
</div>
</main>
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate"
title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>
</div>
</div>
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js"
crossorigin="anonymous"></script>
<script nomodule
src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController"
crossorigin="anonymous"></script>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>

View File

@@ -1,131 +0,0 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="images">
<head>
<meta charset="utf-8">
<title>Images | Locomotive Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
<div data-module-scroll="main">
<header>
<a href="/"><h1>Locomotive Boilerplate</h1></a>
<nav>
<ul>
<li><a href="images.html">Images</a></li>
<li><a href="form.html" data-load="customTransition">Form</a></li>
<li><a href="grid.html">Grid</a></li>
</ul>
</nav>
</header>
<main>
<div class="o-container">
<h1 class="c-heading -h1">Images</h1>
<section>
<h2 class="c-heading -h2">Lazy load demo</h2>
<h3 class="c-heading -h3">Basic</h3>
<div style="width: 640px; max-width: 100%;">
<div class="o-ratio u-4:3"><img data-load-src="http://picsum.photos/800/600?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
<div class="o-ratio u-4:3"><img data-load-src="http://picsum.photos/800/600?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
</div>
<h4 class="c-heading -h3">Using o-ratio & background-image</h3>
<div style="width: 480px; max-width: 100%;">
<div class="o-ratio u-16:9" data-load-style="background-size: cover; background-position: center; background-image: url(http://picsum.photos/640/480?v=1);"></div>
<div class="o-ratio u-16:9" data-load-style="background-size: cover; background-position: center; background-image: url(http://picsum.photos/640/480?v=2);"></div>
</div>
</section>
<section>
<h3 class="c-heading -h3">Relative to scroll</h3>
<h4 class="c-heading -h3">Using o-ratio & img</h3>
<div style="width: 640px; max-width: 100%;">
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=3" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=4" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
<div class="o-ratio u-4:3">
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/800/600?v=5" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
</div>
</div>
<h4 class="c-heading -h3">Using o-ratio & background-image</h3>
<div style="width: 480px; max-width: 100%;">
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=1"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=2"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=3"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=4"></div>
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/1280/720?v=5"></div>
</div>
<h4 class="c-heading -h3">Using SVG viewport for ratio</h3>
<div style="width: 480px; max-width: 100%;">
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=6"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=7"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
<img
data-scroll
data-scroll-call="lazyLoad, Scroll, main"
data-src="http://picsum.photos/640/480?v=8"
alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
/>
</div>
</section>
</div>
</main>
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate" title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>
</div>
</div>
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js" crossorigin="anonymous"></script>
<script nomodule src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController" crossorigin="anonymous"></script>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>

View File

@@ -1,82 +0,0 @@
<!doctype html>
<html class="is-loading" lang="en" data-page="home">
<head>
<meta charset="utf-8">
<title>Locomotive Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="assets/images/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
<!-- For a dark mode managment and svg favicon add this in your favicon.svg -->
<!--
<style>
path {
fill: #000;
}
@media (prefers-color-scheme: dark) {
path {
fill: #fff;
}
}
</style>
-->
<!-- <link rel="icon" href="assets/images/favicons/favicon.svg"> -->
<!-- Preload Fonts -->
<link rel="preload" href="assets/fonts/SourceSans3-Bold.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="assets/fonts/SourceSans3-BoldIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="assets/fonts/SourceSans3-Regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="assets/fonts/SourceSans3-RegularIt.woff2" as="font" type="font/woff2" crossorigin>
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print"
onload="this.media='all'; this.onload=null; this.isLoaded=true">
</head>
<body data-module-load>
<div data-load-container>
<div data-module-scroll="main">
<header>
<a href="/">
<h1>Locomotive Boilerplate</h1>
</a>
<nav>
<ul>
<li><a href="images.html">Images</a></li>
<li><a href="form.html" data-load="customTransition">Form</a></li>
<li><a href="grid.html">Grid</a></li>
</ul>
</nav>
</header>
<main data-module-example>
<div class="o-container">
<h1 class="c-heading -h1">Hello</h1>
</div>
</main>
<footer>
<p>Made with <a href="https://github.com/locomotivemtl/locomotive-boilerplate"
title="Locomotive Boilerplate" target="_blank" rel="noopener">🚂</a></p>
</footer>
</div>
</div>
<script nomodule src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.6.0/polyfill.min.js"
crossorigin="anonymous"></script>
<script nomodule
src="https://polyfill.io/v3/polyfill.min.js?features=Element.prototype.remove%2CElement.prototype.append%2Cfetch%2CCustomEvent%2CElement.prototype.matches%2CNodeList.prototype.forEach%2CAbortController"
crossorigin="anonymous"></script>
<script src="assets/scripts/vendors.js" defer></script>
<script src="assets/scripts/app.js" defer></script>
</body>
</html>