rework components

This commit is contained in:
Kuba Pyla
2026-05-20 02:58:48 +02:00
parent 9d4f32ecf0
commit 1aa0a96e95
27 changed files with 527 additions and 172 deletions
+4 -4
View File
@@ -1,7 +1,8 @@
import type {Metadata} from 'next';
import {DemoBrowser} from '@/components/DemoBrowser';
import {DemoSubnav} from '@/components/DemoSubnav';
import {SectionHeader} from '@/components/SectionHeader';
import {demoContent} from '@/config/content';
import {orderedDemos} from '@/config/content';
export const metadata: Metadata = {
title: 'Dema konfiguratorów 3D | Ultifide',
@@ -9,8 +10,6 @@ export const metadata: Metadata = {
};
export default function DemosPage() {
const demos = [demoContent.desk, demoContent.room, demoContent.door];
return (
<main>
<section className="sectionBand sectionBand--light demosPage">
@@ -20,7 +19,8 @@ export default function DemosPage() {
title="Sprawdź konfiguratory 3D w jednym miejscu"
description="Wybierz demo z listy, przetestuj je od razu w podglądzie, a potem przejdź do strony z opisem zastosowania i korzyści."
/>
<DemoBrowser demos={demos} />
<DemoSubnav demos={orderedDemos} hrefType="browser" />
<DemoBrowser demos={orderedDemos} />
</div>
</section>
</main>
+14
View File
@@ -0,0 +1,14 @@
import type {Metadata} from 'next';
import {DemoPage} from '@/components/DemoPage';
import {demoContent} from '@/config/content';
import messages from '../../../../messages/pl.json';
export const metadata: Metadata = {
title: messages.metadata.deskTitle,
description:
'Poznaj konfigurator 3D, który zwiększa konwersję i pozwala klientom tworzyć własne biurka regulowane w czasie rzeczywistym.'
};
export default function DeskDemoPage() {
return <DemoPage demo={demoContent.desk} />;
}
+2 -11
View File
@@ -1,14 +1,5 @@
import type {Metadata} from 'next';
import {DemoPage} from '@/components/DemoPage';
import {demoContent} from '@/config/content';
import messages from '../../../../messages/pl.json';
export const metadata: Metadata = {
title: messages.metadata.doorTitle,
description:
'Poznaj konfigurator 3D drzwi, który pozwala klientom dobrać model, kolor, przeszklenie, klamkę i detale w czasie rzeczywistym.'
};
import {redirect} from 'next/navigation';
export default function DoorDemoPage() {
return <DemoPage demo={demoContent.door} />;
redirect('/pl/demo-drzwi');
}
+14
View File
@@ -0,0 +1,14 @@
import type {Metadata} from 'next';
import {DemoPage} from '@/components/DemoPage';
import {demoContent} from '@/config/content';
import messages from '../../../../messages/pl.json';
export const metadata: Metadata = {
title: messages.metadata.doorTitle,
description:
'Poznaj konfigurator 3D drzwi, który pozwala klientom dobrać model, kolor, przeszklenie, klamkę i detale w czasie rzeczywistym.'
};
export default function DoorDemoPage() {
return <DemoPage demo={demoContent.door} />;
}
+14
View File
@@ -0,0 +1,14 @@
import type {Metadata} from 'next';
import {DemoPage} from '@/components/DemoPage';
import {demoContent} from '@/config/content';
import messages from '../../../../messages/pl.json';
export const metadata: Metadata = {
title: messages.metadata.roomTitle,
description:
'Poznaj konfigurator 3D, który pozwala klientom projektować całe pomieszczenia i zestawy mebli w czasie rzeczywistym.'
};
export default function RoomDemoPage() {
return <DemoPage demo={demoContent.room} />;
}
+2 -11
View File
@@ -1,14 +1,5 @@
import type {Metadata} from 'next';
import {DemoPage} from '@/components/DemoPage';
import {demoContent} from '@/config/content';
import messages from '../../../../messages/pl.json';
export const metadata: Metadata = {
title: messages.metadata.roomTitle,
description:
'Poznaj konfigurator 3D, który pozwala klientom projektować całe pomieszczenia i zestawy mebli w czasie rzeczywistym.'
};
import {redirect} from 'next/navigation';
export default function RoomDemoPage() {
return <DemoPage demo={demoContent.room} />;
redirect('/pl/demo-pokoj');
}
+2 -11
View File
@@ -1,14 +1,5 @@
import type {Metadata} from 'next';
import {DemoPage} from '@/components/DemoPage';
import {demoContent} from '@/config/content';
import messages from '../../../../messages/pl.json';
export const metadata: Metadata = {
title: messages.metadata.deskTitle,
description:
'Poznaj konfigurator 3D, który zwiększa konwersję i pozwala klientom tworzyć własne biurka regulowane w czasie rzeczywistym.'
};
import {redirect} from 'next/navigation';
export default function DeskDemoPage() {
return <DemoPage demo={demoContent.desk} />;
redirect('/pl/demo-biurko');
}
+21 -4
View File
@@ -1,8 +1,9 @@
import type {Metadata} from 'next';
import {Poppins} from 'next/font/google';
import localFont from 'next/font/local';
import {NextIntlClientProvider} from 'next-intl';
import {getMessages} from 'next-intl/server';
import {notFound} from 'next/navigation';
import {ContactSection} from '@/components/ContactSection';
import {Footer} from '@/components/Footer';
import {Header} from '@/components/Header';
import {routing} from '@/i18n/routing';
@@ -12,9 +13,24 @@ type LocaleLayoutProps = {
params: Promise<{locale: string}>;
};
const poppins = Poppins({
subsets: ['latin', 'latin-ext'],
weight: ['400', '600', '700'],
const poppins = localFont({
src: [
{
path: '../fonts/Poppins-Regular.ttf',
weight: '400',
style: 'normal'
},
{
path: '../fonts/Poppins-SemiBold.ttf',
weight: '600',
style: 'normal'
},
{
path: '../fonts/Poppins-Bold.ttf',
weight: '700',
style: 'normal'
}
],
display: 'swap'
});
@@ -44,6 +60,7 @@ export default async function LocaleLayout({children, params}: LocaleLayoutProps
<NextIntlClientProvider messages={messages}>
<Header />
{children}
<ContactSection />
<Footer />
</NextIntlClientProvider>
</body>
+12 -15
View File
@@ -7,8 +7,7 @@ import {Faq} from '@/components/Faq';
import {HeroVisual} from '@/components/HeroVisual';
import {SectionHeader} from '@/components/SectionHeader';
import {Stats} from '@/components/Stats';
import {contact} from '@/config/contact';
import {demoContent, homeContent, marketingFaq} from '@/config/content';
import {homeContent, marketingFaq, orderedDemos} from '@/config/content';
import messages from '../../../messages/pl.json';
export const metadata: Metadata = {
@@ -20,8 +19,6 @@ const platformIcons = [Settings2, Workflow, Plug, ShoppingCart];
const industryIcons = [Box, Layers3, CheckCircle2];
export default function HomePage() {
const demos = [demoContent.desk, demoContent.room, demoContent.door];
return (
<main>
<section className="hero sectionBand sectionBand--light">
@@ -32,7 +29,7 @@ export default function HomePage() {
<p>{homeContent.hero.description}</p>
<div className="buttonRow">
<ButtonLink href="/pl/dema">{homeContent.hero.primaryCta}</ButtonLink>
<ButtonLink href={contact.url} variant="secondary" isExternal>
<ButtonLink href="#kontakt" variant="secondary">
{homeContent.hero.secondaryCta}
</ButtonLink>
</div>
@@ -41,17 +38,11 @@ export default function HomePage() {
</div>
</section>
<section className="sectionBand statsBand">
<div className="container">
<Stats stats={homeContent.stats} />
</div>
</section>
<section id="dema" className="sectionBand">
<section id="dema" className="sectionBand demosBand">
<div className="container">
<SectionHeader title={homeContent.demosTitle} description={homeContent.demosDescription} />
<div className="demoCards">
{demos.map(demo => (
{orderedDemos.map(demo => (
<article className="demoCard" key={demo.slug}>
{demo.imageUrl ? (
<Image src={demo.imageUrl} alt="" width={420} height={420} />
@@ -93,7 +84,13 @@ export default function HomePage() {
</div>
</section>
<section className="sectionBand">
<section className="sectionBand statsBand">
<div className="container">
<Stats stats={homeContent.stats} />
</div>
</section>
<section className="sectionBand industriesBand">
<div className="container">
<SectionHeader title={homeContent.industriesTitle} />
<div className="featureGrid featureGrid--three">
@@ -151,7 +148,7 @@ export default function HomePage() {
<div className="container finalCta">
<h2>{homeContent.finalCta.title}</h2>
<p>{homeContent.finalCta.description}</p>
<ButtonLink href={contact.url} isExternal>
<ButtonLink href="#kontakt">
{homeContent.finalCta.button}
</ButtonLink>
</div>
Binary file not shown.
Binary file not shown.
Binary file not shown.
+237 -14
View File
@@ -42,18 +42,21 @@ p {
h1 {
max-width: 780px;
font-size: clamp(1.95rem, 3vw, 2.85rem);
font-weight: 600;
line-height: 1.14;
letter-spacing: 0;
}
h2 {
font-size: clamp(2rem, 4vw, 3.35rem);
font-weight: 600;
line-height: 1.12;
letter-spacing: 0;
}
h3 {
font-size: clamp(1.1rem, 2vw, 1.35rem);
font-weight: 600;
line-height: 1.28;
}
@@ -87,6 +90,10 @@ p {
color: $white;
}
.sectionBand--compact {
padding: 24px 0;
}
.siteHeader {
position: sticky;
top: 0;
@@ -160,7 +167,7 @@ p {
border-radius: 6px;
padding: 0 18px;
border: 1px solid transparent;
font-weight: 700;
font-weight: 600;
line-height: 1.2;
transition:
background 160ms ease,
@@ -168,17 +175,27 @@ p {
border-color 160ms ease;
}
.siteHeader__contact,
.button--primary {
background: $primary;
color: $white;
}
.siteHeader__contact:hover,
.button--primary:hover {
background: #208de8;
}
.siteHeader__contact {
border-color: rgba(0, 28, 68, 0.18);
background: $white;
color: $secondary;
}
.siteHeader__contact:hover,
.siteHeader__contact.isActive {
border-color: $primary;
color: $primary;
}
.button--secondary {
border-color: rgba(0, 28, 68, 0.18);
background: $white;
@@ -243,7 +260,7 @@ p {
.eyebrow {
color: $primary;
font-size: 0.8rem;
font-weight: 700;
font-weight: 600;
letter-spacing: 0;
text-transform: uppercase;
}
@@ -370,7 +387,7 @@ p {
.heroVisual__panel > div:first-child {
color: $secondary;
font-weight: 700;
font-weight: 600;
}
.heroVisual__option {
@@ -451,7 +468,7 @@ p {
border-bottom: 1px solid rgba(0, 28, 68, 0.1);
color: $secondary;
font-size: 0.92rem;
font-weight: 700;
font-weight: 600;
}
.demoFrame__bar > span {
@@ -500,7 +517,7 @@ p {
place-items: center;
padding: 24px;
color: $secondary;
font-weight: 700;
font-weight: 600;
text-align: center;
}
@@ -511,7 +528,7 @@ p {
}
.statsBand {
padding: clamp(28px, 4vw, 52px) 0;
padding: clamp(34px, 4vw, 58px) 0 clamp(24px, 3vw, 42px);
}
.statItem {
@@ -607,6 +624,7 @@ p {
}
.demoBrowser__item strong {
font-weight: 600;
font-size: 0.93rem;
line-height: 1.32;
}
@@ -657,6 +675,14 @@ p {
margin-bottom: 34px;
}
.demosBand {
padding-top: clamp(28px, 4vw, 52px);
}
.industriesBand {
padding-top: clamp(34px, 4vw, 56px);
}
.demoCards,
.featureGrid,
.processGrid {
@@ -710,7 +736,9 @@ p {
.demoCard > div {
display: grid;
grid-template-rows: auto auto 1fr auto;
gap: 14px;
height: 100%;
}
.demoCard p:not(.eyebrow),
@@ -722,9 +750,98 @@ p {
.demoCard a {
display: inline-flex;
align-items: center;
align-self: end;
gap: 8px;
margin-top: 10px;
color: $primary;
font-weight: 700;
font-weight: 600;
}
.demoSubnav {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
margin-bottom: 24px;
}
.demoSubnav a {
display: grid;
gap: 5px;
min-height: 78px;
align-content: center;
padding: 14px 16px;
border: 1px solid rgba(0, 28, 68, 0.1);
border-radius: 8px;
background: $white;
color: $secondary;
font-size: 0.94rem;
font-weight: 600;
line-height: 1.3;
}
.demoSubnav a span {
color: $primary;
font-size: 0.72rem;
font-weight: 600;
text-transform: uppercase;
}
.demoSubnav a.isActive {
border-color: rgba(66, 166, 255, 0.7);
background: rgba(66, 166, 255, 0.09);
box-shadow: 0 12px 30px rgba(0, 28, 68, 0.08);
}
.demoSubnavBar {
position: sticky;
top: 78px;
z-index: 19;
border-bottom: 1px solid rgba(0, 28, 68, 0.1);
background: rgba(255, 255, 255, 0.94);
backdrop-filter: blur(14px);
}
.demoSubnavBar .demoSubnav {
display: flex;
gap: 24px;
align-items: center;
justify-content: center;
margin-bottom: 0;
}
.demoSubnavBar .demoSubnav a {
min-height: 52px;
padding: 0;
border: 0;
border-radius: 0;
background: transparent;
box-shadow: none;
color: rgba(0, 28, 68, 0.78);
font-size: 0.9rem;
white-space: nowrap;
}
.demoSubnavBar .demoSubnav a span {
display: none;
}
.demoSubnavBar .demoSubnav a.isActive {
position: relative;
border: 0;
background: transparent;
box-shadow: none;
color: $primary;
}
.demoSubnavBar .demoSubnav a.isActive::after {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 3px;
border-radius: 999px 999px 0 0;
background: $primary;
content: '';
}
.splitSection {
@@ -808,7 +925,7 @@ p {
border-radius: 6px;
background: $primary;
color: $white;
font-weight: 700;
font-weight: 600;
}
.faqList {
@@ -825,7 +942,7 @@ p {
.faqList summary {
cursor: pointer;
padding: 20px 22px;
font-weight: 700;
font-weight: 600;
}
.faqList p {
@@ -857,6 +974,92 @@ p {
grid-template-columns: minmax(0, 1.1fr) minmax(300px, 0.9fr);
}
.contactSection {
scroll-margin-top: 88px;
background: $tertiary;
}
.contactSection__grid {
display: grid;
gap: clamp(18px, 3vw, 28px);
}
.contactSection__intro {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(320px, 0.5fr);
gap: clamp(28px, 5vw, 72px);
align-items: end;
}
.contactSection__intro > div:first-child {
display: grid;
gap: 16px;
}
.contactSection__grid h2 {
max-width: 680px;
}
.contactSection__grid p:not(.eyebrow) {
max-width: 640px;
color: $gray-light;
}
.contactSection__schedulerWrap {
display: grid;
gap: 14px;
}
.contactSection__scheduler {
width: 100%;
height: 555px;
max-height: 555px;
border: 1px solid rgba(0, 28, 68, 0.1);
border-radius: 8px;
background: $tertiary;
}
.contactSection__details {
display: grid;
align-self: end;
gap: 14px;
padding: clamp(22px, 3vw, 30px);
border: 1px solid rgba(0, 28, 68, 0.1);
border-radius: 8px;
background: $white;
font-style: normal;
}
.contactSection__details > div {
display: grid;
grid-template-columns: 24px 1fr;
gap: 12px;
align-items: start;
}
.contactSection__details svg {
margin-top: 2px;
color: $primary;
}
.contactSection__details span {
display: grid;
gap: 4px;
}
.contactSection__details strong,
.contactSection__details a {
color: $secondary;
font-weight: 600;
line-height: 1.5;
}
.contactSection__fallback {
justify-self: start;
color: $primary;
font-weight: 600;
}
.footer {
background: $secondary;
color: $white;
@@ -865,14 +1068,13 @@ p {
.footer__inner {
display: grid;
grid-template-columns: 1.1fr 0.8fr 0.9fr auto;
grid-template-columns: 1fr auto;
gap: 32px;
width: min(1180px, calc(100% - 40px));
margin: 0 auto;
}
.footer__brand,
.footer__nav,
.footer__contact,
.footer__social {
display: grid;
@@ -890,6 +1092,12 @@ p {
color: rgba(255, 255, 255, 0.78);
}
.footer__contact {
justify-self: end;
font-style: normal;
text-align: right;
}
.footer__social {
grid-auto-flow: column;
}
@@ -937,13 +1145,26 @@ p {
.siteHeader__mobileNav a {
padding: 14px 0;
font-weight: 700;
font-weight: 600;
}
.demoSubnavBar {
top: 68px;
overflow-x: auto;
}
.demoSubnavBar .demoSubnav {
width: max-content;
min-width: 100%;
justify-content: flex-start;
}
.hero__grid,
.demoHero__grid,
.demoBrowser,
.splitSection,
.contactSection__grid,
.contactSection__intro,
.footer__inner {
grid-template-columns: 1fr;
}
@@ -958,6 +1179,7 @@ p {
.featureGrid--three,
.demoCards,
.demoSubnav,
.processGrid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@@ -995,6 +1217,7 @@ p {
.statsGrid,
.demoCards,
.demoSubnav,
.demoBrowser__list,
.featureGrid,
.featureGrid--three,