|  | 
|  | 1 | +<script lang="ts"> | 
|  | 2 | +	import favicon from '$lib/assets/favicon.svg'; | 
|  | 3 | +
 | 
|  | 4 | +	let { children } = $props(); | 
|  | 5 | +
 | 
|  | 6 | +	const title = '$sv-title-$sv'; | 
|  | 7 | +	const href = '$sv-url-$sv'; | 
|  | 8 | +
 | 
|  | 9 | +	let prefersDark = $state(true); | 
|  | 10 | +	let isDark = $state(true); | 
|  | 11 | +
 | 
|  | 12 | +	function switchTheme() { | 
|  | 13 | +		const value = isDark ? 'light' : 'dark'; | 
|  | 14 | +
 | 
|  | 15 | +		isDark = value === 'dark'; | 
|  | 16 | +		localStorage.setItem('sv:theme', isDark === prefersDark ? 'system' : value); | 
|  | 17 | +	} | 
|  | 18 | +
 | 
|  | 19 | +	$effect(() => { | 
|  | 20 | +		document.documentElement.classList.remove('light', 'dark'); | 
|  | 21 | +		prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | 
|  | 22 | +
 | 
|  | 23 | +		const theme = localStorage.getItem('sv:theme'); | 
|  | 24 | +
 | 
|  | 25 | +		isDark = !theme ? prefersDark : theme === 'dark' || (theme === 'system' && prefersDark); | 
|  | 26 | +		document.documentElement.classList.add(isDark ? 'dark' : 'light'); | 
|  | 27 | +	}); | 
|  | 28 | +</script> | 
|  | 29 | + | 
|  | 30 | +<svelte:head> | 
|  | 31 | +	<title>--from-playground {title}</title> | 
|  | 32 | +	<script> | 
|  | 33 | +		{ | 
|  | 34 | +			const theme = localStorage.getItem('sv:theme'); | 
|  | 35 | +
 | 
|  | 36 | +			document.documentElement.classList.add( | 
|  | 37 | +				!theme || theme === 'system' | 
|  | 38 | +					? window.matchMedia('(prefers-color-scheme: dark)').matches | 
|  | 39 | +						? 'dark' | 
|  | 40 | +						: 'light' | 
|  | 41 | +					: theme | 
|  | 42 | +			); | 
|  | 43 | +		} | 
|  | 44 | +	</script> | 
|  | 45 | +</svelte:head> | 
|  | 46 | + | 
|  | 47 | +<div class="layout"> | 
|  | 48 | +	<nav class="navbar"> | 
|  | 49 | +		<div class="nav-left"> | 
|  | 50 | +			<a href="/" class="svelte-icon"> | 
|  | 51 | +				<img src={favicon} alt="Svelte" width="32" height="32" /> | 
|  | 52 | +			</a> | 
|  | 53 | +			<p class="title">{title}</p> | 
|  | 54 | +		</div> | 
|  | 55 | +		<div class="nav-right"> | 
|  | 56 | +			<a {href} class="raised" target="_blank" rel="noopener noreferrer"> | 
|  | 57 | +				--to-playground | 
|  | 58 | +				<span aria-hidden="true" style="margin-left:0.25em;"> ↗</span> | 
|  | 59 | +			</a> | 
|  | 60 | +			<button class="raised theme-toggle" onclick={switchTheme} aria-label="Toggle theme"> | 
|  | 61 | +				<span class="icon"></span> | 
|  | 62 | +			</button> | 
|  | 63 | +		</div> | 
|  | 64 | +	</nav> | 
|  | 65 | + | 
|  | 66 | +	<main class="content"> | 
|  | 67 | +		{@render children?.()} | 
|  | 68 | +	</main> | 
|  | 69 | +</div> | 
|  | 70 | + | 
|  | 71 | +<style> | 
|  | 72 | +	:global(body) { | 
|  | 73 | +		margin: 0; | 
|  | 74 | +	} | 
|  | 75 | +
 | 
|  | 76 | +	:global(html) { | 
|  | 77 | +		margin: 0; | 
|  | 78 | +		--bg-1: hsl(0, 0%, 100%); | 
|  | 79 | +		--bg-2: hsl(206, 20%, 90%); | 
|  | 80 | +		--bg-3: hsl(206, 20%, 80%); | 
|  | 81 | +		--navbar-bg: #fff; | 
|  | 82 | +		--fg-1: hsl(0, 0%, 13%); | 
|  | 83 | +		--fg-2: hsl(0, 0%, 50%); | 
|  | 84 | +		--fg-3: hsl(0, 0%, 60%); | 
|  | 85 | +		--link: hsl(208, 77%, 47%); | 
|  | 86 | +		--border-radius: 4px; | 
|  | 87 | +		--font: | 
|  | 88 | +			-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', | 
|  | 89 | +			'Helvetica Neue', sans-serif; | 
|  | 90 | +		color-scheme: light; | 
|  | 91 | +		background: var(--bg-1); | 
|  | 92 | +		color: var(--fg-1); | 
|  | 93 | +		font-family: var(--font); | 
|  | 94 | +		line-height: 1.5; | 
|  | 95 | +		height: calc(100vh - 2rem); | 
|  | 96 | +		accent-color: var(--link) !important; | 
|  | 97 | +		min-height: 100vh; | 
|  | 98 | +		background-color: var(--bg-1); | 
|  | 99 | +	} | 
|  | 100 | +
 | 
