157 lines
3.3 KiB
TypeScript
157 lines
3.3 KiB
TypeScript
import React from 'react';
|
||
import type { BaseComponentProps } from '../types';
|
||
import '../../styles/badge-avatar.css';
|
||
|
||
/**
|
||
* Badge component props
|
||
*/
|
||
export interface BadgeProps extends BaseComponentProps {
|
||
children: React.ReactNode;
|
||
variant?:
|
||
| 'default'
|
||
| 'cyber'
|
||
| 'neon'
|
||
| 'nature'
|
||
| 'gaming'
|
||
| 'success'
|
||
| 'warning'
|
||
| 'error';
|
||
dot?: boolean;
|
||
pulse?: boolean;
|
||
clipped?: boolean;
|
||
}
|
||
|
||
export const Badge = ({
|
||
children,
|
||
variant = 'default',
|
||
dot = false,
|
||
pulse = false,
|
||
clipped = false,
|
||
className = '',
|
||
...props
|
||
}: BadgeProps) => {
|
||
const baseClass = 'badge-veza';
|
||
const variantClass = `badge-veza--${variant}`;
|
||
const pulseClass = pulse ? 'badge-veza--pulse' : '';
|
||
const clippedClass = clipped ? 'badge-veza--clipped' : '';
|
||
|
||
const classes = [baseClass, variantClass, pulseClass, clippedClass, className]
|
||
.filter(Boolean)
|
||
.join(' ');
|
||
|
||
return (
|
||
<span className={classes} {...props}>
|
||
{dot && <span className="badge-veza__dot" />}
|
||
{children}
|
||
</span>
|
||
);
|
||
};
|
||
|
||
/**
|
||
* Tag component props
|
||
*/
|
||
export interface TagProps extends BaseComponentProps {
|
||
children: React.ReactNode;
|
||
variant?: 'default' | 'cyber' | 'neon';
|
||
active?: boolean;
|
||
closable?: boolean;
|
||
onClose?: () => void;
|
||
}
|
||
|
||
export const Tag = ({
|
||
children,
|
||
variant = 'default',
|
||
active = false,
|
||
closable = false,
|
||
onClose,
|
||
className = '',
|
||
...props
|
||
}: TagProps) => {
|
||
const baseClass = 'tag-veza';
|
||
const variantClass = variant !== 'default' ? `tag-veza--${variant}` : '';
|
||
const activeClass = active ? 'tag-veza--active' : '';
|
||
|
||
const classes = [baseClass, variantClass, activeClass, className]
|
||
.filter(Boolean)
|
||
.join(' ');
|
||
|
||
return (
|
||
<span className={classes} {...props}>
|
||
{children}
|
||
{closable && (
|
||
<button
|
||
className="tag-veza__close"
|
||
onClick={onClose}
|
||
aria-label="Remove tag"
|
||
>
|
||
×
|
||
</button>
|
||
)}
|
||
</span>
|
||
);
|
||
};
|
||
|
||
/**
|
||
* Avatar component props
|
||
*/
|
||
export interface AvatarProps extends BaseComponentProps {
|
||
children?: React.ReactNode;
|
||
src?: string;
|
||
alt?: string;
|
||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
||
variant?: 'default' | 'cyber' | 'neon' | 'gaming';
|
||
status?: 'online' | 'away' | 'busy' | 'offline';
|
||
}
|
||
|
||
export const Avatar = ({
|
||
children,
|
||
src,
|
||
alt = '',
|
||
size = 'md',
|
||
variant = 'default',
|
||
status,
|
||
className = '',
|
||
...props
|
||
}: AvatarProps) => {
|
||
const baseClass = 'avatar-veza';
|
||
const sizeClass = `avatar-veza--${size}`;
|
||
const variantClass = variant !== 'default' ? `avatar-veza--${variant}` : '';
|
||
|
||
const classes = [baseClass, sizeClass, variantClass, className]
|
||
.filter(Boolean)
|
||
.join(' ');
|
||
|
||
return (
|
||
<div className={classes} {...props}>
|
||
{src ? (
|
||
<img src={src} alt={alt} className="avatar-veza__img" />
|
||
) : (
|
||
children
|
||
)}
|
||
{status && (
|
||
<span
|
||
className={`avatar-veza__status avatar-veza__status--${status}`}
|
||
/>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
/**
|
||
* Avatar Group component props
|
||
*/
|
||
export interface AvatarGroupProps extends BaseComponentProps {
|
||
children: React.ReactNode;
|
||
}
|
||
|
||
export const AvatarGroup = ({
|
||
children,
|
||
className = '',
|
||
...props
|
||
}: AvatarGroupProps) => {
|
||
return (
|
||
<div className={`avatar-group-veza ${className}`} {...props}>
|
||
{children}
|
||
</div>
|
||
);
|
||
};
|