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

157 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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