|  | 101 | +	:global(html.dark) { | 
|  | 102 | +		color-scheme: dark; | 
|  | 103 | +		--bg-1: hsl(0, 0%, 18%); | 
|  | 104 | +		--bg-2: hsl(0, 0%, 30%); | 
|  | 105 | +		--bg-3: hsl(0, 0%, 40%); | 
|  | 106 | +		--navbar-bg: hsl(220, 14%, 16%); | 
|  | 107 | +		--fg-1: hsl(0, 0%, 75%); | 
|  | 108 | +		--fg-2: hsl(0, 0%, 40%); | 
|  | 109 | +		--fg-3: hsl(0, 0%, 30%); | 
|  | 110 | +		--link: hsl(206, 96%, 72%); | 
|  | 111 | +	} | 
|  | 112 | +
 | 
|  | 113 | +	.navbar { | 
|  | 114 | +		color: var(--fg-1); | 
|  | 115 | +		display: flex; | 
|  | 116 | +		justify-content: space-between; | 
|  | 117 | +		align-items: center; | 
|  | 118 | +		padding: 0em 2.5rem; | 
|  | 119 | +		height: 3.7rem; | 
|  | 120 | +		background-color: var(--navbar-bg); | 
|  | 121 | +		box-shadow: | 
|  | 122 | +			0 2px 8px 0 rgba(0, 0, 0, 0.08), | 
|  | 123 | +			0 1.5px 4px 0 rgba(0, 0, 0, 0.04); | 
|  | 124 | +	} | 
|  | 125 | +
 | 
|  | 126 | +	.nav-left { | 
|  | 127 | +		display: flex; | 
|  | 128 | +		align-items: center; | 
|  | 129 | +		gap: 0.5rem; | 
|  | 130 | +	} | 
|  | 131 | +
 | 
|  | 132 | +	.svelte-icon { | 
|  | 133 | +		display: flex; | 
|  | 134 | +		align-items: center; | 
|  | 135 | +		text-decoration: none; | 
|  | 136 | +		transition: opacity 0.2s ease; | 
|  | 137 | +	} | 
|  | 138 | +
 | 
|  | 139 | +	.svelte-icon:hover { | 
|  | 140 | +		opacity: 0.8; | 
|  | 141 | +	} | 
|  | 142 | +
 | 
|  | 143 | +	.title { | 
|  | 144 | +		font-size: 1.5rem; | 
|  | 145 | +		font-weight: 400; | 
|  | 146 | +		margin: 0; | 
|  | 147 | +	} | 
|  | 148 | +
 | 
|  | 149 | +	.nav-right { | 
|  | 150 | +		display: flex; | 
|  | 151 | +		align-items: center; | 
|  | 152 | +		gap: 1rem; | 
|  | 153 | +	} | 
|  | 154 | +
 | 
|  | 155 | +	.raised { | 
|  | 156 | +		background: var(--navbar-bg); | 
|  | 157 | +		border-left: 0.5px solid var(--fg-3); | 
|  | 158 | +		border-top: 0.5px solid var(--fg-3); | 
|  | 159 | +		border-bottom: none; | 
|  | 160 | +		border-right: none; | 
|  | 161 | +		border-radius: var(--border-radius); | 
|  | 162 | +		color: var(--fg-1); | 
|  | 163 | +		cursor: pointer; | 
|  | 164 | +		transition: all 0.2s ease; | 
|  | 165 | +		box-shadow: | 
|  | 166 | +			0 2px 4px rgba(0, 0, 0, 0.1), | 
|  | 167 | +			0 1px 2px rgba(0, 0, 0, 0.06); | 
|  | 168 | +		text-decoration: none; | 
|  | 169 | +		font-weight: 500; | 
|  | 170 | +		padding: 0.25rem 0.75rem; | 
|  | 171 | +		font-size: 0.8rem; | 
|  | 172 | +	} | 
|  | 173 | +
 | 
