GrProgressCircle

  • ядро
  • Обратная связь
  • API · 11 props

Берут, когда места по ширине нет.

import { GrProgressCircle } from '@feugene/granularity/components/GrProgressCircle'

Обзор

Когда брать

  • места по ширине нет — плитка дашборда, ячейка, карточка показателя;
  • значение важнее хода — число в центре читается как показатель, а не как ожидание;
  • нужна шкала-«спидометр» — shape разрывает кольцо, когда так понятнее;
  • состояние нужно значком — statusIcon заменяет число на успех или отказ по завершении.

Когда взять другое

НужноБерите
Места по ширине хватаетGrProgressBar
Доля неизвестна, контент уже естьGrLoading
Число без шкалыGrStatistic
Доли нескольких частей целогоGrChartPie

Варианты все тона и виды — настоящим компонентом

Варианты · GrProgressCircle
tone \ shapecircledashboard
primary
neutral
success
warning
danger
info
slate
azure

Размеры

  • xs
  • sm
  • md
  • lg

Playground контролы выводятся из API, а не пишутся руками

Сцена

Загружается…

0 изменено· состояние — в адресе

Примеры 5 у каждого — живое демо и его код

  • Квоты там, где полосе нет места

    Кольцо помещается в плитку рядом с подписью, а show-value ставит долю внутрь — без числа кольцо читается украшением. Тон — вердикт: спокойный до 80 %, дальше warning, у потолка danger. Видимого заголовка у кольца нет, поэтому имя даёт aria-label.

    Business planLimits reset in 12 days
    46%
    Storage23 of 50 GB
    85%
    Seats17 of 20 members
    98%
    API calls today98,120 of 100,000
  • Отмена в центре, вердикт в конце

    Слот по умолчанию владеет центром — здесь кнопка отмены, пока файл грузится. Она стоит рядом с ролью progressbar, а не внутри неё, и для диктора остаётся кнопкой; слой центра указатель не ловит, кнопка включает его себе обратно. В конце status-icon показывает галочку, а на danger — крест.

    Attachments
    scan-invoice-0418.pdf0.9 of 2.4 MB · 36%
    contract-northwind.pdf1.1 MB · uploaded
    receipt-lunch.heicConnection lost at 52% — try again
  • Шкалы на карточке сервера

    shape="dashboard" раскрывает кольцо снизу: шкала читается как измерение, а не как задача, идущая к концу. format-value говорит в единицах читателя и становится заодно aria-valuetext; слот получает клампнутое значение и рисует две строки; thickness утончает обводку.

    api-eu-2c6g.xlarge · Frankfurt · last 5 minutes
    High memory
    38%
    CPU · 4 cores
    13.0 GB
    Memory · of 16 GB
    128of 200 GB
    Disk · /var/lib
  • Сначала неизвестно, потом известно

    Пока экспорт считает счета, его объём неизвестен, и indeterminate крутит кольцо, не объявляя значения, — кольцо, замершее на нуле, читалось бы зависшей задачей. Потом доля заполняется, а status-icon превращает сто процентов в галочку. В живой регион идёт только смена фазы, а не каждый процент.

    Export 214 invoicesSeptember 2026 · Excel with line items

API порождается из пакета · разойтись не может

Props

PropTypeпо умолчаниюОписание
tone
"primary" | "neutral" | "success" | "warning" | "danger" | ""primary" | "neutral" | "success" | "warning" | "danger" | "info" | "slate" | "azure" | undefined
undefinedЦветовая тональность дуги.
size"xs" | "sm" | "md" | "lg" | undefinedundefinedДиаметр кольца по шкале пакета.
ariaLabelstring | undefinedundefinedМетка для скринридера (обязательна, если рядом нет видимого заголовка).
valuenumber | undefined0Текущее значение `0..100`; выходящие за границы клампятся, `NaN` → `0`.
shape"circle" | "dashboard" | undefinedundefinedЗамкнутое кольцо или дуга с вырезом снизу.
indeterminateboolean | undefinedfalseПрогресс неизвестен: дуга бежит по кругу, значение наружу не объявляется.
thicknessnumber | undefinedundefinedТолщина обводки в процентах диаметра. Не задана — по ступени `size`.
showValueboolean | undefinedfalseПоказать значение в центре кольца. Слот по умолчанию сильнее.
formatValue((value: number) => string) | undefinedundefinedСвой формат значения. Управляет и подписью, и `aria-valuetext`.
statusIconboolean | undefinedfalseНа завершении — галочка, при `tone="danger"` — крест вместо значения.
tracklessboolean | undefinedundefinedУбрать дорожку: поверх картинки пустая часть кольца только шумит.

Слоты

SlotTypeОписание
default{ value: number; }Содержимое центра вместо значения: иконка, две строки, кнопка отмены.

Типы

Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.

Импорт
import type { GrProgressCircleProps, GrProgressCircleShape, GrArcGeometry } from '@feugene/granularity/components/GrProgressCircle'

Файлdist/types/components/GrProgressCircle/GrProgressCircle.vue.d.ts

GrProgressCirclePropsinterface

Пропы {@link GrProgressCircle}. Круговой индикатор: определённый режим по value, неопределённый по indeterminate, замкнутое кольцо или дуга-«дашборд».

