Examples menu

Leaderboard multiplayer

Vote for pizza toppings, add your own or remove one, and open the page in a second window to watch both lists reorder at once. view(..., viewTransition: true) animates each update, every row has its own view-transition-name, and #[Broadcast(Scope::ROUTE)] sends each change to every tab.

viewTransition: true on view() makes Datastar apply every update render inside document.startViewTransition(). The render on page load and on SSE connect has none.
A view-transition-name per row, lb-{id}, lets the browser match each row before and after the update and move it to its new place. Rows without a partner slide in or fade out.
#[Broadcast(Scope::ROUTE)] sends each vote, new topping and removal to every tab on this page, so all of them animate the same change at the same time.
Sort per tab: sort is a TAB #[Signal], so your order stays yours while the votes stay shared. Switching it animates too.
One render per 400 ms: a new transition skips the one still running, so a burst of votes would jump instead of glide. withBroadcastThrottle() for this route's scope, set in the site's config, lets each transition finish. While one runs, its overlay takes the clicks.
One worker: this demo keeps the toppings in PHP statics, which each worker holds on its own. See What stays per worker before you run it with withWorkerNum().
Sort by
  1. 1 Mozzarella 14 votes
  2. 2 Basil 11 votes
  3. 3 Mushrooms 9 votes
  4. 4 Pepperoni 8 votes
  5. 5 Olives 6 votes
  6. 6 Pineapple 5 votes
  7. 7 Jalapenos 3 votes
  8. 8 Anchovies 2 votes

8 of 12 toppings. Votes and toppings are shared with everyone on this page; the sort is yours.

Signals

sort string tab scope initial: votes

The order this tab shows: votes, name or newest.

draft string tab scope initial: empty string

The topping you are typing. Private to this tab.

Actions

vote

Adds a vote to the topping in ?id= and broadcasts the list.

add

Adds the draft as a new topping, up to 12 toppings of at most 24 characters, and broadcasts.

remove

Removes the topping in ?id= and broadcasts.

reset

Puts back the eight starting toppings and their votes, and broadcasts.

sortBy

Sets this tab's sort from ?by= and renders this tab only.

Views

leaderboard.html.twig

The ranked list, with a view-transition-name on each row. view(..., viewTransition: true) animates every update.