-
Notifications
You must be signed in to change notification settings - Fork 0
/
playground.html
154 lines (153 loc) · 8.79 KB
/
playground.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<meta name="title" content="{{site.title}}" />
<meta name="description" content="{{site.description}}" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@600&display=swap">
<link rel="stylesheet" href="/low.css" />
<link rel="stylesheet" href="/codecake.css" />
<title>Playground - lowCSS</title>
<script type="text/javascript" src="/lz-string.min.js"></script>
<style>
.font-brand {
font-family: Poppins, sans-serif;
}
</style>
</head>
<body class="bg-white m-0 p-0 font-inter text-neutral-800 leading-normal">
<div class="relative w-full flex flex-col flex-none h-screen">
<header class="w-full flex flex-none items-center justify-between px-4 py-4 border-b border-neutral-200">
<div class="flex items-center gap-2 select-none">
<a href="/" class="font-semibold font-brand text-2xl tracking-tighter text-neutral-900">
<span>low<span class="text-neutral-800 pl-px">css</span>.</span>
</a>
<div class="font-medium text-lg leading-none">playground</div>
</div>
<div class="flex gap-2 items-center">
<div data-action="share" class="flex items-center gap-2 cursor-pointer rounded-lg bg-neutral-900 hover:bg-neutral-950 text-white px-3 py-2">
<svg width="1em" height="1em"><use xlink:href="/sprite.svg#share"></use></svg>
<span class="text-sm font-bold">Share</span>
</div>
<div class="flex gap-1 items-center justify-center p-1 bg-neutral-100 rounded-lg text-neutral-700">
<!--
<div data-view="code" class="flex items-center text-xl px-3 py-1 rounded-md cursor-pointer text-neutral-700">
<svg width="1em" height="1em"><use xlink:href="/sprite.svg#square-fill"></use></svg>
</div>
-->
<div data-view="code,split,preview" class="flex items-center text-xl px-3 py-1 rounded-md cursor-pointer bg-white shadow-sm text-neutral-950">
<svg width="1em" height="1em"><use xlink:href="/sprite.svg#square-half"></use></svg>
</div>
<div data-view="preview" class="flex items-center text-xl px-3 py-1 rounded-md text-neutral-700 cursor-pointer">
<svg width="1em" height="1em"><use xlink:href="/sprite.svg#square"></use></svg>
</div>
</div>
</div>
</header>
<main class="flex-auto flex min-h-0">
<div data-panel="code" class="w-full overflow-y-auto bg-neutral-50"></div>
<div data-panel="split" class="bg-neutral-200 w-px"></div>
<div data-panel="preview" class="w-full">
<iframe class="w-full h-full border-0" srcdoc=""></iframe>
</div>
</main>
<div class="absolute bottom-0 left-half translate-x-half-n max-w-xl">
<div data-alert="share:done" class="flex rounded-lg bg-white shadow-sm border border-neutral-200 w-full p-4 mb-4" style="display:none;">
<div class="text-sm">The Playground URL has been copied to your clipboard.</div>
</div>
</div>
</div>
<script type="module">
import * as CodeCake from "./codecake.js";
// method to get the default code of the editor
const getInitialCode = () => {
const urlParams = new URLSearchParams(window.location.hash.substr(1));
const compressedCode = urlParams.get("code");
if (compressedCode) {
return LZString.decompressFromEncodedURIComponent(compressedCode);
}
// generate the example code
const exampleCode = [
`<div class="flex items-center justify-center w-full min-h-screen p-4 text-neutral-700 font-inter leading-normal">`,
` <div class="p-8 w-full max-w-lg rounded-xl border border-neutral-200 bg-white text-sm shadow-lg">`,
` <h1 class="text-xl text-neutral-950 font-bold mb-3">Welcome to the Playground!</h1>`,
` <p>Use this tool to experiment with utilities, create custom styles, and see immediate results. No setup required!</p>`,
` <h3 class="text-base text-neutral-950 font-bold mb-2 mt-4">Instant Feedback</h3>`,
` <p>Make changes and see the results in real-time. Experiment with different utility classes and visualize the effects of each change without needing to refresh.</p>`,
` <h3 class="text-base text-neutral-950 font-bold mb-2 mt-4">Experiment Freely</h3>`,
` <p>Test out new ideas and combinations without affecting your production code. The Playground is a safe environment for trying things out, from complex layouts to subtle styling tweaks.</p>`,
` <h3 class="text-base text-neutral-950 font-bold mb-2 mt-4">Fast Prototyping</h3>`,
` <p>Get a head start on your design by prototyping layouts and components in the Playground. Once you are happy with the result, you can copy the HTML directly into your project.</p>`,
` </div>`,
`</div>`,
``,
``,
];
return exampleCode.join("\n");
};
// helper method to display a message
const displayMessage = (messageId, delay = 5000) => {
const alertElement = document.querySelector(`[data-alert="${messageId}"]`);
alertElement.style.display = "";
setTimeout(() => {
alertElement.style.display = "none";
}, delay);
};
const codePanel = document.querySelector(`[data-panel="code"]`);
const previewPanel = document.querySelector(`[data-panel="preview"]`);
const editor = CodeCake.create(codePanel, {
code: getInitialCode(),
language: "html",
className: "codecake-light",
highlight: CodeCake.highlight,
lineNumbers: true,
lineWrap: true,
});
// listen for changes in the code
editor.onChange(code => {
const iframeCode = [
`<html lang="en">`,
`<head>`,
` <meta charSet="utf-8" />`,
` <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />`,
` <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" />`,
` <link rel="stylesheet" href="/low.css" />`,
`</head>`,
`<body class="bg-white m-0 p-0">`,
` ${code}`,
`</body>`,
`</html>`,
];
previewPanel.querySelector("iframe").srcdoc = iframeCode.join("\n");
});
// Register interactions to show/hide the code panel
const viewElements = Array.from(document.querySelectorAll(`[data-view]`));
viewElements.forEach(viewElement => {
viewElement.addEventListener("click", event => {
// 1. show/hide panels
const panelsToDisplay = viewElement.dataset.view.split(",");
["code", "split", "preview"].forEach(view => {
document.querySelector(`[data-panel="${view}"]`).style.display = panelsToDisplay.includes(view) ? "" : "none";
});
// 2. update styles of other view elements
viewElements.filter(el => el !== viewElement).forEach(el => {
el.classList.remove("bg-white", "text-neutral-950", "shadow-sm");
// el.classList.add("cursor-pointer");
});
// 3. Update styles of this element
viewElement.classList.add("bg-white", "text-neutral-950", "shadow-sm");
// viewElement.classList.remove("cursor-pointer");
});
});
// Register action events
document.querySelector(`[data-action="share"]`).addEventListener("click", event => {
const code = editor.getCode();
const compressedCode = LZString.compressToEncodedURIComponent(code);
const url = `${location.origin}${location.pathname}#code=${compressedCode}`;
navigator.clipboard.writeText(url).then(() => {
displayMessage("share:done");
});
});
</script>
</body>