mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-08 06:35:44 +00:00
feat: enhance landing page with new hero section, badges, and improved styles
This commit is contained in:
@@ -251,51 +251,132 @@ function Header({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HERO_BADGE_ICONS = {
|
||||||
|
secure: IconShieldCheck,
|
||||||
|
bilingual: IconLanguage,
|
||||||
|
tracking: IconActivity,
|
||||||
|
} as const;
|
||||||
|
|
||||||
function Hero({ primaryHref, isAuthed }: { primaryHref: string; isAuthed: boolean }) {
|
function Hero({ primaryHref, isAuthed }: { primaryHref: string; isAuthed: boolean }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const theme = useMantineTheme();
|
const theme = useMantineTheme();
|
||||||
|
const badgeKeys = Object.keys(HERO_BADGE_ICONS) as (keyof typeof HERO_BADGE_ICONS)[];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
id="home"
|
id="home"
|
||||||
component="section"
|
component="section"
|
||||||
|
pos="relative"
|
||||||
style={{
|
style={{
|
||||||
background: theme.other?.heroGradient as string,
|
background: theme.other?.heroGradient as string,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
|
overflow: 'hidden',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Container size="xl" py={80}>
|
{/* Decorative glow circles — same device as AuthShell's hero panel. */}
|
||||||
<Stack gap="md" align="center" ta="center" className="ema-landing-fade">
|
<Box
|
||||||
|
pos="absolute"
|
||||||
|
top={-120}
|
||||||
|
right={-100}
|
||||||
|
w={420}
|
||||||
|
h={420}
|
||||||
|
style={{ borderRadius: '50%', background: 'rgba(255,255,255,0.08)' }}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
pos="absolute"
|
||||||
|
bottom={-160}
|
||||||
|
left={-120}
|
||||||
|
w={380}
|
||||||
|
h={380}
|
||||||
|
style={{ borderRadius: '50%', background: 'rgba(255,255,255,0.06)' }}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
pos="absolute"
|
||||||
|
top="30%"
|
||||||
|
left="8%"
|
||||||
|
w={140}
|
||||||
|
h={140}
|
||||||
|
visibleFrom="md"
|
||||||
|
style={{ borderRadius: '50%', background: 'rgba(255,255,255,0.05)' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Container size="xl" py={{ base: 88, sm: 120, lg: 148 }} pos="relative">
|
||||||
|
<Stack gap="lg" align="center" ta="center" className="ema-landing-fade">
|
||||||
<Text fz="sm" fw={600} style={{ opacity: 0.85, letterSpacing: 0.5 }}>
|
<Text fz="sm" fw={600} style={{ opacity: 0.85, letterSpacing: 0.5 }}>
|
||||||
{t('landing.hero.eyebrow')}
|
{t('landing.hero.eyebrow')}
|
||||||
</Text>
|
</Text>
|
||||||
<Title order={1} fz={{ base: 32, sm: 44 }} maw={780}>
|
<Title order={1} fz={{ base: 34, sm: 48, lg: 56 }} lh={1.1} maw={860}>
|
||||||
{t('landing.hero.title')}
|
{t('landing.hero.title')}
|
||||||
</Title>
|
</Title>
|
||||||
<Text fz={{ base: 'md', sm: 'lg' }} maw={640} style={{ opacity: 0.92 }}>
|
<Text fz={{ base: 'md', sm: 'xl' }} fw={500} maw={680} style={{ opacity: 0.95 }}>
|
||||||
{t('landing.hero.subtitle')}
|
{t('landing.hero.subtitle')}
|
||||||
</Text>
|
</Text>
|
||||||
<Group gap="md" mt="md" justify="center">
|
<Text fz={{ base: 'sm', sm: 'md' }} maw={600} style={{ opacity: 0.82 }}>
|
||||||
<Button
|
{t('landing.hero.description')}
|
||||||
component={Link}
|
</Text>
|
||||||
to={isAuthed ? primaryHref : '/signup'}
|
|
||||||
size="md"
|
<Group gap="md" mt="sm" justify="center">
|
||||||
variant="white"
|
{isAuthed ? (
|
||||||
color="dark"
|
<Button
|
||||||
leftSection={<IconShip size={18} />}
|
component={Link}
|
||||||
>
|
to={primaryHref}
|
||||||
{t('landing.cta.seafarerPortal')}
|
size="lg"
|
||||||
</Button>
|
variant="white"
|
||||||
<Button
|
color="dark"
|
||||||
component={Link}
|
style={{ boxShadow: '0 8px 24px rgba(0,0,0,0.18)' }}
|
||||||
to={isAuthed ? primaryHref : '/signup'}
|
>
|
||||||
size="md"
|
{t('landing.auth.dashboard')}
|
||||||
variant="outline"
|
</Button>
|
||||||
color="white"
|
) : (
|
||||||
leftSection={<IconAnchor size={18} />}
|
<>
|
||||||
>
|
<Button
|
||||||
{t('landing.cta.vesselOwnerPortal')}
|
component={Link}
|
||||||
</Button>
|
to="/signup"
|
||||||
|
size="lg"
|
||||||
|
variant="white"
|
||||||
|
color="dark"
|
||||||
|
leftSection={<IconShip size={20} />}
|
||||||
|
style={{ boxShadow: '0 8px 24px rgba(0,0,0,0.18)' }}
|
||||||
|
>
|
||||||
|
{t('landing.cta.iAmSeafarer')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
component={Link}
|
||||||
|
to="/signup"
|
||||||
|
size="lg"
|
||||||
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
leftSection={<IconAnchor size={20} />}
|
||||||
|
>
|
||||||
|
{t('landing.cta.iAmVesselOwner')}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
|
||||||
|
<Group gap="xs" mt="xl" justify="center" wrap="wrap">
|
||||||
|
{badgeKeys.map((key) => {
|
||||||
|
const Icon = HERO_BADGE_ICONS[key];
|
||||||
|
return (
|
||||||
|
<Group
|
||||||
|
key={key}
|
||||||
|
gap={6}
|
||||||
|
wrap="nowrap"
|
||||||
|
px="sm"
|
||||||
|
py={6}
|
||||||
|
style={{
|
||||||
|
borderRadius: 999,
|
||||||
|
background: 'rgba(255,255,255,0.12)',
|
||||||
|
border: '1px solid rgba(255,255,255,0.18)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon size={14} />
|
||||||
|
<Text fz="xs" fw={600}>
|
||||||
|
{t(`landing.hero.badges.${key}`)}
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ export const landingEn = {
|
|||||||
eyebrow: 'Federal Democratic Republic of Ethiopia',
|
eyebrow: 'Federal Democratic Republic of Ethiopia',
|
||||||
title: 'Ethiopian Maritime Authority',
|
title: 'Ethiopian Maritime Authority',
|
||||||
subtitle: 'Digital Maritime Services for Seafarers, Vessel Owners and Logistics Operators',
|
subtitle: 'Digital Maritime Services for Seafarers, Vessel Owners and Logistics Operators',
|
||||||
|
description:
|
||||||
|
'Apply, upload documents and track every application from one secure account — built for seafarers, vessel owners and logistics operators across Ethiopia.',
|
||||||
|
badges: {
|
||||||
|
secure: 'Secure & Verified',
|
||||||
|
bilingual: 'English & አማርኛ',
|
||||||
|
tracking: 'Real-Time Tracking',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
about: {
|
about: {
|
||||||
@@ -44,8 +51,8 @@ export const landingEn = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
cta: {
|
cta: {
|
||||||
seafarerPortal: 'Seafarer Portal',
|
iAmSeafarer: "I'm a Seafarer",
|
||||||
vesselOwnerPortal: 'Vessel Owner Portal',
|
iAmVesselOwner: "I'm a Vessel Owner",
|
||||||
},
|
},
|
||||||
|
|
||||||
quickAccess: {
|
quickAccess: {
|
||||||
@@ -212,6 +219,13 @@ export const landingAm: LandingCopy = {
|
|||||||
eyebrow: 'የኢትዮጵያ ፌዴራላዊ ዲሞክራሲያዊ ሪፐብሊክ',
|
eyebrow: 'የኢትዮጵያ ፌዴራላዊ ዲሞክራሲያዊ ሪፐብሊክ',
|
||||||
title: 'የኢትዮጵያ ማሪታይም ባለስልጣን',
|
title: 'የኢትዮጵያ ማሪታይም ባለስልጣን',
|
||||||
subtitle: 'ለመርከበኞች፣ ለመርከብ ባለቤቶች እና ለሎጂስቲክስ ኦፕሬተሮች የተዘጋጁ ዲጂታል የባህር አገልግሎቶች',
|
subtitle: 'ለመርከበኞች፣ ለመርከብ ባለቤቶች እና ለሎጂስቲክስ ኦፕሬተሮች የተዘጋጁ ዲጂታል የባህር አገልግሎቶች',
|
||||||
|
description:
|
||||||
|
'ከመለያዎ ማመልከቻ ያስገቡ፣ ሰነድ ይስቀሉ እንዲሁም ሁኔታ ይከታተሉ — ለመርከበኞች፣ ለመርከብ ባለቤቶችና ለሎጂስቲክስ ኦፕሬተሮች የተዘጋጀ ነው።',
|
||||||
|
badges: {
|
||||||
|
secure: 'ደህንነቱ የተጠበቀ',
|
||||||
|
bilingual: 'አማርኛና እንግሊዝኛ',
|
||||||
|
tracking: 'የቀጥታ ክትትል',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
about: {
|
about: {
|
||||||
@@ -225,8 +239,8 @@ export const landingAm: LandingCopy = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
cta: {
|
cta: {
|
||||||
seafarerPortal: 'የመርከበኞች ፖርታል',
|
iAmSeafarer: 'መርከበኛ ነኝ',
|
||||||
vesselOwnerPortal: 'የመርከብ ባለቤቶች ፖርታል',
|
iAmVesselOwner: 'የመርከብ ባለቤት ነኝ',
|
||||||
},
|
},
|
||||||
|
|
||||||
quickAccess: {
|
quickAccess: {
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
.ema-hover-lift, portal's --ema-surface-*) is available here, so this file
|
.ema-hover-lift, portal's --ema-surface-*) is available here, so this file
|
||||||
is self-contained. */
|
is self-contained. */
|
||||||
|
|
||||||
.ema-landing {
|
/* `scroll-behavior` only affects the element that actually scrolls — for a
|
||||||
|
full page that's `html`, not this div, so it has to live here. Scoped with
|
||||||
|
:has() so it only applies while the landing page is mounted. */
|
||||||
|
html:has(.ema-landing) {
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +48,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.ema-landing {
|
html:has(.ema-landing) {
|
||||||
scroll-behavior: auto;
|
scroll-behavior: auto;
|
||||||
}
|
}
|
||||||
.ema-landing .ema-landing-fade,
|
.ema-landing .ema-landing-fade,
|
||||||
|
|||||||
Reference in New Issue
Block a user