feat: backport lots of improvements from another project

This commit is contained in:
Joshua Seigler 2016-10-23 03:07:58 -04:00
parent 683e645028
commit 056ce5f777
6 changed files with 570 additions and 133 deletions

View file

@ -15,4 +15,4 @@ After you have edited index.html to your liking, you can run `npm run build` to
## Gotchas:
Firefox and Chrome handle `file:///` urls differently. In Firefox, local files are allowed to interact with LocalStorage, but on Chrome they are not. To circumvent this issue, you have to serve the file on `localhost` with `npm run start` or some other local server.
Firefox and Chrome handle `file:///` urls differently. In Firefox, local files are allowed to interact with LocalStorage, but on Chrome they are not. To circumvent this issue in Chrome, you have to serve the file on `localhost` with `npm run start` or some other local server.

View file

@ -2,13 +2,14 @@
<html>
<head>
<meta charset="utf-8">
<title>Janus Presentation Framework</title>
<title>Tech Talk: Responsive Typography</title>
<link rel="stylesheet" href="styles/main.css" charset="utf-8">
<script type="text/javascript" src="libs/prefixfree/prefixfree.min.js"></script>
</head>
<body class="is-loading">
<nav>
<label for="commandField">Command:</label>
<input list="commands" type="text" id="commandField" autocomplete="off" pattern="[0-9]+|[spc]">
<input list="commands" type="text" id="commandField" autocomplete="off" pattern="[0-9]+|[spcr]">
<ul class="help">
<li>
<strong>#</strong> - jump to a slide item
@ -22,56 +23,118 @@
<li>
<strong>c</strong> - clone window
</li>
<li>
<strong>r</strong> - reset stored state
</li>
</ul>
</nav>
<main>
<section style="background: linear-gradient(-30deg, black, rebeccapurple)">
<h1>Janus Presentations</h1>
<h2>Hotkey powered, multi-window presentations</h2>
<div><small>
Press <kbd>Escape</kbd> for commands. <kbd>Page Up</kbd> / <kbd>Page Down</kbd> to navigate.
</small></div>
<div><a href="https://github.com/seigler/janus">Get the code on GitHub</a></div>
</section>
<section style="background: linear-gradient(-30deg, #400, black)">
<h1>Hotkeys</h1>
<div janus-timeline>
Clone Window: <kbd>F2</kbd>
</div>
<div janus-timeline>
Navigation: <kbd>Page Down</kbd>, <kbd>Page Up</kbd>
</div>
<div janus-timeline>
Toggle Presenter Mode: <kbd>F1</kbd>
</div>
</section>
<section style="color: black">
<img class="cover" src="https://placekitten.com/1024/768" alt="" />
<h1>Self-scaling cover images with <code>object-fit</code></h1>
</section>
<section style="background: linear-gradient(60deg, #060, black)">
<h1>Simple default markup</h1>
<div>
Any <code>section</code> tag or item with attribute <code>janus-timeline</code> is added to the timeline and revealed in sequence.
</div>
</section>
<section style="background: linear-gradient(-60deg, black, #630)">
<h1>Animations controlled by CSS</h1>
<div>
Framework sets custom attribute <code>janus-timeline</code> to <code>past</code>, <code>present</code>, or <code>future</code>
</div>
</section>
<section style="color: black; background-color: #FA0">
<h1>Cross-window synchronization with JavaScript <code>localStorage</code> events.</h1>
<section class="title-page" style="background: linear-gradient(to bottom, black 30%, rebeccapurple)">
<h1 style="font-size: 3.2em">Janus</h1>
<h2>A live-coding web presentation framework.</h2>
<p><kbd>Page Down</kbd> to continue</p>
<p><kbd>Esc</kbd> for commands</p>
</section>
<section>
<h1>The end.</h1>
<blockquote>
<p>Blockquotes are pretty cool, right?</p>
<cite>Thomas Jefferson, probably</cite>
</blockquote>
</section>
<section id="demo1" style="--mouse-x: 0.5">
<div class="live-coding col" style="justify-content: center;">
<div class="browser" style="max-width: calc(100vw * var(--mouse-x)); min-width: 2em; margin-bottom: 0.2em;">
<iframe src="about:blank" frameborder="0"></iframe>
</div>
<div class="row" style="min-height: 50%">
<input type="radio" id="demo1-markup" name="demo1" janus-sync>
<div class="live-coding__component" style="--theme-color: #E34F26;">
<label for="demo1-markup">HTML</label>
<textarea name="html" cols="1" id="demo1-html" spellcheck="false" janus-sync>
<nav>
<a href="#">Home</a>
<a href="#">Shop</a>
<a href="#">Blog</a>
<a href="#">About</a>
</nav>
<div class="content">
<div class="sidebar">Ads ads ads ads</div>
<main>
<section>Content content content</section>
<section>Content content content</section>
<section>Content content content</section>
<section>Content content content</section>
</main>
</div>
<footer>&copy; by us, forever. Neener neener.</footer>
</textarea>
</div>
<input type="radio" id="demo1-styles" name="demo1" checked janus-sync>
<div class="live-coding__component" style="--theme-color: #0070BA;">
<label for="demo1-styles">CSS</label>
<textarea name="css" cols="1" id="demo1-css" spellcheck="false" janus-sync>* { margin: 0; padding: 0; box-size: border-box; }
body {
display: flex;
flex-direction: column;
align-items: stretch;
font-size: calc(1vw + 1em);
height: 100vh;
}
nav {
display: flex;
margin-bottom: -0.1em;
flex-wrap: wrap;
}
nav > a {
flex: 1 1 auto;
max-width: 7em;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 0.5em;
text-align: center;
white-space: nowrap;
border: 0.1em solid black;
}
nav > a + a {
margin-left: -0.1em;
}
.content {
display: flex;
flex-grow: 1;
}
.sidebar {
width: 7em;
order: 1;
border: 0.1em solid;
}
main {
flex-grow: 1;
}
section {
min-height: 3em;
border: solid;
border-width: 0.1em 0;
}
section + section {
margin-top: -0.1em;
}
</textarea>
</div>
<input type="radio" id="demo1-script" name="demo1" janus-sync>
<div class="live-coding__component" style="--theme-color: #F7DF1E;">
<label for="demo1-script">JS</label>
<textarea name="js" cols="1" id="demo1-js" spellcheck="false" janus-sync>// no JS needed
</textarea>
</div>
</div>
</div>
</section>
<section>
<h1>The End</h1>
</section>
</main>