|  | 174 | +	.raised:hover { | 
|  | 175 | +		border-left-color: var(--fg-2); | 
|  | 176 | +		border-top-color: var(--fg-2); | 
|  | 177 | +		box-shadow: | 
|  | 178 | +			0 4px 8px rgba(0, 0, 0, 0.15), | 
|  | 179 | +			0 2px 4px rgba(0, 0, 0, 0.1); | 
|  | 180 | +		transform: translate(-1px, -1px); | 
|  | 181 | +	} | 
|  | 182 | +
 | 
|  | 183 | +	.content { | 
|  | 184 | +		padding: 1rem; | 
|  | 185 | +		color: var(--fg-1); | 
|  | 186 | +	} | 
|  | 187 | +
 | 
|  | 188 | +	.theme-toggle { | 
|  | 189 | +		display: flex; | 
|  | 190 | +		align-items: center; | 
|  | 191 | +		justify-content: center; | 
|  | 192 | +		width: 1.8rem; | 
|  | 193 | +		height: 1.8rem; | 
|  | 194 | +		padding: 0; | 
|  | 195 | +		min-width: 2rem; | 
|  | 196 | +	} | 
|  | 197 | +
 | 
|  | 198 | +	.icon { | 
|  | 199 | +		display: inline-block; | 
|  | 200 | +		width: 1.5rem; | 
|  | 201 | +		height: 1.5rem; | 
|  | 202 | +		-webkit-mask-size: 1.5rem; | 
|  | 203 | +		mask-size: 1.5rem; | 
|  | 204 | +		-webkit-mask-repeat: no-repeat; | 
|  | 205 | +		mask-repeat: no-repeat; | 
|  | 206 | +		-webkit-mask-position: center; | 
|  | 207 | +		mask-position: center; | 
|  | 208 | +		background-color: var(--fg-1); | 
|  | 209 | +	} | 
|  | 210 | +
 | 
|  | 211 | +	.icon { | 
|  | 212 | +		mask-image: url('data:image/svg+xml,%3csvg%20xmlns="http://www.w3.org/2000/svg"%20viewBox="0%200%2024%2024"%3e%3cpath%20fill="%23666"%20d="M12%2021q-3.775%200-6.388-2.613T3%2012q0-3.45%202.25-5.988T11%203.05q.625-.075.975.45t-.025%201.1q-.425.65-.638%201.375T11.1%207.5q0%202.25%201.575%203.825T16.5%2012.9q.775%200%201.538-.225t1.362-.625q.525-.35%201.075-.037t.475.987q-.35%203.45-2.937%205.725T12%2021Zm0-2q2.2%200%203.95-1.213t2.55-3.162q-.5.125-1%20.2t-1%20.075q-3.075%200-5.238-2.163T9.1%207.5q0-.5.075-1t.2-1q-1.95.8-3.163%202.55T5%2012q0%202.9%202.05%204.95T12%2019Zm-.25-6.75Z"/%3e%3c/svg%3e'); | 
|  | 213 | +	} | 
|  | 214 | +
 | 
|  | 215 | +	:global(html.dark) .icon { | 
|  | 216 | +		mask-image: url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3e%3cpath%20fill='%23d4d4d4'%20d='M12%2019a1%201%200%200%201%20.993.883L13%2020v1a1%201%200%200%201-1.993.117L11%2021v-1a1%201%200%200%201%201-1zm6.313-2.09.094.083.7.7a1%201%200%200%201-1.32%201.497l-.094-.083-.7-.7a1%201%200%200%201%201.218-1.567l.102.07zm-11.306.083a1%201%200%200%201%20.083%201.32l-.083.094-.7.7a1%201%200%200%201-1.497-1.32l.083-.094.7-.7a1%201%200%200%201%201.414%200zM4%2011a1%201%200%200%201%20.117%201.993L4%2013H3a1%201%200%200%201-.117-1.993L3%2011h1zm17%200a1%201%200%200%201%20.117%201.993L21%2013h-1a1%201%200%200%201-.117-1.993L20%2011h1zM6.213%204.81l.094.083.7.7a1%201%200%200%201-1.32%201.497l-.094-.083-.7-.7A1%201%200%200%201%206.11%204.74l.102.07zm12.894.083a1%201%200%200%201%20.083%201.32l-.083.094-.7.7a1%201%200%200%201-1.497-1.32l.083-.094.7-.7a1%201%200%200%201%201.414%200zM12%202a1%201%200%200%201%20.993.883L13%203v1a1%201%200%200%201-1.993.117L11%204V3a1%201%200%200%201%201-1zm0%205a5%205%200%201%201-4.995%205.217L7%2012l.005-.217A5%205%200%200%201%2012%207z'/%3e%3c/svg%3e"); | 
|  | 217 | +	} | 
|  | 218 | +</style> | 
0 commit comments