Fl4m3Ph03n1x

Fl4m3Ph03n1x

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

  1. Does someone know how to create a a radial progress bar component using the default setup that comes with Phoenix LiveView 1.7?
  2. Am I missing some component that already does this?

Marked As Solved

Fl4m3Ph03n1x

Fl4m3Ph03n1x OP

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

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

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

LostKobrakai

No. Not sure where you got that html you posted, but it’s using alpine.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews