Loading...
Loading...
This skill should be used when the user asks to "add Alpine.js", "create Alpine component", "use Alpine directives", "build interactive UI with Alpine", or needs guidance on Alpine.js development patterns and best practices.
npx skill4agent add the-perfect-developer/the-perfect-opencode alpinejs<head><script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>defernpm install alpinejsimport Alpine from 'alpinejs'
window.Alpine = Alpine
Alpine.start()x-datax-data<div x-data="{ count: 0, message: 'Hello' }">
<!-- State is accessible within this element and its children -->
</div>x-on:@<button @click="count++">Increment</button>
<button x-on:click="count++">Increment (verbose)</button>.prevent.stop.outside.window.debounce<input @keyup.enter="submit()">
<input @keyup.shift.enter="specialSubmit()"><span x-text="message"></span><div x-html="htmlContent"></div><div x-show="isVisible">Content</div><template x-if="shouldShow">
<div>Content</div>
</template>x-showx-if<template x-for="item in items" :key="item.id">
<li x-text="item.name"></li>
</template><template>:keyx-bind::<img :src="imageUrl" :alt="description">
<button :disabled="isProcessing">Submit</button><div :class="{ 'active': isActive, 'error': hasError }"><div :style="{ color: textColor, fontSize: size + 'px' }"><input x-model="username" type="text">
<textarea x-model="message"></textarea>
<select x-model="country">
<option value="us">United States</option>
<option value="ca">Canada</option>
</select>.number.debounce.throttle<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open" x-transition>
Content to show/hide
</div>
</div><div x-data="{ open: false }">
<button @click="open = !open">Open Dropdown</button>
<div x-show="open" @click.outside="open = false">
<a href="#">Option 1</a>
<a href="#">Option 2</a>
</div>
</div><div x-data="{
search: '',
items: ['Apple', 'Banana', 'Cherry'],
get filteredItems() {
return this.items.filter(i =>
i.toLowerCase().includes(this.search.toLowerCase())
)
}
}">
<input x-model="search" placeholder="Search...">
<template x-for="item in filteredItems" :key="item">
<div x-text="item"></div>
</template>
</div><div x-data="{
email: '',
get isValid() {
return this.email.includes('@')
}
}">
<input x-model="email" type="email">
<button :disabled="!isValid">Submit</button>
<span x-show="!isValid" class="error">Invalid email</span>
</div>x-transition<div x-show="open" x-transition>
Content with fade and scale transition
</div><div x-show="open" x-transition.duration.500ms><div
x-show="open"
x-transition:enter.duration.500ms
x-transition:leave.duration.1000ms
><div x-show="open" x-transition.opacity>
<div x-show="open" x-transition.scale>Alpine.data()Alpine.data('dropdown', () => ({
open: false,
toggle() {
this.open = !this.open
},
close() {
this.open = false
}
}))<div x-data="dropdown">
<button @click="toggle">Toggle</button>
<div x-show="open" @click.outside="close">
Dropdown content
</div>
</div>Alpine.store()Alpine.store('auth', {
user: null,
loggedIn: false,
login(user) {
this.user = user
this.loggedIn = true
}
})<div x-data>
<span x-show="$store.auth.loggedIn" x-text="$store.auth.user"></span>
<button @click="$store.auth.login('John')">Login</button>
</div>$el$refsx-ref$store$watch$dispatch$nextTick$root$data$id<div x-data>
<input x-ref="emailInput" type="email">
<button @click="$refs.emailInput.focus()">Focus Email</button>
</div><!-- Good -->
<div x-data="{ open: false }">
<!-- Avoid over-engineering -->
<div x-data="{ state: { ui: { modal: { open: false } } } }">{
items: [1, 2, 3],
get total() {
return this.items.reduce((sum, i) => sum + i, 0)
}
}x-cloak<style>
[x-cloak] { display: none !important; }
</style>
<div x-data x-cloak>
<!-- Content hidden until Alpine initializes -->
</div>// Instead of inline in HTML
Alpine.data('complexForm', () => ({
// Complex initialization and methods
}))<form @submit.prevent="handleSubmit">
<div @click.outside="close"><!-- Wrong -->
<div x-for="item in items">
<!-- Correct -->
<template x-for="item in items">
<div x-text="item"></div>
</template><template x-if="condition">
<div>Content</div>
</template>this{
items: ['a', 'b'],
get filteredItems() {
return this.items.filter(...) // Must use this.items
}
}<!-- Ensures Alpine loads after DOM is ready -->
<script defer src="...alpine.min.js"></script>| Directive | Purpose | Example |
|---|---|---|
| Define component state | |
| Set text content | |
| Set HTML content | |
| Toggle visibility | |
| Conditional rendering | |
| Loop over array | |
| Listen to events | |
| Bind attributes | |
| Two-way binding | |
| Add transitions | |
references/directives-reference.mdreferences/advanced-patterns.md