Semi Circle Progress

v0.0.10

v0.0.10StableHeadlessStatelessAccessibleApache-2.0
Installation mix mishka.ui.gen.headless semi_circle_progress
Source View Source

Overview of the Phoenix and LiveView Headless Semi Circle Progress Component

The Mishka Chelekom Headless Semi Circle Progress is an unstyled Phoenix function component for a half-circle gauge. It renders a role="progressbar" element with an SVG arc. The filled arc is calculated on the server when the component renders, from value, min and max, using stroke-dasharray and stroke-dashoffset. There is no JavaScript. A default slot holds an optional readout, such as the number in the middle of the gauge.

The component sets no colors or thickness. You choose them with stroke and stroke-width classes on the track and indicator parts, and you size the SVG with svg_class. shape="full" closes the arc into a ring. Because the arc is drawn at render time, a LiveView only has to change the value assign to move it.

Base UI Semi Circle Progress example - gauge with a centered readout (Phoenix headless)

Base UI Semi Circle Progress example - gauge with a centered readout (Phoenix headless)

72score
heex
<.semi_circle_progress
  value={72}
  label="Score"
  class="relative inline-block w-48 [&_[data-part=svg]]:w-full [&_[data-part=track]]:[stroke:#e5e5e5] [&_[data-part=track]]:[stroke-width:12] [&_[data-part=indicator]]:[stroke:#f97316] [&_[data-part=indicator]]:[stroke-width:12] dark:[&_[data-part=track]]:[stroke:#404040] [&_[data-part=label]]:absolute [&_[data-part=label]]:inset-x-0 [&_[data-part=label]]:bottom-1 [&_[data-part=label]]:flex [&_[data-part=label]]:flex-col [&_[data-part=label]]:items-center [&_[data-part=label]]:text-neutral-900 dark:[&_[data-part=label]]:text-white"
>
  <span class="text-2xl font-bold">72</span>
  <span class="text-xs text-neutral-500">score</span>
</.semi_circle_progress>

Semi Circle Progress example - closed ring with shape full (Phoenix headless)

Semi Circle Progress example - closed ring with shape full (Phoenix headless)

70%
heex
<.semi_circle_progress
  id="semi-circle-ring"
  shape="full"
  value={70}
  label="Progress"
  class="inline-grid place-items-center *:[grid-area:1/1] text-neutral-950 dark:text-white"
  svg_class="overflow-visible w-20"
  track_class="[stroke-width:16] [stroke:color-mix(in_oklab,currentColor_20%,transparent)]"
  indicator_class="[stroke-width:16] [stroke:currentColor] [stroke-linecap:round] motion-safe:transition-[stroke-dashoffset] motion-safe:duration-300 motion-safe:ease-[ease-out]"
  label_class="text-[0.875rem] font-semibold"
>
  70%
</.semi_circle_progress>

Value, range and label

value takes a number or a numeric string. Anything else counts as 0. min (default 0) and max (default 100) are integers. The filled part of the arc is (value - min) / (max - min), kept between 0 and 1. The root gets aria-valuemin, aria-valuemax and aria-valuenow from min, max and the value, and aria-label from label.

Shapes and drawing the arc

shape is semi by default, a half circle drawn in a 0 0 200 108 viewBox. full draws a closed ring in a square 0 0 200 200 viewBox. The arc is made of two SVG paths: track is the background and indicator is the filled part, drawn with round line caps. Color and thickness come from your classes on track_class and indicator_class, for example [stroke:#f97316] and [stroke-width:12], or [stroke:currentColor] to follow the text color. svg_class sizes the SVG, for example w-full or w-20. The ring example also adds a transition on stroke-dashoffset to the indicator.

Parts & data attributes

The root has role="progressbar". Inside it, the svg part is data-part="svg", with the track and indicator paths inside. The readout is data-part="label" and is only rendered when you give the component content. The classes are class, svg_class, track_class, indicator_class and label_class. Each element also has a structural class such as chelekom-semi-circle-progress__indicator.

Accessibility

Uses the WAI-ARIA progressbar role with aria-valuemin, aria-valuemax and aria-valuenow. Always pass label so the bar has a name. The gauge is not interactive, so it has no keyboard behavior.