From 5cd550c5a1f261c5401090ce5162179c723388f2 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Fri, 12 Dec 2025 02:40:44 +0100 Subject: [PATCH] fix(contacts): improve ContactList and FilterBar styling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update ContactList with better spacing and layout - Improve FilterBar responsiveness - Adjust app.css for new component styles 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- apps/contacts/apps/web/src/app.css | 30 +- .../web/src/lib/components/ContactList.svelte | 205 ++------ .../web/src/lib/components/FilterBar.svelte | 468 ++++++++++++------ 3 files changed, 392 insertions(+), 311 deletions(-) diff --git a/apps/contacts/apps/web/src/app.css b/apps/contacts/apps/web/src/app.css index 0c2d643fa..3c4caffdd 100644 --- a/apps/contacts/apps/web/src/app.css +++ b/apps/contacts/apps/web/src/app.css @@ -37,10 +37,10 @@ @layer components { /* Card styles */ .card { - background-color: hsl(var(--card)); + background-color: var(--color-card); border-radius: var(--radius-lg); padding: var(--spacing-lg); - border: 1px solid hsl(var(--border)); + border: 1px solid var(--color-border); transition: transform var(--transition-base), box-shadow var(--transition-base); } @@ -56,14 +56,14 @@ gap: var(--spacing-md); padding: var(--spacing-md); border-radius: var(--radius-md); - border: 1px solid hsl(var(--border)); - background-color: hsl(var(--card)); + border: 1px solid var(--color-border); + background-color: var(--color-card); transition: all var(--transition-base); } .contact-card:hover { - border-color: hsl(var(--primary)); - background-color: hsl(var(--accent)); + border-color: var(--color-primary); + background-color: var(--color-accent); } /* Avatar styles */ @@ -72,8 +72,8 @@ height: 56px; min-width: 56px; border-radius: var(--radius-full); - background-color: hsl(var(--primary)); - color: hsl(var(--primary-foreground)); + background-color: var(--color-primary); + color: var(--color-primary-foreground); display: flex; align-items: center; justify-content: center; @@ -98,27 +98,27 @@ } .btn-primary { - background: hsl(var(--primary)); - color: hsl(var(--primary-foreground)); + background: var(--color-primary); + color: var(--color-primary-foreground); } .btn-primary:hover { - background: hsl(var(--primary) / 0.9); + filter: brightness(0.9); } /* Input styles */ .input { padding: var(--spacing-sm) var(--spacing-md); - border: 2px solid hsl(var(--border)); + border: 2px solid var(--color-border); border-radius: var(--radius-md); - background-color: hsl(var(--background)); - color: hsl(var(--foreground)); + background-color: var(--color-background); + color: var(--color-foreground); transition: border-color var(--transition-fast); } .input:focus { outline: none; - border-color: hsl(var(--primary)); + border-color: var(--color-primary); } /* Tag styles */ diff --git a/apps/contacts/apps/web/src/lib/components/ContactList.svelte b/apps/contacts/apps/web/src/lib/components/ContactList.svelte index 6bd22cbc7..cb5e4e3d2 100644 --- a/apps/contacts/apps/web/src/lib/components/ContactList.svelte +++ b/apps/contacts/apps/web/src/lib/components/ContactList.svelte @@ -4,12 +4,8 @@ import { contactsStore } from '$lib/stores/contacts.svelte'; import { viewModeStore } from '$lib/stores/view-mode.svelte'; import { goto } from '$app/navigation'; - import ViewModeToggle from '$lib/components/ViewModeToggle.svelte'; - import SortToggle, { type SortField } from '$lib/components/SortToggle.svelte'; - import FilterBar, { - type ContactFilter, - type BirthdayFilter, - } from '$lib/components/FilterBar.svelte'; + import type { ContactFilter, BirthdayFilter } from '$lib/components/FilterBar.svelte'; + import ContactsToolbar, { type SortField } from '$lib/components/ContactsToolbar.svelte'; import ContactListView from '$lib/components/views/ContactListView.svelte'; import ContactGridView from '$lib/components/views/ContactGridView.svelte'; import ContactAlphabetView from '$lib/components/views/ContactAlphabetView.svelte'; @@ -32,9 +28,6 @@ let birthdayFilter = $state('all'); let selectedCompany = $state(null); - // Count favorites for quick filter button - let favoritesCount = $derived(contactsStore.contacts.filter((c) => c.isFavorite).length); - // Batch selection state let selectionMode = $state(false); let selectedIds = $state>(new Set()); @@ -277,32 +270,7 @@
-
-

{$_('contacts.title')}

-
- - - - + - {$_('contacts.new')} - -
-
+

{$_('contacts.title')}

