UNPKG

@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
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; }>;