veza/apps/web/src/components/base/Badge.tsx

158 lines
3.3 KiB
TypeScript
Raw Normal View History

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>
);
};