index.html 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. <html>
  2. <head>
  3. <meta charset="utf-8"/>
  4. <style>
  5. .hidden { display: none; }
  6. [x-cloak] { display: none; }
  7. .opacity-0 { opacity: 0; }
  8. .opacity-100 { opacity: 1; }
  9. .transition-slow { transition-duration: 300ms; }
  10. .transition-medium { transition-duration: 200ms; }
  11. .transition-faster { transition-duration: 100ms; }
  12. .scale-90 { transform: scale(0.9); }
  13. .scale-100 { transform: scale(1); }
  14. .ease-in { transition-timing-function: cubic-bezier(0.4, 0, 1, 1); }
  15. .ease-out { transition-timing-function: cubic-bezier(0, 0, 0.2, 1); }
  16. /** Thanks Animate.css */
  17. .animation {animation-duration: 1000ms; --animate-duration: 1000ms; }
  18. @keyframes jackInTheBox {
  19. from { opacity: 0; transform: scale(0.1) rotate(30deg); transform-origin: center bottom; }
  20. 50% { transform: rotate(-10deg); }
  21. 70% { transform: rotate(3deg); }
  22. to { opacity: 1; transform: scale(1); }
  23. }
  24. @keyframes hinge {
  25. 0% {animation-timing-function: ease-in-out;}
  26. 20%, 60% { transform: rotate3d(0, 0, 1, 80deg); animation-timing-function: ease-in-out; }
  27. 40%, 80% { transform: rotate3d(0, 0, 1, 60deg); animation-timing-function: ease-in-out; opacity: 1; }
  28. to { transform: translate3d(0, 700px, 0); opacity: 0; }
  29. }
  30. .jackInTheBox {animation-name: jackInTheBox;}
  31. .hinge {
  32. animation-duration: calc(var(--animate-duration) * 2);
  33. animation-name: hinge;
  34. transform-origin: top left;
  35. }
  36. </style>
  37. <script src="/dist/alpine.js" defer></script>
  38. <!-- <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script> -->
  39. </head>
  40. <body>
  41. <table>
  42. <thead>
  43. <tr>
  44. <th>Feature</th>
  45. <th>Demo</th>
  46. </tr>
  47. </thead>
  48. <tbody>
  49. <tr>
  50. <td>Broken Components</td>
  51. <td>
  52. <div x-data="some.bad.expression()">I'm a broken component</div>
  53. <button x-data x-on:click="something()">I break on click</button>
  54. <div x-data x-spread="not.good">Broken x-spread</div>
  55. </td>
  56. </tr>
  57. <tr>
  58. <td>Simple x-if</td>
  59. <td>
  60. <div x-data="{ show: false }">
  61. <template x-if="show">
  62. <span>hey</span>
  63. </template>
  64. <button @click="show = ! show">Show</button>
  65. </div>
  66. </td>
  67. </tr>
  68. <tr>
  69. <td>Dropdown</td>
  70. <td>
  71. <div x-data="{ open: false }">
  72. <button x-on:click="open= true">Open Dropdown</button>
  73. <ul
  74. x-bind:class="{ 'hidden': ! open }"
  75. x-on:click.away="open= false"
  76. x-cloak>
  77. Dropdown Body
  78. </ul>6
  79. </div>
  80. </td>
  81. </tr>
  82. <tr>
  83. <td>Tabs</td>
  84. <td>
  85. <div x-data="{ currentTab: 'tab1' }">
  86. <button x-bind:class="{ 'active': currentTab ===
  87. 'tab1' }" x-on:click="currentTab= 'tab1'">Foo</button>
  88. <button x-bind:class="{ 'active': currentTab ===
  89. 'tab2' }" x-on:click="currentTab= 'tab2'">Bar</button>
  90. <div x-bind:class="{ 'hidden': currentTab !== 'tab1'
  91. }">Tab Foo</div>
  92. <div class="hidden" x-bind:class="{ 'hidden':
  93. currentTab !== 'tab2' }">Tab Bar</div>
  94. </div>
  95. </td>
  96. </tr>
  97. <tr>
  98. <td>Data Binding</td>
  99. <td>
  100. <div x-data="{ text: 'foo', checkbox: ['foo'], radio:
  101. 'foo', select: 'foo', 'multiselect': ['foo'] }">
  102. Text:
  103. <span x-text="JSON.stringify(text)"></span>
  104. <input type="text" x-model="text">
  105. Checkbox:
  106. <span x-text="JSON.stringify(checkbox)"></span>
  107. <input type="checkbox" x-model="checkbox"
  108. value="foo">
  109. <input type="checkbox" x-model="checkbox"
  110. :value="0">
  111. <input type="checkbox" x-model="checkbox"
  112. value="bar">
  113. Radio:
  114. <span x-text="JSON.stringify(radio)"></span>
  115. <input type="radio" x-model="radio" value="foo">
  116. <input type="radio" x-model="radio" value="bar">
  117. Select:
  118. <span x-text="JSON.stringify(select)"></span>
  119. <select x-model="select">
  120. <option>foo</option>
  121. <option>bar</option>
  122. </select>
  123. Multiple Select:
  124. <span x-text="JSON.stringify(multiselect)"></span>
  125. <select x-model="multiselect" multiple>
  126. <option>foo</option>
  127. <option>bar</option>
  128. </select>
  129. </div>
  130. </td>
  131. </tr>
  132. <tr>
  133. <td>Cast to number</td>
  134. <td>
  135. <div x-data="{ number: 1 }">
  136. <div x-text="JSON.stringify($data.number)"></div>
  137. <input type="text" x-model.number="number">
  138. </div>
  139. </td>
  140. </tr>
  141. <tr>
  142. <td>Nested Binding</td>
  143. <td>
  144. <div x-data="{ foo: { bar: 'baz' } }">
  145. <div x-text="foo.bar"></div>
  146. <input type="text" x-model="foo.bar">
  147. </div>
  148. </td>
  149. </tr>
  150. <tr>
  151. <td>On Click</td>
  152. <td>
  153. <div x-data="{ show: false }">
  154. <div x-show="show">Hi There!</div>
  155. <button x-on:click="show= ! show">Show/Hide</button>
  156. </div>
  157. </td>
  158. </tr>
  159. <tr>
  160. <td>Refs</td>
  161. <td>
  162. <div x-data="{ someText: 'bar' }">
  163. <div x-ref="remove-target">Remove Me</div>
  164. <button
  165. x-on:click="$refs['remove-target'].remove()">Remove</button>
  166. </div>
  167. </td>
  168. </tr>
  169. <tr>
  170. <td>x-on:click.stop</td>
  171. <td>
  172. <div x-data="{ someText: 'bar' }">
  173. <span x-text="someText"></span>
  174. <div x-on:click="someText= 'baz'">
  175. <button x-on:click.stop>Shouldn't change to baz</button>
  176. </div>
  177. </div>
  178. </td>
  179. </tr>
  180. <tr>
  181. <td>x-on:click (with return false)</td>
  182. <td>
  183. <div x-data>
  184. <label for="checkbox-frozen">I should be frozen on un-checked</label>
  185. <input id="checkbox-frozen" type="checkbox" @click="return false"></input>
  186. </div>
  187. </td>
  188. </tr>
  189. <tr>
  190. <td>x-on:click.prevent</td>
  191. <td>
  192. <div x-data="{}">
  193. <a href="https://google.com" x-on:click.prevent>Shouldn't
  194. go to Google</a>
  195. </div>
  196. </td>
  197. </tr>
  198. <tr>
  199. <td>x-on:click.once</td>
  200. <td>
  201. <div x-data="{ count: 0 }">
  202. <button x-on:click.once="count++">I've been clicked:
  203. <span x-text="count"></span></button>
  204. </div>
  205. </td>
  206. </tr>
  207. <tr>
  208. <td>Append DOM</td>
  209. <td>
  210. <div id="goHere">Click me.</div>
  211. <script>
  212. const thing = document.querySelector('#goHere')
  213. const handler = (e) => {
  214. thing.removeEventListener('click', handler)
  215. const div = document.createElement('div')
  216. div.setAttribute('x-data', '{hey: "there"}')
  217. div.innerHTML = '<input type="text" x-model="hey"><h1 x-text="hey"></h1>'
  218. e.target.appendChild(div)
  219. }
  220. var listener = thing.addEventListener('click', handler)
  221. </script>
  222. </td>
  223. </tr>
  224. <tr>
  225. <td>Append Nested DOM</td>
  226. <td>
  227. <div id="goHere2">Click me.</div>
  228. <script>
  229. const thing2 = document.querySelector('#goHere2')
  230. const handler2 = (e) => {
  231. thing2.removeEventListener('click', handler2)
  232. e.target.innerHTML = `
  233. <article>
  234. <div x-data="{hey: 'there'}">
  235. <input type="text" x-model="hey"><h1 x-text="hey"></h1>
  236. </div>
  237. </article>
  238. `
  239. }
  240. var listener = thing2.addEventListener('click', handler2)
  241. </script>
  242. </td>
  243. </tr>
  244. <tr>
  245. <td>x-for</td>
  246. <td>
  247. <div x-data="{ items: ['foo', 'bar'], foo: 'bar' }">
  248. <input type="checkbox" x-model="items" value="foo">
  249. <input type="checkbox" x-model="items" value="bar">
  250. <input type="checkbox" x-model="items" value="baz">
  251. <button @click="items = ['bar', 'bob']">hey</button>
  252. <template x-for="item in items" :key="item">
  253. <div x-text="item" x-transition:enter-start="opacity-0 scale-90"
  254. x-transition:enter="ease-out transition-medium"
  255. x-transition:enter-end="opacity-100 scale-100"
  256. x-transition:leave-start="opacity-100 scale-100"
  257. x-transition:leave="ease-in transition-faster"
  258. x-transition:leave-end="opacity-0 scale-90"
  259. ></div>
  260. </template>
  261. </div>
  262. </td>
  263. </tr>
  264. <tr>
  265. <td>Nested x-for</td>
  266. <td>
  267. <div x-data="{ foos: [{bars: [{bobs: ['one', 'two']}, {bobs: ['three', 'four']}]}, {bars: [{bobs: ['five', 'six']}, {bobs: ['seven', 'eight']}]}] }">
  268. <template x-for="foo in foos">
  269. <div>
  270. <template x-for="bar in foo.bars">
  271. <div>
  272. <template x-for="bob in bar.bobs">
  273. <span x-text="bob"></span>
  274. </template>
  275. </div>
  276. </template>
  277. </div>
  278. </template>
  279. </div>
  280. </td>
  281. </tr>
  282. <tr>
  283. <td>x-for over a range using <code>i in 10</code> syntax</td>
  284. <td>
  285. <div x-data>
  286. <template x-for="i in 10" :key="i">
  287. <span x-text="i"></span>
  288. </template>
  289. </div>
  290. </td>
  291. </tr>
  292. <tr>
  293. <td>x-for over a range using <code>i in 10</code> syntax and data property</td>
  294. <td>
  295. <div x-data="{ count: 10 }">
  296. <template x-for="i in count" :key="i">
  297. <span x-text="i"></span>
  298. </template>
  299. <button type="button" @click="count++">Increment count</button>
  300. </div>
  301. </td>
  302. </tr>
  303. <tr>
  304. <td>Transitions</td>
  305. <td>
  306. <div x-data="{ open: false }">
  307. <button x-on:click="open= ! open">
  308. Open Modal
  309. </button>
  310. <div x-show="open"
  311. x-transition:enter="transition-medium"
  312. x-transition:leave="transition-medium">
  313. <div x-show="open"
  314. x-transition:enter="transition-medium"
  315. x-transition:enter-start="opacity-0"
  316. x-transition:leave-end="opacity-0"
  317. x-transition:leave="transition-medium"></div>
  318. <div x-show="open"
  319. x-transition:enter-start="opacity-0 scale-90"
  320. x-transition:enter="ease-out transition-medium"
  321. x-transition:enter-end="opacity-100 scale-100"
  322. x-transition:leave-start="opacity-100 scale-100"
  323. x-transition:leave="ease-in transition-faster"
  324. x-transition:leave-end="opacity-0 scale-90">
  325. <div>
  326. hey
  327. </div>
  328. <div>
  329. <button x-on:click="open= false" type="button">
  330. Cancel
  331. </button>
  332. </div>
  333. </div>
  334. </div>
  335. </div>
  336. </td>
  337. </tr>
  338. <tr>
  339. <td>CSS animations</td>
  340. <td>
  341. <div x-data="{ open: false }">
  342. <button x-on:click="open= ! open">
  343. Open Modal
  344. </button>
  345. <div x-show="open"
  346. x-transition:enter="animation jackInTheBox"
  347. x-transition:leave="animation hinge">
  348. <div>
  349. hey
  350. </div>
  351. <div>
  352. <button x-on:click="open= false" type="button">
  353. Cancel
  354. </button>
  355. </div>
  356. </div>
  357. </div>
  358. </div>
  359. </td>
  360. </tr>
  361. <tr>
  362. <td>Transitions (with x-if)</td>
  363. <td>
  364. <div x-data="{ open: false }">
  365. <button x-on:click="open= ! open">
  366. Open Modal
  367. </button>
  368. <template x-if="open">
  369. <div x-transition:enter-start="opacity-0 scale-90"
  370. x-transition:enter="ease-out transition-medium"
  371. x-transition:enter-end="opacity-100 scale-100"
  372. x-transition:leave-start="opacity-100 scale-100"
  373. x-transition:leave="ease-in transition-faster"
  374. x-transition:leave-end="opacity-0 scale-90">
  375. hey
  376. </div>
  377. </template>
  378. </div>
  379. </td>
  380. </tr>
  381. <tr>
  382. <td>Nested Transitions (with x-show)</td>
  383. <td>
  384. <div x-data="{ open: false }">
  385. <button x-on:click="open= ! open">
  386. Open Modal
  387. </button>
  388. <div x-show="open">
  389. I shouldn't leave until the transition finishes.
  390. <div x-show="open"
  391. x-transition:leave-start="opacity-100 scale-100"
  392. x-transition:leave="ease-in transition-slow"
  393. x-transition:leave-end="opacity-0 scale-90">
  394. I'm transitioning
  395. </div>
  396. </div>
  397. </div>
  398. </td>
  399. </tr>
  400. <tr>
  401. <td>Init function callback access refs and mutate data</td>
  402. <td>
  403. <div x-data="initialData()" x-init="init()">
  404. <div :style="'width: '+width+'px; background: purple;'">hey</div>
  405. <button x-ref="inc">increase</button>
  406. </div>
  407. <script>
  408. function initialData() {
  409. return {
  410. width: 20,
  411. init() {
  412. this.$refs.inc.addEventListener('click', () => {
  413. this.width = this.width + 20
  414. })
  415. }
  416. }
  417. }
  418. </script>
  419. </td>
  420. </tr>
  421. <tr>
  422. <td>Dispatch</td>
  423. <td>
  424. <div x-data="{ foo: 'bar' }" x-on:custom-event="foo = $event.detail.newValue">
  425. <span x-text="foo"></span>
  426. <button x-on:click="$dispatch('custom-event', {newValue: 'baz'})">Turn 'bar' to 'baz'</button>
  427. </div>
  428. </td>
  429. </tr>
  430. <tr>
  431. <td>x-bind spread</td>
  432. <td>
  433. <div x-data="modal()">
  434. I should be "hey": <span x-spread="bound"></span>
  435. </div>
  436. <script>
  437. function modal() {
  438. return {
  439. foo: { bar: 'hey' },
  440. bound: {
  441. ['x-text']() { return this.foo.bar }
  442. },
  443. }
  444. }
  445. </script>
  446. </td>
  447. </tr>
  448. <tr>
  449. <td>Cloak</td>
  450. <td>
  451. <div x-data="{}" x-cloak>
  452. I'm cloaked
  453. </div>
  454. </td>
  455. </tr>
  456. </tbody>
  457. </table>
  458. </body>
  459. </html>