Skip to content

merge/probar history - #1

Merged
imanimanyara merged 24 commits into
mainfrom
merge/probar-history
Oct 1, 2026
Merged

imanimanyara merged 24 commits into
mainfrom
merge/probar-history

Conversation

@imanimanyara

Copy link
Copy Markdown
Member
  • Initial release
  • Add CLI/terminal renderer, segments, multi-progress, error UX, i18n
  • Document v0.6.0, add multi-progress/CLI examples and demos
  • Redesign the demo as an Apple-style site (landing + playground + build)
  • Trim leading blank from extracted changelog release body
  • Fix gradient rendering bugs; broaden Web Component/React; update docs
  • Harden headless/terminal paths and fix audit findings
  • Fix headless toJSON crash; latch group done; tidy bind interval cleanup
  • Redesign the leading peg as a clean shine; add inline status messages
  • Remove peg; add configurator, multicolor, data-attrs; fix glow/tooltip/segments
  • Harden mountTo resolution; fix attribute drift; doc cleanups
  • Make height fill the container; fix demo grey strip; redesign configurator
  • Default height 6px; document height units (px/rem/em/%/all)
  • Docs: document the full current option/method surface
  • Group: keep completed children visible instead of leaving empty rows
  • Design-system + architecture consistency sweep
  • Round glow + add border; success completes to 100%; one visual fixture
  • Rebuild the demo site on Webpixels CSS; keep the library framework-free
  • Fix radius-attribute coercion, trackXHR leak, and degenerate geometry
  • Fix data-tabar-colors parsing for functional colors; tailwind example reset
  • Playground: fixed-position overlay clears itself (autoHide on done)
  • Stop publishing the internal types/api-check.ts fixture to npm
  • Route vulnerability disclosure to security@simtabi.com

Tabar — a dependency-free, framework-agnostic progress bar.

Linear bars (top/bottom/left/right/inline) and circular SVG rings, all sharing the
same configuration, themes, gradients, glow, stripes, tooltips, persistence and API.
Upload/download tracking with smoothed speed and ETA; an error state; reactivity via
bind() and a reactive React hook; JSON + API config with two-way reporting; events
(instance, global bus, DOM); localization (i18n); a Web Component; full TypeScript
types; and SCSS-sourced, responsive styles.
Terminal (ANSI) renderer + `tabar` CLI bin drive the same Tabar API headlessly
in Node (TTY redraw / non-TTY lines, spinner, color, width). Multi-progress:
segments on one bar (stacked + overlay with mode-aware aggregation) and a
TabarGroup container of child bars with an auto-aggregated overall. Error UX:
warning/success states, retry()/retryWith, stall detection, aria-live
announcements, errorTimeout. i18n: ten built-in locales incl. Arabic with
RTL-aware linear fill and circular sweep. complete/attempts getters. New
entries: ./node, ./terminal, ./group. Headless goto() bug fixed.
Bump to 0.6.0 with a CHANGELOG entry covering the terminal/CLI renderer,
segments, TabarGroup, error UX and full i18n/RTL. Add a multi-progress/CLI
docs page and README coverage (web+CLI, segments, feedback). New examples
(cli.js, multi-progress.html) and demo sections for segments, groups and
state feedback.
Replace the single demo page with a marketing site under site/: a hero +
features + live shapes showcase landing page and a dedicated, grouped
playground covering every capability (shapes, themes, transfers, segments,
groups, states, events). A small esbuild+Sass step builds site/ to the
git-ignored site/dist/; serve.js serves it with a repo-root fallback for
examples/ and dist/. Adds cli.js + multi-progress.html examples and removes
the old demo/.
The release workflow already passes the tagged version's CHANGELOG section as the GitHub release body (body_path) alongside generate_release_notes; skip leading blank lines so the body starts at the first content, and echo a preview in the log.
Gradients:
- The 'gradient' theme is now a real computed fill, so setGradientType/Shape/
  Position/Angle apply to it (previously a no-op: the SCSS fell back to a
  hardcoded linear-gradient).
- A circular 'gradient' ring now paints an SVG <linearGradient> stroke instead
  of rendering solid.
