mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2025-11-29 02:38:00 +08:00
chore: import new ui system (#73)
* chore: import new ui system * chore: modified padding and rounded * chore: remove vertical padding * chore: add shadow * chore: add shadcn popover (#76) * chore: add circle progress (#77) * chore: add input (#78) * feat: add shadcn toast (#80) * chore: initial import * chore: style * chore: important * chore: add dropdown menu (#81) * feat: add shadcn tooltip (#79) * chore: initial import * chore: style * chore: fix text size * chore: add tooltip shortcut * chore: code cleanup and add flex col * chore: add avatar (#82) * chore: add dialog (#83) --------- Co-authored-by: Richard Shiue <71320345+richardshiue@users.noreply.github.com>
This commit is contained in:
153
src/components/ui/progress.tsx
Normal file
153
src/components/ui/progress.tsx
Normal file
@@ -0,0 +1,153 @@
|
||||
import * as React from 'react';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const progressVariants = cva(
|
||||
'relative block',
|
||||
{
|
||||
variants: {
|
||||
size: {
|
||||
sm: 'h-4 w-4',
|
||||
md: 'h-6 w-6',
|
||||
lg: 'h-8 w-8',
|
||||
xl: 'h-10 w-10',
|
||||
},
|
||||
variant: {
|
||||
default: '',
|
||||
success: '',
|
||||
warning: '',
|
||||
destructive: '',
|
||||
theme: '',
|
||||
},
|
||||
isIndeterminate: {
|
||||
true: 'animate-progress-container',
|
||||
false: '',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'md',
|
||||
variant: 'default',
|
||||
isIndeterminate: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const circleVariants = cva(
|
||||
'fill-fill-transparent ',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'stroke-fill-tertiary',
|
||||
theme: 'stroke-fill-tertiary',
|
||||
success: 'stroke-fill-tertiary',
|
||||
warning: 'stroke-fill-tertiary',
|
||||
destructive: 'stroke-fill-tertiary',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const progressCircleVariants = cva(
|
||||
'fill-fill-transparent transition-all',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'stroke-fill-secondary',
|
||||
theme: 'stroke-fill-theme-thick',
|
||||
success: 'stroke-fill-success-thick',
|
||||
warning: 'stroke-warning-thick',
|
||||
destructive: 'stroke-error-thick',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
export interface ProgressProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof progressVariants> {
|
||||
/** Progress value between 0 and 100. When undefined, shows indeterminate state */
|
||||
value?: number;
|
||||
/** Line ending style */
|
||||
strokeLinecap?: 'round' | 'square';
|
||||
/** Custom stroke width in pixels */
|
||||
strokeWidth?: number;
|
||||
}
|
||||
|
||||
export function Progress ({
|
||||
value,
|
||||
size = 'md',
|
||||
variant = 'default',
|
||||
strokeLinecap = 'round',
|
||||
strokeWidth = 3.5,
|
||||
className,
|
||||
...props
|
||||
}: ProgressProps) {
|
||||
// Calculate dimensions based on size variant
|
||||
const dimensions: number = {
|
||||
sm: 16,
|
||||
md: 24,
|
||||
lg: 32,
|
||||
xl: 40,
|
||||
}[size as string] || 24;
|
||||
|
||||
const radius = dimensions / 2 - strokeWidth;
|
||||
const circumference = Math.ceil(2 * Math.PI * radius);
|
||||
const isIndeterminate = value === undefined;
|
||||
|
||||
// Calculate percentage offset for the progress circle
|
||||
const offset = isIndeterminate
|
||||
? circumference * 0.25 // 25% offset for indeterminate state
|
||||
: Math.ceil(circumference * ((100 - Math.min(Math.max(0, value || 0), 100)) / 100));
|
||||
|
||||
// Calculate viewBox to add padding around the circles
|
||||
const viewBox = `-${dimensions * 0.125} -${dimensions * 0.125} ${dimensions * 1.25} ${
|
||||
dimensions * 1.25
|
||||
}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(progressVariants({ size, variant, isIndeterminate, className }))}
|
||||
{...props}
|
||||
>
|
||||
<svg
|
||||
width={dimensions}
|
||||
height={dimensions}
|
||||
viewBox={viewBox}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style={{ transform: 'rotate(-90deg)' }}
|
||||
>
|
||||
{/* Base Circle */}
|
||||
<circle
|
||||
r={radius}
|
||||
cx={dimensions / 2}
|
||||
cy={dimensions / 2}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeDasharray={circumference}
|
||||
strokeDashoffset="0"
|
||||
className={cn(circleVariants({ variant }), isIndeterminate && 'hidden')}
|
||||
/>
|
||||
{/* Progress Circle */}
|
||||
<circle
|
||||
r={radius}
|
||||
cx={dimensions / 2}
|
||||
cy={dimensions / 2}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeLinecap={strokeLinecap}
|
||||
strokeDasharray={circumference}
|
||||
strokeDashoffset={offset}
|
||||
className={cn(
|
||||
progressCircleVariants({
|
||||
variant,
|
||||
}),
|
||||
)}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user