Theme Toggle (Store)
Shared theme state using a store, with multiple subscribing components.
Live Demo
Three independent components, all reacting to one store.
MyApp
Home
About
Contact
Dashboard
Welcome back. You have 3 new notifications.
Source
HTML + JavaScript + CSS
<!-- Three independent components, all reacting to one store -->
<div data-component="theme-button">
<button data-action="toggle" data-bind="label"></button>
</div>
<div data-component="theme-navbar">
<div data-bind-class="navClass">
<strong data-bind-class="brandClass">MyApp</strong>
<span data-bind-class="linkClass">Home</span>
<span data-bind-class="linkClass">About</span>
</div>
</div>
<div data-component="theme-card">
<div data-bind-class="cardClass">
<h4 data-bind-class="titleClass">Dashboard</h4>
<p data-bind-class="textClass">Welcome back.</p>
</div>
</div>
<script>
// Store: shared theme state with built-in persistence
wildflower.store('theme', {
storageKey: 'app-theme',
autoSave: true,
state: {
darkMode: true
},
toggle() {
this.darkMode = !this.darkMode;
}
});
// Component A: toggle button
wildflower.component('theme-button', {
subscribe: { theme: ['darkMode'] },
computed: {
label() {
return this.stores.theme?.darkMode ? 'Switch to Light' : 'Switch to Dark';
}
},
toggle() {
this.stores.theme.toggle();
}
});
// Component B: navbar (subscribes to same store)
wildflower.component('theme-navbar', {
subscribe: { theme: ['darkMode'] },
computed: {
navClass() {
return this.stores.theme?.darkMode
? 'nav-dark' : 'nav-light';
},
brandClass() {
return this.stores.theme?.darkMode
? 'brand-dark' : 'brand-light';
},
linkClass() {
return this.stores.theme?.darkMode
? 'link-dark' : 'link-light';
}
}
});
// Component C: content card (subscribes to same store)
wildflower.component('theme-card', {
subscribe: { theme: ['darkMode'] },
computed: {
cardClass() {
return this.stores.theme?.darkMode
? 'card-dark' : 'card-light';
},
titleClass() {
return this.stores.theme?.darkMode
? 'title-dark' : 'title-light';
},
textClass() {
return this.stores.theme?.darkMode
? 'text-dark' : 'text-light';
}
}
});
</script>
<style>
/* Dark theme */
.nav-dark { background: #1a1a1a; border: 1px solid #333; }
.brand-dark { color: #6b996a; }
.link-dark { color: #a0a0a0; }
.card-dark { background: #1a1a1a; border: 1px solid #333; }
.title-dark { color: #f0f0f0; }
.text-dark { color: #a0a0a0; }
/* Light theme */
.nav-light { background: #f8f9fa; border: 1px solid #dee2e6; }
.brand-light { color: #2d5a2d; }
.link-light { color: #555; }
.card-light { background: #ffffff; border: 1px solid #dee2e6; }
.title-light { color: #212529; }
.text-light { color: #6c757d; }
/* Smooth transition between themes */
[class*="nav-"], [class*="card-"] { transition: all 0.3s; }
</style>
Key Points
wildflower.store()creates shared state; any component can subscribe to itsubscribe: { theme: ['darkMode'] }tells the component to re-render whendarkModechanges- Components access store state via
this.stores.theme.darkModeand call store methods viathis.stores.theme.toggle() - Three independent components (the toggle button, the navbar, and the card) all react to the same store change with no event wiring or prop passing
storageKey+autoSave: truepersists state to localStorage automatically. No manualsetItemcalls needed- This is the same pattern the WildflowerJS documentation site uses for its own theme toggle