123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- <html>
- <head>
- <meta charset="utf-8"/>
- <style>
- .hidden { display: none; }
- [x-cloak] { display: none; }
- .opacity-0 { opacity: 0; }
- .opacity-100 { opacity: 1; }
- .transition-slow { transition-duration: 300ms; }
- .transition-medium { transition-duration: 200ms; }
- .transition-faster { transition-duration: 100ms; }
- .scale-90 { transform: scale(0.9); }
- .scale-100 { transform: scale(1); }
- .ease-in { transition-timing-function: cubic-bezier(0.4, 0, 1, 1); }
- .ease-out { transition-timing-function: cubic-bezier(0, 0, 0.2, 1); }
- /** Thanks Animate.css */
- .animation {animation-duration: 1000ms; --animate-duration: 1000ms; }
- @keyframes jackInTheBox {
- from { opacity: 0; transform: scale(0.1) rotate(30deg); transform-origin: center bottom; }
- 50% { transform: rotate(-10deg); }
- 70% { transform: rotate(3deg); }
- to { opacity: 1; transform: scale(1); }
- }
- @keyframes hinge {
- 0% {animation-timing-function: ease-in-out;}
- 20%, 60% { transform: rotate3d(0, 0, 1, 80deg); animation-timing-function: ease-in-out; }
- 40%, 80% { transform: rotate3d(0, 0, 1, 60deg); animation-timing-function: ease-in-out; opacity: 1; }
- to { transform: translate3d(0, 700px, 0); opacity: 0; }
- }
- .jackInTheBox {animation-name: jackInTheBox;}
- .hinge {
- animation-duration: calc(var(--animate-duration) * 2);
- animation-name: hinge;
- transform-origin: top left;
- }
- </style>
- <script src="/dist/alpine.js" defer></script>
- <!-- <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script> -->
- </head>
- <body>
- <table>
- <thead>
- <tr>
- <th>Feature</th>
- <th>Demo</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>Broken Components</td>
- <td>
- <div x-data="some.bad.expression()">I'm a broken component</div>
- <button x-data x-on:click="something()">I break on click</button>
- <div x-data x-spread="not.good">Broken x-spread</div>
- </td>
- </tr>
- <tr>
- <td>Simple x-if</td>
- <td>
- <div x-data="{ show: false }">
- <template x-if="show">
- <span>hey</span>
- </template>
- <button @click="show = ! show">Show</button>
- </div>
- </td>
- </tr>
- <tr>
- <td>Dropdown</td>
- <td>
- <div x-data="{ open: false }">
- <button x-on:click="open= true">Open Dropdown</button>
- <ul
- x-bind:class="{ 'hidden': ! open }"
- x-on:click.away="open= false"
- x-cloak>
- Dropdown Body
- </ul>6
- </div>
- </td>
- </tr>
- <tr>
- <td>Tabs</td>
- <td>
- <div x-data="{ currentTab: 'tab1' }">
- <button x-bind:class="{ 'active': currentTab ===
- 'tab1' }" x-on:click="currentTab= 'tab1'">Foo</button>
- <button x-bind:class="{ 'active': currentTab ===
- 'tab2' }" x-on:click="currentTab= 'tab2'">Bar</button>
- <div x-bind:class="{ 'hidden': currentTab !== 'tab1'
- }">Tab Foo</div>
- <div class="hidden" x-bind:class="{ 'hidden':
- currentTab !== 'tab2' }">Tab Bar</div>
- </div>
- </td>
- </tr>
- <tr>
- <td>Data Binding</td>
- <td>
- <div x-data="{ text: 'foo', checkbox: ['foo'], radio:
- 'foo', select: 'foo', 'multiselect': ['foo'] }">
- Text:
- <span x-text="JSON.stringify(text)"></span>
- <input type="text" x-model="text">
- Checkbox:
- <span x-text="JSON.stringify(checkbox)"></span>
- <input type="checkbox" x-model="checkbox"
- value="foo">
- <input type="checkbox" x-model="checkbox"
- :value="0">
- <input type="checkbox" x-model="checkbox"
- value="bar">
- Radio:
- <span x-text="JSON.stringify(radio)"></span>
- <input type="radio" x-model="radio" value="foo">
- <input type="radio" x-model="radio" value="bar">
- Select:
- <span x-text="JSON.stringify(select)"></span>
- <select x-model="select">
- <option>foo</option>
- <option>bar</option>
- </select>
- Multiple Select:
- <span x-text="JSON.stringify(multiselect)"></span>
- <select x-model="multiselect" multiple>
- <option>foo</option>
- <option>bar</option>
- </select>
- </div>
- </td>
- </tr>
- <tr>
- <td>Cast to number</td>
- <td>
- <div x-data="{ number: 1 }">
- <div x-text="JSON.stringify($data.number)"></div>
- <input type="text" x-model.number="number">
- </div>
- </td>
- </tr>
- <tr>
- <td>Nested Binding</td>
- <td>
- <div x-data="{ foo: { bar: 'baz' } }">
- <div x-text="foo.bar"></div>
- <input type="text" x-model="foo.bar">
- </div>
- </td>
- </tr>
- <tr>
- <td>On Click</td>
- <td>
- <div x-data="{ show: false }">
- <div x-show="show">Hi There!</div>
- <button x-on:click="show= ! show">Show/Hide</button>
- </div>
- </td>
- </tr>
- <tr>
- <td>Refs</td>
- <td>
- <div x-data="{ someText: 'bar' }">
- <div x-ref="remove-target">Remove Me</div>
- <button
- x-on:click="$refs['remove-target'].remove()">Remove</button>
- </div>
- </td>
- </tr>
- <tr>
- <td>x-on:click.stop</td>
- <td>
- <div x-data="{ someText: 'bar' }">
- <span x-text="someText"></span>
- <div x-on:click="someText= 'baz'">
- <button x-on:click.stop>Shouldn't change to baz</button>
- </div>
- </div>
- </td>
- </tr>
- <tr>
- <td>x-on:click (with return false)</td>
- <td>
- <div x-data>
- <label for="checkbox-frozen">I should be frozen on un-checked</label>
- <input id="checkbox-frozen" type="checkbox" @click="return false"></input>
- </div>
- </td>
- </tr>
- <tr>
- <td>x-on:click.prevent</td>
- <td>
- <div x-data="{}">
- <a href="https://google.com" x-on:click.prevent>Shouldn't
- go to Google</a>
- </div>
- </td>
- </tr>
- <tr>
- <td>x-on:click.once</td>
- <td>
- <div x-data="{ count: 0 }">
- <button x-on:click.once="count++">I've been clicked:
- <span x-text="count"></span></button>
- </div>
- </td>
- </tr>
- <tr>
- <td>Append DOM</td>
- <td>
- <div id="goHere">Click me.</div>
- <script>
- const thing = document.querySelector('#goHere')
- const handler = (e) => {
- thing.removeEventListener('click', handler)
- const div = document.createElement('div')
- div.setAttribute('x-data', '{hey: "there"}')
- div.innerHTML = '<input type="text" x-model="hey"><h1 x-text="hey"></h1>'
- e.target.appendChild(div)
- }
- var listener = thing.addEventListener('click', handler)
- </script>
- </td>
- </tr>
- <tr>
- <td>Append Nested DOM</td>
- <td>
- <div id="goHere2">Click me.</div>
- <script>
- const thing2 = document.querySelector('#goHere2')
- const handler2 = (e) => {
- thing2.removeEventListener('click', handler2)
- e.target.innerHTML = `
- <article>
- <div x-data="{hey: 'there'}">
- <input type="text" x-model="hey"><h1 x-text="hey"></h1>
- </div>
- </article>
- `
- }
- var listener = thing2.addEventListener('click', handler2)
- </script>
- </td>
- </tr>
- <tr>
- <td>x-for</td>
- <td>
- <div x-data="{ items: ['foo', 'bar'], foo: 'bar' }">
- <input type="checkbox" x-model="items" value="foo">
- <input type="checkbox" x-model="items" value="bar">
- <input type="checkbox" x-model="items" value="baz">
- <button @click="items = ['bar', 'bob']">hey</button>
- <template x-for="item in items" :key="item">
- <div x-text="item" x-transition:enter-start="opacity-0 scale-90"
- x-transition:enter="ease-out transition-medium"
- x-transition:enter-end="opacity-100 scale-100"
- x-transition:leave-start="opacity-100 scale-100"
- x-transition:leave="ease-in transition-faster"
- x-transition:leave-end="opacity-0 scale-90"
- ></div>
- </template>
- </div>
- </td>
- </tr>
- <tr>
- <td>Nested x-for</td>
- <td>
- <div x-data="{ foos: [{bars: [{bobs: ['one', 'two']}, {bobs: ['three', 'four']}]}, {bars: [{bobs: ['five', 'six']}, {bobs: ['seven', 'eight']}]}] }">
- <template x-for="foo in foos">
- <div>
- <template x-for="bar in foo.bars">
- <div>
- <template x-for="bob in bar.bobs">
- <span x-text="bob"></span>
- </template>
- </div>
- </template>
- </div>
- </template>
- </div>
- </td>
- </tr>
- <tr>
- <td>x-for over a range using <code>i in 10</code> syntax</td>
- <td>
- <div x-data>
- <template x-for="i in 10" :key="i">
- <span x-text="i"></span>
- </template>
- </div>
- </td>
- </tr>
- <tr>
- <td>x-for over a range using <code>i in 10</code> syntax and data property</td>
- <td>
- <div x-data="{ count: 10 }">
- <template x-for="i in count" :key="i">
- <span x-text="i"></span>
- </template>
- <button type="button" @click="count++">Increment count</button>
- </div>
- </td>
- </tr>
- <tr>
- <td>Transitions</td>
- <td>
- <div x-data="{ open: false }">
- <button x-on:click="open= ! open">
- Open Modal
- </button>
- <div x-show="open"
- x-transition:enter="transition-medium"
- x-transition:leave="transition-medium">
- <div x-show="open"
- x-transition:enter="transition-medium"
- x-transition:enter-start="opacity-0"
- x-transition:leave-end="opacity-0"
- x-transition:leave="transition-medium"></div>
- <div x-show="open"
- x-transition:enter-start="opacity-0 scale-90"
- x-transition:enter="ease-out transition-medium"
- x-transition:enter-end="opacity-100 scale-100"
- x-transition:leave-start="opacity-100 scale-100"
- x-transition:leave="ease-in transition-faster"
- x-transition:leave-end="opacity-0 scale-90">
- <div>
- hey
- </div>
- <div>
- <button x-on:click="open= false" type="button">
- Cancel
- </button>
- </div>
- </div>
- </div>
- </div>
- </td>
- </tr>
- <tr>
- <td>CSS animations</td>
- <td>
- <div x-data="{ open: false }">
- <button x-on:click="open= ! open">
- Open Modal
- </button>
- <div x-show="open"
- x-transition:enter="animation jackInTheBox"
- x-transition:leave="animation hinge">
- <div>
- hey
- </div>
- <div>
- <button x-on:click="open= false" type="button">
- Cancel
- </button>
- </div>
- </div>
- </div>
- </div>
- </td>
- </tr>
- <tr>
- <td>Transitions (with x-if)</td>
- <td>
- <div x-data="{ open: false }">
- <button x-on:click="open= ! open">
- Open Modal
- </button>
- <template x-if="open">
- <div x-transition:enter-start="opacity-0 scale-90"
- x-transition:enter="ease-out transition-medium"
- x-transition:enter-end="opacity-100 scale-100"
- x-transition:leave-start="opacity-100 scale-100"
- x-transition:leave="ease-in transition-faster"
- x-transition:leave-end="opacity-0 scale-90">
- hey
- </div>
- </template>
- </div>
- </td>
- </tr>
- <tr>
- <td>Nested Transitions (with x-show)</td>
- <td>
- <div x-data="{ open: false }">
- <button x-on:click="open= ! open">
- Open Modal
- </button>
- <div x-show="open">
- I shouldn't leave until the transition finishes.
- <div x-show="open"
- x-transition:leave-start="opacity-100 scale-100"
- x-transition:leave="ease-in transition-slow"
- x-transition:leave-end="opacity-0 scale-90">
- I'm transitioning
- </div>
- </div>
- </div>
- </td>
- </tr>
- <tr>
- <td>Init function callback access refs and mutate data</td>
- <td>
- <div x-data="initialData()" x-init="init()">
- <div :style="'width: '+width+'px; background: purple;'">hey</div>
- <button x-ref="inc">increase</button>
- </div>
- <script>
- function initialData() {
- return {
- width: 20,
- init() {
- this.$refs.inc.addEventListener('click', () => {
- this.width = this.width + 20
- })
- }
- }
- }
- </script>
- </td>
- </tr>
- <tr>
- <td>Dispatch</td>
- <td>
- <div x-data="{ foo: 'bar' }" x-on:custom-event="foo = $event.detail.newValue">
- <span x-text="foo"></span>
- <button x-on:click="$dispatch('custom-event', {newValue: 'baz'})">Turn 'bar' to 'baz'</button>
- </div>
- </td>
- </tr>
- <tr>
- <td>x-bind spread</td>
- <td>
- <div x-data="modal()">
- I should be "hey": <span x-spread="bound"></span>
- </div>
- <script>
- function modal() {
- return {
- foo: { bar: 'hey' },
- bound: {
- ['x-text']() { return this.foo.bar }
- },
- }
- }
- </script>
- </td>
- </tr>
- <tr>
- <td>Cloak</td>
- <td>
- <div x-data="{}" x-cloak>
- I'm cloaked
- </div>
- </td>
- </tr>
- </tbody>
- </table>
- </body>
- </html>
|