Skip to content

feat: add ring component#817

Open
enieuwy wants to merge 19 commits into
FelixKratz:masterfrom
enieuwy:feat/ring-component
Open

feat: add ring component#817
enieuwy wants to merge 19 commits into
FelixKratz:masterfrom
enieuwy:feat/ring-component

Conversation

@enieuwy

@enieuwy enieuwy commented May 22, 2026

Copy link
Copy Markdown

TL;DR: This is the conservative CGContext-rendered ring component: it establishes the public API, layout behavior, marker, and badge semantics. This first iteration has already been improved upon in a stacked CoreAnimation follow-up, enieuwy#2, which keeps the API unchanged but makes live/concurrent ring animations much smoother. The CG path is functional and keeps this review focused on the component API, but high-frequency value/color updates redraw through the window CGContext, which can look visibly janky compared with the compositor-backed CA implementation.

Why

SketchyBar's graph is great for timeseries, and slider is great for the common "0–100% of one thing" case (battery, audio level, focus percentage, pomodoro). However, a circular variant can show greater scale while occupying less bar space—think of how iOS shows battery levels for several devices (earbuds, phone, watch) in a small widget.

This PR adds a compact circular ring component with a centered marker glyph and optional badge, stacked on top of the badge feature in #816.

What

  • New top-level component: --add ring <name> <position> <diameter>.
  • Properties: ring.value (0.0–1.0), ring.percentage (read-only mirror), ring.color, ring.track_color, ring.line_width, ring.start_angle, ring.clockwise, ring.cap, ring.marker.*, and ring.badge.*.
  • Animations work via the existing --animate machinery over ring.value.
  • Layout integration: the ring participates in bar_item like other components; marker glyph and badge are non-layout overlays, so the ring footprint is exactly its diameter.

Demo

Demo recording: badge-and-ring-demo.mp4

image

Stacking

This PR is stacked on #816. Until #816 lands, the upstream PR diff may include badge-base changes; the clean ring-only diff remains visible in enieuwy#1.

The CoreAnimation follow-up is enieuwy#2. It is intentionally separate so the component API can be reviewed independently from the CA/SkyLight surface backend.

Verification

  • make arm64 builds clean.
  • Built and ran from ~/dev/SketchyBar/bin/sketchybar; --query battery.ring and --query bluetooth.ring exercised on the live daemon. Marker and badge fields serialize correctly.
  • Reversible smoke test (__ring_live_test item) confirmed all ring properties round-trip via --query.

@oschrenk

oschrenk commented Jun 1, 2026

Copy link
Copy Markdown

Neat.

I just found this. I actually made my own icon font for a similar use case. Battery charging icon with 100 different levels, so that i can accurately see the battery level.

@enieuwy

enieuwy commented Jun 1, 2026

Copy link
Copy Markdown
Author

I tried a similar first approach, and raised another PR for SF symbols accepting values for their variables. Was limited by the symbols available and had inconsistent results.

The ring component allows huge flexibility. It can even mimic a loading spinner, which is nice to show my VPN connecting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants