bgoosman
Livebook: How do folks display progress?
It’s easy to create a Kino.frame and render some status text like “Loading” or “Idle”. Ideally I’d like to disable the submit button in my form and display a spinner inside it.
I’m wondering what elixirforum friendly folks do in their Livebooks! ![]()
Marked As Solved
hugobarauna
You can build your own spinner UI component based on Kino.HTML like that:
defmodule KinoSpinner do
def new(dimensions \\ "30px") do
Kino.HTML.new("""
<div class="loader"></div>
<style>
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: #{dimensions};
height: #{dimensions};
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
""")
end
end
And use like this in a form:
form =
Kino.Control.form(
[
name: Kino.Input.text("Data", default: "some data to process")
],
submit: "Submit"
)
output_frame = frame()
Kino.listen(form, fn _event ->
Kino.Frame.render(output_frame, grid([text("Processing..."), KinoSpinner.new()]))
Process.sleep(2_000)
Kino.Frame.render(output_frame, "Processing is done. ✅")
end)
grid([form, output_frame])
Here’s a quick video demo: CleanShot 2024-09-18 at 13.47.38 · CleanShot Cloud
Or you can use a custom kino from the community, like this one from Andrés Alejos:
form =
Kino.Control.form(
[
name: Kino.Input.text("Data", default: "some data to process")
],
submit: "Submit"
)
output_frame = frame()
Kino.listen(form, fn _event ->
progress_bar = KinoProgressBar.new(max: 100)
Kino.Frame.render(output_frame, progress_bar)
Enum.each(1..100, fn index ->
KinoProgressBar.update(progress_bar, index, 100)
Process.sleep(50)
end)
Kino.Frame.render(output_frame, "Processing is done. ✅")
end)
grid([form, output_frame])
Here’s a quick video demo: CleanShot 2024-09-18 at 13.49.15 · CleanShot Cloud
Here’s the notebook with both demos: How to display progress using Kino · GitHub
Also Liked
bgoosman
Wow, thanks for the high effort post Hugo!
bgoosman
~btw I think you meant to write Kino.Frame.new() instead of frame()? Where does frame() come from?~
Nevermind, import Kino.Shorts is the answer.
hugobarauna
You can report on Issues · livebook-dev/livebook · GitHub
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








