style: format NewContactModal component

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-12-14 16:18:00 +01:00
parent 6ce385a42e
commit d76f2ddcf1
2 changed files with 323 additions and 7 deletions

View file

@ -34,6 +34,22 @@
let country = $state('');
let notes = $state('');
// Social Media
let linkedin = $state('');
let twitter = $state('');
let facebook = $state('');
let instagram = $state('');
let xing = $state('');
let github = $state('');
let youtube = $state('');
let tiktok = $state('');
let telegram = $state('');
let whatsapp = $state('');
let signal = $state('');
let discord = $state('');
let bluesky = $state('');
let socialSectionOpen = $state(false);
const initials = $derived(() => {
const f = firstName?.[0] || '';
const l = lastName?.[0] || '';
@ -120,6 +136,20 @@
postalCode: postalCode || null,
country: country || null,
notes: notes || null,
// Social Media
linkedin: linkedin || null,
twitter: twitter || null,
facebook: facebook || null,
instagram: instagram || null,
xing: xing || null,
github: github || null,
youtube: youtube || null,
tiktok: tiktok || null,
telegram: telegram || null,
whatsapp: whatsapp || null,
signal: signal || null,
discord: discord || null,
bluesky: bluesky || null,
});
// Upload photo if selected
@ -503,6 +533,214 @@
></textarea>
</section>
<!-- Social Media Section (Collapsible) -->
<section class="form-section">
<button
type="button"
class="section-header section-header-toggle"
onclick={() => (socialSectionOpen = !socialSectionOpen)}
>
<div class="section-icon">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"
/>
</svg>
</div>
<h2 class="section-title">Social Media</h2>
<svg
class="chevron-icon"
class:chevron-open={socialSectionOpen}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
</button>
{#if socialSectionOpen}
<div class="social-grid">
<div class="form-field">
<label for="linkedin" class="label social-label">
<span class="social-icon-label">in</span>
LinkedIn
</label>
<input
id="linkedin"
type="url"
bind:value={linkedin}
class="input"
placeholder="https://linkedin.com/in/..."
/>
</div>
<div class="form-field">
<label for="twitter" class="label social-label">
<span class="social-icon-label">X</span>
Twitter / X
</label>
<input
id="twitter"
type="text"
bind:value={twitter}
class="input"
placeholder="@username"
/>
</div>
<div class="form-field">
<label for="facebook" class="label social-label">
<span class="social-icon-label">f</span>
Facebook
</label>
<input
id="facebook"
type="url"
bind:value={facebook}
class="input"
placeholder="https://facebook.com/..."
/>
</div>
<div class="form-field">
<label for="instagram" class="label social-label">
<span class="social-icon-label">ig</span>
Instagram
</label>
<input
id="instagram"
type="text"
bind:value={instagram}
class="input"
placeholder="@username"
/>
</div>
<div class="form-field">
<label for="xing" class="label social-label">
<span class="social-icon-label">xi</span>
Xing
</label>
<input
id="xing"
type="url"
bind:value={xing}
class="input"
placeholder="https://xing.com/profile/..."
/>
</div>
<div class="form-field">
<label for="github" class="label social-label">
<span class="social-icon-label">gh</span>
GitHub
</label>
<input
id="github"
type="text"
bind:value={github}
class="input"
placeholder="username"
/>
</div>
<div class="form-field">
<label for="youtube" class="label social-label">
<span class="social-icon-label">yt</span>
YouTube
</label>
<input
id="youtube"
type="url"
bind:value={youtube}
class="input"
placeholder="https://youtube.com/@..."
/>
</div>
<div class="form-field">
<label for="tiktok" class="label social-label">
<span class="social-icon-label">tt</span>
TikTok
</label>
<input
id="tiktok"
type="text"
bind:value={tiktok}
class="input"
placeholder="@username"
/>
</div>
<div class="form-field">
<label for="telegram" class="label social-label">
<span class="social-icon-label">tg</span>
Telegram
</label>
<input
id="telegram"
type="text"
bind:value={telegram}
class="input"
placeholder="@username"
/>
</div>
<div class="form-field">
<label for="whatsapp" class="label social-label">
<span class="social-icon-label">wa</span>
WhatsApp
</label>
<input
id="whatsapp"
type="tel"
bind:value={whatsapp}
class="input"
placeholder="+49..."
/>
</div>
<div class="form-field">
<label for="signal" class="label social-label">
<span class="social-icon-label">sg</span>
Signal
</label>
<input
id="signal"
type="tel"
bind:value={signal}
class="input"
placeholder="+49..."
/>
</div>
<div class="form-field">
<label for="discord" class="label social-label">
<span class="social-icon-label">dc</span>
Discord
</label>
<input
id="discord"
type="text"
bind:value={discord}
class="input"
placeholder="username#1234"
/>
</div>
<div class="form-field">
<label for="bluesky" class="label social-label">
<span class="social-icon-label">bs</span>
Bluesky
</label>
<input
id="bluesky"
type="text"
bind:value={bluesky}
class="input"
placeholder="@handle.bsky.social"
/>
</div>
</div>
{/if}
</section>
<!-- Action Buttons -->
<div class="actions">
<button type="button" onclick={onClose} class="btn btn-secondary"> Abbrechen </button>
@ -957,5 +1195,66 @@
.actions {
flex-direction: column-reverse;
}
.social-grid {
grid-template-columns: 1fr;
}
}
/* Social Media Section */
.section-header-toggle {
width: 100%;
background: none;
border: none;
cursor: pointer;
border-bottom: 1px solid hsl(var(--color-border) / 0.5);
margin-bottom: 0;
}
.section-header-toggle:hover {
background: hsl(var(--color-surface-hover) / 0.3);
margin: 0 -1rem;
padding: 0 1rem 0.625rem;
width: calc(100% + 2rem);
border-radius: 0.5rem 0.5rem 0 0;
}
.chevron-icon {
width: 1rem;
height: 1rem;
margin-left: auto;
color: hsl(var(--color-muted-foreground));
transition: transform 0.2s ease;
}
.chevron-open {
transform: rotate(180deg);
}
.social-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
padding-top: 0.75rem;
}
.social-label {
display: flex;
align-items: center;
gap: 0.5rem;
}
.social-icon-label {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.25rem;
height: 1.25rem;
border-radius: 0.25rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
font-size: 0.625rem;
font-weight: 700;
text-transform: lowercase;
}
</style>