- Anchor any gradient fill to the full track via --tabar-fill-scale so its
  colors stay put as the bar grows instead of compressing/shifting. Removed the
  redundant gradient-theme rule whose `background` shorthand reset the anchor;
  rainbow keeps its scroll (background-repeat).

Web Component: accept `segments` as a JSON attribute plus the v0.6.0 options
(segment-mode, aggregate, announce, stall-timeout, gradient-shape/position,
direction, locale). React hook: re-render on error/warning/success and expose
`complete`.

Docs: refresh CONTRIBUTING (new layout/scripts), installation (entry points,
Node/CLI, SSR), configuration (segments/feedback options, new vars + data
attrs), theming (gradient theme controls + anchoring + circular), events (new
events + ten built-in locales).
Fix a real crash: indeterminate() touched the DOM with no headless guard, so it
threw under the terminal renderer. Remove the shared aria-live region with the
last bar (was orphaned); guard debounced persistence against post-destroy
writes; mint monotonic segment ids (no collision after remove+add); restore a
100% persisted bar as done. Terminal: don't flood non-TTY output when active or
indeterminate, gate the spinner to TTY and unref its timer so the process can
exit. CLI: a bare number without --total is a percentage. <tabar-bar>: empty
numeric attrs are unset and persist accepts a JSON object; useTabar re-renders
on error/warning/success and exposes complete. Group children accept a weight.
Validation surfaced another headless crash: toJSON() referenced the browser-only
`Element` global unguarded, throwing in Node (breaking config export and
fromJSON round-trips there). Guard it with `typeof Element !== 'undefined'`.
TabarGroup now emits `done` exactly once per completion (re-arming when a new
incomplete child is added) instead of on every child completion while already
done. bind({interval}) is no longer tracked in the timeout set — destroy() runs
the unbind, which clears it with clearInterval. Adds Node-env regression tests.
The peg was a fixed 100px box-shadow rectangle colored with --tabar-color and
tilted rotate(2deg) translateY(-2px) — on tall or gradient bars it rendered as
a clashing, offset rectangle (the reported artifact). Replace it with a soft,
color-agnostic leading-edge shine clipped to the fill (RTL + vertical aware,
--tabar-peg to recolor).

Add inline status messages: `messages` maps each state (plus a `default`) to a
string or (percent, bar) => string shown on the bar, with setMessages/
setMessage, a `message` getter, messageAlign/messageColor and --tabar-message-*
CSS vars. Content is rendered via textContent (no HTML injection). Wired into
the site's upload/states showcase and the playground. Types, docs and tests.
…p/segments

Two rounds of styling/config work consolidated on this branch:

Bug fixes
- Tooltip never showed: the wrapper only opened overflow for glow, clipping the
  tip rendered above the bar; setTooltip() also attached the tip to the SVG arc
  for circular rings. Open overflow on [data-tooltip-tabar-on] and attach to the
  wrapper for circular.
- Glow was a faint, clipped shadow: replace it with a layered, --tabar-glow-size
  driven halo that bleeds onto surroundings; demo stages no longer clip it.
- Segments could not advance past three chunks (a playground bug): advance the
  bar's live segments on the 0-100 scale instead of three hardcoded ones.

Features
- Remove the leading-edge "peg" entirely (option, element, CSS, --tabar-peg).
- Full live configurator in the playground driving the whole option surface,
  with a generated code snippet and a dynamic multi-color stop editor.
- Centered edge positions (top/bottom/left/right-center) and a configurable
  fixed-bar length/offset (--tabar-length/--tabar-offset).
- Multiple colors: a `colors` multi-stop alias, colorMode gradient|bands (hard
  blocks) and colorAnimate (scrolling), with matching setters.
- Circular options: trackColor, lineCap, startAngle, clockwise, glowSize.
- Declarative config: expand the <tabar-bar> attribute surface and read
  data-tabar-* off the mount element for plain instances (JS options win);
  coercion shared via src/attrs.js so the paths can't drift.
- Group the demo-site assets under assets/{css,js,img} in site/ and site/dist/.

