All you need to do is add the state.js file into your projects JS folder and add the following code with your state.js location as the src. Put this code in to your head HTML tags.
<script src="/js/state.js"></script>
Or just add a CDN instead (coming soon)
<script src="https://cdn.jsdelivr.net/npm/@idevgames/state-js/src/state.js"></script>
To activate state.js add the data attribute "data-state" or a class "enable-state" to your html element. State.js automatically tracks element visibility and adds the "state" and "state-visible" classes when elements appear on screen.
<div class="fadeIn" data-state> </div>
.fadeIn{ opacity:0; }
.fadeIn.state{ animation: fadeIn 1s normal forwards ease-in-out; }
@keyframes fadeIn { 0% { opacity:0; } 100% { opacity:1; } }
State.js can watch data attributes and automatically expose them as CSS variables. Perfect for progress indicators, counters, stats, and dynamic data visualization!
<div id="player" data-state
data-state-watch="health,score"
data-health="100"
data-health-min="0"
data-health-max="100"
data-score="0">
</div>
#player .health-bar {
width: var(--state-health-percent);
background: linear-gradient(90deg, red, yellow, green);
}
[data-health="0"] {
animation: death 2s forwards;
}
Move the slider to change the health value (no JavaScript needed!):
<!-- Slider automatically updates healthDemo element -->
<input type="range"
data-state
data-state-bind="healthDemo"
data-state-attr="health"
min="0" max="100" value="75">
<!-- Health bar watches the health attribute -->
<div id="healthDemo"
data-state
data-state-watch="health"
data-health="75"
data-health-min="0"
data-health-max="100">
<div class="health-bar">
<div class="health-fill"
style="width: var(--state-health-percent);">
</div>
</div>
<div>Health: <span data-state-display="health">75</span>%</div>
</div>
Make buttons control state without writing JavaScript! Use increment for clickers and counters:
<div id="clickerDemo"
data-state
data-state-watch="clicks"
data-clicks="0">
<div>Clicks: <span data-state-display="clicks">0</span></div>
<!-- Button increments by 1 -->
<button data-state
data-state-trigger
data-state-bind="clickerDemo"
data-state-attr="clicks"
data-state-increment="1">
CLICK ME +1
</button>
<!-- Button increments by 5 -->
<button data-state
data-state-trigger
data-state-bind="clickerDemo"
data-state-attr="clicks"
data-state-increment="5">
CLICK ME +5
</button>
<!-- Progress bar using CSS variable -->
<div class="progress-bar"
style="width: var(--state-clicks-percent);"></div>
</div>
Automatically fire triggers when conditions become true - perfect for passive income, auto-unlocks, achievements, and automatic progression!
<!-- Passive income: auto-convert 10 gold → 1 gem -->
<button id="autoConvert"
data-state
data-state-trigger
data-state-bind="player"
data-state-attr="gold"
data-state-decrement="10"
data-state-condition="gold >= 10"
data-state-autofire="true"
data-state-trigger-chain="addGem"
style="display:none">
</button>
<!-- Auto-unlock at level 20 -->
<button data-state
data-state-trigger
data-state-bind="player"
data-state-attr="unlocked"
data-state-set="true"
data-state-condition="gold >= 20"
data-state-autofire="true"
style="display:none">
</button>
The Magic:
When a condition transitions from false → true, the trigger fires automatically! No click required. No visibility required. This is the missing primitive for automatic game mechanics.
Seven new declarative primitives for building complete games with ZERO hand-written JavaScript logic!
Triggers that fire automatically on a timer - perfect for passive income and cooldowns!
Each worker generates 1 gold per second automatically! Hire more workers to increase your income.
<!-- Hidden trigger fires every 1000ms -->
<button data-state
data-state-trigger
data-state-bind="player"
data-state-attr="gold"
data-state-increment="calc(var(--state-workers))"
data-state-interval="1000"
data-state-condition="workers > 0"
style="display:none">
</button>
data-state-set sets exact values, data-state-text uses template strings!
Text updates automatically using {token} syntax! Full Heal uses data-state-set with calc() to restore to max.
<!-- Template string with tokens -->
<h2 data-state
data-state-bind="player"
data-state-text="Level {level} {name}">
</h2>
<!-- Set to exact value using calc() -->
<button data-state-trigger
data-state-bind="player"
data-state-attr="health"
data-state-set="calc(var(--state-healthmax))">
Full Heal
</button>
Automatically add/remove CSS classes based on conditions - perfect for visual feedback!
≤50 HP: Yellow pulse | ≤20 HP: Red shake | 100 HP: Green glow
<div data-state
data-state-bind="player"
data-state-class="health-low"
data-state-class-condition="health <= 50"
data-state-class-2="health-critical"
data-state-class-condition-2="health <= 20"
data-state-class-3="health-full"
data-state-class-condition-3="health >= 100">
</div>
<style>
.health-low { animation: pulse 1s infinite; }
.health-critical { animation: shake 0.5s infinite; }
.health-full { box-shadow: 0 0 20px green; }
</style>
Fire-and-forget Web Audio sounds - no audio files needed! Click the buttons to hear:
click • coin • buy • levelup
Generated with Web Audio API - zero external dependencies!
<button data-state-trigger
data-state-bind="player"
data-state-attr="score"
data-state-increment="10"
data-state-sound="coin">
Collect Coin
</button>
data-state-persist saves to localStorage, data-state-event dispatches CustomEvents!
1. Click "Increment & Save" a few times
2. Reload the page - your count persists!
3. Watch the event log below for CustomEvents
<div id="game"
data-state
data-state-watch="score,level"
data-state-persist="true"
data-state-persist-key="my-game">
</div>
<button data-state-trigger
data-state-attr="score"
data-state-increment="10"
data-state-event="score-up">
</button>
<script>
document.addEventListener('state:score-up', (e) => {
console.log('Score increased!', e.detail);
});
</script>
State.js creates CSS variables automatically based on your configuration:
The data attribute will also update in increments for CSS attribute selectors like [data-state-health="50"]{ }
You can use the below data attributes for additional features
<div id="yourelement"
data-state
data-state-var="true"
data-state-watch="health,mana,xp"
data-state-toggles="active,locked"
data-state-dimensions="true"
data-state-media="true"
data-state-global="true"
data-state-increment="10">
</div>