First Release v1.0.0
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
---
|
||||
/**
|
||||
* Skeleton Component
|
||||
* Loading placeholder with pulse animation
|
||||
*/
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
import { cn } from '@/lib/cn';
|
||||
import { skeletonVariants } from './skeleton.variants';
|
||||
|
||||
interface Props extends HTMLAttributes<'div'> {
|
||||
variant?: 'default' | 'circular' | 'text';
|
||||
width?: string;
|
||||
height?: string;
|
||||
animated?: boolean;
|
||||
}
|
||||
|
||||
const {
|
||||
variant = 'default',
|
||||
width,
|
||||
height,
|
||||
animated = true,
|
||||
class: className,
|
||||
...attrs
|
||||
} = Astro.props;
|
||||
|
||||
const style = [
|
||||
width && `width: ${width}`,
|
||||
height && `height: ${height}`,
|
||||
].filter(Boolean).join('; ');
|
||||
---
|
||||
|
||||
<div
|
||||
class={cn(skeletonVariants({ variant, animated }), className)}
|
||||
style={style || undefined}
|
||||
aria-hidden="true"
|
||||
role="presentation"
|
||||
{...attrs}
|
||||
/>
|
||||
|
||||
<style>
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-pulse {
|
||||
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,26 @@
|
||||
import { type HTMLAttributes, type Ref } from 'react';
|
||||
import { cn } from '@/lib/cn';
|
||||
import { skeletonVariants, type SkeletonVariants } from './skeleton.variants';
|
||||
|
||||
interface SkeletonProps extends Omit<HTMLAttributes<HTMLDivElement>, 'ref'> {
|
||||
ref?: Ref<HTMLDivElement>;
|
||||
variant?: SkeletonVariants['variant'];
|
||||
width?: string;
|
||||
height?: string;
|
||||
animated?: boolean;
|
||||
}
|
||||
|
||||
export function Skeleton({ ref, variant = 'default', width, height, animated = true, className, style, ...rest }: SkeletonProps) {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(skeletonVariants({ variant, animated }), className)}
|
||||
style={{ ...style, width, height }}
|
||||
aria-hidden="true"
|
||||
role="presentation"
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Skeleton;
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default } from './Skeleton.astro';
|
||||
export { Skeleton } from './Skeleton';
|
||||
export { skeletonVariants, type SkeletonVariants } from './skeleton.variants';
|
||||
@@ -0,0 +1,20 @@
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
|
||||
export const skeletonVariants = cva('bg-secondary', {
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'rounded-md',
|
||||
circular: 'rounded-full',
|
||||
text: 'rounded h-4',
|
||||
},
|
||||
animated: {
|
||||
true: 'animate-pulse',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
animated: true,
|
||||
},
|
||||
});
|
||||
|
||||
export type SkeletonVariants = VariantProps<typeof skeletonVariants>;
|
||||
Reference in New Issue
Block a user