style: badge code_to_icon refactor + core variant-* → preset-* migration

badge ae_comp__badge_obj_view_v2.svelte:
- Replace FA HTML string dict (code_to_html) with Lucide component map
  (code_to_icon) — no FontAwesome dependency for dietary/option icons
- option_1 maps: Biohazard (generic/allergy), Utensils (dietary), Bone,
  Fish, Carrot for specific diets
- option_2 maps: Asterisk (generic flag), Hand (first-time attendee)
- Template: replace {@html option_other_*} with {@const Icon}<Icon /> pattern
- Back-of-badge: shows text label + inline icon

core/ (21 files):
- variant-soft-* → preset-tonal-* (6 variants)
- variant-filled-* → preset-filled-* (6 variants)
- variant-glass-surface → preset-tonal-surface (Skeleton v4 has no glass)
- bare variant-soft → preset-tonal-surface

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-16 14:42:28 -04:00
parent 37c9d830f6
commit 80baaa9d91
22 changed files with 289 additions and 277 deletions

View File

@@ -52,7 +52,7 @@
<h1 class="h2 font-black tracking-tight">Contact Management</h1>
</div>
<button
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
class="btn btn-sm preset-filled-primary font-bold shadow-lg"
onclick={() => show_add_form = !show_add_form}
>
{#if show_add_form}
@@ -78,7 +78,7 @@
</div>
{/if}
<div class="card p-6 shadow-xl variant-glass-surface border border-surface-500/10">
<div class="card p-6 shadow-xl preset-tonal-surface border border-surface-500/10">
<div class="max-w-2xl space-y-1">
<span class="label block text-xs font-bold opacity-75 uppercase tracking-wider ml-1">Search Directory</span>
<div class="flex bg-surface-200-700-token rounded-lg overflow-hidden border border-surface-500/20 shadow-inner group focus-within:ring-2 focus-within:ring-primary-500/50 transition-all">
@@ -91,7 +91,7 @@
bind:value={qry_str}
placeholder="Search by name, title, email, or phone..."
/>
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_contacts} disabled={loading}>
<button class="preset-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_contacts} disabled={loading}>
{#if loading}
<span class="animate-spin text-xl"></span>
{:else}
@@ -107,30 +107,30 @@
<div class="placeholder animate-pulse w-full h-full rounded-2xl"></div>
</div>
{:else if filtered_li.length === 0}
<div class="card p-12 text-center variant-glass-surface border-2 border-dashed border-surface-500/20 rounded-2xl">
<div class="card p-12 text-center preset-tonal-surface border-2 border-dashed border-surface-500/20 rounded-2xl">
<Contact size={48} class="mx-auto mb-4 opacity-20" />
<h3 class="h3 font-bold opacity-50">No Contacts Found</h3>
<p class="opacity-60 max-w-xs mx-auto mt-2">Business and support contacts will appear here.</p>
</div>
{:else}
<div class="card p-6 variant-glass-surface shadow-xl border border-surface-500/10">
<div class="card p-6 preset-tonal-surface shadow-xl border border-surface-500/10">
<h3 class="h4 font-bold border-b border-surface-500/30 pb-2 mb-6 flex items-center gap-2">
<ListFilter size={18} class="text-secondary-500" />
Directory Results
<span class="badge variant-soft-secondary ml-auto">{filtered_li.length} entries</span>
<span class="badge preset-tonal-secondary ml-auto">{filtered_li.length} entries</span>
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{#each filtered_li as con (con.contact_id_random)}
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
<div class="card p-5 space-y-4 preset-tonal-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
<div class="absolute top-4 right-4">
<span class="badge {con.enable ? 'variant-filled-success' : 'variant-filled-error'} text-[8px] uppercase font-bold shadow-sm">
<span class="badge {con.enable ? 'preset-filled-success' : 'preset-filled-error'} text-[8px] uppercase font-bold shadow-sm">
{con.enable ? 'Active' : 'Disabled'}
</span>
</div>
<header class="flex items-center gap-3">
<div class="avatar variant-filled-primary w-12 h-12 flex items-center justify-center rounded-full shadow-inner group-hover:scale-110 transition-transform">
<div class="avatar preset-filled-primary w-12 h-12 flex items-center justify-center rounded-full shadow-inner group-hover:scale-110 transition-transform">
<User size={24} />
</div>
<div class="pr-12">
@@ -150,7 +150,7 @@
</div>
</div>
<a class="btn btn-sm variant-filled-primary font-bold w-full shadow-lg group-hover:brightness-110 transition-all" href="/core/contacts/{con.contact_id_random}">
<a class="btn btn-sm preset-filled-primary font-bold w-full shadow-lg group-hover:brightness-110 transition-all" href="/core/contacts/{con.contact_id_random}">
Manage Contact
</a>
</div>

View File

@@ -50,7 +50,7 @@
<div class="container mx-auto p-4 space-y-6">
<header class="flex flex-wrap justify-between items-center bg-surface-50-900-token p-4 rounded-xl shadow-lg border border-surface-500/10 gap-4">
<div class="flex items-center gap-4">
<a class="btn btn-sm variant-soft-surface shadow-sm" href="/core/contacts">
<a class="btn btn-sm preset-tonal-surface shadow-sm" href="/core/contacts">
<ArrowLeft size={16} />
</a>
<div class="flex items-center gap-3">
@@ -64,14 +64,14 @@
</div>
</div>
<div class="flex gap-2">
<button class="btn btn-sm variant-soft-secondary font-bold shadow-sm" onclick={() => is_editing = !is_editing} disabled={loading}>
<button class="btn btn-sm preset-tonal-secondary font-bold shadow-sm" onclick={() => is_editing = !is_editing} disabled={loading}>
{#if is_editing}
<Eye size={16} class="mr-2" /> View Mode
{:else}
<Edit size={16} class="mr-2" /> Edit Mode
{/if}
</button>
<button class="btn btn-sm variant-soft-error font-bold shadow-sm" onclick={handle_delete} disabled={loading}>
<button class="btn btn-sm preset-tonal-error font-bold shadow-sm" onclick={handle_delete} disabled={loading}>
<Trash2 size={16} class="mr-2" /> Delete
</button>
</div>
@@ -96,7 +96,7 @@
{:else}
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 animate-fade-in">
<div class="lg:col-span-2 space-y-6">
<div class="card p-6 shadow-xl variant-glass-surface border border-surface-500/10 space-y-6">
<div class="card p-6 shadow-xl preset-tonal-surface border border-surface-500/10 space-y-6">
<h3 class="h4 font-bold border-b border-surface-500/30 pb-2 flex items-center gap-2">
<Contact size={20} class="text-primary-500" />
Core Information
@@ -135,7 +135,7 @@
</div>
</div>
<div class="card p-6 shadow-xl variant-glass-surface border border-surface-500/10 space-y-6">
<div class="card p-6 shadow-xl preset-tonal-surface border border-surface-500/10 space-y-6">
<h3 class="h4 font-bold border-b border-surface-500/30 pb-2 flex items-center gap-2">
<Phone size={20} class="text-secondary-500" />
Communication & Social
@@ -172,7 +172,7 @@
</div>
<div class="space-y-6">
<div class="card p-6 shadow-xl variant-glass-surface border border-surface-500/10 space-y-6">
<div class="card p-6 shadow-xl preset-tonal-surface border border-surface-500/10 space-y-6">
<h3 class="h4 font-bold border-b border-surface-500/30 pb-2 flex items-center gap-2">
<ShieldCheck size={20} class="text-warning-500" />
Status & Flags
@@ -180,26 +180,26 @@
<div class="space-y-4">
<div class="flex justify-between items-center p-3 bg-black/5 rounded-lg">
<span class="text-sm font-bold opacity-75">Enabled</span>
<span class="badge {contact.enable ? 'variant-filled-success' : 'variant-filled-error'} px-4 py-1 shadow-sm">
<span class="badge {contact.enable ? 'preset-filled-success' : 'preset-filled-error'} px-4 py-1 shadow-sm">
{contact.enable ? 'ACTIVE' : 'DISABLED'}
</span>
</div>
<div class="flex justify-between items-center p-3 bg-black/5 rounded-lg">
<span class="text-sm font-bold opacity-75">Hidden</span>
<span class="badge {contact.hide ? 'variant-filled-warning' : 'variant-filled-surface'} px-4 py-1 shadow-sm">
<span class="badge {contact.hide ? 'preset-filled-warning' : 'preset-filled-surface'} px-4 py-1 shadow-sm">
{contact.hide ? 'YES' : 'NO'}
</span>
</div>
<div class="flex justify-between items-center p-3 bg-black/5 rounded-lg">
<span class="text-sm font-bold opacity-75">Priority</span>
<span class="badge {contact.priority ? 'variant-filled-secondary' : 'variant-filled-surface'} px-4 py-1 shadow-sm">
<span class="badge {contact.priority ? 'preset-filled-secondary' : 'preset-filled-surface'} px-4 py-1 shadow-sm">
{contact.priority ? 'YES' : 'NO'}
</span>
</div>
</div>
</div>
<div class="card p-5 variant-soft-surface shadow-inner border border-surface-500/10 space-y-3">
<div class="card p-5 preset-tonal-surface shadow-inner border border-surface-500/10 space-y-3">
<p class="text-[10px] uppercase font-black opacity-40 tracking-widest border-b border-surface-500/20 pb-1">System Audit</p>
<div class="space-y-2 text-[10px] font-mono opacity-60">
<p class="flex justify-between"><span>ID:</span> <span class="text-primary-500 font-bold">{contact.contact_id_random}</span></p>

View File

@@ -105,7 +105,7 @@
}
</script>
<form onsubmit={handleSubmit} class="card p-6 space-y-6 shadow-xl variant-glass-surface">
<form onsubmit={handleSubmit} class="card p-6 space-y-6 shadow-xl preset-tonal-surface">
<header class="flex justify-between items-center border-b border-surface-500/30 pb-4">
<h3 class="h3 flex items-center gap-2">
<UserPlus size={24} />
@@ -113,11 +113,11 @@
</h3>
<div class="flex gap-2">
{#if onCancel}
<button type="button" class="btn btn-sm variant-soft-surface" onclick={onCancel}>
<button type="button" class="btn btn-sm preset-tonal-surface" onclick={onCancel}>
<X size={16} class="mr-1" /> Cancel
</button>
{/if}
<button type="submit" class="btn btn-sm variant-filled-primary font-bold shadow-lg" disabled={is_loading}>
<button type="submit" class="btn btn-sm preset-filled-primary font-bold shadow-lg" disabled={is_loading}>
{#if is_loading}
<span class="animate-spin mr-2"></span>
{:else}
@@ -129,7 +129,7 @@
</header>
{#if error_msg}
<aside class="alert variant-filled-error">
<aside class="alert preset-filled-error">
<div class="alert-message">
<p>{error_msg}</p>
</div>
@@ -143,17 +143,17 @@
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-title">Title / Name</label>
<input class="input variant-filled-surface rounded-lg placeholder-surface-400 p-2" id="contact-title" type="text" bind:value={formData.title} required placeholder="Business Office" />
<input class="input preset-filled-surface rounded-lg placeholder-surface-400 p-2" id="contact-title" type="text" bind:value={formData.title} required placeholder="Business Office" />
</div>
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-tagline">Tagline</label>
<input class="input variant-filled-surface rounded-lg placeholder-surface-400 p-2" id="contact-tagline" type="text" bind:value={formData.tagline} placeholder="Primary contact for business inquiries" />
<input class="input preset-filled-surface rounded-lg placeholder-surface-400 p-2" id="contact-tagline" type="text" bind:value={formData.tagline} placeholder="Primary contact for business inquiries" />
</div>
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-email">Email Address</label>
<div class="input-group input-group-divider grid-cols-[auto_1fr] variant-filled-surface rounded-lg overflow-hidden">
<div class="input-group input-group-divider grid-cols-[auto_1fr] preset-filled-surface rounded-lg overflow-hidden">
<div class="input-group-shim"><Mail size={16} /></div>
<input class="bg-transparent border-0 ring-0 focus:ring-0 placeholder-surface-400 p-2" id="contact-email" type="email" bind:value={formData.email} placeholder="contact@example.com" />
</div>
@@ -167,14 +167,14 @@
<div class="grid grid-cols-2 gap-2">
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-phone-mobile">Mobile Phone</label>
<div class="input-group input-group-divider grid-cols-[auto_1fr] variant-filled-surface rounded-lg overflow-hidden">
<div class="input-group input-group-divider grid-cols-[auto_1fr] preset-filled-surface rounded-lg overflow-hidden">
<div class="input-group-shim"><Phone size={16} /></div>
<input class="bg-transparent border-0 ring-0 focus:ring-0 placeholder-surface-400 p-2" id="contact-phone-mobile" type="tel" bind:value={formData.phone_mobile} placeholder="+1..." />
</div>
</div>
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-phone-office">Office Phone</label>
<div class="input-group input-group-divider grid-cols-[auto_1fr] variant-filled-surface rounded-lg overflow-hidden">
<div class="input-group input-group-divider grid-cols-[auto_1fr] preset-filled-surface rounded-lg overflow-hidden">
<div class="input-group-shim"><Phone size={16} /></div>
<input class="bg-transparent border-0 ring-0 focus:ring-0 placeholder-surface-400 p-2" id="contact-phone-office" type="tel" bind:value={formData.phone_office} placeholder="+1..." />
</div>
@@ -183,7 +183,7 @@
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-website">Website URL</label>
<div class="input-group input-group-divider grid-cols-[auto_1fr] variant-filled-surface rounded-lg overflow-hidden">
<div class="input-group input-group-divider grid-cols-[auto_1fr] preset-filled-surface rounded-lg overflow-hidden">
<div class="input-group-shim"><Globe size={16} /></div>
<input class="bg-transparent border-0 ring-0 focus:ring-0 placeholder-surface-400 p-2" id="contact-website" type="url" bind:value={formData.website_url} placeholder="https://..." />
</div>
@@ -196,7 +196,7 @@
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-linkedin">LinkedIn URL</label>
<div class="input-group input-group-divider grid-cols-[auto_1fr] variant-filled-surface rounded-lg overflow-hidden">
<div class="input-group input-group-divider grid-cols-[auto_1fr] preset-filled-surface rounded-lg overflow-hidden">
<div class="input-group-shim"><Linkedin size={16} /></div>
<input class="bg-transparent border-0 ring-0 focus:ring-0 placeholder-surface-400 p-2" id="contact-linkedin" type="url" bind:value={formData.linkedin_url} placeholder="https://linkedin.com/in/..." />
</div>
@@ -205,14 +205,14 @@
<div class="grid grid-cols-2 gap-2">
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-facebook">Facebook URL</label>
<div class="input-group input-group-divider grid-cols-[auto_1fr] variant-filled-surface rounded-lg overflow-hidden">
<div class="input-group input-group-divider grid-cols-[auto_1fr] preset-filled-surface rounded-lg overflow-hidden">
<div class="input-group-shim"><Facebook size={16} /></div>
<input class="bg-transparent border-0 ring-0 focus:ring-0 placeholder-surface-400 p-2" id="contact-facebook" type="url" bind:value={formData.facebook_url} placeholder="https://facebook.com/..." />
</div>
</div>
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-instagram">Instagram URL</label>
<div class="input-group input-group-divider grid-cols-[auto_1fr] variant-filled-surface rounded-lg overflow-hidden">
<div class="input-group input-group-divider grid-cols-[auto_1fr] preset-filled-surface rounded-lg overflow-hidden">
<div class="input-group-shim"><Instagram size={16} /></div>
<input class="bg-transparent border-0 ring-0 focus:ring-0 placeholder-surface-400 p-2" id="contact-instagram" type="url" bind:value={formData.instagram_url} placeholder="https://instagram.com/..." />
</div>
@@ -241,13 +241,13 @@
<div class="space-y-1">
<label class="label text-xs font-bold opacity-75" for="contact-notes">Internal Notes</label>
<textarea class="textarea variant-filled-surface rounded-lg placeholder-surface-400 p-2" id="contact-notes" rows="2" bind:value={formData.notes} placeholder="Additional details..."></textarea>
<textarea class="textarea preset-filled-surface rounded-lg placeholder-surface-400 p-2" id="contact-notes" rows="2" bind:value={formData.notes} placeholder="Additional details..."></textarea>
</div>
</fieldset>
</div>
<footer class="flex justify-end gap-2 border-t border-surface-500/30 pt-4">
<button type="submit" class="btn variant-filled-primary font-bold shadow-lg w-full md:w-auto" disabled={is_loading}>
<button type="submit" class="btn preset-filled-primary font-bold shadow-lg w-full md:w-auto" disabled={is_loading}>
{#if is_loading}
<span class="animate-spin mr-2"></span>
{/if}