@gfazioli/mantine-rings-progress
Version:
A Mantine 9 concentric ring progress component inspired by Apple Watch activity rings — animated, glowing, accessible, with per-ring customization.
105 lines (104 loc) • 5.16 kB
TypeScript
import { BoxProps, ElementProps, Factory, StylesApiProps, type MantineColor, type RingProgressProps, type TooltipFloatingProps } from '@mantine/core';
import React from 'react';
export type RingProgressSection = RingProgressProps['sections'][number];
export interface RingsProgressRing {
/** Ring value (0-100) */
value: number;
/** Ring color, key of theme.colors or CSS color value */
color: MantineColor;
/** Tooltip content displayed when withTooltip is enabled */
tooltip?: React.ReactNode;
/** Override thickness for this specific ring */
thickness?: number;
/** Override roundCaps for this specific ring */
roundCaps?: boolean;
/** Glow intensity (blur radius in px) for this ring, overrides global glow */
glowIntensity?: number;
/** Glow color for this ring, defaults to ring color */
glowColor?: MantineColor;
/** Override rootColor for this specific ring (defaults to alpha of ring color) */
rootColor?: MantineColor;
/** Accessible label for this ring, defaults to "Ring {index}: {value}%" */
ariaLabel?: string;
/**
* Two-stop linear gradient applied to this ring's stroke. Overrides `color`.
* `deg` follows the CSS convention (0° = bottom→top, 90° = left→right,
* 180° = top→bottom). Default 0°.
*/
gradient?: {
from: MantineColor;
to: MantineColor;
deg?: number;
};
/** Show a value label positioned at the endpoint of this ring's arc. Overrides the global `showValues`. */
showValue?: boolean;
/** Custom formatter for this ring's value label. Receives the numeric value, returns the displayed string. Falls back to the global `formatValue`. */
formatValue?: (value: number) => string;
/** Called when the ring is clicked. The ring becomes keyboard-focusable (Enter/Space activates it) and the cursor switches to pointer. */
onClick?: (ring: RingsProgressRing, index: number) => void;
/** Called on pointer enter and leave. Receives `hovered` so consumers can react to both edges of the hover. */
onHover?: (ring: RingsProgressRing, index: number, hovered: boolean) => void;
}
export type RingsProgressStylesNames = 'root' | 'ring' | 'label' | 'valueLabel';
export type RingsProgressCssVariables = {
root: '--rp-transition-duration';
};
export interface RingsProgressProps extends BoxProps, StylesApiProps<RingsProgressFactory>, ElementProps<'div'> {
/** List of rings to display as concentric circles */
rings: RingsProgressRing[];
/** Gap between rings, default: 8 */
gap?: number;
/** Alpha for root color derived from ring color, default: 0.15 */
rootColorAlpha?: number;
/** Width and height of the outermost ring, default: 120 */
size?: number;
/** Ring thickness, default: 12 */
thickness?: number;
/** Rounded line caps, default: true */
roundCaps?: boolean;
/** Label displayed in the center of the rings */
label?: React.ReactNode;
/** Enable entrance animation (mount from 0 to target), default: false */
animate?: boolean;
/**
* Smoothly animate value changes after the entrance animation has completed.
* Reuses `transitionDuration` for the duration (or 500 ms when `transitionDuration`
* is 0). Respects `prefers-reduced-motion`.
* @default false
*/
animateValueChanges?: boolean;
/** Transition duration in ms for entrance animation and value changes, default: 0 */
transitionDuration?: number;
/** Delay between each ring's entrance animation in ms, default: 0 (simultaneous) */
staggerDelay?: number;
/** Default Tooltip.Floating props applied to all ring tooltips */
tooltipProps?: Omit<TooltipFloatingProps, 'label' | 'children'>;
/** Enable glow effect. true = default 6px blur, number = custom blur radius in px. Default: false */
glow?: boolean | number;
/** Trigger a pulse animation when a ring reaches 100%, default: false */
pulseOnComplete?: boolean;
/** Start angle in degrees (0 = 12 o'clock position), default: 0 */
startAngle?: number;
/** Ring fill direction, default: 'clockwise' */
direction?: 'clockwise' | 'counterclockwise';
/** Callback fired when a ring value reaches 100% */
onRingComplete?: (index: number, ring: RingsProgressRing) => void;
/** Show a unified tooltip with all rings info on hover, default: false */
withTooltip?: boolean;
/** Show a value label at the endpoint of every ring's arc. Each ring can override with `showValue`. */
showValues?: boolean;
/** Default formatter for value labels. Each ring can override with its own `formatValue`. Defaults to `${Math.round(value)}%`. */
formatValue?: (value: number) => string;
}
export type RingsProgressFactory = Factory<{
props: RingsProgressProps;
ref: HTMLDivElement;
stylesNames: RingsProgressStylesNames;
vars: RingsProgressCssVariables;
}>;
export declare const RingsProgress: import("@mantine/core").MantineComponent<{
props: RingsProgressProps;
ref: HTMLDivElement;
stylesNames: RingsProgressStylesNames;
vars: RingsProgressCssVariables;
}>;