Tests/CI
- Add Playwright: a deterministic visual gallery + fixed-position fixture and a
  functional click-through of every control, run on light/dark in the official
  Playwright Linux container with committed baselines; new CI job.
- Expand unit coverage (tooltip, positions/length, multicolor, circular, data
  attributes, >3-segment advance) and a web-component test.
Follow-up audit fixes:
- An invalid `mountTo` selector string threw a DOMException from the constructor
  (both the new data-attribute resolver and `_resolveHost`). Guard
  `document.querySelector` and fall back to the default mount; `_resolveHost`
  now reuses the shared resolver.
- attribute drift: `max` and `debug` were real options but missing from the
  shared attribute list, so they couldn't be set via `<tabar-bar>` or
  `data-tabar-*`; add them. Remove the dead `min` coercion key (no such option).
- Make `setClockwise`'s `--tabar-flip` formula match `_applyTheme`'s verbatim.
- Fix a stale `site/visual.js` path in CONTRIBUTING after the asset move.
- Tests for invalid-selector fallback and data-tabar-max/-debug.
…rator

- height: a linear bar's `height` now accepts any CSS length (e.g. '100%') so it
  can fill its host; numbers stay px, circular keeps a numeric stroke. Settable
  via setHeight() and the `height`/`data-tabar-height` attribute (number or
  string).
- Demos: every inline demo bar now fills its track (height:'100%') and the track
  surface is the bar's only track, so the grey "bottom border" strip below a
  shorter bar is gone.
- Configurator: redesigned the section — a preview card and a grouped action
  toolbar (Progress / States / View) instead of one long button row; refined the
  mini-button styling. The preview host sizes to the configured thickness (and
  drops the track box for circular rings).
- Tests for string/percentage height (incl. data-tabar-height) and circular
  staying numeric.
- Bump the default `height` from 3px to 6px for a more visible bar out of the box
  (SCSS $height, DEFAULTS, and the fallbacks in _applyTheme/setHeight).
- Document that a linear bar's `height` already accepts any CSS length — number →
  px, string passes through (rem/em/%/vh/calc) — with guidance on which to pick:
  px for predictable chrome (the default), rem to scale with type, % to fill a
  sized host. Circular height stays numeric px.
- Tests: default is 6px; rem/em/% all honored.
- README: feature bullets now cover center positions + length, multi-color modes
  (bands/animated), the bleeding glow and flexible height; integration bullet notes
  data-tabar-* attributes; the API-at-a-glance table gains the new setters
  (setLength/setOffset/setTrackColor/setLineCap/setStartAngle/setClockwise,
  setColors/addColorStop/removeColorStop/setColorMode/setColorAnimate, setGlowSize).
- integration.md: rewrote the declarative-config section — the full <tabar-bar>
  attribute surface plus the plain-mount data-tabar-* fallback and the JS-only
  function-option caveat.
- architecture.md: a Declarative configuration note covering the shared src/attrs.js
  coercion and the data-attr-under-JS merge order.
- theming.md: height defaults to 6px and accepts px/rem/em/% (cross-links to the new
  configuration.md "Height units" guidance).
A TabarGroup child inherited the default autoHide, so on done() it hid its bar
(and reset to 0) while its row kept the reserved min-height — producing a growing
stack of empty white rows after downloads finished, and dropping the overall
aggregate. Default group children to autoHide:false so they persist at their final
value (filled rows, accurate aggregate); opt back in per-child with autoHide:true.

Regression test added.
Library
- Circular setHeight/setSize are live now: recompute the ring radius/
  circumference and repaint, so changing stroke/diameter no longer mis-scales
  the arc (_recomputeRing). setShape rebuilds linear↔circular preserving state.
- Broader, consistent API: setSize/setShape/setPosition/setDirection/setMax/
  setMinimum/setSegmentMode/setZIndex, read-only getters for every option, and
  TabarGroup setChildDefaults/setOverallDefaults. Document colors>gradient>theme
  precedence and the glow/striped-as-modifier model.
