Display

Barber Pole Task

Indeterminate progress with no invented ratio: the track is filled edge to edge with moving hatching, and a counter of finished work stands in for the percentage.

  • progress
  • indeterminate
  • loading
  • display

Preview

1440pxHost theme

Use it with AI

  1. 1. Copy the link.
  2. 2. Write to your agent in your own words and drop the link into the sentence.
  3. 3. The agent opens the link and installs the component from the registry.

put this in the header: https://vibeui.ru/c/progress-007?lang=en

Indexing the archive
обработано 12 480 документовидёт 3 мин
Show the full instructions

What the link says, spelled out. Use it when your agent cannot open links — paste this text instead.

# Install and place "progress-007" (Barber Pole Task) from VibeUI

## 1. Install first — do not skip, do not recreate
Run this exact command before writing any code:
npx shadcn@latest add https://vibeui.ru/r/progress-007.json

Registry item: https://vibeui.ru/r/progress-007.json
Installs to: components/vibeui/progress-007.tsx (the exact path follows this project's components.json aliases).
npm dependencies: none.
Registry dependencies: none.

Install it from the registry. Do not recreate it from the description,
do not substitute a similar component from another library, and do not
rewrite it to match the project's existing style.

## 2. What it is
Indeterminate progress with no invented ratio: the track is filled edge to edge with moving hatching, and a counter of finished work stands in for the percentage.

Indeterminate progress: moving hatching instead of a ratio and an honest counter of work done instead of a percent. Zero dependencies, one file, server rendered.

## 3. How to use it
import { Progress007 } from "@/components/vibeui/progress-007"

<Progress007
  label="Indexing the archive"
  processed={12480}
  unit="documents"
  elapsed="running 3 min"
/>

Read the installed file for the full prop list.

## 4. Where to place it
This is a small inline component. Put it exactly where the user asked,
inside the existing markup. Do not create a new page, section or
wrapper for it. If a similar control already sits in that spot,
replace it instead of adding a second one.

Placement: ___
(The user fills this line in. If it is still blank, ask where to put it
instead of guessing.)

## 5. Keep exactly as installed
- the local --vibeui-progress-007-* palette — do not swap it for your theme tokens
- the absence of aria-valuenow: any percentage set here would be invented
- the aria-valuetext about the unknown duration — otherwise the progressbar role sounds empty
- the background-position animation rather than a width change: width forces layout on every frame
- the counter of finished work: it is the only honest number in the block
- the card's own light surface: without it the dark text disappears on a dark background

## 6. You may change
- the heading through label
- the amount done through processed and its unit through unit
- the elapsed line through elapsed
- the hatching colour through the accent variable

## 7. Rules
- Once the ratio becomes known, swap this block for a determinate bar instead of bolting percentages onto it.
- Fast hatching is tiring: a period under 0.7s reads as flicker.
- processed is formatted with the ru-RU locale — change it along with the language.
- Do not lift the CSS variables into globals.css: the component has to stay a single file.

## 8. Verify
- it renders with no console errors;
- it looks like the preview on the VibeUI page you copied this from;
- if it does not, you changed something listed in section 5 — put it back.

For developers

npx shadcn@latest add https://vibeui.ru/r/progress-007.json
https://vibeui.ru/r/progress-007.json

Компонент самодостаточен: один файл, без зависимостей, собственная палитра в локальных переменных --vibeui-progress-007-*. Серверный: хуков нет. Движение задано анимацией background-position по repeating-linear-gradient, поэтому дорожка остаётся одним элементом без бегунка внутри и без пересчёта раскладки на каждом кадре. У role="progressbar" сознательно нет aria-valuenow: как только атрибут появляется, скринридер называет процент, которого никто не считал; вместо него стоит aria-valuetext про неизвестную длительность. Точка-маячок в заголовке пульсирует прозрачностью и остаётся признаком работы, когда дорожка не попала в поле зрения. При запрете движения штриховка снимается и дорожка становится ровной заливкой.

Component source

The same file your agent installs. Here in case you would rather copy it by hand.

import type { ComponentPropsWithoutRef, CSSProperties } from "react"

export type Progress007Props = Omit<
  ComponentPropsWithoutRef<"div">,
  "children"
> & {
  label?: string
  /** Сколько единиц работы уже сделано: честное число вместо выдуманной доли. */
  processed?: number
  unit?: string
  elapsed?: string
}

// Идея компонента: длительность неизвестна, поэтому доли нет вовсе. Дорожка
// залита штриховкой во всю ширину, движение задано background-position, а
// вместо процентов показан счётчик уже сделанной работы — единственное
// число, которое здесь честно. aria-valuenow сознательно не выставлен.
const STYLES = `
:where([data-vibeui-block="progress-007"]){
--vibeui-progress-007-bg:oklch(1 0 0);
--vibeui-progress-007-fg:oklch(0.25 0.016 265);
--vibeui-progress-007-muted:oklch(0.56 0.014 265);
--vibeui-progress-007-border:oklch(0.9 0.006 265);
--vibeui-progress-007-track:oklch(0.93 0.005 265);
--vibeui-progress-007-accent:oklch(0.6 0.15 262);
--vibeui-progress-007-font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
[data-vibeui-block="progress-007"]{
display:flex;flex-direction:column;gap:0.625rem;
width:100%;max-width:24rem;box-sizing:border-box;padding:0.9375rem 1.0625rem;
background:var(--vibeui-progress-007-bg);
border:1px solid var(--vibeui-progress-007-border);border-radius:0.875rem;
font-family:var(--vibeui-progress-007-font);color:var(--vibeui-progress-007-fg);
}
[data-vibeui-block="progress-007"] [data-part="head"]{
display:flex;align-items:center;gap:0.5rem;font-size:0.8125rem;font-weight:650;
}
/* Точка-маячок: подпись остаётся живой, даже когда полосу не видно. */
[data-vibeui-block="progress-007"] [data-part="pip"]{
flex:none;width:0.4375rem;height:0.4375rem;border-radius:9999px;
background:var(--vibeui-progress-007-accent);
animation:vibeui-progress-007-pulse 1.6s ease-in-out infinite;
}
/* Штриховка едет по всей дорожке: конца у неё нет, и это честно. */
[data-vibeui-block="progress-007"] [data-part="track"]{
height:0.5rem;border-radius:9999px;overflow:hidden;
background-color:var(--vibeui-progress-007-track);
background-image:repeating-linear-gradient(
115deg,
var(--vibeui-progress-007-accent) 0 0.5rem,
color-mix(in oklch,var(--vibeui-progress-007-accent) 45%,var(--vibeui-progress-007-track)) 0.5rem 1rem);
background-size:2rem 100%;
animation:vibeui-progress-007-drift 0.9s linear infinite;
}
@keyframes vibeui-progress-007-drift{
0%{background-position:0 0}
100%{background-position:-2rem 0}
}
@keyframes vibeui-progress-007-pulse{
0%,100%{opacity:1}
50%{opacity:.3}
}
[data-vibeui-block="progress-007"] [data-part="foot"]{
display:flex;justify-content:space-between;gap:0.75rem;
font-size:0.6875rem;color:var(--vibeui-progress-007-muted);
font-variant-numeric:tabular-nums;
}
[data-vibeui-block="progress-007"] [data-part="foot"] strong{
color:var(--vibeui-progress-007-fg);font-weight:650;
}
@media (prefers-reduced-motion:reduce){
[data-vibeui-block="progress-007"] *{animation:none!important;transition:none!important}
[data-vibeui-block="progress-007"] [data-part="track"]{background-image:none;background-color:color-mix(in oklch,var(--vibeui-progress-007-accent) 35%,var(--vibeui-progress-007-track))}
}
`

/**
 * Неопределённый прогресс: штриховка вместо доли, счётчик вместо процента.
 * Один файл, ноль зависимостей, собственная палитра.
 */
export function Progress007({
  label = "Индексируем архив",
  processed = 12_480,
  unit = "документов",
  elapsed = "идёт 3 мин",
  className,
  style,
  ...props
}: Progress007Props) {
  return (
    <>
      <style href="vibeui-progress-007" precedence="medium">
        {STYLES}
      </style>
      <div
        {...props}
        data-vibeui-block="progress-007"
        className={className}
        style={style as CSSProperties}
      >
        <div data-part="head">
          <span data-part="pip" aria-hidden="true" />
          <span>{label}</span>
        </div>
        <div
          data-part="track"
          role="progressbar"
          aria-label={label}
          aria-valuetext="Длительность неизвестна"
        />
        <div data-part="foot">
          <span>
            обработано <strong>{processed.toLocaleString("ru-RU")}</strong>{" "}
            {unit}
          </span>
          <span>{elapsed}</span>
        </div>
      </div>
    </>
  )
}