mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-16 04:28:38 +00:00
* Taskheader * Subtask messages * View subtask * subtasks in history items * i18n * Table * Lighter visuals * bug * fix: Align tests with implementation behavior * refactor: extract CircularProgress component from TaskHeader - Created reusable CircularProgress component for displaying percentage as a ring - Moved inline SVG calculation from TaskHeader.tsx to dedicated component - Added comprehensive tests for CircularProgress component (14 tests) - Component supports customizable size, strokeWidth, and className - Includes proper accessibility attributes (progressbar role, aria-valuenow) * chore: update StandardTooltip default delay to 600ms As mentioned in the PR description, increased the tooltip delay to 600ms for less intrusive tooltips. The delay is still configurable via the delay prop for components that need a different value. --------- Co-authored-by: Roo Code <roomote@roocode.com>
78 lines
2 KiB
TypeScript
78 lines
2 KiB
TypeScript
import { memo } from "react"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
interface CircularProgressProps {
|
|
/** Progress percentage (0-100) */
|
|
percentage: number
|
|
/** Size of the SVG in pixels (default: 16) */
|
|
size?: number
|
|
/** Stroke width in pixels (default: 2) */
|
|
strokeWidth?: number
|
|
/** Additional CSS classes */
|
|
className?: string
|
|
}
|
|
|
|
/**
|
|
* A circular progress indicator component that displays a percentage as a ring.
|
|
* The ring fills clockwise from the top based on the percentage value.
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* <CircularProgress percentage={75} />
|
|
* <CircularProgress percentage={50} size={24} strokeWidth={3} />
|
|
* ```
|
|
*/
|
|
export const CircularProgress = memo(function CircularProgress({
|
|
percentage,
|
|
size = 16,
|
|
strokeWidth = 2,
|
|
className,
|
|
}: CircularProgressProps) {
|
|
// Clamp percentage between 0 and 100
|
|
const clampedPercentage = Math.max(0, Math.min(100, percentage))
|
|
|
|
// Calculate the radius based on size and stroke width
|
|
// The radius needs to fit within the viewBox accounting for stroke width
|
|
const radius = (size - strokeWidth) / 2
|
|
const center = size / 2
|
|
|
|
// Calculate the circumference and dash offset for the progress ring
|
|
const circumference = 2 * Math.PI * radius
|
|
const strokeDashoffset = circumference - (clampedPercentage / 100) * circumference
|
|
|
|
return (
|
|
<svg
|
|
width={size}
|
|
height={size}
|
|
viewBox={`0 0 ${size} ${size}`}
|
|
className={cn("shrink-0", className)}
|
|
role="progressbar"
|
|
aria-valuenow={clampedPercentage}
|
|
aria-valuemin={0}
|
|
aria-valuemax={100}>
|
|
{/* Background circle */}
|
|
<circle
|
|
cx={center}
|
|
cy={center}
|
|
r={radius}
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth={strokeWidth}
|
|
opacity="0.2"
|
|
/>
|
|
{/* Progress circle */}
|
|
<circle
|
|
cx={center}
|
|
cy={center}
|
|
r={radius}
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth={strokeWidth}
|
|
strokeDasharray={circumference}
|
|
strokeDashoffset={strokeDashoffset}
|
|
strokeLinecap="round"
|
|
transform={`rotate(-90 ${center} ${center})`}
|
|
/>
|
|
</svg>
|
|
)
|
|
})
|