refactor(shell): KakaoFloatButton 컴포넌트 추출 — PublicShell 인라인 → 별도 컴포넌트
D 트랙 2/4. P1 Task 3 review I-1 후속: - PublicShell의 인라인 카카오 버튼 JSX + style 블록 → KakaoFloatButton.tsx - KAKAO_OPENCHAT_URL은 lib/contact 에서 import - SVG에 aria-hidden 추가 (parent aria-label 우선) 향후 admin shell 또는 다른 surface에서 재사용 가능. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
62
app/components/KakaoFloatButton.tsx
Normal file
62
app/components/KakaoFloatButton.tsx
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import { KAKAO_OPENCHAT_URL } from '@/lib/contact';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 카카오 1:1 상담 플로팅 버튼.
|
||||||
|
* PublicShell footer 다음에 마운트되어 모든 공개 페이지에 노출.
|
||||||
|
*/
|
||||||
|
export default function KakaoFloatButton() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<a
|
||||||
|
href={KAKAO_OPENCHAT_URL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="kakao-float-btn"
|
||||||
|
aria-label="카카오 오픈채팅 상담"
|
||||||
|
title="카카오 오픈채팅으로 1:1 상담"
|
||||||
|
>
|
||||||
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor" aria-hidden>
|
||||||
|
<path d="M12 3C6.477 3 2 6.589 2 11c0 2.713 1.574 5.117 4 6.663V21l3.5-2.1A11.5 11.5 0 0 0 12 19c5.523 0 10-3.589 10-8s-4.477-8-10-8z"/>
|
||||||
|
</svg>
|
||||||
|
<span className="kakao-float-label">1:1 상담</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style>{`
|
||||||
|
.kakao-float-btn {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 28px;
|
||||||
|
right: 28px;
|
||||||
|
z-index: 50;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: #FEE500;
|
||||||
|
color: #3A1D1D;
|
||||||
|
padding: 12px 18px;
|
||||||
|
border-radius: 100px;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 14px;
|
||||||
|
text-decoration: none;
|
||||||
|
box-shadow: 0 4px 20px rgba(254,229,0,0.4), 0 2px 8px rgba(0,0,0,0.15);
|
||||||
|
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.kakao-float-btn:hover {
|
||||||
|
transform: translateY(-3px) scale(1.04);
|
||||||
|
box-shadow: 0 8px 28px rgba(254,229,0,0.5), 0 4px 12px rgba(0,0,0,0.15);
|
||||||
|
}
|
||||||
|
.kakao-float-btn:active {
|
||||||
|
transform: translateY(-1px) scale(0.98);
|
||||||
|
}
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.kakao-float-btn {
|
||||||
|
bottom: 20px;
|
||||||
|
right: 16px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import TopNav from './TopNav';
|
import TopNav from './TopNav';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import KakaoFloatButton from './KakaoFloatButton';
|
||||||
|
|
||||||
export default function PublicShell({ children }: { children: React.ReactNode }) {
|
export default function PublicShell({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
@@ -116,57 +117,7 @@ export default function PublicShell({ children }: { children: React.ReactNode })
|
|||||||
</footer>
|
</footer>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{/* 카카오 오픈채팅 플로팅 버튼 */}
|
<KakaoFloatButton />
|
||||||
<a
|
|
||||||
href="https://open.kakao.com/o/s9stoNvb"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="kakao-float-btn"
|
|
||||||
aria-label="카카오 오픈채팅 상담"
|
|
||||||
title="카카오 오픈채팅으로 1:1 상담"
|
|
||||||
>
|
|
||||||
<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path d="M12 3C6.477 3 2 6.589 2 11c0 2.713 1.574 5.117 4 6.663V21l3.5-2.1A11.5 11.5 0 0 0 12 19c5.523 0 10-3.589 10-8s-4.477-8-10-8z"/>
|
|
||||||
</svg>
|
|
||||||
<span className="kakao-float-label">1:1 상담</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<style>{`
|
|
||||||
.kakao-float-btn {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 28px;
|
|
||||||
right: 28px;
|
|
||||||
z-index: 50;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
background: #FEE500;
|
|
||||||
color: #3A1D1D;
|
|
||||||
padding: 12px 18px;
|
|
||||||
border-radius: 100px;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 14px;
|
|
||||||
text-decoration: none;
|
|
||||||
box-shadow: 0 4px 20px rgba(254,229,0,0.4), 0 2px 8px rgba(0,0,0,0.15);
|
|
||||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.kakao-float-btn:hover {
|
|
||||||
transform: translateY(-3px) scale(1.04);
|
|
||||||
box-shadow: 0 8px 28px rgba(254,229,0,0.5), 0 4px 12px rgba(0,0,0,0.15);
|
|
||||||
}
|
|
||||||
.kakao-float-btn:active {
|
|
||||||
transform: translateY(-1px) scale(0.98);
|
|
||||||
}
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.kakao-float-btn {
|
|
||||||
bottom: 20px;
|
|
||||||
right: 16px;
|
|
||||||
padding: 10px 14px;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user