feat: add contact component
- update css - update data.json - update types
This commit is contained in:
154
src/lib/components/Contact.svelte
Normal file
154
src/lib/components/Contact.svelte
Normal file
@@ -0,0 +1,154 @@
|
||||
<script lang="ts">
|
||||
import type { Contact } from '$lib/types/data';
|
||||
|
||||
let { title, anchorId, subtitle, form }: Contact = $props();
|
||||
|
||||
let emailData = $state({
|
||||
to: "frodo06@gmx.de",
|
||||
subject: "",
|
||||
message: ""
|
||||
});
|
||||
|
||||
function handleSubmit(event: SubmitEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
const subject = encodeURIComponent(emailData.subject);
|
||||
const body = encodeURIComponent(emailData.message);
|
||||
|
||||
// Construct the mailto URL
|
||||
const mailtoUrl = `mailto:${emailData.to}?subject=${subject}&body=${body}`;
|
||||
|
||||
// Open the user's email client
|
||||
window.location.href = mailtoUrl;
|
||||
}
|
||||
</script>
|
||||
|
||||
<section id={anchorId}>
|
||||
<h2>{title}</h2>
|
||||
{#if (subtitle)}
|
||||
<p>{subtitle}</p>
|
||||
{/if}
|
||||
<form onsubmit={handleSubmit} class="flex flex-col gap-4">
|
||||
<p>{form.title}</p>
|
||||
<input
|
||||
bind:value={emailData.subject}
|
||||
placeholder={form.subjectPlaceholder}
|
||||
required
|
||||
/>
|
||||
|
||||
<textarea
|
||||
bind:value={emailData.message}
|
||||
placeholder={form.messagePlaceholder}
|
||||
rows="5"
|
||||
></textarea>
|
||||
|
||||
<button type="submit">
|
||||
{form.submit}
|
||||
</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
padding: 5rem 1rem;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
padding: 6rem 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: unset;
|
||||
|
||||
font-size: 1.875rem;
|
||||
text-align: center;
|
||||
|
||||
color: transparent;
|
||||
background-image: var(--color-headline-background-image);
|
||||
background-clip: text;
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: unset;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
font-size: 1.125rem;
|
||||
text-align: center;
|
||||
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
@media (min-width: 768px) {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
|
||||
max-width: 32rem;
|
||||
width: 100%;
|
||||
padding: 2rem;
|
||||
background-color: var(--color-contact-background);
|
||||
border: 1px solid var(--color-contact-background-border);
|
||||
border-radius: 1rem;
|
||||
color: var(--color-contact-text);
|
||||
|
||||
p {
|
||||
margin-bottom: 1rem;
|
||||
color: var(--color-contact-text);
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
padding: 1rem;
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
background-color: var(--color-contact-background-input);
|
||||
border: 1px solid var(--color-contact-background-border);
|
||||
border-radius: 0.75rem;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border: 1px solid var(--color-contact-background-input-border-focused);
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
appearance: none;
|
||||
padding: 1rem 1.5rem;
|
||||
background-image: var(--color-contact-background-button);
|
||||
border: unset;
|
||||
border-radius: 0.75rem;
|
||||
color: var(--color-contact-text);
|
||||
font-size: 1.125rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.5;
|
||||
transition: translate ease-in-out 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-image: var(--color-contact-background-button-hover);
|
||||
translate: 0 -0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -184,5 +184,16 @@
|
||||
"items": ["SEO", "Accessibility", "KI-basierte Tools"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"contact": {
|
||||
"title": "Kontakt",
|
||||
"anchorId": "contact",
|
||||
"subtitle": "Hinterlassen Sie mir eine Nachricht",
|
||||
"form": {
|
||||
"title": "Schneller Kontakt",
|
||||
"subjectPlaceholder": "Dein Name",
|
||||
"messagePlaceholder": "Deine Nachricht",
|
||||
"submit": "Email öffnen"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,22 @@
|
||||
|
||||
--color-card-box-shadow: 0 0 0 0 rgba(0, 0, 0, 0), oklab(0.623 -0.0378409 -0.210628 / 0.5) 0 25px 50px -12px;
|
||||
|
||||
--color-contact-background: oklch(0.278 0.033 256.848);
|
||||
--color-contact-background-border: oklab(0.623 -0.0378409 -0.210628 / 0.3);
|
||||
--color-contact-text: oklch(0.967 0.003 264.542);
|
||||
--color-contact-background-input: oklch(0.373 0.034 259.733);
|
||||
--color-contact-background-input-border-focused: oklch(70.7% 0.165 254.624);
|
||||
--color-contact-background-button: linear-gradient(
|
||||
to right,
|
||||
oklch(0.623 0.214 259.815) 0%,
|
||||
oklch(0.511 0.262 276.966) 100%
|
||||
);
|
||||
--color-contact-background-button-hover: linear-gradient(
|
||||
to right,
|
||||
oklch(0.546 0.245 262.881) 0%,
|
||||
oklch(0.457 0.24 277.023) 100%
|
||||
);
|
||||
|
||||
--z-index-header: 50;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ export type Data = {
|
||||
profile: Profile;
|
||||
projects: Projects;
|
||||
skills: Skills;
|
||||
contact: Contact;
|
||||
};
|
||||
|
||||
export type Header = {
|
||||
@@ -60,8 +61,22 @@ export type Skills = {
|
||||
|
||||
export type SkillEntry = {
|
||||
title: string;
|
||||
icon: LucideIconName;
|
||||
icon: string;
|
||||
items: string[];
|
||||
};
|
||||
|
||||
export type LucideIconName = keyof typeof icons;
|
||||
|
||||
export type Contact = {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
anchorId: string;
|
||||
form: ContactForm;
|
||||
};
|
||||
|
||||
export type ContactForm = {
|
||||
title: string;
|
||||
subjectPlaceholder: string;
|
||||
messagePlaceholder: string;
|
||||
submit: string;
|
||||
};
|
||||
Reference in New Issue
Block a user