josefaidt / svelte-themer Goto Github PK
View Code? Open in Web Editor NEWA theming engine for your Svelte apps using CSS Variables, persisted.
Home Page: https://svelte-themer.vercel.app/
License: MIT License
A theming engine for your Svelte apps using CSS Variables, persisted.
Home Page: https://svelte-themer.vercel.app/
License: MIT License
This could be done with a wrapping element that does not affect the dom's structure beyond css. A mix of setProperty() and removeProperty() could be used to handle the theme transitions.
I do like your object storage for variable settings. A lot cleaner than what I was working on.
Possible benefits:
Global default variables could be defined in script to handle non-js systems. (rare to be sure)
-- global defaults also allow for partial rewrites of the variables. (i.e. no need to rewrite media breakpoints unless desired.)
Applying to a wrapping element allows for the nesting of variable settings. Perhaps modals look different.
Named wrappers could still use localStorage for defaults.
This allows for easier real-time changes with user-defined themes.
Property setters make the code cleaner since you don't have to build complex strings beyond your tiered variable names.
Listed below is a simple example. Everything in the slot would see the variable --txtColor as red.
display: contents; removes the wrapper from creating display issues (grids, etc).
<script>
import { onMount } from 'svelte';
let el;
onMount(() => {
el.style.setProperty('--txtColor','red')
});
</script>
<div bind:this={el} style="display: contents; ">
<slot ></slot>
</div>
// themes.js
export default {
themer: {
light: {},
dark: {},
colors: {},
},
forest: {
light: {},
dark: {},
colors: {},
},
solarized: {
light: {},
dark: {},
colors: {},
},
}
Hi,
this looks great — do you know if it could work in IE11?
https://svelte-themer.now.sh/ does not seem to work out of the box, but are you aware if any of the polyfills mentioned here: https://stackoverflow.com/questions/46429937/ie11-does-a-polyfill-script-exist-for-css-variables could make it work?
Thanks!
This is super useful!
I have a very special case where I might want to theme within containers. Do you know if it's possible to add a container flag such as
.container > :global(svg)
I am not sure how one would inject the .container > :global
part...
The exampIe got this from is here:
https://svelte.dev/repl/4e04a629ab934863b09c4ee3f69d99a1?version=3.8.1
I'll try to check out your code to see if I can solve it but if you have a quick idea how to do it I'd appreciate it!!
Cheers, /Jon
if number, set string of current
if not found, set stirng of current
I have installed through yarn add -D svelte-themer
, however I have also tried adding as a normal dependency and nothing changed.
At build time I get the following
[rollup-plugin-svelte] The following packages did not export their `package.json` file so we could not check the "svelte" field. If you had difficulties importing svelte components from a package, then please contact the author and ask them to export the package.json file.
- svelte-themer
When I try to access the website I get the following:
Error: <ThemeWrapper> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules
at validate_component (/.../project/__sapper__/dev/server/server.js:95:15)
at /.../project/__sapper__/dev/server/server.js:15381:3
at Object.$$render (/.../project/__sapper__/dev/server/server.js:113:22)
at /.../project/__sapper__/dev/server/server.js:15438:40
at $$render (/.../project/__sapper__/dev/server/server.js:113:22)
at Object.render (/.../project/__sapper__/dev/server/server.js:121:26)
at /.../project/__sapper__/dev/server/server.js:20314:49
at Generator.next (<anonymous>)
at fulfilled (/.../project/__sapper__/dev/server/server.js:15757:58)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Error: <ThemeWrapper> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules
at validate_component (/.../project/__sapper__/dev/server/server.js:95:15)
at /.../project/__sapper__/dev/server/server.js:15381:3
at Object.$$render (/.../project/__sapper__/dev/server/server.js:113:22)
at /.../project/__sapper__/dev/server/server.js:15438:40
at $$render (/.../project/__sapper__/dev/server/server.js:113:22)
at Object.render (/.../project/__sapper__/dev/server/server.js:121:26)
at /.../project/__sapper__/dev/server/server.js:20314:49
at Generator.next (<anonymous>)
at fulfilled (/.../project/__sapper__/dev/server/server.js:15757:58)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Error: <ThemeWrapper> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules
at validate_component (/.../project/__sapper__/dev/server/server.js:95:15)
at /.../project/__sapper__/dev/server/server.js:15381:3
at Object.$$render (/.../project/__sapper__/dev/server/server.js:113:22)
at /.../project/__sapper__/dev/server/server.js:15438:40
at $$render (/.../project/__sapper__/dev/server/server.js:113:22)
at Object.render (/.../project/__sapper__/dev/server/server.js:121:26)
at /.../project/__sapper__/dev/server/server.js:20314:49
at Generator.next (<anonymous>)
at fulfilled (/.../project/__sapper__/dev/server/server.js:15757:58)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Provide readable release notes with thanks to contributors.
Hi.
Using sveltejs/template
with nothing modified except svelte-themer ^0.4.8
installed as a dev dependency.
// App.svelte
<script>
import { ThemeWrapper, ThemeToggle } from 'svelte-themer'
</script>
<ThemeWrapper>
<main>
<h1>svelte themer</h1>
<ThemeToggle />
</main>
</ThemeWrapper>
<style>
:global(html) {
background-color: var(--theme-colors-background, initial);
color: var(--theme-colors-text, initial);
}
</style>
npm run dev
In the browser console all I get is
Uncaught TypeError: ThemeWrapper is not a constructor
create_fragment bundle.js:2449
init index.mjs:1500
App bundle.js:2518
app main.js:3
<anonymous> bundle.js:2536
I'm a Svelte noob, am I missing something?
Thank you for your consideration.
So my problem is that when I try to use this package it somehow breaks my page.js routing but it works if I refresh the page after clicking the link for the page in the navbar. Tried it on npm run dev
and npm run build
// App.svelte
<script>
import router from "page";
import { ThemeWrapper, ThemeToggle } from "svelte-themer";
import Home from "./pages/Home.svelte";
import Files from "./pages/Files.svelte";
import ThemesPage from "./pages/Themes.svelte";
import Account from "./pages/Account.svelte";
import Nav from "./components/Nav.svelte";
import Footer from "./components/Footer.svelte";
let page;
router("/", () => (page = Home));
router("/files", () => (page = Files));
router("/themes", () => (page = ThemesPage));
router("/account", () => (page = Account));
router.start();
</script>
<ThemeWrapper>
<Nav />
<svelte:component this={page} />
<ThemeToggle />
<Footer />
</ThemeWrapper>
// Nav.svelte
<nav class="pa3 pa4-ns">
<div class="tc pb3">
<a
class="fas fa-folder-open link dim f6 f5-ns dib mr3 pointer"
href="/">home</a>
<a
class="fas fa-folder-open link dim f6 f5-ns dib mr3 pointer"
href="/files">files</a>
<a
class="fas fa-folder-open link dim f6 f5-ns dib mr3 pointer"
href="/themes">themes</a>
<a
class="fas fa-folder-open link dim f6 f5-ns dib mr3 pointer"
href="/account">account</a>
</div>
</nav>
Also I get this error in the console after importing this package and I don't really know what may be causing it
Uncaught Error: Function called outside component initialization
get_current_component index.js:119
setContext index.js:129
instance index.js:514
flush index.mjs:723
init index.mjs:1477
App main.js:5818
app main.js:3
<anonymous> main.js:5835
index.js:119:18
afterUpdate
for theme settertheme.css
file (must be linked to index.html and available)
themes.js
OR feed theme.css
Hello,
svelte-themer
0.4.9 as a dev dependency, sveltejs/template
.
Getting an error because getContext('theme')
is undefined
when trying to implement my own theme toggle button. Note that using the provided ThemeToggle
everything worked.
// App.svelte
<script>
import { ThemeWrapper } from 'svelte-themer'
import ThemeButton from './components/ThemeButton.svelte'
import themes from './themes.js'
</script>
<ThemeWrapper themes="{themes}">
<main>
<p>Hello</p>
<ThemeButton />
</main>
</ThemeWrapper>
<style>
:global(html) {
background-color: var(--theme-colors-background, initial);
color: var(--theme-colors-text, initial);
}
</style>
// components/ThemeButton.svelte
<script>
import { getContext } from 'svelte'
let { toggle, current, theme } = getContext('theme')
</script>
<button on:click="{toggle}">
<slot>{$current}</slot>
</button>
Am I doing anything wrong?
Thanks
Add a preprocessor (ref #32) to generate CSS file for external consumption or preprocess into the ThemeWrapper
style block (with global styles), negating the need for the current JS-based solution to load on mount.
:global(html)
or :root
? Does this have unintended behaviors with initial load?Support nested theme keys for supplied theme.
When supplied:
const themes = [{
name: 'light',
colors: {
grey: {
_: '#8b868c',
dark: '#5a535b',
},
},
}]
CSS Variables should generate as
--theme-light-grey: #d46a6a;
--theme-light-grey-dark: #5a535b;
This should not change the functionality of supplying underscores in keys (i.e. primary_dark
) as this is more for added flexibility and plans of adding base theme props.
Support prefers-color-scheme
with window.matchMedia()
to determine user theme on first visit.
Current Behavior:
on visit, active theme choice is decided by
themes
arrayProposed Behavior:
on visit, active theme choice is decided by
prefers-color-scheme
choice (will be light
or dark
and themes should have a palette with one of these names)themes
arraydisablePrefersColorScheme
? Forcing the new behavior may cause unwanted UX adjustmentsHello Jose,
Great writeup on svelte theming! I came here after I failed to persist the themes myself, but it looks like I'll face the same issue here. If I'm using Sapper, or any other kind of SSR, then I won't have access to the window variable in my code (or localStorage or sessionStorage ...). Is there any way to remove that dependency? I see you use it to check the preferred mode of the browser. I noticed your localStorage is properly set inside onMount however!
First off, nice job on the theme provider 👏 I like the linear approach to themes, but I was curious about your thoughts on having dark mode styling on a per theme basis v. independent themes (i.e., "light" and "dark")?
Instead of doing this:
[{
name: 'light',
colors: {
text: '#282230',
background: '#f1f1f1',
primary: '#01796f',
primary_dark: '#016159',
secondary: '#562931',
}
}]
You could do something like this:
[{
name: 'forest',
defaults: {
colors: {
text: '#282230',
background: '#f1f1f1',
primary: '#01796f',
primary_dark: '#016159',
secondary: '#562931',
}
},
dark: {
colors: {
background: '#000'
}
}
}]
The defaults
would contain all of theme variables, and dark
would contain only the values you would want to override/modify.
You could expose a new mode
toggle and allow each theme to control it's own dark mode presentation.
I'll create a PR with these changes.
Support using a custom prefix for CSS variables through a prefix
prop on ThemeWrapper
PREFIX
constant with value of theme
in module scope of ThemeWrapperprefix
prop with default PREFIX
Behavior:
prefix={"vendor"}
, CSS variables will look like --vendor-...
prefix={null}
, CSS variables will look like --...
prefix={""}
, ThemeWrapper should throw an error "Invalid prefix string supplied"prefix={" "}
, ThemeWrapper should throw an error "Invalid prefix string supplied" (be sure to .trim()
prefix string)A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.