feat: enhance chat components with improved accessibility features, including ARIA attributes for search and user status, and implement message length validation and file type checks in message input handling

This commit is contained in:
2025-12-08 23:16:05 -03:00
parent e46738c5bf
commit 1810cbabe2
22 changed files with 1364 additions and 249 deletions

View File

@@ -1,13 +1,55 @@
<script lang="ts">
import { User } from 'lucide-svelte';
import { getCachedAvatar } from '$lib/utils/avatarCache';
import { onMount } from 'svelte';
interface Props {
fotoPerfilUrl?: string | null;
nome: string;
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
userId?: string; // ID do usuário para cache
}
let { fotoPerfilUrl, nome, size = 'md' }: Props = $props();
let { fotoPerfilUrl, nome, size = 'md', userId }: Props = $props();
let cachedAvatarUrl = $state<string | null>(null);
let loading = $state(true);
onMount(async () => {
if (fotoPerfilUrl) {
loading = true;
try {
cachedAvatarUrl = await getCachedAvatar(fotoPerfilUrl, userId);
} catch (error) {
console.warn('Erro ao carregar avatar:', error);
cachedAvatarUrl = null;
} finally {
loading = false;
}
} else {
loading = false;
}
});
// Atualizar quando fotoPerfilUrl mudar
$effect(() => {
if (fotoPerfilUrl) {
loading = true;
getCachedAvatar(fotoPerfilUrl, userId)
.then((url) => {
cachedAvatarUrl = url;
loading = false;
})
.catch((error) => {
console.warn('Erro ao carregar avatar:', error);
cachedAvatarUrl = null;
loading = false;
});
} else {
cachedAvatarUrl = null;
loading = false;
}
});
const sizeClasses = {
xs: 'w-8 h-8',
@@ -30,11 +72,25 @@
<div
class={`${sizeClasses[size]} bg-base-200 text-base-content/50 flex items-center justify-center overflow-hidden rounded-full`}
>
{#if fotoPerfilUrl}
{#if loading}
<span class="loading loading-spinner loading-xs"></span>
{:else if cachedAvatarUrl}
<img
src={cachedAvatarUrl}
alt={`Foto de perfil de ${nome}`}
class="h-full w-full object-cover"
loading="lazy"
onerror={() => {
cachedAvatarUrl = null;
}}
/>
{:else if fotoPerfilUrl}
<!-- Fallback: usar URL original se cache falhar -->
<img
src={fotoPerfilUrl}
alt={`Foto de perfil de ${nome}`}
class="h-full w-full object-cover"
loading="lazy"
/>
{:else}
<User size={iconSizes[size]} />