Browse Source

feat : hero 수정

remotes/origin/main
이시연 1 month ago
parent
commit
ec48057b74
  1. 66
      src/components/SubHero.jsx
  2. 2
      src/css/common.css
  3. 82
      src/pages/company/AboutPage.jsx
  4. 33
      src/pages/company/HistoryPage.jsx
  5. 48
      src/pages/company/PartnersPage.jsx

66
src/components/SubHero.jsx

@ -64,7 +64,12 @@ function NetworkGlobe() {
const y2 = y * cosX - z1 * sinX; const y2 = y * cosX - z1 * sinX;
const z2 = y * sinX + z1 * cosX; const z2 = y * sinX + z1 * cosX;
const scale = 1 / (1.6 + z2 * 0.4); const scale = 1 / (1.6 + z2 * 0.4);
return { sx: cx + x1 * R * scale, sy: cy + y2 * R * scale, sz: z2, scale }; return {
sx: cx + x1 * R * scale,
sy: cy + y2 * R * scale,
sz: z2,
scale,
};
} }
function draw() { function draw() {
@ -100,7 +105,8 @@ function NetworkGlobe() {
const d = Math.sqrt(dx * dx + dy * dy + dz * dz); const d = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (d < 0.55) { if (d < 0.55) {
const depth = (a.sz + b.sz) * 0.5; const depth = (a.sz + b.sz) * 0.5;
const alpha = Math.max(0, 0.05 + (depth + 1) * 0.1) * (1 - d / 0.55); const alpha =
Math.max(0, 0.05 + (depth + 1) * 0.1) * (1 - d / 0.55);
const aHex = Math.round(Math.min(255, alpha * 255)) const aHex = Math.round(Math.min(255, alpha * 255))
.toString(16) .toString(16)
.padStart(2, "0"); .padStart(2, "0");
@ -129,7 +135,14 @@ function NetworkGlobe() {
.toString(16) .toString(16)
.padStart(2, "0"); .padStart(2, "0");
const glow = ctx.createRadialGradient(n.sx, n.sy, 0, n.sx, n.sy, r * 3.5); const glow = ctx.createRadialGradient(
n.sx,
n.sy,
0,
n.sx,
n.sy,
r * 3.5,
);
glow.addColorStop(0, n.color + gHex); glow.addColorStop(0, n.color + gHex);
glow.addColorStop(1, n.color + "00"); glow.addColorStop(1, n.color + "00");
ctx.beginPath(); ctx.beginPath();
@ -165,7 +178,7 @@ function NetworkGlobe() {
export default function SubHero({ title, desc, navItems, rightSlot }) { export default function SubHero({ title, desc, navItems, rightSlot }) {
const { pathname } = useLocation(); const { pathname } = useLocation();
const titleLines = typeof title === "string" ? title.split("\n") : [title]; const titleLines = typeof title === "string" ? title.split("\n") : null;
const [isPill, setIsPill] = useState(false); const [isPill, setIsPill] = useState(false);
const navRef = useRef(null); const navRef = useRef(null);
@ -182,12 +195,17 @@ export default function SubHero({ title, desc, navItems, rightSlot }) {
<section className={`sh4${rightSlot ? " sh4--split" : ""}`}> <section className={`sh4${rightSlot ? " sh4--split" : ""}`}>
<div className="sh4-inner"> <div className="sh4-inner">
<div className="sh4-left"> <div className="sh4-left">
<motion.span className="sh4-label" initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}> <motion.span
className="sh4-label"
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
>
{menuMap["/" + pathname.split("/")[1]]?.label} {menuMap["/" + pathname.split("/")[1]]?.label}
</motion.span> </motion.span>
<h1 className="sh4-title"> <h1 className="sh4-title">
{titleLines.map((line, li) => ( {typeof title === "string"
? titleLines.map((line, li) => (
<span key={li} className="sh4-title-line"> <span key={li} className="sh4-title-line">
{line.split("").map((char, ci) => ( {line.split("").map((char, ci) => (
<motion.span <motion.span
@ -205,18 +223,32 @@ export default function SubHero({ title, desc, navItems, rightSlot }) {
</motion.span> </motion.span>
))} ))}
</span> </span>
))} ))
: title}
</h1> </h1>
{desc && ( {desc && (
<motion.p className="sh4-desc" initial={{ opacity: 0, y: 16 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.7, delay: 0.8, ease: [0.16, 1, 0.3, 1] }}> <motion.p
className="sh4-desc"
initial={{ opacity: 0, y: 16 }}
animate={{ opacity: 1, y: 0 }}
transition={{
duration: 0.7,
delay: 0.8,
ease: [0.16, 1, 0.3, 1],
}}
>
{desc} {desc}
</motion.p> </motion.p>
)} )}
</div> </div>
{rightSlot && ( {rightSlot && (
<motion.div className="sh4-right" initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 0.3 }}> <motion.div
className="sh4-right"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1, delay: 0.3 }}
>
{rightSlot} {rightSlot}
</motion.div> </motion.div>
)} )}
@ -224,10 +256,18 @@ export default function SubHero({ title, desc, navItems, rightSlot }) {
</section> </section>
{navItems?.length > 1 && ( {navItems?.length > 1 && (
<nav ref={navRef} className={`sh4-nav-wrap${isPill ? " is-pill" : ""}`} aria-label="Sub Navigation"> <nav
ref={navRef}
className={`sh4-nav-wrap${isPill ? " is-pill" : ""}`}
aria-label="Sub Navigation"
>
<div className="sh4-nav"> <div className="sh4-nav">
{navItems.map((item) => ( {navItems.map((item) => (
<Link key={item.to} to={item.to} className={`sh4-nav-tab${pathname === item.to ? " sh4-nav-tab--active" : ""}`}> <Link
key={item.to}
to={item.to}
className={`sh4-nav-tab${pathname === item.to ? " sh4-nav-tab--active" : ""}`}
>
{item.label} {item.label}
</Link> </Link>
))} ))}

2
src/css/common.css

@ -33,6 +33,8 @@ body{overflow-x:hidden;}
.sh4-right{position:relative;height:100%;min-height:320px;} .sh4-right{position:relative;height:100%;min-height:320px;}
.sh4-label{display:block;font-size:11px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:rgba(26,31,94,.38);margin-bottom:20px;opacity:0;transform:translateY(10px);animation:sh4Up .55s cubic-bezier(.16,1,.3,1) forwards;} .sh4-label{display:block;font-size:11px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:rgba(26,31,94,.38);margin-bottom:20px;opacity:0;transform:translateY(10px);animation:sh4Up .55s cubic-bezier(.16,1,.3,1) forwards;}
.sh4-title{margin:0 0 20px;font-size:clamp(40px,6vw,80px);font-weight:900;line-height:1.05;letter-spacing:-.055em;color:var(--navy);} .sh4-title{margin:0 0 20px;font-size:clamp(40px,6vw,80px);font-weight:900;line-height:1.05;letter-spacing:-.055em;color:var(--navy);}
.sh4-title em{font-style:normal;background:var(--grad-brand-h);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;}
.sh4-title-line{display:block;} .sh4-title-line{display:block;}
.sh4-char{display:inline-block;} .sh4-char{display:inline-block;}
.sh4-desc{font-size:clamp(14px,1.2vw,17px);line-height:1.8;color:rgba(26,31,94,.42);word-break:keep-all;margin:0;opacity:0;transform:translateY(12px);animation:sh4Up .6s .5s cubic-bezier(.16,1,.3,1) forwards;} .sh4-desc{font-size:clamp(14px,1.2vw,17px);line-height:1.8;color:rgba(26,31,94,.42);word-break:keep-all;margin:0;opacity:0;transform:translateY(12px);animation:sh4Up .6s .5s cubic-bezier(.16,1,.3,1) forwards;}

82
src/pages/company/AboutPage.jsx

@ -24,15 +24,43 @@ const STATS = [
]; ];
const VALUES = [ const VALUES = [
{ idx: "01", title: "기술 혁신", en: "Innovation", desc: "항공 데이터와 UTM 기술의 경계를 지속적으로 확장하며 미래 모빌리티 시대를 선도합니다." }, {
{ idx: "02", title: "신뢰와 책임", en: "Trust", desc: "공공·항공 분야의 핵심 인프라를 다루는 만큼 모든 서비스에 안전과 신뢰를 최우선으로 합니다." }, idx: "01",
{ idx: "03", title: "파트너십", en: "Partnership", desc: "고객사와 장기 파트너로서 구축부터 운영·유지보수까지 전 과정을 함께합니다." }, title: "기술 혁신",
{ idx: "04", title: "전문성", en: "Expertise", desc: "항공 IT 분야 10년 이상의 전문 인력이 SI, R&D, 솔루션 개발을 일관되게 수행합니다." }, en: "Innovation",
desc: "항공 데이터와 UTM 기술의 경계를 지속적으로 확장하며 미래 모빌리티 시대를 선도합니다.",
},
{
idx: "02",
title: "신뢰와 책임",
en: "Trust",
desc: "공공·항공 분야의 핵심 인프라를 다루는 만큼 모든 서비스에 안전과 신뢰를 최우선으로 합니다.",
},
{
idx: "03",
title: "파트너십",
en: "Partnership",
desc: "고객사와 장기 파트너로서 구축부터 운영·유지보수까지 전 과정을 함께합니다.",
},
{
idx: "04",
title: "전문성",
en: "Expertise",
desc: "항공 IT 분야 10년 이상의 전문 인력이 SI, R&D, 솔루션 개발을 일관되게 수행합니다.",
},
]; ];
const AWARDS = [ const AWARDS = [
{ year: "2022", title: "인천 항공산업 선도기업 유망기업 선정", org: "인천시 · 인천테크노파크" }, {
{ year: "2021", title: "소프트웨어 품질인증 GS 인증 획득", org: "한국정보통신기술협회(TTA)" }, year: "2022",
title: "인천 항공산업 선도기업 유망기업 선정",
org: "인천시 · 인천테크노파크",
},
{
year: "2021",
title: "소프트웨어 품질인증 GS 인증 획득",
org: "한국정보통신기술협회(TTA)",
},
{ year: "2021", title: "기업부설연구소 인정", org: "한국산업기술진흥협회" }, { year: "2021", title: "기업부설연구소 인정", org: "한국산업기술진흥협회" },
{ year: "2020", title: "조달청 우수제품 지정", org: "비행상황관제 시스템" }, { year: "2020", title: "조달청 우수제품 지정", org: "비행상황관제 시스템" },
]; ];
@ -63,7 +91,10 @@ export default function AboutPage() {
onEnter: () => { onEnter: () => {
statRefs.current.forEach((el, i) => { statRefs.current.forEach((el, i) => {
if (!el) return; if (!el) return;
setTimeout(() => animateCount(el, STATS[i].num, STATS[i].suffix), i * 100); setTimeout(
() => animateCount(el, STATS[i].num, STATS[i].suffix),
i * 100,
);
}); });
}, },
}); });
@ -144,7 +175,18 @@ export default function AboutPage() {
return ( return (
<article> <article>
{/* ① 히어로 */} {/* ① 히어로 */}
<SubHero title={"가치를 실천하는\n항공 IT 전문기업"} desc="팔네트웍스는 항공 데이터와 통합 관제 기술을 기반으로 안전한 하늘길을 만들어갑니다." navItems={COMPANY_NAV} rightSlot={heroRight} /> <SubHero
title={
<>
<span style={{ color: "#111" }}>가치를 실천하는</span>
<br />
<em>항공 IT 전문기업</em>
</>
}
desc="팔네트웍스는 항공 데이터와 통합 관제 기술을 기반으로 안전한 하늘길을 만들어갑니다."
navItems={COMPANY_NAV}
rightSlot={heroRight}
/>
{/* ② 소개 — 흰 배경, 히어로와 자연스럽게 연결 */} {/* ② 소개 — 흰 배경, 히어로와 자연스럽게 연결 */}
<section className="ab-intro"> <section className="ab-intro">
@ -164,8 +206,15 @@ export default function AboutPage() {
<span>2010 설립 이후</span> <span>2010 설립 이후</span>
<strong>항공 IT </strong> <strong>항공 IT </strong>
</div> </div>
<p>팔네트웍스는 2010 설립 이후 항공 예약 플랫폼, 비행상황관제 시스템, UTM 솔루션까지 항공 IT 분야의 핵심 기술을 꾸준히 개발해왔습니다.</p> <p>
<p>인천광역시 로봇랜드에서 UAM/UATM 미래 기술을 선행 연구하며 안전한 하늘길을 만들어가고 있습니다.</p> 팔네트웍스는 2010 설립 이후 항공 예약 플랫폼, 비행상황관제
시스템, UTM 솔루션까지 항공 IT 분야의 핵심 기술을 꾸준히
개발해왔습니다.
</p>
<p>
인천광역시 로봇랜드에서 UAM/UATM 미래 기술을 선행 연구하며 안전한
하늘길을 만들어가고 있습니다.
</p>
</div> </div>
</div> </div>
</section> </section>
@ -173,7 +222,9 @@ export default function AboutPage() {
{/* ③ Stats — 연한 네이비 배경 */} {/* ③ Stats — 연한 네이비 배경 */}
<section className="ab-stats"> <section className="ab-stats">
<div className="ab-stats-inner"> <div className="ab-stats-inner">
<span className="ab-eyebrow ab-eyebrow--light">PAL Networks in Numbers</span> <span className="ab-eyebrow ab-eyebrow--light">
PAL Networks in Numbers
</span>
<div className="ab-stats-grid"> <div className="ab-stats-grid">
{STATS.map((s, i) => ( {STATS.map((s, i) => (
<div className="ab-si" key={s.note}> <div className="ab-si" key={s.note}>
@ -182,7 +233,10 @@ export default function AboutPage() {
{s.suffix} {s.suffix}
</span> </span>
<span className="ab-si-note">{s.note}</span> <span className="ab-si-note">{s.note}</span>
<strong className="ab-si-num" ref={(el) => (statRefs.current[i] = el)}> <strong
className="ab-si-num"
ref={(el) => (statRefs.current[i] = el)}
>
{s.num} {s.num}
{s.suffix} {s.suffix}
</strong> </strong>
@ -247,7 +301,9 @@ export default function AboutPage() {
<br /> <br />
함께하세요 함께하세요
</h2> </h2>
<p className="ab-cta-desc">파트너십 문의, 채용, 사업 협력 무엇이든 편하게 연락주세요.</p> <p className="ab-cta-desc">
파트너십 문의, 채용, 사업 협력 무엇이든 편하게 연락주세요.
</p>
<div className="ab-cta-btns"> <div className="ab-cta-btns">
<Link to="/contact/inquiry" className="ab-cta-btn ab-cta-btn--fill"> <Link to="/contact/inquiry" className="ab-cta-btn ab-cta-btn--fill">
문의하기 문의하기

33
src/pages/company/HistoryPage.jsx

@ -12,7 +12,10 @@ const HISTORY = [
{ {
year: "2024", year: "2024",
items: [ items: [
{ month: "11월", text: "UAM 통합 교통관리 시스템(UATM) 1단계 연구개발 착수" }, {
month: "11월",
text: "UAM 통합 교통관리 시스템(UATM) 1단계 연구개발 착수",
},
{ month: "06월", text: "KT G-cloud 인천 총판 계약 체결" }, { month: "06월", text: "KT G-cloud 인천 총판 계약 체결" },
{ month: "03월", text: "비행상황관제 시스템 v3.0 고도화 완료" }, { month: "03월", text: "비행상황관제 시스템 v3.0 고도화 완료" },
], ],
@ -21,7 +24,10 @@ const HISTORY = [
year: "2023", year: "2023",
items: [ items: [
{ month: "09월", text: "인천광역시 로봇랜드 14층 본사 이전" }, { month: "09월", text: "인천광역시 로봇랜드 14층 본사 이전" },
{ month: "07월", text: "스마트 관광 예약 플랫폼 제주도관광공사 구축 완료" }, {
month: "07월",
text: "스마트 관광 예약 플랫폼 제주도관광공사 구축 완료",
},
{ month: "04월", text: "기업부설연구소 인정 (한국산업기술진흥협회)" }, { month: "04월", text: "기업부설연구소 인정 (한국산업기술진흥협회)" },
{ month: "01월", text: "UTM 드론 비행 승인 시스템 실증 사업 참여" }, { month: "01월", text: "UTM 드론 비행 승인 시스템 실증 사업 참여" },
], ],
@ -44,8 +50,14 @@ const HISTORY = [
{ {
year: "2019", year: "2019",
items: [ items: [
{ month: "08월", text: "인천국제공항공사 항공 운영 시스템 유지보수 계약" }, {
{ month: "03월", text: "드론 관제 및 비행 계획 승인 시스템 프로토타입 개발" }, month: "08월",
text: "인천국제공항공사 항공 운영 시스템 유지보수 계약",
},
{
month: "03월",
text: "드론 관제 및 비행 계획 승인 시스템 프로토타입 개발",
},
], ],
}, },
{ {
@ -66,7 +78,10 @@ const HISTORY = [
year: "2010", year: "2010",
items: [ items: [
{ month: "05월", text: "주식회사 팔네트웍스 설립" }, { month: "05월", text: "주식회사 팔네트웍스 설립" },
{ month: "05월", text: "항공 IT 소프트웨어 개발 전문 기업으로 사업 시작" }, {
month: "05월",
text: "항공 IT 소프트웨어 개발 전문 기업으로 사업 시작",
},
], ],
}, },
]; ];
@ -78,7 +93,13 @@ export default function HistoryPage() {
<article ref={ref}> <article ref={ref}>
<SubHero <SubHero
label="Company" label="Company"
title="14년의 기술 여정" title={
<>
<span style={{ color: "#111" }}>하늘길 기술의</span>
<br />
<em>변화와 성장</em>
</>
}
desc="항공 IT의 기초부터 UAM/UATM 미래 기술까지, 팔네트웍스가 걸어온 발자취입니다." desc="항공 IT의 기초부터 UAM/UATM 미래 기술까지, 팔네트웍스가 걸어온 발자취입니다."
navItems={COMPANY_NAV} navItems={COMPANY_NAV}
/> />

48
src/pages/company/PartnersPage.jsx

@ -44,19 +44,25 @@ export default function PartnersPage() {
<article ref={ref}> <article ref={ref}>
<SubHero <SubHero
label="Company" label="Company"
title="함께하는 고객과 파트너" title={
<>
<span style={{ color: "#111" }}>함께하는</span>
<br />
<em>고객과 파트너</em>
</>
}
desc="공공·항공·국방 분야 주요 기관과의 신뢰를 바탕으로 성장해왔습니다." desc="공공·항공·국방 분야 주요 기관과의 신뢰를 바탕으로 성장해왔습니다."
navItems={COMPANY_NAV} navItems={COMPANY_NAV}
/> />
<div className="sub-content"> <div className="sub-content">
{/* 주요 고객사 */} {/* 주요 고객사 */}
<section className="sub-section"> <section className="sub-section">
<span className="sub-section-eyebrow sub-fade-in">Clients</span> <span className="sub-section-eyebrow sub-fade-in">Clients</span>
<h2 className="sub-section-title sub-fade-in">주요 고객사</h2> <h2 className="sub-section-title sub-fade-in">주요 고객사</h2>
<p className="sub-section-lead sub-fade-in"> <p className="sub-section-lead sub-fade-in">
인천국제공항공사, 국방부 항공·공공 분야 핵심 기관들과 장기 파트너십을 유지하며 안정적인 IT 서비스를 제공합니다. 인천국제공항공사, 국방부 항공·공공 분야 핵심 기관들과 장기
파트너십을 유지하며 안정적인 IT 서비스를 제공합니다.
</p> </p>
<div className="partners-grid" style={{ marginTop: "40px" }}> <div className="partners-grid" style={{ marginTop: "40px" }}>
@ -77,7 +83,8 @@ export default function PartnersPage() {
<span className="sub-section-eyebrow sub-fade-in">Partners</span> <span className="sub-section-eyebrow sub-fade-in">Partners</span>
<h2 className="sub-section-title sub-fade-in">기술 협력사</h2> <h2 className="sub-section-title sub-fade-in">기술 협력사</h2>
<p className="sub-section-lead sub-fade-in"> <p className="sub-section-lead sub-fade-in">
국내외 선도 IT 기업들과의 협력을 통해 최적의 기술 솔루션을 고객에게 제공합니다. 국내외 선도 IT 기업들과의 협력을 통해 최적의 기술 솔루션을 고객에게
제공합니다.
</p> </p>
<div className="partners-grid" style={{ marginTop: "40px" }}> <div className="partners-grid" style={{ marginTop: "40px" }}>
@ -95,7 +102,8 @@ export default function PartnersPage() {
{/* 협력 제안 CTA */} {/* 협력 제안 CTA */}
<section className="sub-section sub-fade-in"> <section className="sub-section sub-fade-in">
<div style={{ <div
style={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "space-between", justifyContent: "space-between",
@ -104,13 +112,34 @@ export default function PartnersPage() {
padding: "48px 56px", padding: "48px 56px",
background: "var(--color-primary)", background: "var(--color-primary)",
borderRadius: "24px", borderRadius: "24px",
}}> }}
>
<div> <div>
<p style={{ margin: "0 0 8px", fontSize: "13px", fontWeight: 700, letterSpacing: ".12em", textTransform: "uppercase", color: "rgba(255,255,255,.65)" }}> <p
style={{
margin: "0 0 8px",
fontSize: "13px",
fontWeight: 700,
letterSpacing: ".12em",
textTransform: "uppercase",
color: "rgba(255,255,255,.65)",
}}
>
Become a Partner Become a Partner
</p> </p>
<h3 style={{ margin: 0, fontSize: "clamp(22px,2.2vw,30px)", fontWeight: 800, color: "#fff", letterSpacing: "-.03em", lineHeight: 1.25 }}> <h3
팔네트웍스와 함께 성장할<br />파트너를 찾습니다 style={{
margin: 0,
fontSize: "clamp(22px,2.2vw,30px)",
fontWeight: 800,
color: "#fff",
letterSpacing: "-.03em",
lineHeight: 1.25,
}}
>
팔네트웍스와 함께 성장할
<br />
파트너를 찾습니다
</h3> </h3>
</div> </div>
<a <a
@ -135,7 +164,6 @@ export default function PartnersPage() {
</a> </a>
</div> </div>
</section> </section>
</div> </div>
</article> </article>
); );

Loading…
Cancel
Save