Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable mode-watcher to manage the theme-color meta tag #48

Merged
merged 14 commits into from
Jan 29, 2024

Conversation

ollema
Copy link
Collaborator

@ollema ollema commented Jan 14, 2024

closes #40.

progress:

  • refactored how variables are passed into the FOUC prevention snippet in src/lib/mode-watcher.svelte. FOUC prevention snippet should work based on my testing - both for existing functionality and for the theme-color setting
  • improved demo app: src/routes/+page.svelte by adding derived stores that displays how the html element and the new meta element is updated
  • added themeColors prop in the demo app: src/routes/+layout.svelte
  • added pre-existing <meta name="theme-color" content="..." /> in src/app.html for the demo app, see below

todo:

  • right now, based on the existing code in Add option to set theme-color property #40, this requires an existing <meta name="theme-color" content="..." /> entry since we check for it's existing before overwriting it. is this intentional or should we always write (create a meta element for theme-color if needed) if themeColors are set?
  • the big one: I could not figure out how to pass props from the component to the stores, see TODOs in src/lib/stores.ts. could you help me out here @huntabyte - I'm searching for some pattern where props passed to a component could somehow be read from stores which are initialised somewhere else... do we perhaps need to add some helper function for creating stores/components? use context="module"? I'm not sure, I have not encountered this before
  • tests, when/if the two above are resolved
  • changeset, when/if the all of the above are resolved

Copy link

changeset-bot bot commented Jan 14, 2024

🦋 Changeset detected

Latest commit: 1b42b67

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
mode-watcher Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@huntabyte
Copy link
Member

Hey @ollema, currently traveling this week but I'll try to find some time to check this out!

@huntabyte
Copy link
Member

Hey @ollema, hit me up on Discord when you see this!

Copy link
Collaborator Author

