feat: add CTAButton component with customizable variants, sizes, and arrows
This commit is contained in:
+240
-29
@@ -266,53 +266,264 @@ html {
|
||||
::-webkit-scrollbar-thumb { background: rgba(136, 145, 199, 0.28); border-radius: var(--radius-sm); }
|
||||
::-webkit-scrollbar-thumb:hover { background: rgba(39, 63, 148, 0.7); }
|
||||
|
||||
/* === Buttons === */
|
||||
.btn {
|
||||
/* === CTA Button System === */
|
||||
/* Reusable across all sections — primary | secondary | ghost | link, sizes sm | md | lg.
|
||||
Arrow handled via .cta-arrow capsule; data-arrow="up-right" rotates on hover, "right" translates X. */
|
||||
.cta-btn {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.625rem;
|
||||
padding: 0.875rem 1.75rem;
|
||||
gap: 0.65rem;
|
||||
border-radius: 999px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.08em;
|
||||
font-family: inherit;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: transform 0.25s cubic-bezier(0.16,1,0.3,1), box-shadow 0.25s ease, background 0.25s ease, color 0.25s ease;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
isolation: isolate;
|
||||
overflow: hidden;
|
||||
border: 1px solid transparent;
|
||||
transition: transform 0.3s cubic-bezier(0.16,1,0.3,1), box-shadow 0.3s, background 0.3s, border-color 0.3s, color 0.3s;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.btn:hover { transform: translateY(-1px); }
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #3a55c4 0%, #273F94 55%, #1a2e6e 100%);
|
||||
color: #FBFBFD;
|
||||
box-shadow: 0 8px 28px rgba(39, 63, 148, 0.45), inset 0 1px 0 rgba(222, 224, 240, 0.25);
|
||||
.cta-btn:focus-visible {
|
||||
outline: 2px solid #DEE0F0;
|
||||
outline-offset: 3px;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
box-shadow: 0 12px 38px rgba(58, 85, 196, 0.6), inset 0 1px 0 rgba(222, 224, 240, 0.35);
|
||||
.cta-btn:disabled,
|
||||
.cta-btn[aria-disabled='true'] {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
background: rgba(222, 224, 240, 0.04);
|
||||
color: #FBFBFD;
|
||||
border-color: rgba(199, 207, 230, 0.28);
|
||||
backdrop-filter: blur(12px);
|
||||
/* sizes */
|
||||
.cta-sm { padding: 0.62rem 1.05rem; font-size: 0.64rem; letter-spacing: 0.22em; }
|
||||
.cta-md { padding: 0.95rem 1.45rem; font-size: 0.74rem; }
|
||||
.cta-lg { padding: 1.05rem 1.7rem; font-size: 0.8rem; letter-spacing: 0.24em; }
|
||||
|
||||
/* shared arrow capsule */
|
||||
.cta-arrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 999px;
|
||||
background: rgba(222, 224, 240, 0.12);
|
||||
border: 1px solid rgba(222, 224, 240, 0.22);
|
||||
color: currentColor;
|
||||
transition: transform 0.35s, background 0.35s, border-color 0.35s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.btn-ghost:hover {
|
||||
background: rgba(39, 63, 148, 0.16);
|
||||
border-color: rgba(136, 145, 199, 0.6);
|
||||
color: #DEE0F0;
|
||||
.cta-sm .cta-arrow { width: 20px; height: 20px; }
|
||||
.cta-md .cta-arrow { width: 24px; height: 24px; }
|
||||
.cta-lg .cta-arrow { width: 26px; height: 26px; }
|
||||
|
||||
/* PRIMARY — filled gradient, strongest emphasis */
|
||||
.cta-primary {
|
||||
background: linear-gradient(135deg, #5a76e8 0%, #4a66d8 35%, #2f4cb4 70%, #273F94 100%);
|
||||
color: #FFFFFF;
|
||||
box-shadow:
|
||||
0 24px 56px rgba(39, 63, 148, 0.55),
|
||||
0 0 0 1px rgba(222, 224, 240, 0.22),
|
||||
0 0 32px rgba(74, 102, 216, 0.4),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.24);
|
||||
}
|
||||
.cta-primary::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(120deg, transparent 30%, rgba(255, 255, 255, 0.2) 50%, transparent 70%);
|
||||
transform: translateX(-100%);
|
||||
transition: transform 0.7s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
.cta-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow:
|
||||
0 30px 66px rgba(39, 63, 148, 0.7),
|
||||
0 0 0 1px rgba(222, 224, 240, 0.32),
|
||||
0 0 44px rgba(74, 102, 216, 0.55),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
.cta-primary:hover::before { transform: translateX(100%); }
|
||||
.cta-primary .cta-arrow {
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
border-color: rgba(255, 255, 255, 0.24);
|
||||
}
|
||||
.cta-primary:hover .cta-arrow {
|
||||
background: rgba(255, 255, 255, 0.32);
|
||||
border-color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
/* SECONDARY — glassmorphism, supporting actions */
|
||||
.cta-secondary {
|
||||
border-color: rgba(222, 224, 240, 0.55);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(58, 85, 196, 0.16), rgba(14, 13, 18, 0.55) 60%),
|
||||
rgba(14, 13, 18, 0.55);
|
||||
color: #FFFFFF;
|
||||
backdrop-filter: blur(14px);
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
box-shadow:
|
||||
0 14px 32px rgba(0, 0, 0, 0.55),
|
||||
inset 0 1px 0 rgba(222, 224, 240, 0.22),
|
||||
0 0 0 1px rgba(58, 85, 196, 0.18);
|
||||
}
|
||||
.cta-secondary::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(120deg, transparent 30%, rgba(222, 224, 240, 0.16) 50%, transparent 70%);
|
||||
transform: translateX(-100%);
|
||||
transition: transform 0.7s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
.cta-secondary:hover {
|
||||
border-color: rgba(222, 224, 240, 0.82);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(74, 102, 216, 0.3), rgba(20, 22, 38, 0.62) 60%),
|
||||
rgba(20, 22, 38, 0.62);
|
||||
transform: translateY(-2px);
|
||||
box-shadow:
|
||||
0 22px 46px rgba(0, 0, 0, 0.62),
|
||||
inset 0 1px 0 rgba(222, 224, 240, 0.3),
|
||||
0 0 0 1px rgba(58, 85, 196, 0.5),
|
||||
0 0 32px rgba(58, 85, 196, 0.4);
|
||||
}
|
||||
.cta-secondary:hover::before { transform: translateX(100%); }
|
||||
|
||||
/* GHOST — outline, low-emphasis action */
|
||||
.cta-ghost {
|
||||
border-color: rgba(222, 224, 240, 0.28);
|
||||
background: transparent;
|
||||
color: #ECEEF6;
|
||||
}
|
||||
.cta-ghost:hover {
|
||||
border-color: rgba(222, 224, 240, 0.6);
|
||||
background: rgba(58, 85, 196, 0.14);
|
||||
color: #FFFFFF;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.cta-ghost .cta-arrow {
|
||||
background: rgba(222, 224, 240, 0.08);
|
||||
border-color: rgba(222, 224, 240, 0.2);
|
||||
}
|
||||
.cta-ghost:hover .cta-arrow {
|
||||
background: rgba(58, 85, 196, 0.22);
|
||||
border-color: rgba(222, 224, 240, 0.4);
|
||||
}
|
||||
|
||||
/* LINK — text-only for minor inline links */
|
||||
.cta-link {
|
||||
padding: 0.45rem 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #DEE0F0;
|
||||
border-color: rgba(136, 145, 199, 0.55);
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.2em;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-radius: 0;
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
}
|
||||
.cta-link:hover {
|
||||
color: #FFFFFF;
|
||||
border-bottom-color: rgba(222, 224, 240, 0.55);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
.cta-link .cta-arrow {
|
||||
width: auto;
|
||||
height: auto;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
.cta-link:hover .cta-arrow { transform: translate(3px, -1px); }
|
||||
|
||||
/* arrow motion per direction */
|
||||
.cta-btn[data-arrow='up-right']:hover .cta-arrow { transform: rotate(45deg); }
|
||||
.cta-btn[data-arrow='right']:hover .cta-arrow { transform: translateX(3px); }
|
||||
.cta-link[data-arrow='up-right']:hover .cta-arrow,
|
||||
.cta-link[data-arrow='right']:hover .cta-arrow { transform: translate(3px, -1px); }
|
||||
|
||||
/* full-width on small screens for primary CTA wrappers */
|
||||
.cta-btn.cta-full {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* === Legacy .btn aliases — kept for backward compat, route to new system === */
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.65rem;
|
||||
padding: 0.95rem 1.45rem;
|
||||
border-radius: 999px;
|
||||
font-size: 0.74rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
transition: transform 0.3s cubic-bezier(0.16,1,0.3,1), box-shadow 0.3s, background 0.3s, color 0.3s, border-color 0.3s;
|
||||
}
|
||||
.btn:hover { transform: translateY(-2px); }
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #5a76e8 0%, #4a66d8 35%, #2f4cb4 70%, #273F94 100%);
|
||||
color: #FFFFFF;
|
||||
box-shadow:
|
||||
0 24px 56px rgba(39, 63, 148, 0.55),
|
||||
0 0 0 1px rgba(222, 224, 240, 0.22),
|
||||
0 0 32px rgba(74, 102, 216, 0.4),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.24);
|
||||
}
|
||||
.btn-primary:hover {
|
||||
box-shadow:
|
||||
0 30px 66px rgba(39, 63, 148, 0.7),
|
||||
0 0 0 1px rgba(222, 224, 240, 0.32),
|
||||
0 0 44px rgba(74, 102, 216, 0.55),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
.btn-ghost {
|
||||
background:
|
||||
linear-gradient(135deg, rgba(58, 85, 196, 0.16), rgba(14, 13, 18, 0.55) 60%),
|
||||
rgba(14, 13, 18, 0.55);
|
||||
color: #FFFFFF;
|
||||
border-color: rgba(222, 224, 240, 0.55);
|
||||
backdrop-filter: blur(14px);
|
||||
box-shadow:
|
||||
0 14px 32px rgba(0, 0, 0, 0.55),
|
||||
inset 0 1px 0 rgba(222, 224, 240, 0.22),
|
||||
0 0 0 1px rgba(58, 85, 196, 0.18);
|
||||
}
|
||||
.btn-ghost:hover {
|
||||
border-color: rgba(222, 224, 240, 0.82);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(74, 102, 216, 0.3), rgba(20, 22, 38, 0.62) 60%),
|
||||
rgba(20, 22, 38, 0.62);
|
||||
color: #FFFFFF;
|
||||
box-shadow:
|
||||
0 22px 46px rgba(0, 0, 0, 0.62),
|
||||
inset 0 1px 0 rgba(222, 224, 240, 0.3),
|
||||
0 0 0 1px rgba(58, 85, 196, 0.5),
|
||||
0 0 32px rgba(58, 85, 196, 0.4);
|
||||
}
|
||||
.btn-outline {
|
||||
background: transparent;
|
||||
color: #ECEEF6;
|
||||
border-color: rgba(222, 224, 240, 0.28);
|
||||
}
|
||||
.btn-outline:hover {
|
||||
background: rgba(39, 63, 148, 0.14);
|
||||
background: rgba(58, 85, 196, 0.14);
|
||||
border-color: rgba(222, 224, 240, 0.6);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* === Layout helpers === */
|
||||
|
||||
+12
-22
@@ -4,7 +4,7 @@ import { FooterAndContact } from '@/components/FooterAndContact';
|
||||
import { Hero3DRobotics } from '@/components/robotics/Hero3DRobotics';
|
||||
import { BrandShowcase } from '@/components/robotics/BrandShowcase';
|
||||
import { CategoryShowcaseScroll } from '@/components/robotics/CategoryShowcaseScroll';
|
||||
import { RobotProductCard } from '@/components/robotics/RobotProductCard';
|
||||
import { FeaturedRobotsShowcase } from '@/components/robotics/FeaturedRobotsShowcase';
|
||||
import { IndustryUseCases } from '@/components/robotics/IndustryUseCases';
|
||||
import { DemoCTA } from '@/components/robotics/DemoCTA';
|
||||
import { ConfigureCTA } from '@/components/robotics/ConfigureCTA';
|
||||
@@ -83,7 +83,7 @@ export default function HomePage() {
|
||||
</div>
|
||||
</MotionSection>
|
||||
|
||||
<MotionSection style={{ padding: 'clamp(1.5rem, 3vw, 2.5rem) 0 clamp(3rem, 6vw, 5rem)' }} id="categories">
|
||||
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="categories">
|
||||
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||
<SectionHeading
|
||||
eyebrow="Robot categories"
|
||||
@@ -97,21 +97,11 @@ export default function HomePage() {
|
||||
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="featured">
|
||||
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||
<SectionHeading
|
||||
eyebrow="Featured robots"
|
||||
title="Available exclusively in the UAE through YS Lootah Robotics."
|
||||
description="A live snapshot of robots ready to demo at our Dubai showroom or deploy at your venue. Request a UAE quotation or book a live demo."
|
||||
eyebrow="Dubai showroom"
|
||||
title="Robots you can see, test, and deploy now."
|
||||
description="Four exhibits on our Dubai showroom floor — step in, request a live demo, or ask for a price."
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gap: '1.25rem',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(min(280px, 100%), 1fr))',
|
||||
}}
|
||||
>
|
||||
{FEATURED_ROBOTS.map((r, idx) => (
|
||||
<RobotProductCard key={r.id} robot={r} priority={idx === 0} />
|
||||
))}
|
||||
</div>
|
||||
<FeaturedRobotsShowcase robots={FEATURED_ROBOTS} />
|
||||
</div>
|
||||
</MotionSection>
|
||||
|
||||
@@ -124,9 +114,9 @@ export default function HomePage() {
|
||||
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="services">
|
||||
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||
<SectionHeading
|
||||
eyebrow="Our solutions"
|
||||
title="Intelligent robotics across the full lifecycle."
|
||||
description="From autonomous robotics and intelligent automation to motion programming, SDKs, and remote diagnostics a complete robotics partner for UAE businesses."
|
||||
eyebrow="UAE deployment"
|
||||
title="Real robots, deployed and supported across the UAE."
|
||||
description="From Dubai showroom demo to live venue deployment — procurement, configuration, installation, training, and ongoing support, handled by one local team."
|
||||
/>
|
||||
<ServicesGrid />
|
||||
</div>
|
||||
@@ -147,9 +137,9 @@ export default function HomePage() {
|
||||
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="how-it-works">
|
||||
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||
<SectionHeading
|
||||
eyebrow="How we work"
|
||||
title="From inquiry to live deployment."
|
||||
description="Three steps from your first message to a robot running in your venue fully supported by our Dubai team."
|
||||
eyebrow="Deployment timeline"
|
||||
title="Five steps from procurement to support."
|
||||
description="The robotics implementation journey — what changes at every stage, in order."
|
||||
/>
|
||||
<HowItWorks />
|
||||
</div>
|
||||
|
||||
@@ -177,10 +177,7 @@ export default async function RobotDetailPage({ params }: { params: Promise<Para
|
||||
</MotionSection>
|
||||
|
||||
<MotionSection>
|
||||
<ConfigureCTA
|
||||
title={`Configure ${robot.name} for your business.`}
|
||||
description="Choose persona, attire, color, and accessories visualize your deployment before requesting a quotation."
|
||||
/>
|
||||
<ConfigureCTA />
|
||||
</MotionSection>
|
||||
|
||||
{related.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user