Merge pull request #1901 from sveltejs/embedded-repl

embedded REPLs
pull/1913/head
Rich Harris 6 years ago committed by GitHub
commit 93f37c3eeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,11 @@
<script>
let count = 0;
function increment() {
count += 1;
}
</script>
<button on:click={increment}>
clicks: {count}
</button>

@ -0,0 +1,12 @@
<script>
import Foo from './Foo.html';
</script>
<style>
p {
font-weight: bold;
}
</style>
<p>this &lt;p&gt; is bold but not red</p>
<Foo/>

@ -0,0 +1,7 @@
<style>
p {
color: red;
}
</style>
<p>this &lt;p&gt; is red but not bold</p>

@ -0,0 +1,74 @@
<script>
import { quintOut } from 'svelte/easing';
import { fade, draw, fly } from 'svelte/transition';
import { expand, blur } from './custom-transitions.js';
import { inner, outer } from './shape.js';
let visible = true;
</script>
<style>
svg {
width: 100%;
height: 100%;
}
path {
fill: white;
opacity: 1;
}
label {
position: absolute;
top: 1em;
left: 1em;
}
.centered {
font-size: 20vw;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
font-family: 'Overpass';
letter-spacing: 0.12em;
color: #676778;
font-weight: 100;
}
.centered span {
will-change: filter;
}
</style>
{#if visible}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<g out:fade="{{duration: 200}}" opacity=0.2>
<path
in:expand="{{duration: 400, delay: 1000, easing: quintOut}}"
style="stroke: #ff3e00; fill: #ff3e00; stroke-width: 50;"
d={outer}
/>
<path
in:draw="{{duration: 1000}}"
style="stroke:#ff3e00; stroke-width: 1.5"
d={inner}
/>
</g>
</svg>
<div class="centered" out:fly="{{y: -20, duration: 800}}">
{#each 'SVELTE' as char, i}
<span
in:blur="{{delay: 1000 + i * 150, duration: 800}}"
>{char}</span>
{/each}
</div>
{/if}
<label>
<input type="checkbox" bind:checked={visible}>
toggle me
</label>
<link href="https://fonts.googleapis.com/css?family=Overpass:100" rel="stylesheet">

@ -0,0 +1,34 @@
import { cubicOut } from 'svelte/easing';
export function expand(node, params) {
const {
delay = 0,
duration = 400,
easing = cubicOut
} = params;
const w = parseFloat(getComputedStyle(node).strokeWidth);
return {
delay,
duration,
easing,
css: t => `opacity: ${t}; stroke-width: ${t * w}`
};
}
export function blur(node, params) {
const {
b = 10,
delay = 0,
duration = 400,
easing = cubicOut
} = params;
return {
delay,
duration,
easing,
css: (t, u) => `opacity: ${t}; filter: blur(${u * b}px);`
};
}

@ -0,0 +1,5 @@
export const inner = `M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45`;
export const outer = `
M65,34 L37,52 A1 1 0 0 0 44 60 L70.5,44.5 A1 1 0 0 0 65,34Z
M64,67 L36,85 A1 1 0 0 0 42 94 L68,77.5 A1 1 0 0 0 64,67Z`;

@ -57,7 +57,7 @@
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
width: 100vw;
height: var(--nav-h);
padding: 0 var(--side-nav);
margin: 0 auto;
@ -162,7 +162,7 @@
position: fixed;
top: 0;
left: 0;
width: 100%;
width: 100vw;
height: var(--nav-h);
padding: 0 var(--side-nav) 0 var(--side-nav);
display: flex;

@ -3,10 +3,14 @@
import Nav from '../components/TopNav.html';
export let child;
export let path;
</script>
<InlineSvg />
<Nav segment={child.segment} />
{#if path !== '/repl/embed'}
<Nav segment={child.segment} />
{/if}
<main>
<svelte:component this={child.component} {...child.props} />
</main>
@ -15,7 +19,7 @@
main {
position: relative;
margin: 0 auto;
padding: var(--nav-h) 0 0 0;
padding: var(--nav-h) var(--side-nav) 0 var(--side-nav);
overflow-x: hidden;
}
</style>

@ -53,22 +53,21 @@ function createExample(slug) {
export function get(req, res) {
const { slug } = req.params;
if (!slugs.has(slug)) {
try {
if (!lookup.has(slug) || process.env.NODE_ENV !== 'production') {
lookup.set(slug, createExample(slug));
}
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(lookup.get(slug));
} catch (err) {
res.writeHead(404, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify({ error: 'not found' }));
return;
}
if (!lookup.has(slug) || process.env.NODE_ENV !== 'production') {
lookup.set(slug, createExample(slug));
}
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(lookup.get(slug));
}

@ -77,15 +77,6 @@
text-transform: uppercase;
}
/* .post:first-child .byline::after {
content: 'Latest post';
font-weight: 700;
color: var(--second);
text-transform: uppercase;
margin-left: 1em;
} */
.post p {
font-size: var(--h5);
max-width: 30em;
@ -103,21 +94,4 @@
.posts a:hover > h2 {
color: var(--flash)
}
.byline {
/* width: 100%; */
padding: 1.6rem 0 0 0;
/* border-bottom: 1px solid var(--second); */
font: 300 var(--code-fs)/1.7 var(--font-mono);
}
time {
/* border-bottom: 1px solid var(--second); */
}
.byline a {
color: var(--second);
}
.byline a:hover { color: var(--flash) }
</style>

@ -8,7 +8,8 @@
<style>
.container {
position: relative;
margin: 10rem var(--side-page);
margin: 10rem auto;
max-width: 120rem;
}
.container ul {
@ -57,15 +58,6 @@
opacity: 0.7;
}
.learn-btn {
all: unset;
cursor: pointer;
display: block;
margin-top: 4rem;
}
.legend { padding-top: 4rem }
.box {
padding: 2em;
display: flex;
@ -107,12 +99,18 @@
background: url(/icons/arrow-right.svg);
}
h6 {
max-width: 25em;
padding: 2.4rem;
.example {
display: grid;
grid-template-columns: 1fr 4fr;
align-items: start;
}
iframe {
/* grid-column: 2/4; */
width: 100%;
height: 420px;
border: 1px solid #999;
border-radius: var(--border-r);
font: 300 1rem/1.4 var(--font-mono);
text-align: center;
}
@media screen and (min-width: 870px) {
@ -142,7 +140,7 @@
<ul class='grid stretch'>
<li class='box bg-prime white'>
<h2 style='padding:2.4rem 0 0 0'>Write less code</h2>
<p>Write boilerplate-free components using languages you already know — HTML, CSS and JavaScript</p>
<p>Build boilerplate-free components using languages you already know — HTML, CSS and JavaScript</p>
<a href="TODO-blog-post-on-loc">learn more</a>
</li>
@ -163,11 +161,13 @@
</ul>
</section>
<section class="container grid half">
<section class="container grid half linkify">
<div>
<p>Svelte is a radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the <em>browser</em>, Svelte shifts that work into a <em>compile step</em> that happens when you build your app.</p>
<p>Instead of using techniques like virtual DOM diffing, Svelte writes code that surgically updates the DOM when the state of your app changes.</p>
<p><a href="TODO-svelte-3-blog-post">Read the introductory blog post</a> to learn more.</p>
</div>
<div>
@ -175,6 +175,54 @@
</div>
</section>
<section class="container grid example linkify">
<div>
<p>Svelte components are written in HTML files. Just add data.</p>
</div>
<iframe
title="Hello world example"
src="/repl/embed?demo=homepage-demo-hello-world"
scrolling="no"
></iframe>
</section>
<section class="container grid example linkify">
<div>
<p>CSS is component-scoped by default — no more style collisions or specificity wars. Or you can <a href="TODO-blog-post-on-css-in-js">use your favourite CSS-in-JS library</a>.</p>
</div>
<iframe
title="Hello world example"
src="/repl/embed?demo=homepage-demo-scoped-styles"
scrolling="no"
></iframe>
</section>
<section class="container grid example linkify">
<div>
<p>Trigger efficient, granular updates by assigning to local variables. The compiler does the rest.</p>
</div>
<iframe
title="Hello world example"
src="/repl/embed?demo=homepage-demo-reactivity"
scrolling="no"
></iframe>
</section>
<section class="container grid example linkify">
<div>
<p>Build beautiful UIs with a powerful, performant transition engine built right into the framework.</p>
</div>
<iframe
title="Hello world example"
src="/repl/embed?demo=homepage-demo-transitions"
scrolling="no"
></iframe>
</section>
<section class="container grid half">
<p>TODO finish building this page. Ideas: Who's using Svelte? Example code (interactive, ideally). What else?</p>
</section>

@ -22,7 +22,8 @@
.user {
position: relative;
display: inline-block;
padding: 0em 3.2rem 0 1.6rem;
padding: 0em 1.2rem 0 1.6rem;
height: 0.8em;
line-height: 1;
z-index: 99;
}
@ -40,7 +41,7 @@
span {
/* position: relative; padding: 0 2em 0 0; */
line-height: 1;
display: inline-block;
display: none;
font-family: var(--font-ui);
font-size: 1.3rem;
opacity: 0.7;
@ -54,17 +55,18 @@
position: absolute;
top: -0.05em;
right: 0;
width: 2.4rem;
height: 2.4rem;
width: 2.1rem;
height: 2.1rem;
border: 1px solid rgba(255,255,255,0.3);
border-radius: 0.2rem;
}
.menu {
position: absolute;
width: calc(100% - 0rem);
width: calc(100% + 1.6rem);
min-width: 6em;
top: 3rem;
left: 0rem;
right: -1.6rem;
background-color: var(--second);
padding: 0.8rem 1.6rem;
z-index: 99;
@ -82,4 +84,19 @@
.menu button:hover {
opacity: 1;
}
@media (min-width: 600px) {
.user {
padding: 0em 3.2rem 0 1.6rem;
}
img {
width: 2.4rem;
height: 2.4rem;
}
span {
display: inline-block;
}
}
</style>

@ -276,7 +276,7 @@ export default app;` });
{:else}
<button class="icon" on:click={login}>
<Icon name="log-in" />
&nbsp;Log in to save
<span>&nbsp;Log in to save</span>
</button>
{/if}
</div>
@ -307,6 +307,8 @@ export default app;` });
}
.icon {
position: relative;
top: -0.1rem;
display: inline-block;
padding: 0.2em;
opacity: .7;
@ -338,8 +340,15 @@ export default app;` });
opacity: 1;
}
@media (min-width: 768px) {
.icon[title^='fullscreen'] { display: inline }
button span {
display: none;
}
@media (min-width: 600px) {
.icon[title^='fullscreen'] { display: inline }
button span {
display: inline-block;
}
}
</style>

@ -18,9 +18,9 @@
export let mode;
export let code;
export let readonly;
export let error;
export let errorLoc;
export let readonly = false;
export let error = null;
export let errorLoc = null;
export let warningCount = 0;
export let flex = false;
export let lineNumbers = true;
@ -146,7 +146,10 @@
<style>
.codemirror-container {
position: relative;
width: 100%;
height: 100%;
border: none;
}
.codemirror-container :global(.CodeMirror) {
@ -165,17 +168,6 @@
padding: 0;
}
@media (min-width: 768px) {
.codemirror-container {
height: 100%;
border: none;
}
.codemirror-container :global(.CodeMirror) {
height: 100%;
}
}
.codemirror-container :global(.CodeMirror-gutters) {
padding: 0 1.6rem 0 .8rem;
border: none;

@ -168,7 +168,7 @@
</style>
<div class="component-selector">
<div class="file-tabs" on:dblclick="{() => dispatch('create')}">
<div class="file-tabs" on:dblclick="{addNew}">
{#each $component_store as component}
<button
id={component.name}

@ -13,7 +13,7 @@
background: var(--back-light);
}
@media (min-width: 768px) {
@media (min-width: 600px) {
.editor-wrapper {
/* make it easier to interact with scrollbar */
padding-right: 8px;

@ -0,0 +1,77 @@
<style>
.input-output-toggle {
display: grid;
position: absolute;
user-select: none;
grid-template-columns: 1fr 40px 1fr;
grid-gap: 0.5em;
align-items: center;
width: 100%;
height: 4.2rem;
border-top: 1px solid var(--second);
}
input {
display: block;
position: relative;
height: 1em;
width: calc(100% - 0.6em);
top: -2px;
border-radius: 0.5em;
-webkit-appearance: none;
outline: none;
margin: 0 0.6em 0 0;
}
input::before {
content: "";
position: absolute;
display: block;
height: 100%;
width: 100%;
border-radius: 1em;
top: 0px;
left: 0px;
background: var(--second);
box-sizing: border-box;
-webkit-transition: .25s ease-out;
padding: 2px;
box-sizing: content-box;
}
input:checked::before {
background: var(--prime);
}
input::after {
content: "";
position: absolute;
display: block;
height: 1em;
width: 1em;
top: 2px;
left: 2px;
border-radius: 1em;
background: white;
box-shadow: 0 0px 1px rgba(0,0,0,.4), 0 4px 2px rgba(0,0,0,.1);
-webkit-transition: .2s ease-out;
}
input:checked::after {
left: calc(100% - 9px);
}
span {
color: #ccc;
}
.active {
color: #555;
}
</style>
<label class="input-output-toggle">
<span class:active={!checked} style="text-align: right">input</span>
<input type="checkbox" bind:checked>
<span class:active={checked}>output</span>
</label>

@ -297,29 +297,19 @@
<style>
.iframe-container {
border-top: 1px solid #ccc;
background-color: white;
border: none;
height: 100%;
}
iframe {
width: 100%;
height: calc(100vh -3em);
height: 100%;
/* height: calc(100vh - var(--nav-h)); */
border: none;
display: block;
}
@media (min-width: 768px) {
.iframe-container {
border: none;
height: 100%;
}
iframe {
height: 100%;
}
}
.greyed-out {
filter: grayscale(50%) blur(1px);
opacity: .25;

@ -13,6 +13,7 @@
export let values_store;
export let json5;
export let sourceError;
export let sourceErrorLoc;
export let runtimeError;
// refs
@ -37,12 +38,17 @@
viewer.setProp(prop, value);
updateValues(prop, value);
}
function navigate(event) {
// TODO handle navigation from error messages
}
</script>
<style>
.view-toggle {
height: var(--pane-controls-h);
border-bottom: 1px solid #eee;
white-space: nowrap;
}
button {
@ -108,9 +114,8 @@
>CSS output</button>
</div>
{#if view === 'result'}
<SplitPane type="vertical">
<SplitPane type="vertical" pos={67}>
<div slot="a">
{#if bundle}
<Viewer
@ -122,7 +127,6 @@
{props}
{sourceError}
bind:error={runtimeError}
on:data="{e => updateData(e.detail.current)}"
on:navigate={navigate}
on:binding="{e => setPropFromViewer(e.detail.prop, e.detail.value)}"
/>
@ -159,7 +163,7 @@
</section>
</SplitPane>
{:else}
<SplitPane type="vertical">
<SplitPane type="vertical" pos={67}>
<div slot="a">
<CodeMirror
mode="javascript"

@ -6,6 +6,7 @@
import CodeMirror from './CodeMirror.html';
import Input from './Input/index.html';
import Output from './Output/index.html';
import InputOutputToggle from './InputOutputToggle.html';
export let version = 'alpha'; // TODO change this to latest when the time comes
export let app;
@ -55,6 +56,9 @@
let sourceErrorLoc;
let runtimeErrorLoc;
let width = typeof window !== 'undefined' ? window.innerWidth : 300;
let show_output = false;
onMount(async () => {
workers = {
compiler: new Worker('/workers/compiler.js'),
@ -64,7 +68,7 @@
workers.compiler.postMessage({ type: 'init', version });
workers.compiler.onmessage = event => {
js = event.data.js;
css = event.data.css;
css = event.data.css || `/* Add a <style> tag to see compiled CSS */`;
if (event.data.props) props = event.data.props;
};
@ -169,7 +173,17 @@
</script>
<style>
.repl-inner { height: 100% }
.container {
position: relative;
width: 100%;
height: calc(100% - 4.2rem);
}
.repl-inner {
width: 200%;
height: 100%;
transition: transform 0.3s;
}
.repl-inner :global(section) {
position: relative;
@ -232,51 +246,63 @@
cursor: pointer;
}
@media (min-width: 768px) {
.show-if-mobile { display: none }
.offset {
transform: translate(-50%,0);
}
@media (min-width: 600px) {
.container {
height: 100%;
}
.repl-outer.zen-mode {
position: fixed;
.repl-inner {
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 11;
}
section { height: 100% }
.input-output-toggle {
display: none;
}
.offset {
transition: none;
transform: none;
}
}
</style>
<div class="repl-inner">
<SplitPane type="horizontal">
<section slot=a>
<Input
{component_store}
{selected_store}
{values_store}
error={sourceError}
errorLoc="{sourceErrorLoc || runtimeErrorLoc}"
{warningCount}
on:remove={removeComponent}
on:change="{handleChange}"
/>
</section>
<section slot=b style='height: 100%;'>
<Output
{version}
{selected_store}
{js}
{css}
{bundle}
{ssr}
{dom}
{props}
{values_store}
{sourceError}
{runtimeError}
/>
</section>
</SplitPane>
<div class="container" bind:clientWidth={width}>
<div class="repl-inner" class:offset="{show_output}">
<SplitPane type="horizontal" fixed="{600 > width}" pos={60} fixed_pos={50}>
<section slot=a>
<Input
{component_store}
{selected_store}
{values_store}
error={sourceError}
errorLoc="{sourceErrorLoc || runtimeErrorLoc}"
{warningCount}
on:remove={removeComponent}
on:change="{handleChange}"
/>
</section>
<section slot=b style='height: 100%;'>
<Output
{version}
{selected_store}
{js}
{css}
{bundle}
{ssr}
{dom}
{props}
{values_store}
{sourceError}
{runtimeError}
/>
</section>
</SplitPane>
</div>
</div>
<InputOutputToggle bind:checked={show_output}/>

@ -5,13 +5,17 @@
const dispatch = createEventDispatcher();
export let type;
export let pos = 50;
export let fixed = false;
export let fixed_pos = pos;
export let min = 50;
// export let min1 = min;
// export let min2 = min;
const refs = {};
const side = type === 'horizontal' ? 'left' : 'top';
const dimension = type === 'horizontal' ? 'width' : 'height';
let pos = 50;
let dragging = false;
function setPos(event) {
@ -122,45 +126,36 @@
height: 1px;
}
@media (max-width: 767px) {
.pane {
/* override divider-set dimensions */
width: 100% !important;
height: auto !important;
}
.left, .right, .divider {
display: block;
}
@media (min-width: 768px) {
.left, .right, .divider {
display: block;
}
.left, .right {
height: 100%;
float: left;
}
.top, .bottom {
position: absolute;
width: 100%;
}
.left, .right {
height: 100%;
float: left;
}
.top { top: 0; }
.bottom { bottom: 0; }
.top, .bottom {
position: absolute;
width: 100%;
}
.top { top: 0; }
.bottom { bottom: 0; }
</style>
<div class="container" bind:this={refs.container}>
<div class="pane" style="{dimension}: {pos}%;">
<div class="pane" style="{dimension}: {fixed ? fixed_pos : pos}%;">
<slot name="a"></slot>
</div>
<div class="pane" style="{dimension}: {100 - pos}%;">
<div class="pane" style="{dimension}: {100 - (fixed ? fixed_pos : pos)}%;">
<slot name="b"></slot>
</div>
<div class="{type} divider" style="{side}: calc({pos}% - 8px)" use:drag={setPos}></div>
{#if !fixed}
<div class="{type} divider" style="{side}: calc({pos}% - 8px)" use:drag={setPos}></div>
{/if}
</div>
{#if dragging}

@ -0,0 +1,108 @@
<script>
import { onMount } from 'svelte';
import * as fleece from 'golden-fleece';
import Repl from './_components/Repl.html';
export let query;
let version = query.version || 'alpha';
let app = {
components: [],
values: {}
};
let name = 'loading...';
onMount(() => {
fetch(`https://unpkg.com/svelte@${version}/package.json`)
.then(r => r.json())
.then(pkg => {
version = pkg.version;
});
if (query.gist) {
fetch(`gist/${query.gist}`).then(r => r.json()).then(data => {
const { id, description, files } = data;
name = description;
let values = {};
const components = Object.keys(files)
.map(file => {
const dot = file.lastIndexOf('.');
if (!~dot) return;
const source = files[file].content;
// while we're here...
if (file === 'data.json' || file === 'data.json5') {
values = tryParseData(source) || {};
}
return {
name: file.slice(0, dot),
type: file.slice(dot + 1),
source
};
})
.filter(x => x.type === 'html' || x.type === 'js')
.sort((a, b) => {
if (a.name === 'App' && a.type === 'html') return -1;
if (b.name === 'App' && b.type === 'html') return 1;
if (a.type !== b.type) return a.type === 'html' ? -1 : 1;
return a.name < b.name ? -1 : 1;
});
app = { components, values };
});
} else if (query.demo) {
const url = `api/examples/${query.demo}`;
fetch(url).then(async response => {
if (response.ok) {
const data = await response.json();
app = {
values: tryParseData(data.json5) || {}, // TODO make this more error-resistant
components: data.components
};
}
});
}
});
function tryParseData(json5) {
try {
return fleece.evaluate(json5);
} catch (err) {
return null;
}
}
</script>
<style>
.repl-outer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--back);
overflow: hidden;
box-sizing: border-box;
--pane-controls-h: 4.2rem;
}
</style>
<svelte:head>
<title>{name} • Svelte REPL</title>
</svelte:head>
<div class="repl-outer">
{#if process.browser}
<Repl {version} {app}/>
{/if}
</div>

@ -137,35 +137,29 @@
<style>
.repl-outer {
position: relative;
min-height: calc(100vh - var(--nav-h));
height: calc(100vh - var(--nav-h));
--app-controls-h: 5.6rem;
--pane-controls-h: 4.2rem;
overflow: hidden;
background-color: var(--back);
padding: var(--app-controls-h) 0 0 0;
margin: 0 -0.8rem;
box-sizing: border-box;
}
.pane { width: 100%; height: 100% }
h3 {
margin: 4rem 0 0 0;
padding: 0 2.4rem .8rem;
font-size: 1.3rem;
.zen-mode {
position: fixed;
width: 100%;
height: 100%;
top: 0;
z-index: 11;
}
@media (min-width: 768px) {
.repl-outer {
height: calc(100vh - var(--nav-h));
background-color: var(--back);
overflow: hidden;
--app-controls-h: 5.6rem;
padding: var(--app-controls-h) 0 0 0;
box-sizing: border-box;
}
.pane { width: 100%; height: 100% }
.repl-outer.zen-mode {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 11;
@media (min-width: 600px) {
.repl-outer {
margin: 0 -4.8rem; /* can't do calc(0 - var(--side-nav)) */
}
}

@ -11,7 +11,6 @@ html {
-ms-text-size-adjust: 62.5%;
-webkit-text-size-adjust: 62.5%;
-ms-overflow-style: -ms-autohiding-scrollbar;
overflow-y: scroll;
box-sizing: border-box;
border-collapse: collapse;
}
@ -61,7 +60,7 @@ a:focus {
--sidebar-w: 24rem;
--main-width: 80rem;
--code-w: 72em;
--side-nav: 4.8rem;
--side-nav: .8rem;
--side-page: var(--side-nav);
/* easings */
@ -230,16 +229,21 @@ button[outline] {
padding: 0 .4rem .1rem;
border-bottom: .1rem solid hsla(15, 100%, 50%, 0.5); /* muted --prime */
user-select: none;
white-space: nowrap;
/* white-space: nowrap; */
color: inherit;
transition: color .2s;
transition: color .2s, border .2s, padding .2s;
}
.linkify a:not(.open-in-repl):hover {
color: var(--flash);
}
.linkify a:not(.open-in-repl):before {
.linkify a:not(.open-in-repl):hover {
padding: 0 .4rem 0;
border-bottom: .2rem solid hsla(15, 100%, 50%, 1);
}
/* .linkify a:not(.open-in-repl):before {
content: '';
position: absolute;
width: 100%;
@ -259,7 +263,7 @@ button[outline] {
.linkify a:not(.open-in-repl):hover:before {
visibility: visible;
transform: scaleX(1);
}
} */
a:hover > .icon { stroke: var(--flash) }
@ -386,6 +390,7 @@ table span {
:root {
--side-page: 14vw;
--top-offset: 10rem;
--side-nav: 4.8rem;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Loading…
Cancel
Save