make more resilent indicator

This commit is contained in:
Nate Kelley 2025-02-26 10:40:42 -07:00
parent 419378356a
commit bef209244d
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
2 changed files with 62 additions and 29 deletions

View File

@ -0,0 +1,52 @@
import type { Meta, StoryObj } from '@storybook/react';
import { StatusIndicator } from './StatusIndicator';
const meta = {
title: 'Base/StatusIndicator',
component: StatusIndicator,
parameters: {
layout: 'centered'
},
tags: ['autodocs']
} satisfies Meta<typeof StatusIndicator>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Loading: Story = {
args: {
status: 'loading'
}
};
export const Completed: Story = {
args: {
status: 'completed'
}
};
export const Failed: Story = {
args: {
status: 'failed'
}
};
// Story that shows all states side by side
export const AllStates: Story = {
render: () => (
<div className="flex gap-4">
<div className="flex flex-col items-center gap-2">
<StatusIndicator status="loading" />
<span className="text-sm">Loading</span>
</div>
<div className="flex flex-col items-center gap-2">
<StatusIndicator status="completed" />
<span className="text-sm">Completed</span>
</div>
<div className="flex flex-col items-center gap-2">
<StatusIndicator status="failed" />
<span className="text-sm">Failed</span>
</div>
</div>
)
};

View File

@ -1,8 +1,7 @@
import React from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import { createStyles } from 'antd-style';
import { CircleSpinnerLoader } from '@/components/ui/loaders/CircleSpinnerLoader';
import { AppMaterialIcons } from '@/components/ui';
import { RadioChecked, Radio, CircleWarning } from '../icons';
import { cn } from '@/lib/classMerge';
const animationConfig = {
initial: { opacity: 0 },
@ -13,28 +12,24 @@ const animationConfig = {
export const StatusIndicator: React.FC<{ status?: 'completed' | 'loading' | 'failed' }> =
React.memo(({ status }) => {
const { styles, cx } = useStyles();
const inProgress = status === 'loading';
const failed = status === 'failed';
return (
<div
className={cx(
styles.indicatorContainer,
inProgress && 'in-progress',
'relative flex items-center justify-center transition-all duration-300'
className={cn(
'text-gray-light relative flex h-[11px] w-[11px] items-center justify-center rounded-full transition-all duration-200',
inProgress && 'text-primary',
failed && 'text-danger-foreground'
)}>
<AnimatePresence mode="wait">
<motion.div
{...animationConfig}
className={cx(
inProgress && 'in-progress',
key={status}
className={cn(
'ml-[0.5px] flex items-center justify-center transition-all duration-300'
)}>
{inProgress ? (
<AppMaterialIcons icon="circle_with_ring" size={10} />
) : (
<AppMaterialIcons icon="circle_with_ring" size={10} />
)}
{failed ? <CircleWarning /> : <RadioChecked />}
</motion.div>
</AnimatePresence>
</div>
@ -42,17 +37,3 @@ export const StatusIndicator: React.FC<{ status?: 'completed' | 'loading' | 'fai
});
StatusIndicator.displayName = 'StatusIndicator';
const useStyles = createStyles(({ token, css }) => ({
indicatorContainer: css`
width: 11px;
height: 11px;
border-radius: 100%;
color: ${token.colorTextPlaceholder};
&.in-progress {
color: ${token.colorPrimary};
}
`
}));