interface GrProgressCircleProps {
    /** Текущее значение `0..100`; выходящие за границы клампятся, `NaN` → `0`. */
    value?: number;
    /** Прогресс неизвестен: дуга бежит по кругу, значение наружу не объявляется. */
    indeterminate?: boolean;
    /** Замкнутое кольцо или дуга с вырезом снизу. */
    shape?: GrProgressCircleShape;
    /** Показать значение в центре кольца. Слот по умолчанию сильнее. */
    showValue?: boolean;
    /** Свой формат значения. Управляет и подписью, и `aria-valuetext`. */
    formatValue?: (value: number) => string;

Файлdist/types/components/GrProgressCircle/geometry.d.ts

GrProgressCircleShapetype
type GrProgressCircleShape = typeof GR_PROGRESS_CIRCLE_SHAPES[number];
GrArcGeometryinterface
interface GrArcGeometry {
    /** Радиус с поправкой на толщину: обводка рисуется по обе стороны линии. */
    radius: number;
    circumference: number;
    /** Длина дорожки — вся окружность либо её часть у «дашборда». */
    arcLength: number;
    /** `stroke-dasharray` дорожки. */
    trackDashArray: string;
    /** `stroke-dasharray` дуги значения. */
    valueDashArray: string;
    rotation: number;
}

Файлdist/types/components/GrProgressCircle/grProgressCircleStyles.d.ts

GrProgressCircleTonetype
type GrProgressCircleTone = GrTone;
GrProgressCircleSizetype
type GrProgressCircleSize = GrComponentSize;

Файлdist/types/components/GrProgressCircle/config.d.ts

grProgressCircleConfigconst
const grProgressCircleConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrProgressCircle">;

Файлdist/types/components/GrProgressCircle/safelist.d.ts

grProgressCircleSafelistconst
const grProgressCircleSafelist: string[];

Файлdist/types/components/GrProgressCircle/defaults.d.ts

GrProgressCircleConfigurablePropsinterface

Пропы GrProgressCircle, настраиваемые глобально через componentDefaults. Только оформление: значение и режим принадлежат конкретному экземпляру.

interface GrProgressCircleConfigurableProps {
    size: GrProgressCircleSize;
    tone: GrProgressCircleTone;
    shape: GrProgressCircleShape;
    trackless: boolean;
}

Файлdist/types/components/GrProgressCircle/index.d.ts

GrProgressCircleInstancetype
type GrProgressCircleInstance = ComponentExposed<typeof GrProgressCircleComponent>;

Использование из прозы библиотеки

Центр лежит рядом с ролью, а не внутри неё

Разметка нарочно двухслойная: role="progressbar" несёт только SVG, а содержимое центра — его сосед с абсолютным позиционированием.

Причина не косметическая. Роль-виджет объявляет своих потомков презентационными, и кнопка «Отменить» внутри кольца — первый же сценарий аплоада — оказалась бы nested-interactive: скринридер потерял бы и кнопку, и индикатор. Слот центра обязан оставаться местом, куда можно положить что угодно, включая интерактив.

Сам слой центра не ловит указатель (pointer-events: none) — иначе он накрыл бы кольцо; интерактив внутри включает события себе обратно.

Значение, иконка, слот

Приоритет содержимого центра: слот → иконка итога → значение.

  • showValue печатает проценты, formatValue задаёт свой текст и заодно aria-valuetext;
  • statusIcon меняет число на галочку при value >= 100 и на крест при tone="danger" — то есть только в терминальных состояниях;
  • слот по умолчанию получает уже клампнутое значение и перебивает оба варианта. Пустой слот (например, кнопка под v-if) центр не занимает — считается содержимое, а не факт передачи слота.

Значение в центре помещается начиная с sm; на xs его либо не показывают, либо уменьшают кегль токеном --gr-progress-circle-value-size.

Формы

circle — замкнутое кольцо, отсчёт с двенадцати часов по часовой. dashboard — три четверти окружности с вырезом строго снизу: под значением освобождается место для подписи, а шкала читается как спидометр. Значение в обеих формах означает одно и то же — доля пройденного, — меняется только длина дорожки.

Тона общие с полосой

Дуга красится теми же переменными, что и GrProgressBar (--gr-progress-bg, --gr-progress-success-bg и соседи): слой темизации у прогресса один, и потребитель, перекрасивший его, ждёт, что круг и полоса сойдутся. Каждая переменная берётся с фолбэком на роль темы — при гранулярном импорте одного круга покомпонентная тема полосы не подключается, и без фолбэка дуга осталась бы без цвета.

Своя у круга только геометрия: --gr-progress-circle-size, --gr-progress-circle-track, --gr-progress-circle-cap, --gr-progress-circle-value-size.

Неизвестный прогресс

indeterminate пускает дугу по кругу и не объявляет значения: aria-valuenow не выставляется, подпись не печатается.

Под prefers-reduced-motion компонент показывает замкнутое нейтральное кольцо, а не останавливает вращение. Остановленная четверть дуги читалась бы как «прогресс 25 %» — тот же довод, по которому у GrProgressBar своя ветка reduce, а не общий кламп анимаций.

Границы
  • buffer не переносится с полосы: слой «загружено с запасом» читается на шкале, которую видно слева направо целиком; на кольце две вложенные дуги выглядят одной толстой;
  • размер только по шкале пакета — пиксельный escape-hatch есть ровно у GrAvatar и GrIcon; точечная подгонка идёт через --gr-progress-circle-size, а геометрия дуги считается в единицах viewBox и от диаметра не зависит;
  • градиента по дуге нет — он требует <linearGradient> со своим id в каждом экземпляре, то есть ещё одного источника расхождений гидрации;
  • сегментов и рисок нет — кольцо с делениями это индикатор шагов, а не прогресса.