View file

@ -13,6 +13,21 @@
networkStore.setSearch(contactsFilterStore.searchQuery);
});
// Refocus view when search results change
let previousNodeCount = $state(0);
$effect(() => {
const currentNodeCount = networkStore.nodes.length;
const hasSearch = contactsFilterStore.searchQuery.length > 0;
// If search is active and node count changed, reset zoom to show all results
if (hasSearch && currentNodeCount !== previousNodeCount && currentNodeCount > 0) {
setTimeout(() => {
graphComponent?.resetZoom();
}, 100);
}
previousNodeCount = currentNodeCount;
});
let graphComponent: NetworkGraph;
let graphContainer: HTMLDivElement;
@ -179,10 +194,10 @@
flex-direction: column;
}
/* Floating Controls */
/* Floating Controls - positioned above QuickInputBar and PillNav */
.controls-wrapper {
position: absolute;
top: 1rem;
position: fixed;
bottom: calc(140px + env(safe-area-inset-bottom));
left: 50%;
transform: translateX(-50%);
z-index: 10;
@ -192,7 +207,7 @@
/* Error Banner */
.error-banner {
position: absolute;
top: 5rem;
top: 1rem;
left: 50%;
transform: translateX(-50%);
z-index: 10;
@ -219,9 +234,11 @@
/* Modal Sidebar Wrapper - Override modal positioning */
.modal-sidebar-wrapper {
position: fixed;
top: 5rem; /* Below the pill nav */
top: 1rem;
right: 1rem;
bottom: 1rem;
bottom: calc(
200px + env(safe-area-inset-bottom)
); /* Above controls + QuickInputBar + PillNav */
width: 400px;
max-width: calc(100vw - 2rem);
z-index: 50;
@ -291,7 +308,7 @@
@media (max-width: 768px) {
.controls-wrapper {
top: 1rem;
bottom: calc(160px + env(safe-area-inset-bottom));
width: calc(100% - 2rem);
max-width: none;
}