Skip to content

Commit d45c4f2

Browse files
committed
Merge branch 'main' into compiler-warnings-errors
2 parents 4812715 + 1d95502 commit d45c4f2

File tree

20 files changed

+340
-355
lines changed

20 files changed

+340
-355
lines changed

apps/svelte.dev/content/docs/svelte/02-template-syntax/01-component-fundamentals.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ If you export a `const`, `class` or `function`, it is readonly from outside the
112112
</script>
113113
```
114114

115-
Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](bindings#bind-this).
115+
Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](bindings#bind:this).
116116

117117
### Reactive variables
118118

apps/svelte.dev/scripts/sync-docs/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const packages: Package[] = [
2727
name: 'svelte',
2828
local: `${REPOS}/svelte`,
2929
repo: 'sveltejs/svelte',
30-
branch: 'docs-fixes',
30+
branch: 'main',
3131
pkg: 'packages/svelte',
3232
docs: 'documentation/docs',
3333
process_modules: async (modules: Modules) => {
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.svelte

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
1515
let repl = $state() as Repl;
1616
let name = $state(data.gist.name);
17-
let zen_mode = $state(false);
18-
let modified_count = $state(0);
17+
let modified = $state(false);
1918
let version = data.version;
2019
let setting_hash: any = null;
2120
@@ -51,7 +50,7 @@
5150
5251
if (!hash) {
5352
repl?.set({
54-
files: data.gist.components
53+
files: structuredClone(data.gist.components)
5554
});
5655
5756
return;
@@ -91,12 +90,12 @@
9190
}
9291
9392
function handle_change({ files }: { files: File[] }) {
94-
const old_count = modified_count;
95-
modified_count = files.filter((c) => c.modified).length;
93+
const was_modified = modified;
94+
modified = files.some((c) => c.modified);
9695
9796
if (
98-
old_count === 0 &&
99-
modified_count > 0 &&
97+
!was_modified &&
98+
modified &&
10099
name === data.gist.name &&
101100
data.examples.some((section) =>
102101
section.examples.some((example) => example.slug === data.gist.id)
@@ -130,7 +129,7 @@
130129
}}
131130
/>
132131

133-
<div class="repl-outer {zen_mode ? 'zen-mode' : ''}">
132+
<div class="repl-outer">
134133
<AppControls
135134
examples={data.examples}
136135
user={data.user}
@@ -139,8 +138,7 @@
139138
saved={handle_save}
140139
{repl}
141140
bind:name
142-
bind:zen_mode
143-
bind:modified_count
141+
bind:modified
144142
/>
145143

146144
{#if browser}
@@ -158,7 +156,7 @@
158156
remove={handle_change}
159157
blur={() => {
160158
// Only change hash on editor blur to not pollute everyone's browser history
161-
if (modified_count !== 0) {
159+
if (modified) {
162160
const json = JSON.stringify({ files: repl.toJSON().files });
163161
change_hash(json);
164162
}

apps/svelte.dev/src/routes/(authed)/playground/[id]/AppControls.svelte

Lines changed: 106 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,22 @@
1010
import { get_app_context } from '../../app-context';
1111
import type { Gist, User } from '$lib/db/types';
1212
import type { File } from '@sveltejs/repl';
13+
import { browser } from '$app/environment';
1314
1415
interface Props {
1516
examples: Array<{ title: string; examples: any[] }>;
1617
user: User | null;
1718
repl: Repl;
1819
gist: Gist;
1920
name: string;
20-
zen_mode: boolean;
21-
modified_count: number;
21+
modified: boolean;
2222
forked: (value: { gist: Gist }) => void;
2323
saved: () => void;
2424
}
2525
2626
let {
2727
name = $bindable(),
28-
zen_mode = $bindable(),
29-
modified_count = $bindable(),
28+
modified = $bindable(),
3029
user,
3130
repl,
3231
gist,
@@ -41,6 +40,7 @@
4140
let downloading = $state(false);
4241
let justSaved = $state(false);
4342
let justForked = $state(false);
43+
let select: HTMLSelectElement;
4444
4545
function wait(ms: number) {
4646
return new Promise((f) => setTimeout(f, ms));
@@ -84,7 +84,7 @@
8484
const gist = await r.json();
8585
forked({ gist });
8686
87-
modified_count = 0;
87+
modified = false;
8888
repl.markSaved();
8989
9090
if (intentWasSave) {
@@ -146,7 +146,7 @@
146146
throw new Error(`Received an HTTP ${r.status} response: ${error}`);
147147
}
148148
149-
modified_count = 0;
149+
modified = false;
150150
repl.markSaved();
151151
saved();
152152
justSaved = true;
@@ -209,6 +209,14 @@ export default app;`
209209
210210
downloading = false;
211211
}
212+
213+
// modifying an app should reset the `<select>`, so that
214+
// the example can be reselected
215+
$effect(() => {
216+
if (modified) {
217+
select.value = '';
218+
}
219+
});
212220
</script>
213221