18
libs/prefixfree/prefixfree.min.js vendored Normal file
View file

@ -0,0 +1,18 @@
/**
* StyleFix 1.0.3 & PrefixFree 1.0.7
* @author Lea Verou
* MIT license
*/
(function(){function k(a,b){return[].slice.call((b||document).querySelectorAll(a))}if(window.addEventListener){var e=window.StyleFix={link:function(a){var c=a.href||a.getAttribute("data-href");try{if(!c||"stylesheet"!==a.rel||a.hasAttribute("data-noprefix"))return}catch(b){return}var d=c.replace(/[^\/]+$/,""),h=(/^[a-z]{3,10}:/.exec(d)||[""])[0],l=(/^[a-z]{3,10}:\/\/[^\/]+/.exec(d)||[""])[0],g=/^([^?]*)\??/.exec(c)[1],m=a.parentNode,f=new XMLHttpRequest,n;f.onreadystatechange=function(){4===f.readyState&&
n()};n=function(){var b=f.responseText;if(b&&a.parentNode&&(!f.status||400>f.status||600<f.status)){b=e.fix(b,!0,a);if(d)var b=b.replace(/url\(\s*?((?:"|')?)(.+?)\1\s*?\)/gi,function(b,a,c){return/^([a-z]{3,10}:|#)/i.test(c)?b:/^\/\//.test(c)?'url("'+h+c+'")':/^\//.test(c)?'url("'+l+c+'")':/^\?/.test(c)?'url("'+g+c+'")':'url("'+d+c+'")'}),c=d.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1"),b=b.replace(RegExp("\\b(behavior:\\s*?url\\('?\"?)"+c,"gi"),"$1");c=document.createElement("style");c.textContent='/*# sourceURL='+a.getAttribute('href')+' */\n/*@ sourceURL='+a.getAttribute('href')+' */\n' +
b;c.media=a.media;c.disabled=a.disabled;c.setAttribute("data-href",a.getAttribute("href"));m.insertBefore(c,a);m.removeChild(a);c.media=a.media}};try{f.open("GET",c),f.send(null)}catch(p){"undefined"!=typeof XDomainRequest&&(f=new XDomainRequest,f.onerror=f.onprogress=function(){},f.onload=n,f.open("GET",c),f.send(null))}a.setAttribute("data-inprogress","")},styleElement:function(a){if(!a.hasAttribute("data-noprefix")){var b=a.disabled;a.textContent=e.fix(a.textContent,!0,a);a.disabled=b}},styleAttribute:function(a){var b=
a.getAttribute("style"),b=e.fix(b,!1,a);a.setAttribute("style",b)},process:function(){k('link[rel="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link);k("style").forEach(StyleFix.styleElement);k("[style]").forEach(StyleFix.styleAttribute)},register:function(a,b){(e.fixers=e.fixers||[]).splice(void 0===b?e.fixers.length:b,0,a)},fix:function(a,b,c){for(var d=0;d<e.fixers.length;d++)a=e.fixers[d](a,b,c)||a;return a},camelCase:function(a){return a.replace(/-([a-z])/g,function(b,a){return a.toUpperCase()}).replace("-",
"")},deCamelCase:function(a){return a.replace(/[A-Z]/g,function(b){return"-"+b.toLowerCase()})}};(function(){setTimeout(function(){k('link[rel="stylesheet"]').forEach(StyleFix.link)},10);document.addEventListener("DOMContentLoaded",StyleFix.process,!1)})()}})();
(function(k){function e(b,c,d,h,l){b=a[b];b.length&&(b=RegExp(c+"("+b.join("|")+")"+d,"gi"),l=l.replace(b,h));return l}if(window.StyleFix&&window.getComputedStyle){var a=window.PrefixFree={prefixCSS:function(b,c,d){var h=a.prefix;-1<a.functions.indexOf("linear-gradient")&&(b=b.replace(/(\s|:|,)(repeating-)?linear-gradient\(\s*(-?\d*\.?\d*)deg/ig,function(b,a,c,d){return a+(c||"")+"linear-gradient("+(90-d)+"deg"}));b=e("functions","(\\s|:|,)","\\s*\\(","$1"+h+"$2(",b);b=e("keywords","(\\s|:)","(\\s|;|\\}|$)",
"$1"+h+"$2$3",b);b=e("properties","(^|\\{|\\s|;)","\\s*:","$1"+h+"$2:",b);if(a.properties.length){var l=RegExp("\\b("+a.properties.join("|")+")(?!:)","gi");b=e("valueProperties","\\b",":(.+?);",function(a){return a.replace(l,h+"$1")},b)}c&&(b=e("selectors","","\\b",a.prefixSelector,b),b=e("atrules","@","\\b","@"+h+"$1",b));b=b.replace(RegExp("-"+h,"g"),"-");return b=b.replace(/-\*-(?=[a-z]+)/gi,a.prefix)},property:function(b){return(0<=a.properties.indexOf(b)?a.prefix:"")+b},value:function(b,c){b=
e("functions","(^|\\s|,)","\\s*\\(","$1"+a.prefix+"$2(",b);b=e("keywords","(^|\\s)","(\\s|$)","$1"+a.prefix+"$2$3",b);0<=a.valueProperties.indexOf(c)&&(b=e("properties","(^|\\s|,)","($|\\s|,)","$1"+a.prefix+"$2$3",b));return b},prefixSelector:function(b){return b.replace(/^:{1,2}/,function(b){return b+a.prefix})},prefixProperty:function(b,c){var d=a.prefix+b;return c?StyleFix.camelCase(d):d}};(function(){var b={},c=[],d=getComputedStyle(document.documentElement,null),h=document.createElement("div").style,
l=function(a){if("-"===a.charAt(0)){c.push(a);a=a.split("-");var d=a[1];for(b[d]=++b[d]||1;3<a.length;)a.pop(),d=a.join("-"),StyleFix.camelCase(d)in h&&-1===c.indexOf(d)&&c.push(d)}};if(0<d.length)for(var g=0;g<d.length;g++)l(d[g]);else for(var e in d)l(StyleFix.deCamelCase(e));var g=0,f,k;for(k in b)d=b[k],g<d&&(f=k,g=d);a.prefix="-"+f+"-";a.Prefix=StyleFix.camelCase(a.prefix);a.properties=[];for(g=0;g<c.length;g++)e=c[g],0===e.indexOf(a.prefix)&&(f=e.slice(a.prefix.length),StyleFix.camelCase(f)in
h||a.properties.push(f));!("Ms"!=a.Prefix||"transform"in h||"MsTransform"in h)&&"msTransform"in h&&a.properties.push("transform","transform-origin");a.properties.sort()})();(function(){function b(a,b){h[b]="";h[b]=a;return!!h[b]}var c={"linear-gradient":{property:"backgroundImage",params:"red, teal"},calc:{property:"width",params:"1px + 5%"},element:{property:"backgroundImage",params:"#foo"},"cross-fade":{property:"backgroundImage",params:"url(a.png), url(b.png), 50%"}};c["repeating-linear-gradient"]=
c["repeating-radial-gradient"]=c["radial-gradient"]=c["linear-gradient"];var d={initial:"color","zoom-in":"cursor","zoom-out":"cursor",box:"display",flexbox:"display","inline-flexbox":"display",flex:"display","inline-flex":"display",grid:"display","inline-grid":"display","max-content":"width","min-content":"width","fit-content":"width","fill-available":"width"};a.functions=[];a.keywords=[];var h=document.createElement("div").style,e;for(e in c){var g=c[e],k=g.property,g=e+"("+g.params+")";!b(g,k)&&
b(a.prefix+g,k)&&a.functions.push(e)}for(var f in d)k=d[f],!b(f,k)&&b(a.prefix+f,k)&&a.keywords.push(f)})();(function(){function b(a){e.textContent=a+"{}";return!!e.sheet.cssRules.length}var c={":read-only":null,":read-write":null,":any-link":null,"::selection":null},d={keyframes:"name",viewport:null,document:'regexp(".")'};a.selectors=[];a.atrules=[];var e=k.appendChild(document.createElement("style")),l;for(l in c){var g=l+(c[l]?"("+c[l]+")":"");!b(g)&&b(a.prefixSelector(g))&&a.selectors.push(l)}for(var m in d)g=
m+" "+(d[m]||""),!b("@"+g)&&b("@"+a.prefix+g)&&a.atrules.push(m);k.removeChild(e)})();a.valueProperties=["transition","transition-property"];k.className+=" "+a.prefix;StyleFix.register(a.prefixCSS)}})(document.documentElement);

View file

@ -1,14 +1,20 @@
/*jslint browser: true*/
/*global shortcut*/
(function () {
'use strict';
var slides = [],
currentSlideNumber = 0,
slideNext,
slidePrev,
commandBar,
commandField,
commandBarVisible = true;
syncFormElements = [],
currentSlideNumber = 0,
slideNext,
slidePrev,
commandBar,
commandField,
commandBarVisible = true,
localStorageActions;
/* Dom helper functions. Who needs JQuery?? */
function $(selector) {
return document.querySelector(selector);
}
@ -39,19 +45,17 @@
});
}
var sessionListener = function(e) {
if (e.url === window.location.href) {
if (e.key === 'janus-currentSlideNumber') {
setCurrentSlide(+e.newValue, false);
}
function sessionListener(event) {
if (event.url === window.location.href && localStorageActions[event.key]) {
localStorageActions[event.key](event);
}
};
}
var toggleCommandBar = function() {
if (commandBarVisible) {
function toggleCommandBar(visible) {
if (visible === false) {
commandBar.style.display = 'none';
commandBarVisible = false;
} else {
} else if (visible === true) {
commandBar.style.display = 'flex';
commandField.value = '';
commandField.focus();
@ -59,70 +63,220 @@
}
}
var commandListener = function(event) {
function setMouseX(value, storeChange) {
$('section[janus-timeline="present"]').style.setProperty("--mouse-x", value);
if (storeChange) {
localStorage.setItem('mouse-x', value);
}
}
function mouseListener(event) {
var x = event.clientX / window.innerWidth;
if (event.ctrlKey) {
setMouseX(x, true);
}
}
function runCommand(command) {
var commands, s;
commands = {
's': function () {
document.body.classList.toggle('simulate-projection');
},
'p': function () {
document.body.classList.toggle('show-notes');
},
'c': function () {
window.open(window.location.href, '_blank');
},
'r': function () {
localStorage.clear();
setCurrentSlide(0, true);
}
};
s = command.split();
if (s.length === 1 && /^[0-9]+$/.test(s[0])) {
setCurrentSlide(+s[0], true);
} else if (s.length === 1 && commands[s]) {
commands[s]();
}
}
function commandListener(event) {
var typed = String.fromCharCode(event.keyCode).toLowerCase();
console.log(event);
console.log(typed);
if (/[0-9]/.test(typed)) {
return;
} else if (event.keyCode === 13) {
runCommand(commandField.value);
toggleCommandBar();
} else if (/[spc]/.test(typed)) {
toggleCommandBar(false);
} else if (/[spcr]/.test(typed)) {
runCommand(commandField.value + typed);
toggleCommandBar();
}
};
var runCommand = function(command) {
var s = command.split();
if (s.length === 1 && /^[0-9]+$/.test(s[0])) {
setCurrentSlide(+s[0], true);
} else if (s.length === 1) {
switch(s[0]) {
case 's':
document.body.classList.toggle('simulate-projection');
break;
case 'p':
document.body.classList.toggle('show-notes');
break;
case 'c':
window.open(window.location.href, '_blank');
break;
}
toggleCommandBar(false);
}
}
var init = function() {
function editorListenerGenerator(editor) {
var markupEl, styleEl, scriptEl, frameEl, frameWindow, listener;
markupEl = editor.querySelector('[name="html"]');
styleEl = editor.querySelector('[name="css"]');
scriptEl = editor.querySelector('[name="js"]');
frameEl = editor.querySelector('iframe');
if (frameEl.contentWindow) {
frameWindow = frameEl.contentWindow;
} else {
if (frameEl.contentDocument && frameEl.contentDocument.document) {
frameWindow = frameEl.contentDocument.document;
} else {
frameWindow = frameEl.contentDocument;
}
}
function editorAction() {
var compiled = '<!DOCTYPE html><html><head><style>' + styleEl.value + '</style></head><body>' + markupEl.value + '<scr' + 'ipt>' + scriptEl.value + '</scr' + 'ipt></body></html>';
frameWindow.document.open();
frameWindow.document.write(compiled);
frameWindow.document.close();
// frameEl.src = 'data:text/html;charset=utf-8,' + encodeURI(compiled);
}
// listener = function () {
// if (this.timeoutId) {
// window.clearTimeout(this.timeoutId);
// }
// this.timeoutId = window.setTimeout(editorAction, 100);
// };
[markupEl, styleEl, scriptEl].forEach(function (current, index, array) {
var syncFormElementsIndex = syncFormElements.indexOf(current);
current.addEventListener('keyup', editorAction);
if (syncFormElementsIndex >= 0) {
// add a listener to receive changes from localStorage
localStorageActions['janus-input-' + syncFormElementsIndex] = function (event) {
var storedValue = event.newValue,
decodedValue = storedValue.split('/', 2);
decodedValue.push(storedValue.slice(decodedValue.join(' ').length + 1));
current.value = decodedValue[2];
current.setSelectionRange(+decodedValue[0], +decodedValue[1]);
editorAction();
current.focus();
};
}
});
editorAction();
}
function init() {
var storedSlideNumber;
commandField = $('#commandField');
commandField.addEventListener('keydown', commandListener);
commandField.addEventListener('blur', function (event) {
toggleCommandBar(false);
});
commandBar = $('body > nav');
toggleCommandBar();
toggleCommandBar(false);
slides = $$('main>section, [janus-timeline]');
currentSlideNumber = 0;
shortcut.add('F1', function() {
document.body.classList.toggle('show-notes');
});
shortcut.add('F2', function() {
window.open(window.location.href, '_blank');
});
shortcut.add('Page_down', function() {
shortcut.add('Page_down', function () {
setCurrentSlide(currentSlideNumber + 1, true);
});
shortcut.add('Page_up', function() {
shortcut.add('Page_up', function () {
setCurrentSlide(currentSlideNumber - 1, true);
});
shortcut.add('Escape', toggleCommandBar);
var storedSlideNumber;
if (storedSlideNumber = localStorage.getItem('janus-currentSlideNumber')) {
shortcut.add('Escape', function () {
toggleCommandBar(!commandBarVisible);
});
storedSlideNumber = localStorage.getItem('janus-currentSlideNumber');
if (storedSlideNumber) {
setCurrentSlide(storedSlideNumber, false);
} else {
setCurrentSlide(0);
}
document.addEventListener('mousemove', mouseListener);
localStorageActions = {
'janus-currentSlideNumber': function (event) {
setCurrentSlide(+event.newValue, false);
},
'mouse-x' : function (event) {
setMouseX(event.newValue, false);
}
};
$$('[janus-sync]').forEach(function (current, index, array) {
var currentKey, storedValue, decodedValue, group;
syncFormElements.push(current);
if (current.type === 'textarea' || current.type === 'text') {
currentKey = 'janus-input-' + index;
storedValue = localStorage.getItem(currentKey);
if (storedValue) {
decodedValue = storedValue.split('/', 2);
decodedValue.push(storedValue.slice(decodedValue.join(' ').length + 1));
current.value = decodedValue[2];
current.setSelectionRange(+decodedValue[0], +decodedValue[1]);
} else {
localStorage.setItem(currentKey, '0/0/' + current.value);
}
// add a listener to store changes
current.addEventListener('keyup', function () {
localStorage.setItem(currentKey, current.selectionStart + '/' + current.selectionEnd + '/' + current.value);
});
// add a listener to respond to localStorage updates
if (!localStorageActions[currentKey]) {
localStorageActions[currentKey] = function (event) {
var storedValue = event.newValue,
decodedValue = storedValue.split('/', 2);
decodedValue.push(storedValue.slice(decodedValue.join(' ').length + 1));
current.value = decodedValue[2];
current.focus();
current.setSelectionRange(+decodedValue[0], +decodedValue[1]);
};
}
} else if (current.type === 'checkbox') {
currentKey = 'janus-input-' + index;
storedValue = localStorage.getItem(currentKey);
if (storedValue !== null) {
current.checked = (storedValue === 'true');
} else {
localStorage.setItem(currentKey, current.checked);
}
// add a listener to store changes
current.addEventListener('change', function () {
localStorage.setItem(currentKey, current.checked);
});
// add a listener to respond to localStorage updates
if (!localStorageActions[currentKey]) {
localStorageActions[currentKey] = function (event) {
current.checked = (event.newValue === 'true');
};
}
} else if (current.type === 'radio') {
group = current.getAttribute('name');
currentKey = 'janus-input-' + group;
storedValue = localStorage.getItem(currentKey);
if (storedValue !== null && +storedValue === index) {
current.checked = true;
} else if (current.checked) {
localStorage.setItem(currentKey, index);
}
// add a listener to store changes
current.addEventListener('change', function () {
localStorage.setItem(currentKey, index);
});
// add a listener to respond to localStorage updates
if (!localStorageActions[currentKey]) {
localStorageActions[currentKey] = function (event) {
syncFormElements[+event.newValue].checked = true;
};
}
}
});
$$('.live-coding').forEach(function (current, index, array) {
editorListenerGenerator(current);
});
document.body.classList.remove('is-loading');
};
}
document.addEventListener('DOMContentLoaded', init);
window.addEventListener('storage', sessionListener);
})();
}());

BIN
styles/browser-bar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -7,15 +7,33 @@
}
:root {
--main-font: sans-serif;
--monospace-font: monospace;
--mouse-x: 100vw;
box-sizing: border-box;
font-family: sans-serif;
font-size: calc(2vw + 2em);
font-family: var(--main-font);
font-size: calc(5vw);
cursor: default;
line-height: 1.1;
box-sizing: border-box;
}
::selection {
text-shadow: none;
background: #FF0;
color: black;
}
a {
color: inherit;
cursor: pointer;
text-decoration: none;
display: inline-block;
background-image: linear-gradient(to right, currentcolor, currentcolor);
background-position: 0 1.9ex;
background-repeat: repeat-x;
background-size: 8px 0.08ex;
}
li {
@ -23,29 +41,83 @@ li {
}
code {
font-family: Consolas, monaco, monospace;
font-family: monospace;
font-family: var(--monospace-font, monospace);
}
kbd {
font-family: Consolas, monaco, monospace;
background-color: hsla(0, 0%, 100%, 0.2);
border-radius: 0.5em;
padding: 0.1em 0.4em 0;
margin: -0.1em 0 0;
font-size: 0.7em;
border-radius: 0.2em;
padding: 0.1em;
font-family: inherit;
text-transform: uppercase;
display: inline-block;
border: 0.1em solid;
}
textarea {
font-family: monospace;
font-family: var(--monospace-font, monospace);
font-size: 0.5em;
height: 100%;
}
h1 {
font-size: 1.5rem;
position: relative;
margin: 0 -10vw;
padding: 0 10vw 0.1em;
background-color: hsla(0, 0%, 100%, 0.2);
font-size: 1.5em;
font-weight: 400;
}
h2 {
font-size: 1rem;
font-size: 1em;
font-weight: 900;
}
h1, h2 {
font-weight: bold;
sup {
display: inline-block;
margin-top: -0.5em;
}
sub {
display: inline-block;
margin-bottom: -0.5em;
}
img.thumbnail {
height: 1em;
}
iframe {
background-color: white;
}
blockquote {
quotes: "\201C""\201D""\2018""\2019";
text-align: left;
margin: 0 2em;
}
blockquote > p::before, blockquote > p::after {
display: inline-block;
position: absolute;
margin: -0.2em;
font-size: 4em;
opacity: 0.25;
pointer-events: none;
}
blockquote > p::before {
content: open-quote;
}
blockquote > p::after {
content: close-quote;
}
blockquote > cite {
font-style: normal;
font-size: 0.8em;
text-align: right;
}
blockquote > cite::before {
content: '- ';
}
/* Layout */
@ -56,6 +128,11 @@ body {
margin: 0;
background-color: black;
color: white;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
@ -75,7 +152,7 @@ body.is-loading:after {
}
body.simulate-projection {
filter: brightness(1.5) contrast(0.65);
filter: contrast(0.8);
}
main {
@ -85,6 +162,27 @@ main {
height: 100vh;
}
.row, .col {
display: flex;
flex-grow: 1;
flex-basis: 0;
align-items: stretch;
}
.row--shrink, .col--shrink {
flex: 0 1 auto;
align-self: center;
}
.row {
flex-direction: row;
}
.col {
flex-direction: column;
align-items: stretch;
}
/* Components */
nav {
flex-wrap: wrap;
@ -93,11 +191,11 @@ nav {
top: 0;
left: 0;
right: 0;
padding: 0.25em 0.25em 4em;
padding: 0.25em 0.25em 6em;
transition: transform ease 0.5s;
font-size: 0.5rem;
z-index: 2;
background-image: linear-gradient(to top, hsla(0, 0%, 0%, 0), hsla(0, 0%, 0%, 0.5));
background-image: linear-gradient(to top, hsla(0, 0%, 0%, 0), hsla(0, 0%, 0%, 1));
}
nav > label {
@ -127,7 +225,7 @@ ul.help {
ul.help li {
display: inline-block;
background-color: hsla(0, 0%, 100%, 0.2);
background-color: hsla(0, 0%, 40%, 0.6);
border-radius: 0.5em;
padding: 0 0.5em;
}
@ -141,7 +239,6 @@ section {
width: 100%;
height: 100%;
margin: 0;
padding: 1em;
overflow: hidden;
text-align: center;
background-color: black;
@ -149,34 +246,134 @@ section {
transform-origin: 50% 50%;
}
/*
section > * {
transform: rotate(-7deg);
/* live-coding */
.live-coding {
display: flex;
flex: 1 1 100%;
}
*/
.live-coding textarea {
font-size: 0.5em;
resize: none;
flex: 1 1 auto;
color: white;
background: #333;
border: none;
padding: 0.1em;
outline: none;
}
.live-coding textarea::selection {
background-color: black;
color: var(--theme-color, white);
}
.live-coding__component {
display: flex;
flex: 1 1 auto;
}
.col > .live-coding__component {
flex-direction: column;
}
.live-coding__component label {
line-height: 1;
color: var(--theme-color, inherit);
}
.hidden,
.live-coding input[type="radio"],
.live-coding input[type="checkbox"],
.live-coding input[type="radio"]:not(:checked) + .live-coding__component > textarea,
.live-coding input[type="checkbox"]:not(:checked) + .live-coding__component > textarea {
position: fixed;
visibility: hidden;
right: 110vw;
}
.live-coding input[type="radio"]:not(:checked) + .live-coding__component,
.live-coding input[type="checkbox"]:not(:checked) + .live-coding__component {
flex: 0 1 auto;
}
.row > .live-coding__component label {
writing-mode: vertical-rl;
text-align: right;
transform: rotate(180deg);
border-left: 0.1em solid var(--theme-color, currentcolor);
line-height: 1;
flex: 0 0 auto;
}
.col > .live-coding__component label {
text-align: left;
max-height: 1em;
border-bottom: 0.1em solid var(--theme-color, currentcolor);
}
/* adapted from Lea Verou's http://dabblet.com/gist/14cf7ecbd12505768478b36510f623c8 */
.browser {
position: relative;
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
overflow: auto;
margin: 0 auto;
border-radius: 0.5vmin;
overflow: hidden;
--chrome-height: 4vmin;
padding-top: var(--chrome-height);
background-color: #DDD;
}
.browser::before {
content: "";
position: absolute;
top: 0; right: 0; left: 0;
border: solid;
--right: 146; --left: 201;
border-width: var(--chrome-height) calc(var(--right) / 38 * var(--chrome-height)) 0 calc(var(--left) / 38 * var(--chrome-height));
border-image: url('browser-bar.png') 100% var(--right) 0 var(--left) repeat;
}
.browser iframe {
pointer-events: none;
flex: 1 1 auto;
height: 100%;
width: 100%;
}
/* states and transitions */
[janus-timeline='past'] {
transition: transform ease-in 0.5s, opacity ease-in 0.5s, visibility step-end 0.5s;
transition: transform ease 0.5s, opacity ease 0.5s, visibility step-end 0.5s;
}
section[janus-timeline='present'] [janus-timeline='past'] {
transition: transform ease 0.5s, opacity ease 0.5s;
}
[janus-timeline='present'] {
transition: transform ease-out 0.5s, opacity ease-out 0.5s, visibility step-start 0.5s;
transition: transform ease 0.5s, opacity ease 0.5s, visibility step-start 0.5s;
}
[janus-timeline='future'] {
opacity: 0;
visibility: hidden;
}
body.show-notes section [janus-timeline='future'] {
visibility: visible;
opacity: 0.25;
opacity: 0.4;
}
body.show-notes section[janus-timeline='future'] [janus-timeline='future'] {
opacity: 1;
}
section[janus-timeline='past'] {
section[janus-timeline='past'], body:not(.show-notes) [janus-timeline='past'][janus-past='big'], body:not(.show-notes) [janus-timeline='future'][janus-future='big'] {
transform: translate3d(0, 0, 0) scale(5);
opacity: 0;
visibility: hidden;
@ -196,16 +393,21 @@ section[janus-timeline='future'] {
pointer-events: none;
}
img.cover {
img.cover, img.contain {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
object-fit: cover;
z-index: -1;
transform: none;
}
img.cover {
object-fit: cover;
}
img.contain {
object-fit: contain;
}
body.show-notes section {
transition: none;