File tree Expand file tree Collapse file tree 5 files changed +48
-0
lines changed
packages/svelte-ux/src/lib Expand file tree Collapse file tree 5 files changed +48
-0
lines changed Original file line number Diff line number Diff line change
1
+ ---
2
+ " svelte-ux " : patch
3
+ ---
4
+
5
+ Add ThemeInit component to prevent flash of unstyled content when SSR is enabled
Original file line number Diff line number Diff line change 1
1
<script lang =" ts" >
2
+ import ThemeInit from ' ./ThemeInit.svelte' ;
2
3
import { settings as setSettings , type Settings } from ' ./settings' ;
3
4
4
5
export let settings: Settings ;
6
+ /** Include the ThemeInit component to improve SSR compatibility. */
7
+ export let themeInit = true ;
5
8
6
9
setSettings (settings );
7
10
</script >
8
11
12
+ {#if themeInit }
13
+ <ThemeInit />
14
+ {/if }
9
15
<slot />
Original file line number Diff line number Diff line change
1
+ <script >
2
+ import { createHeadSnippet } from ' ../styles/theme' ;
3
+ import { getSettings } from ' ./settings' ;
4
+
5
+ const darkThemes = getSettings ().themes ? .dark ?? [];
6
+
7
+ let headSnippet = createHeadSnippet (darkThemes);
8
+ < / script>
9
+
10
+ < svelte: head>
11
+ {@html headSnippet}
12
+ < / svelte: head>
Original file line number Diff line number Diff line change @@ -83,6 +83,7 @@ export { default as Tab } from './Tab.svelte';
83
83
export { default as Tabs } from './Tabs.svelte' ;
84
84
export { default as TextField } from './TextField.svelte' ;
85
85
export { default as ThemeButton } from './ThemeButton.svelte' ;
86
+ export { default as ThemeInit } from './ThemeInit.svelte' ;
86
87
export { default as Tilt } from './Tilt.svelte' ;
87
88
export { default as Toggle } from './Toggle.svelte' ;
88
89
export { default as ToggleButton } from './ToggleButton.svelte' ;
Original file line number Diff line number Diff line change @@ -20,3 +20,27 @@ export const colorNames = [
20
20
'surface-300' ,
21
21
'surface-content' ,
22
22
] ;
23
+
24
+ /** Return a script tag that will set the initial theme from localStorage. This allows setting
25
+ * the theme before anything starts rendering, even when SSR is in use.
26
+ *
27
+ * This feels a bit weird compared to just placing the function directly in svelte:head,
28
+ * but it's the only way to inject the `darkThemes` array into the function.
29
+ **/
30
+ export function createHeadSnippet ( darkThemes : string [ ] ) {
31
+ function _applyInitialStyle ( darkThemes ) {
32
+ let theme = localStorage . getItem ( 'theme' ) ;
33
+ if ( theme ) {
34
+ document . documentElement . dataset . theme = theme ;
35
+ if ( darkThemes . includes ( theme ) ) {
36
+ document . documentElement . classList . add ( 'dark' ) ;
37
+ }
38
+ } else if ( window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ) {
39
+ document . documentElement . classList . add ( 'dark' ) ;
40
+ }
41
+ }
42
+
43
+ let darkThemeList = darkThemes . map ( ( theme ) => `'${ theme } '` ) . join ( ', ' ) ;
44
+
45
+ return `<script>(${ _applyInitialStyle . toString ( ) } )([${ darkThemeList } ])</script>` ;
46
+ }
You can’t perform that action at this time.
0 commit comments