214222
<svelte:window on:keydown={handleKeydown} />
@@ -217,10 +225,11 @@ export default app;`
217225
<div class="examples-select">
218226
<span class="raised icon"><Icon name="menu" /></span>
219227
<select
228+
bind:this={select}
220229
title="examples"
221230
value={gist.id}
222-
onchange={e => {
223-
goto(`/playground/${(e.target as HTMLSelectElement).value}`);
231+
onchange={(e) => {
232+
goto(`/playground/${e.currentTarget.value}`);
224233
}}
225234
>
226235
<option value="untitled">Create new</option>
@@ -237,52 +246,55 @@ export default app;`
237246

238247
<input
239248
bind:value={name}
249+
onchange={() => (modified = true)}
240250
onfocus={(e) => e.currentTarget.select()}
241251
use:enter={(e) => (e.currentTarget as HTMLInputElement).blur()}
242252
/>
243253

244254
<div class="buttons">
245-
<button class="raised icon" onclick={() => (zen_mode = !zen_mode)} title="fullscreen editor">
246-
{#if zen_mode}
247-
<Icon size={18} name="close" />
248-
{:else}
249-
<Icon size={18} name="maximize" />
250-
{/if}
251-
</button>
252-
253-
<button class="raised icon" disabled={downloading} onclick={download} title="download zip file">
254-
<Icon size={18} name="download" />
255-
</button>
256-
257-
<button class="raised icon" disabled={saving || !user} onclick={() => fork(false)} title="fork">
255+
<button
256+
class="raised icon"
257+
disabled={saving || !user}
258+
onclick={() => fork(false)}
259+
aria-label={user ? 'fork' : 'log in to fork'}
260+
>
258261
{#if justForked}
259262
<Icon size={18} name="check" />
260263
{:else}
261264
<Icon size={18} name="git-branch" />
262265
{/if}
263266
</button>
264267

265-
<button class="raised icon" disabled={saving || !user} onclick={save} title="save">
268+
<button
269+
class="raised icon"
270+
disabled={saving || !user}
271+
onclick={save}
272+
aria-label={user
273+
? `save (${browser && navigator.platform === 'MacIntel' ? '' : 'Ctrl'}+S)`
274+
: 'log in to save'}
275+
>
266276
{#if justSaved}
267277
<Icon size={18} name="check" />
268278
{:else}
269279
<Icon size={18} name="save" />
270-
{#if modified_count}
271-
<div class="badge">{modified_count}</div>
280+
{#if modified}
281+
<span class="badge"></span>
272282
{/if}
273283
{/if}
274284
</button>
275285

286+
<button
287+
class="raised icon download"
288+
disabled={downloading}
289+
onclick={download}
290+
aria-label="download zip file"
291+
></button>
292+
276293
{#if user}
277294
<UserMenu {user} />
278295
{:else}
279-
<button
280-
class="raised icon"
281-
onclick={(e) => (e.preventDefault(), login())}
282-
style="width: auto; padding: 0 0.4rem"
283-
>
284-
<Icon name="log-in" />
285-
<span>&nbsp;Log in to save</span>
296+
<button class="raised icon login" onclick={login}>
297+
<span>log in</span>
286298
</button>
287299
{/if}
288300
</div>
@@ -319,11 +331,15 @@ export default app;`
319331
320332
.examples-select {
321333
position: relative;
322-
}
323334
324-
.examples-select:has(select:focus-visible) .raised.icon {
325-
outline: 2px solid hsla(var(--sk-theme-1-hsl), 0.6);
326-
border-radius: var(--sk-border-radius);
335+
&:has(select:focus-visible) .raised.icon {
336+
outline: 2px solid hsla(var(--sk-theme-1-hsl), 0.6);
337+
border-radius: var(--sk-border-radius);
338+
}
339+
340+
span {
341+
pointer-events: none;
342+
}
327343
}
328344
329345
select {
@@ -343,6 +359,7 @@ export default app;`
343359
justify-content: center;
344360
width: 3.2rem;
345361
height: 3.2rem;
362+
user-select: none;
346363
}
347364
348365
.icon {
@@ -351,18 +368,62 @@ export default app;`
351368
font-size: var(--sk-font-size-ui-small);
352369
color: var(--sk-text-3);
353370
line-height: 1;
371+
background: 50% 50% no-repeat;
372+
background-size: 1.8rem;
373+
z-index: 999;
374+
375+
&[aria-label]:hover::before {
376+
content: '';
377+
width: 1rem;
378+
height: 1rem;
379+
position: absolute;
380+
background: var(--sk-text-3);
381+
top: calc(100% + 0.5rem);
382+
rotate: 45deg;
383+
}
384+
385+
&[aria-label]:hover::after {
386+
content: attr(aria-label);
387+
position: absolute;
388+
top: calc(100% + 1rem);
389+
background: var(--sk-text-3);
390+
color: var(--sk-back-4);
391+
padding: 0.5em 0.5em;
392+
border-radius: var(--sk-border-radius);
393+
}
394+
395+
&.login {
396+
width: auto;
397+
background-image: url($lib/icons/user-light.svg);
398+
background-position: 0.4rem 50%;
399+
padding: 0 0.4rem 0 2.8rem;
400+
401+
:root.dark & {
402+
background-image: url($lib/icons/user-dark.svg);
403+
}
404+
}
405+
406+
&.download {
407+
background-image: url($lib/icons/download-light.svg);
408+
409+
:root.dark & {
410+
background-image: url($lib/icons/download-dark.svg);
411+
}
412+
}
354413
}
355414
356415
.icon:hover,
357416
.icon:focus-visible {
358417
opacity: 1;
359418
}
419+
420+
/* TODO use lucide-svelte, so we don't need all this customisation? */
360421
.icon:disabled {
361-
opacity: 0.3;
362-
}
422+
color: #ccc;
363423
364-
.icon[title^='fullscreen'] {
365-
display: none;
424+
:root.dark & {
425+
color: #555;
426+
}
366427
}
367428
368429
input {
@@ -378,30 +439,13 @@ export default app;`
378439
font-size: var(--sk-font-size-ui-medium);
379440
}
380441
381-
button span {
382-
display: none;
383-
}
384-
385442
.badge {
386-
background: #ff3e00;
387-
border-radius: 100%;
388-
font-size: 10px;
389-
padding: 0;
390-
width: 15px;
391-
height: 15px;
392-
line-height: 15px;
393443
position: absolute;
394-
top: 10px;
395-
right: 0px;
396-
}
397-
398-
@media (min-width: 600px) {
399-
.icon[title^='fullscreen'] {
400-
display: inline;
401-
}
402-
403-
button span {
404-
display: inline-block;
405-
}
444+
background: var(--sk-theme-1);
445+
border-radius: 50%;
446+
width: 1rem;
447+
height: 1rem;
448+
top: -0.2rem;
449+
right: -0.2rem;
406450
}
407451
</style>

0 commit comments

Comments
 (0)