- Fix: data-tabar-length="240" now reads as 240px (length joined the DIMENSION
  set); React useTabar syncs on start/resume/show/hide/stall/retry; the CLI
  guards against a trailing value flag.

Tooling
- Types for every export (added terminal/element .d.ts, wired into exports);
  license banner on minified bundles; serve.js MIME map + PORT parse; lint the
  demo JS; opt-in coverage (@vitest/coverage-v8 + test:coverage).

Site design system (Apple-rigorous, tokenized, accessible)
- Token layer: 4/8px spacing grid, type/radius/leading/tracking scales,
  breakpoint vars; replaced scattered magic numbers; unified card/demo/panel
  padding and button/input treatments.
- Accessibility: :focus-visible rings on all controls, dark-mode muted-text
  contrast fix, full prefers-reduced-motion coverage, de-duplicated dark theme
  (shared mixin), aria-pressed theme toggle + aria-live event log.
- Favicon + Open Graph/Twitter cards (assets/img/{favicon,og}.svg).

Tests: new coverage for the setters/getters, circular geometry recompute,
setShape rebuild, and numeric data-tabar-length.
- Glow now follows the bar's rounded shape (rounds the fill to --tabar-radius)
  instead of rendering a hard rectangle, and sits outside any border.
- Add a configurable linear-track border: borderWidth/borderStyle/borderColor +
  setBorder()/setBorderColor, --tabar-border-* vars, data-tabar-border-* attrs,
  types, and a configurator group. Reset for circular (a box round a ring is wrong).
- succeed() completes the bar to 100% (green) without auto-hiding; error()/warn()
  keep their current value. set()/reset() still clear transient states.
- Configurator color editor seeds 3 colors and keeps a 3-color minimum for bands.
- Consolidate the two visual fixtures into one visual.html: fixed/center positions
  render inside contained "viewport-frame" tiles (a transform ancestor scopes
  position:fixed); delete visual-fixed.html/.js; regenerate baselines.
- Docs (README/configuration/theming/integration/events), a data-tabar-* bands+border
  example, and tests for the new border/success and the previously-untested setters.
Migrate the demo's presentation to Webpixels CSS (a Bootstrap-based utility +
component framework) instead of a hand-rolled design system, and polish the
landing/playground for consistent, Apple-style rhythm. The library is untouched
and still ships zero CSS-framework dependency.

- Vendor @webpixels/css locally: build-site.js copies dist/all.css ->
  site/dist/assets/css/webpixels.css (offline/CI-deterministic, no runtime CDN).
- index.html + playground.html rebuilt with Bootstrap/Webpixels classes
  (navbar, card, btn, form-control/select/range/check, grid, utilities);
  every id / data-act / data-testid / data-sc hook preserved.
- playground.js control generator emits Bootstrap form classes; landing.js +
  playground.js theme toggle drives Bootstrap's data-bs-theme (persisted).
- styles.scss slimmed to a thin demo-glue layer over --x-* tokens; brand the
  primary token + button blue for contrast; adaptive CTA band; frosted sticky
  navbar; restrained example-card hover.
- visual.html is self-contained (loads no site/framework CSS) so screenshot
  baselines stay stable; examples/webpixels.html added.
- Fix landing inconsistencies: balanced 3x3 features grid (added Persistence),
  py-lg-12 spacing, and a pre-paint inline script to avoid the dark-mode FOUC.
- Docs (README/CONTRIBUTING/CHANGELOG) note the demo=Webpixels vs library=BEM,
  framework-free split.
- cornersToCss now parses string corner values, so radius/innerRadius set via
  <tabar-bar>/data-tabar-*/JSON apply instead of silently falling back to 0
  (bare number -> px, comma/space list -> per-corner, other CSS length passes through).
- trackXHR removes its progress/load/error/abort listeners on completion and on
  destroy() (registered in _unbinds) — no more leaked XHR/instance mid-transfer.
- normalizeValue guards max <= 0 (no divide-by-zero corruption); circular radius
  clamps to >= 0 when size <= stroke (no invalid SVG arc).
- Consolidate the CHANGELOG [Unreleased] into single Added/Changed/Removed/Fixed
  sections (was three Added blocks); ignore local scratch-*.mjs harnesses.