@ollema ollema left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great! left some comments for further improvement (for either of us to fix, I can do it if you don't have time)

src/lib/mode-watcher.svelte Outdated Show resolved Hide resolved

elem.classList[light ? 'remove' : 'add']('dark');
elem.style.colorScheme = light ? 'light' : 'dark';
rootEl.classList[light ? 'remove' : 'add']('dark');
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elem and te was chosen instead of more descriptive names for bundle size reasons. but maybe this was not needed, maybe this code is also minimized. will have to double check!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah man these get minified. Descriptive names > short names (unless you're building a minifier 😉)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could have sworn that this kind of hacky code where you include something that's stringified as a raw html string would not be minified but I am probably mistaken

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you can find rootEl in the client-side bundle I'll send you some $ 😂

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha sure 🤣

does this count?

Screenshot 2024-01-25 at 11 54 20

this is from running pnpm build && pnpm preview. maybe this is not a legit test though?

other functions ARE minimized here but it seems like the FOUC snippet is still untouched with rootEl and the other variable names intact

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No you're fine, I should have done a more thorough review before making bold claims like that 😂 It's because we are stringifying it, and then slapping that stringified version directly into the tag, vs calling the setInitialMode.toString() in there.

Copy link
Collaborator Author

@ollema ollema Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought so too, so I tried:

	{@html `<\u{73}cript nonce="%sveltekit.nonce%">(${setInitialMode.toString()})("dark");</script>`}

similar to skeleton, but that did not work it seems. still did not end up being minimized!

Copy link
Collaborator Author

@ollema ollema Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe the function needs to be defined in a .ts file and exported, let me try that

Copy link
Collaborator Author

@ollema ollema Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tried:

<script lang="ts">
	import { setInitialMode } from './mode.js';
</script>
...

<svelte:head>
	{@html `<\u{73}cript nonce="%sveltekit.nonce%">(${setInitialMode.toString()})("dark", undefined);</script>`}
</svelte:head>

with:

// mode.ts
export function setInitialMode(defaultMode: Mode, themeColors?: ThemeColors) {
	const rootEl = document.documentElement;
	const mode = localStorage.getItem('mode-watcher-mode') || defaultMode;
	const light =
		mode === 'light' ||
		(mode === 'system' && window.matchMedia('(prefers-color-scheme: light)').matches);

	rootEl.classList[light ? 'remove' : 'add']('dark');
	rootEl.style.colorScheme = light ? 'light' : 'dark';

	if (themeColors) {
		const themeMetaEl = document.querySelector('meta[name="theme-color"]');
		if (themeMetaEl) {
			themeMetaEl.setAttribute('content', mode === 'light' ? themeColors.light : themeColors.dark);
		}
	}

	localStorage.setItem('mode', mode);
}

and that still does not work...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get it.

I copied the exact code from skeleton now, just to verify:

<svelte:head>
	<!-- Workaround for a svelte parsing error: https://github.com/sveltejs/eslint-plugin-svelte/issues/492 -->
	{@html `<\u{73}cript nonce="%sveltekit.nonce%">(${setInitialClassState.toString()})();</script>`}
</svelte:head>

and

// mode.ts
export function setInitialClassState() {
	const elemHtmlClasses = document.documentElement.classList;
	// Conditions
	const condLocalStorageUserPrefs = localStorage.getItem('modeUserPrefers') === 'false';
	const condLocalStorageUserPrefsExists = !('modeUserPrefers' in localStorage);
	const condMatchMedia = window.matchMedia('(prefers-color-scheme: dark)').matches;
	// Add/remove `.dark` class to HTML element
	if (condLocalStorageUserPrefs || (condLocalStorageUserPrefsExists && condMatchMedia)) {
		elemHtmlClasses.add('dark');
	} else {
		elemHtmlClasses.remove('dark');
	}
}

still not minified when running pnpm build && pnpm preview. I have no idea what's going on

src/lib/mode-watcher.svelte Outdated Show resolved Hide resolved
src/lib/stores.ts Show resolved Hide resolved
src/lib/stores.ts Show resolved Hide resolved
@huntabyte
Copy link
Member

Let me know once this is ready for re-review/merge!

@ollema ollema changed the title draft: Initial work on theme-color prop Allow mode-watcher to manage the theme-color meta tag Jan 24, 2024
@ollema ollema changed the title Allow mode-watcher to manage the theme-color meta tag Allow mode-watcher to manage the theme-color meta tag Jan 24, 2024
@ollema ollema requested a review from huntabyte January 24, 2024 23:28
@ollema
Copy link
Collaborator Author

ollema commented Jan 24, 2024

Let me know once this is ready for re-review/merge!

should be ready now! all questions/concerns have been resolved I think except for the first one included in the original PR description:

right now, based on the existing code in #40, this requires an existing <meta name="theme-color" content="..." /> entry since we check for it's existing before overwriting it. is this intentional or should we always write (create a meta element for theme-color if needed) if themeColors are set?

I'm tempted to leave as is and solve with better documentation, I think that will be the least surprising option

@huntabyte
Copy link
Member

Let me know once this is ready for re-review/merge!

should be ready now! all questions/concerns have been resolved I think except for the first one included in the original PR description:

right now, based on the existing code in #40, this requires an existing <meta name="theme-color" content="..." /> entry since we check for it's existing before overwriting it. is this intentional or should we always write (create a meta element for theme-color if needed) if themeColors are set?

I'm tempted to leave as is and solve with better documentation, I think that will be the least surprising option

I think we can create one if themeColors is provided as a prop. If we didn't it would be like us ensuring the user has a style or class on their root element already, which we don't.

The code in #40 is more pseudo I believe.

@huntabyte
Copy link
Member

Was able to get the head tag to minify :) merging now!

@huntabyte huntabyte changed the title Allow mode-watcher to manage the theme-color meta tag feat: enable mode-watcher to manage the theme-color meta tag Jan 29, 2024
@huntabyte huntabyte merged commit 733152f into svecosystem:main Jan 29, 2024
3 checks passed
@github-actions github-actions bot mentioned this pull request Jan 29, 2024
@Sija
Copy link

Sija commented Feb 16, 2024

There's a typo either in the implementation or docs, since the former use themeColors property, while the latter the themeColor (singular).

@ollema
Copy link
Collaborator Author

ollema commented Feb 17, 2024

There's a typo either in the implementation or docs, since the former use themeColors property, while the latter the themeColor (singular).

thanks! fixed in #58

@ollema ollema deleted the theme-color branch February 22, 2024 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add option to set theme-color property
3 participants