Kontakt stylizacja

This commit is contained in:
dm
2025-11-25 12:19:30 +01:00
parent c23576f052
commit 6b1dad3bb1
11 changed files with 164 additions and 137 deletions

View File

@@ -10,18 +10,18 @@ const footer = yaml.load(
<footer class="f-footer"> <footer class="f-footer">
<div class="f-footer-inner"> <div class="f-footer-inner">
<div class="f-footer-col"> <div class="f-footer-col">
<h3 class="f-footer-col-title">{footer.company.name}</h3> <h3>{footer.company.name}</h3>
<p class="f-footer-col-text"> <p>
{footer.company.address.line1}<br /> {footer.company.address.line1}<br />
{footer.company.address.line2} {footer.company.address.line2}
</p> </p>
</div> </div>
<div class="f-footer-col"> <div class="f-footer-col">
<h4 class="f-footer-col-title">Kontakt</h4> <h4>Kontakt</h4>
{ {
footer.contact.phones.map((phone: string) => ( footer.contact.phones.map((phone: string) => (
<p class="f-footer=col-text"> <p>
{phone} {phone}
</p> </p>
)) ))
@@ -34,7 +34,7 @@ const footer = yaml.load(
</div> </div>
<div class="f-footer-col"> <div class="f-footer-col">
<h4 class="f-footer-col-title">{footer.services.title}</h4> <h4>{footer.services.title}</h4>
<ul> <ul>
{ {
footer.services.items.map((item: any) => ( footer.services.items.map((item: any) => (

View File

@@ -5,7 +5,6 @@ const links = [
{ name: "START", href: "/" }, { name: "START", href: "/" },
{ name: "INTERNET ŚWIATŁOWODOWY", href: "/internet-swiatlowodowy" }, { name: "INTERNET ŚWIATŁOWODOWY", href: "/internet-swiatlowodowy" },
{ name: "INTERNET I TELEWIZJA", href: "/internet-telewizja" }, { name: "INTERNET I TELEWIZJA", href: "/internet-telewizja" },
{ name: "INTERNET RADIOWY", href: "/internet-radiowy" },
{ name: "TELEFON", href: "/telefon" }, { name: "TELEFON", href: "/telefon" },
{ name: "ZASIĘG SIECI", href: "/mapa-zasiegu" }, { name: "ZASIĘG SIECI", href: "/mapa-zasiegu" },
{ name: "KONTAKT", href: "/#contact" }, { name: "KONTAKT", href: "/#contact" },

View File

@@ -2,7 +2,7 @@
import yaml from "js-yaml"; import yaml from "js-yaml";
import fs from "fs"; import fs from "fs";
import MapGoogle from "../maps/MapGoogle.astro"; import MapGoogle from "../maps/MapGoogle.astro";
import "../../styles/contact.css"; // import "../../styles/contact.css";
const data = yaml.load( const data = yaml.load(
fs.readFileSync("./src/content/contact/contact.yaml", "utf8"), fs.readFileSync("./src/content/contact/contact.yaml", "utf8"),
@@ -11,32 +11,31 @@ const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY;
const form = data.form; const form = data.form;
--- ---
<section id="contact" class="fuz-section"> <section id="contact" class="f-section">
<div class="fuz-contact-grid"> <div class="f-contact-grid">
<!-- Lewa kolumna --> <!-- Lewa kolumna -->
<div class="space-y-6"> <div class="f-contact-col-1">
<h2 class="fuz-section-title">{data.title}</h2> <h2>{data.title}</h2>
<div class="fuz-contact-description" set:html={data.description} /> <div class="f-contact-item" set:html={data.description} />
</div> </div>
<!-- Formularz --> <!-- Formularz -->
<div class="fuz-contact-box"> <div class="f-contact-col-2">
<h2 class="fuz-section-title">{data.contactFormTitle}</h2> <h2>{data.contactFormTitle}</h2>
<form id="contactForm" class="f-contact-form">
<form id="contactForm" class="fuz-contact-form"> <div class="f-contact-form-inner">
<div class="grid grid-cols-2 gap-4">
<input <input
type="text" type="text"
name="firstName" name="firstName"
placeholder={form.firstName.placeholder} placeholder={form.firstName.placeholder}
class="fuz-input" class="f-input"
required required
/> />
<input <input
type="text" type="text"
name="lastName" name="lastName"
placeholder={form.lastName.placeholder} placeholder={form.lastName.placeholder}
class="fuz-input" class="f-input"
required required
/> />
</div> </div>
@@ -46,7 +45,7 @@ const form = data.form;
type="email" type="email"
name="email" name="email"
placeholder={form.email.placeholder} placeholder={form.email.placeholder}
class="fuz-input" class="f-input"
required required
autocomplete="email" autocomplete="email"
/> />
@@ -54,7 +53,7 @@ const form = data.form;
type="tel" type="tel"
name="phone" name="phone"
placeholder={form.phone.placeholder} placeholder={form.phone.placeholder}
class="fuz-input" class="f-input"
required required
autocomplete="tel" autocomplete="tel"
/> />
@@ -64,7 +63,7 @@ const form = data.form;
type="text" type="text"
name="subject" name="subject"
placeholder={form.subject.placeholder} placeholder={form.subject.placeholder}
class="fuz-input" class="f-input"
required required
/> />
@@ -72,16 +71,11 @@ const form = data.form;
name="message" name="message"
rows={form.message.rows} rows={form.message.rows}
placeholder={form.message.placeholder} placeholder={form.message.placeholder}
class="fuz-input" class="f-input"
required></textarea> required></textarea>
<label class="fuz-rodo"> <label class="f-rodo">
<input <input type="checkbox" name="rodo" required />
type="checkbox"
name="rodo"
class="mt-1 h-4 w-4"
required
/>
<span> <span>
{form.rodo.label} {form.rodo.label}
<a <a
@@ -92,17 +86,14 @@ const form = data.form;
</span> </span>
</label> </label>
<button <button title={form.submit.title}>
class="btn btn-outline w-full py-3 text-lg"
title={form.submit.title}
>
{form.submit.label} {form.submit.label}
</button> </button>
</form> </form>
</div> </div>
</div> </div>
<div class="fuz-contact-map-wrapper"> <div class="f-contact-map">
<MapGoogle <MapGoogle
apiKey={apiKey} apiKey={apiKey}
lat={data.lat} lat={data.lat}
@@ -115,11 +106,11 @@ const form = data.form;
mapStyleId={data.maps.mapId} mapStyleId={data.maps.mapId}
/> />
</div> </div>
<!-- TODO: Poprawić obslugę błedu wysyłania wiadomości by pojawiał sie toast i ulozyć css -->
<div id="toast" class="fuz-toast"></div> <div id="toast" class="f-toast"></div>
</section> </section>
<!-- ReCaptcha init --> <!-- ReCaptcha -->
<script <script
is:inline is:inline
define:vars={{ siteKey: import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY }} define:vars={{ siteKey: import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY }}
@@ -132,7 +123,7 @@ const form = data.form;
document.head.appendChild(recaptchaScript); document.head.appendChild(recaptchaScript);
</script> </script>
<!-- Formularz + toast -->
<script <script
is:inline is:inline
define:vars={{ define:vars={{
@@ -144,7 +135,7 @@ const form = data.form;
const form = document.getElementById("contactForm"); const form = document.getElementById("contactForm");
const toast = document.getElementById("toast"); const toast = document.getElementById("toast");
if (!form) return; // Safety if (!form) return;
form.addEventListener("submit", async (e) => { form.addEventListener("submit", async (e) => {
if (!form.reportValidity()) return; if (!form.reportValidity()) return;
@@ -182,14 +173,9 @@ const form = data.form;
${message} ${message}
</div> </div>
`; `;
// reset animacji
toast.classList.remove("visible"); toast.classList.remove("visible");
void toast.offsetWidth; // magiczny hack forcing reflow void toast.offsetWidth;
// pokaż
toast.classList.add("visible"); toast.classList.add("visible");
// ukryj po 3s
setTimeout(() => { setTimeout(() => {
toast.classList.remove("visible"); toast.classList.remove("visible");
}, 3000); }, 3000);

View File

@@ -258,7 +258,7 @@ export default function RangeForm() {
{/* CITY */} {/* CITY */}
<div class="autocomplete-wrapper"> <div class="autocomplete-wrapper">
<input <input
class={`fuz-input w-full ${citySuggest.length ? "autocomplete-open" : ""}`} class={`f-input ${citySuggest.length ? "autocomplete-open" : ""}`}
placeholder="Wpisz miejscowość..." placeholder="Wpisz miejscowość..."
value={city} value={city}
onInput={onCityInput} onInput={onCityInput}
@@ -287,7 +287,7 @@ export default function RangeForm() {
{/* STREET */} {/* STREET */}
<div class="autocomplete-wrapper"> <div class="autocomplete-wrapper">
<input <input
class={`fuz-input w-full ${ class={`f-input ${
streetSuggest.length ? "autocomplete-open" : "" streetSuggest.length ? "autocomplete-open" : ""
} ${streetDisabled ? "opacity-50 cursor-not-allowed" : ""}`} } ${streetDisabled ? "opacity-50 cursor-not-allowed" : ""}`}
placeholder={ placeholder={
@@ -322,7 +322,7 @@ export default function RangeForm() {
{/* NUMBER */} {/* NUMBER */}
<input <input
class="fuz-input" class="f-input"
placeholder="np. 1A" placeholder="np. 1A"
value={number} value={number}
onInput={(e) => setNumber(e.target.value)} onInput={(e) => setNumber(e.target.value)}
@@ -336,7 +336,7 @@ export default function RangeForm() {
{/* BUTTON */} {/* BUTTON */}
<button <button
class="btn btn-outline w-full py-3 flex items-center justify-center gap-2" class="btn btn-outline"
disabled={loading} disabled={loading}
> >
{loading ? ( {loading ? (

View File

@@ -7,6 +7,7 @@
@import "./markdown.css"; @import "./markdown.css";
@import "./footer.css"; @import "./footer.css";
@import "./cookie.css"; @import "./cookie.css";
@import "./contact.css";
.grecaptcha-badge { .grecaptcha-badge {
display: none !important; display: none !important;

View File

@@ -1,8 +1,5 @@
.btn { .btn {
@apply inline-flex items-center justify-center @apply inline-flex items-center justify-center font-semibold rounded-lg px-6 py-3 text-base transition-all duration-200 cursor-pointer select-none;
font-semibold rounded-lg px-6 py-3
text-base transition-all duration-200
cursor-pointer select-none;
} }
.btn-primary { .btn-primary {
@@ -36,39 +33,23 @@
background-color: var(--btn-ghost-hover-bg); background-color: var(--btn-ghost-hover-bg);
} }
.fuz-input { .f-input {
width: 100%; @apply w-full py-3 px-4 rounded-xl border border-[var(--f-input-border)] bg-[var(--f-background)] text-[var(--f-text)] transition-all duration-200;
padding: 0.75rem 1rem; /* bardziej eleganckie */
border-radius: 0.75rem;
/* Kolory z theme.css */
background-color: var(--f-background);
color: var(--f-text);
border: 1px solid var(--fuz-border, #d1d5db); /* fallback dla bezpieczeństwa */
box-shadow: 0 1px 2px rgba(0,0,0,0.06);
transition: all 0.2s ease;
} }
/* Hover odcien zależny od border, nie od Tailwind */ .f-input:hover {
.fuz-input:hover { @apply border-[var(--f-text)] opacity-[0.9];
border-color: var(--f-text); }
opacity: 0.9;
.f-input:focus {
@apply outline-none border-[var(--f-header)];
box-shadow: 0 0 0 3px color-mix(in srgb, var(--f-header) 40%, transparent);
} }
/* Placeholder — używa f-text ale jaśniejszy */
.fuz-input::placeholder { .fuz-input::placeholder {
color: color-mix(in srgb, var(--f-text) 40%, transparent); color: color-mix(in srgb, var(--f-text) 40%, transparent);
} }
/* Focus — używa accent */
.fuz-input:focus {
outline: none;
border-color: var(--fuz-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--fuz-accent) 40%, transparent);
}
/* Error */ /* Error */
.fuz-input-error { .fuz-input-error {
border-color: #ff4d4f !important; border-color: #ff4d4f !important;
@@ -107,11 +88,10 @@
/* Dropdown */ /* Dropdown */
.autocomplete-list { .autocomplete-list {
@apply absolute left-0 right-0 z-50 bg-[var(--f-background)] text-[var(--f-text)] @apply absolute left-0 right-0 z-50 bg-[var(--f-background)] text-[var(--f-text)] border border-gray-300 dark:border-slate-700 rounded-b-xl shadow-xl max-h-56 overflow-auto;
border border-gray-300 dark:border-slate-700
rounded-b-xl shadow-xl max-h-56 overflow-auto;
border-top: none; /* ważne */ border-top: none;
/* ważne */
animation: fadeIn 0.12s ease-out; animation: fadeIn 0.12s ease-out;
} }
@@ -125,6 +105,13 @@
} }
@keyframes fadeIn { @keyframes fadeIn {
from { opacity: 0; transform: translateY(-2px); } from {
to { opacity: 1; transform: translateY(0); } opacity: 0;
transform: translateY(-2px);
}
to {
opacity: 1;
transform: translateY(0);
}
} }

View File

@@ -1,68 +1,97 @@
.fuz-contact-grid { @tailwind base;
.f-contact-grid {
@apply grid md:grid-cols-2 gap-10 items-start max-w-7xl mx-auto; @apply grid md:grid-cols-2 gap-10 items-start max-w-7xl mx-auto;
} }
.fuz-contact-box { .f-contact-col-1 {
background-color: var(--f-background); h1,
color: var(--f-text); h2,
h3,
h4 {
@apply f-section-header;
}
} }
.fuz-contact-description h3 { .f-contact-col-2 {
@apply text-xl font-semibold mb-2; @apply bg-[var(--f-background)] text-[var(--f-text)];
color: var(--f-text);
h1,
h2,
h3,
h4 {
@apply f-section-header;
}
} }
.fuz-contact-description h4 { .f-contact-item {
@apply text-xl font-semibold mb-1; @apply space-y-1;
color: var(--f-text);
h1,
h2,
h3,
h4 {
@apply text-2xl font-semibold text-[var(--f-text)] m-0;
}
p {
@apply text-xl mt-4 leading-relaxed text-[var(--f-text)];
}
} }
.fuz-contact-description p { .f-contact-form {
@apply text-xl mt-4 leading-relaxed; @apply space-y-1;
color: var(--f-text);
.f-contact-form-inner {
@apply grid grid-cols-2 gap-4
}
.f-rodo {
@apply flex items-start gap-3 text-lg text-[var(--f-text)];
a {
@apply text-[var(--f-link-text)];
}
a:hover {
@apply text-[var(--fuz-link-hover)];
}
input {
@apply mt-2 h-4 w-4;
}
}
button {
@apply btn btn-outline w-full py-3 text-lg;
}
} }
.fuz-contact-form { .f-contact-map {
@apply space-y-2; @apply w-full max-w-7xl mx-auto mt-6;
} }
/* --- RODO --- */ .s-toast {
.fuz-rodo {
@apply flex items-start gap-3 text-sm;
color: var(--f-text);
}
/* .fuz-rodo a {
color: var(--fuz-accent);
} */
.fuz-rodo a:hover {
color: var(--fuz-accent-hover); /* jeśli masz globalne zmienne */
}
/* --- TOAST --- */
/* --- TOAST SYSTEM (Tailwind version) --- */
.fuz-toast {
@apply fixed top-5 left-1/2 z-[9999] pointer-events-none; @apply fixed top-5 left-1/2 z-[9999] pointer-events-none;
@apply opacity-0 -translate-y-3 -translate-x-1/2 transition-all duration-300 ease-out; @apply opacity-0 -translate-y-3 -translate-x-1/2 transition-all duration-300 ease-out;
} }
.fuz-toast.visible { .f-toast.visible {
@apply opacity-100 translate-y-0; @apply opacity-100 translate-y-0;
} }
.fuz-toast-msg { .f-toast-msg {
@apply px-5 py-3 rounded-xl shadow-lg text-sm; @apply px-5 py-3 rounded-xl shadow-lg text-sm;
background: var(--fuz-accent); background: var(--fuz-accent);
color: var(--fuz-accent-text); color: var(--fuz-accent-text);
} }
.fuz-toast-msg.success { .f-toast-msg.success {
background: var(--fuz-accent); background: var(--fuz-accent);
} }
.fuz-toast-msg.error { .f-toast-msg.error {
@apply bg-red-500 text-white; @apply bg-red-500 text-white;
} }

View File

@@ -4,31 +4,43 @@
} }
.f-footer-inner { .f-footer-inner {
@apply max-w-7xl mx-auto px-6 grid md:grid-cols-3 gap-12; @apply max-w-7xl mx-auto px-6 grid md:grid-cols-3 gap-12;
} }
.f-footer-col { .f-footer-col {
@apply max-w-sm pt-4 space-y-1; @apply max-w-sm pt-4 space-y-1;
}
.f-footer-col-title { h1,
@apply text-xl font-semibold text-[var(--f-header)]; h2,
h3,
h4,
h5,
h6 {
@apply text-xl font-semibold text-[var(--f-header)];
}
} a {
@apply text-[var(--f-link-text)];
}
.f-footer-col-text { a:hover {
@apply text-base; @apply text-[var(--fuz-link-hover)];
}
p {
@apply text-base;
}
} }
.f-footer-copyright { .f-footer-copyright {
@apply text-center py-4 text-base text-[var(--f-text)]; @apply text-center py-4 text-base text-[var(--f-text)];
} }
.f-footer-recaptcha { .f-footer-recaptcha {
@apply text-base; @apply text-base;
a { a {
@apply text-[var(--f-link-text)]; @apply text-[var(--f-link-text)];
} }
} }
} }

View File

@@ -17,10 +17,7 @@
.fuz-map--card { .fuz-map--card {
@apply w-full h-[350px] overflow-hidden mt-8; @apply w-full h-[350px] overflow-hidden mt-8;
} }
.fuz-contact-map-wrapper {
/* @apply col-span-2 w-full border-cyan-200; */
@apply w-full max-w-7xl mx-auto mt-6;
}
.map-range-container { .map-range-container {
@apply sticky top-[67px] z-[999] flex justify-center w-full pointer-events-auto; @apply sticky top-[67px] z-[999] flex justify-center w-full pointer-events-auto;

View File

@@ -1,3 +1,13 @@
@layer components{
.f-section-header{
@apply text-3xl md:text-4xl font-bold mb-6 text-[var(--f-header)];
}
}
.f-section{
@apply pt-10 pb-1 mx-2;
}
.fuz-section { .fuz-section {
@apply py-10 mx-2; @apply py-10 mx-2;
} }
@@ -46,4 +56,4 @@
.dark .fuz-iframe { .dark .fuz-iframe {
background: transparent !important; background: transparent !important;
} }

View File

@@ -38,6 +38,7 @@
--f-text: var(--text2-light); --f-text: var(--text2-light);
--f-link-text: var(--f-header); --f-link-text: var(--f-header);
--f-link-text-hover: var(--f-text2-light);
--btn-background: var(--surface2-light); --btn-background: var(--surface2-light);
--btn-text: var(--text1-light); --btn-text: var(--text1-light);
@@ -49,6 +50,8 @@
--btn-outline-background-hover: var(--surface4-light); --btn-outline-background-hover: var(--surface4-light);
--btn-outline-text-hover: var(--brand-light); --btn-outline-text-hover: var(--brand-light);
--f-input-border: var(--surface1-light);
/* Invert Color */ /* Invert Color */
--f-background-invert: #0d1117; --f-background-invert: #0d1117;
--f-text-invert: #e6edf3; --f-text-invert: #e6edf3;
@@ -82,6 +85,7 @@
--f-text: var(--text1-dark); --f-text: var(--text1-dark);
--f-link-text: var(--f-header); --f-link-text: var(--f-header);
--f-link-text-hover: var(--f-text2-dark);
--btn-background: var(--surface4-dark); --btn-background: var(--surface4-dark);
--btn-text: var(--text1-dark); --btn-text: var(--text1-dark);
@@ -93,6 +97,8 @@
--btn-outline-background-hover: var(--surface4-dark); --btn-outline-background-hover: var(--surface4-dark);
--btn-outline-text-hover: var(--brand-dark); --btn-outline-text-hover: var(--brand-dark);
--f-input-border: var(--surface4-dark);
/* Invert Color */ /* Invert Color */
--f-background-invert: #ffffff; --f-background-invert: #ffffff;
--f-text-invert: #0d0d0d; --f-text-invert: #0d0d0d;