- Tests for each fix.
… reset

- coerceAttr splits the colors/gradient attribute on top-level commas only, so
  rgb()/hsl()/color-mix() values keep their inner commas
  ("rgb(1,2,3),#fff" -> ['rgb(1,2,3)', '#fff']).
- examples/tailwind.html: Reset chained .show() onto set()'s Promise return,
  which threw — split into two statements.
- Tests for the colors attribute.
opensource@simtabi.com is the community address; security@simtabi.com is the
dedicated disclosure inbox per the org convention, kept separate so a report is
never buried in a feature-request thread.
probar (2020) is tabar's predecessor and lives on GitHub as simtabi/probar, which becomes simtabi/tabar. Merging its history in as an ancestor keeps all 30 of its commits reachable and gives the two histories a common base, so tabar can land on that repository through a normal pull request. probar's three files move unchanged to legacy/probar/; tabar's own files are untouched, and package.json's files whitelist keeps legacy/ out of the npm package.
Copilot AI balanced review requested due to automatic review settings October 1, 2026 22:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved packaging, Web Component, group lifecycle, terminal reuse, and documentation defects affect advertised public behavior.

Review effort: Balanced
Findings: 9 Medium severity · 1 Low severity

Open (10)
What changed in this PR

This PR establishes Tabar’s modern v0.6 codebase, combining browser, terminal, framework integration, documentation, demos, testing, packaging, and project governance.

Changes:

  • Adds terminal, group, React, Web Component, and declarative-attribute integrations.
  • Introduces comprehensive unit/E2E testing, build tooling, package exports, and CI/release automation.
  • Adds a redesigned demo site, examples, API documentation, and legacy ProBar history.
