Fl4m3Ph03n1x
Radial progress bar using TailwinUI
Background
I have a small Phoenix 1.7 app where I am trying to add a radial progress bar, using the default TailwindUI components: Tailwind CSS Components - Tailwind Plus
Unfortunately for me, I was only able to find normal progress bars:
Namely:
<div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700">
<div class="bg-blue-600 h-2.5 rounded-full" style="width: 45%"></div>
</div>
The only radial progress bar I found was one using DaisyUI:
However, I want to avoid installing anything extra, I really just want to use the default tailwindUI and tailwindCSS that come with Phoenix 1.7
Questions
- Does someone know how to create a a radial progress bar component using the default setup that comes with Phoenix LiveView 1.7?
- Am I missing some component that already does this?
Marked As Solved
Fl4m3Ph03n1x
No need to apologize !
Even though the link and code you shared used alpine, it was still very educative. I was able to analyze the code and create a component that does exactly what I want. Its also quite pretty, so I am very proud. This code uses only Phoniex LV vanilla, no extra CSS no extra anything !
core_components:
@doc """
Renders a progress bar for an ongoing operation.
## Examples
<.progress_bar hidden=false progress=15 />
<.progress_bar hidden=false progress=20 message="Activating system ..." />
<.progress_bar hidden=false class="cool-bar" />
"""
attr :hidden, :boolean, default: true, doc: "whether or not to show the progress bar"
attr :progress, :integer, default: 0, doc: "the current progress of the bar"
attr :message, :string, default: "Operation in progress ...", doc: "the message to show while the bar is progressing"
attr :class, :string, default: nil
def progress_bar(assigns) do
assigns = assign(assigns, :circumference, 2 * 22 / 7 * 120)
assigns = assign(assigns, :offset, assigns.circumference - assigns.progress / 100 * assigns.circumference)
~H"""
<div class={@class} hidden={@hidden}>
<div class="flex items-center justify-center">
<p class="text-lg font-semibold"><%= @message %></p>
</div>
<div class="flex items-center justify-center">
<svg class="transform -rotate-90 w-72 h-72">
<circle cx="145" cy="145" r="120" stroke-width="30" fill="transparent" class="stroke-gray-700" />
<circle cx="145" cy="145" r="120" stroke-width="30" fill="transparent"
stroke-dasharray={@circumference}
stroke-dashoffset={@offset}
class="stroke-indigo-500" />
</svg>
<span class="absolute text-5xl stroke-black"><%= @progress %></span>
</div>
</div>
"""
end
Usage in my_app_live.heex.html:
<div class="min-h-full max-w-full mx-auto py-6 sm:px-6 lg:px-8">
<.progress_bar hidden={false} progress={40} message="Activating system ..." />
</div>
Will produce the following:
Possible improvements
Currently i am not sure if there is a more elixir way of updating the assigns:
assigns = assign(assigns, :circumference, 2 * 22 / 7 * 120)
assigns = assign(assigns, :offset, assigns.circumference - assigns.progress / 100 * assigns.circumference)
But other than that, I am pretty happy with it.
Additional info
For those of you curious, you can also check this other solution someone else provided in SO:
I hope this helps!
Also Liked
dfalling
You can compute this circumference outside of the function since it’s never changing.
Eg
# 2 * 22 / 7 * 120
@circumference 754.285714285714286
(not sure how important precision is for that variable)
LostKobrakai
I mean sure if you’re looking at the LV docs and not the Alpine docs. :attr is a short form for x-bind:attr in alpine.
LostKobrakai
Last Post!
dfalling
You can compute this circumference outside of the function since it’s never changing.
Eg
# 2 * 22 / 7 * 120
@circumference 754.285714285714286
(not sure how important precision is for that variable)
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
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security