{#if selectionMode} @@ -381,79 +349,55 @@
{/if} - -
-
- - - - -
- - - { - selectedTagId = id; - if (id) { - contactsStore.setTagId(id); - } else { - contactsStore.setTagId(undefined); - } - contactsStore.loadContacts(); - }} - {contactFilter} - onContactFilterChange={(f) => (contactFilter = f)} - {birthdayFilter} - onBirthdayFilterChange={(f) => (birthdayFilter = f)} - {selectedCompany} - onCompanyChange={(c) => (selectedCompany = c)} + +
+ - (sortField = v)} /> - + + +
+ + (sortField = v)} + {contactFilter} + onContactFilterChange={(f) => (contactFilter = f)} + {birthdayFilter} + onBirthdayFilterChange={(f) => (birthdayFilter = f)} + {selectedTagId} + onTagChange={(id) => { + selectedTagId = id; + if (id) { + contactsStore.setTagId(id); + } else { + contactsStore.setTagId(undefined); + } + contactsStore.loadContacts(); + }} + {selectedCompany} + onCompanyChange={(c) => (selectedCompany = c)} + {selectionMode} + onToggleSelectionMode={toggleSelectionMode} + /> + {#if contactsStore.loading} {#if viewModeStore.mode === 'grid'} @@ -565,57 +509,6 @@ color: hsl(var(--color-error)); } - /* Favorites Quick Filter Button */ - .favorites-quick-btn { - display: flex; - align-items: center; - gap: 0.375rem; - padding: 0.5rem 0.75rem; - background: hsl(var(--background) / 0.75); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border: 1px solid hsl(var(--border) / 0.5); - border-radius: 9999px; - color: hsl(var(--muted-foreground)); - cursor: pointer; - transition: all 0.2s ease; - font-size: 0.875rem; - font-weight: 500; - } - - .favorites-quick-btn:hover { - color: hsl(var(--foreground)); - border-color: hsl(var(--border)); - } - - .favorites-quick-btn.active { - color: #ef4444; - border-color: #ef4444 / 0.5; - background: hsl(0 84% 60% / 0.1); - } - - .favorites-quick-btn.active:hover { - background: hsl(0 84% 60% / 0.15); - } - - .favorites-count { - display: flex; - align-items: center; - justify-content: center; - min-width: 1.25rem; - height: 1.25rem; - padding: 0 0.375rem; - font-size: 0.6875rem; - font-weight: 600; - background: hsl(var(--muted)); - border-radius: 9999px; - } - - .favorites-quick-btn.active .favorites-count { - background: #ef4444; - color: white; - } - /* Infinite scroll */ .load-more-trigger { height: 1px; diff --git a/apps/contacts/apps/web/src/lib/components/FilterBar.svelte b/apps/contacts/apps/web/src/lib/components/FilterBar.svelte index 2eb3b305d..43f0f5c2b 100644 --- a/apps/contacts/apps/web/src/lib/components/FilterBar.svelte +++ b/apps/contacts/apps/web/src/lib/components/FilterBar.svelte @@ -16,6 +16,8 @@ onBirthdayFilterChange: (filter: BirthdayFilter) => void; selectedCompany: string | null; onCompanyChange: (company: string | null) => void; + /** When embedded in a toolbar, renders as just a button without background container */ + embedded?: boolean; } let { @@ -28,6 +30,7 @@ onBirthdayFilterChange, selectedCompany, onCompanyChange, + embedded = false, }: Props = $props(); let tags = $state([]); @@ -81,37 +84,150 @@ }); -
- - +{#if embedded} + +
+ - - {#if activeFilterCount > 0 && !showFilters} -
- {#if selectedTagId} - {@const tag = tags.find((t) => t.id === selectedTagId)} - {#if tag} - + {/if} +
+ {/if} +
+{:else} +
+ + + + + {#if activeFilterCount > 0 && !showFilters} +
+ {#if selectedTagId} + {@const tag = tags.find((t) => t.id === selectedTagId)} + {#if tag} + + {/if} + {/if} + {#if contactFilter !== 'all' && contactFilter !== 'favorites'} + {/if} - {/if} - {#if contactFilter !== 'all' && contactFilter !== 'favorites'} - + {/if} + {#if selectedCompany} + + {/if} + - {/if} - {#if birthdayFilter !== 'all'} - - {/if} - {#if selectedCompany} - - {/if} - -
- {/if} - - - {#if showFilters} -
- -
- -
+ {/if} - -
- - -
- - -
- - -
- - - {#if companies.length > 0} + + {#if showFilters} +
+
- +
- {/if} - - {#if activeFilterCount > 0} - - {/if} -
- {/if} -
+ +
+ + +
+ + +
+ + +
+ + + {#if companies.length > 0} +
+ + +
+ {/if} + + + {#if activeFilterCount > 0} + + {/if} +
+ {/if} +
+{/if}