File Description
vitest.config.js Configures unit tests and coverage.
types/​terminal.d.ts Declares terminal exports.
types/​react.d.ts Declares the React hook.
types/​node.d.ts Declares Node and terminal APIs.
types/​group.d.ts Declares group APIs.
types/​element.d.ts Declares the Web Component.
types/​api-check.ts Exercises public declarations.
tsconfig.json Configures declaration type-checking.
test/​terminal.test.js Tests terminal and headless behavior.
test/​react.test.js Tests React integration.
test/​group.test.js Tests group aggregation and lifecycle.
test/​element.test.js Tests declarative attributes.
src/​terminal.js Implements ANSI terminal rendering.
src/​react.js Implements the React hook.
src/​node.js Defines the Node entry point.
src/​group.js Implements grouped progress bars.
src/​element.js Implements <tabar-bar>.
src/​attrs.js Centralizes attribute coercion.
site/​visual.html Provides the visual fixture page.
site/​index.html Adds the marketing landing page.
site/​assets/​scss/​styles.scss Styles the demo site.
site/​assets/​js/​visual.js Builds visual test scenarios.
site/​assets/​js/​landing.js Drives landing-page interactions.
site/​assets/​img/​og.svg Adds social-preview artwork.
site/​assets/​img/​favicon.svg Adds the site favicon.
site/​assets/​img/​.gitkeep Documents the image directory.
SECURITY.md Defines vulnerability reporting.
scripts/​serve.js Serves demos locally.
scripts/​build.js Bundles package entry points.
scripts/​build-site.js Builds the marketing site.
scripts/​build-css.js Compiles library styles.
README.md Documents features and usage.
playwright.config.js Configures browser testing.
package.json Defines packaging, exports, and scripts.
LICENSE Adds the MIT license.
legacy/​probar/​readme.md Preserves legacy documentation.
legacy/​probar/​ProBar.js Preserves the legacy implementation.
examples/​webpixels.html Adds a Webpixels example.
examples/​tailwind.html Adds a Tailwind example.
examples/​no-framework.html Adds a vanilla example.
examples/​multi-progress.html Demonstrates segments and groups.
examples/​cli.js Demonstrates terminal usage.
examples/​bootstrap.html Adds a Bootstrap example.
eslint.config.js Configures JavaScript linting.
e2e/​visual.spec.js Adds visual regression coverage.
e2e/​playground.spec.js Tests playground interactions.
docs/​tools/​theming.md Documents visual customization.
docs/​tools/​progress.md Documents transfers and reactivity.
docs/​tools/​persistence.md Documents persisted state.
docs/​tools/​multi-and-cli.md Documents groups and terminal usage.
docs/​tools/​integration.md Documents API and framework integration.
docs/​tools/​events.md Documents events and localization.
docs/​tools/​concurrency.md Documents concurrent instances.
docs/​release.md Defines the release process.
docs/​installation.md Documents installation paths.
docs/​configuration.md Documents the option surface.
docs/​architecture.md Explains internal architecture.
CONTRIBUTING.md Defines contributor workflows.
CODE_OF_CONDUCT.md Adds community standards.
CHANGELOG.md Records releases and current changes.
bin/​tabar.js Implements the command-line interface.
.gitignore Excludes generated artifacts.
.github/​workflows/​release.yml Automates releases and publishing.
.github/​workflows/​ci.yml Adds test and visual CI.
.github/​PULL_REQUEST_TEMPLATE.md Adds the PR checklist.
.github/​ISSUE_TEMPLATE/​feature_request.yml Adds feature-request intake.
.github/​ISSUE_TEMPLATE/​config.yml Configures issue routing.
.github/​ISSUE_TEMPLATE/​bug_report.yml Adds bug-report intake.
.github/​dependabot.yml Configures dependency updates.
.editorconfig Defines editor formatting defaults.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread package.json
Comment on lines +81 to +84
"sideEffects": [
"*.css",
"./src/element.js"
],
Comment thread site/assets/js/landing.js
Comment on lines +8 to +17
const prefersDark = () => window.matchMedia?.('(prefers-color-scheme: dark)').matches;
const saved = localStorage.getItem('tabar-theme');
root.setAttribute('data-bs-theme', saved || (prefersDark() ? 'dark' : 'light'));
const reflectTheme = () => themeBtn?.setAttribute('aria-pressed', String(root.getAttribute('data-bs-theme') === 'dark'));
reflectTheme();
themeBtn?.addEventListener('click', () => {
const next = root.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark';
root.setAttribute('data-bs-theme', next);
localStorage.setItem('tabar-theme', next);
reflectTheme();
Comment thread src/element.js
Comment on lines +21 to +25
for (const name of this.getAttributeNames()) {
const key = toCamel(name);
const v = coerceAttr(key, this.getAttribute(name));
if (v !== undefined) cfg[key] = v;
}
Comment thread src/element.js
const coerced = coerceAttr(key, newValue);
if (key === 'value') this._bar.set(coerced);
else if (key === 'segments') this._bar.setSegments(coerced || []);
else this._bar.configure({ [key]: coerced });
Comment thread src/group.js
Comment on lines +34 to +37
const host =
options.mountTo instanceof Element
? options.mountTo
: (typeof options.mountTo === 'string' && document.querySelector(options.mountTo)) || document.body;
Comment thread src/group.js
Comment on lines +120 to +121
this._children.delete(id);
this._sync();
Comment thread src/react.js
export function useTabar(options = {}) {
const ref = useRef(null);
const barRef = useRef(null);
const [snapshot, setSnapshot] = useState({ value: 0, state: 'idle', stats: null });
Comment thread src/terminal.js
if (stopped) return;
const line = buildLine();
if (isTTY) {
stream.write(`\r${color ? ANSI.clearLine : ''}${line}`);
Comment thread src/terminal.js
Comment on lines +113 to +120
const onUpdate = () => {
paint();
if (bar.state === 'indeterminate' && isTTY && !spinTimer) spin();
else if (bar.state !== 'indeterminate') stopSpinner();
};
const onDone = () => {
if (finished) return;
finished = true;
Comment thread SECURITY.md
Comment on lines +24 to +25
Tabar runs in the browser and has no runtime dependencies. It does not make network
requests. It does read and write to `localStorage`/`sessionStorage` when persistence is
@imanimanyara
imanimanyara merged commit 640b351 into main Oct 1, 2026
5 checks passed
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