feat: FAB 플로팅 액션 버튼 컴포넌트
This commit is contained in:
50
src/components/FAB.css
Normal file
50
src/components/FAB.css
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* FAB — Floating Action Button (mobile-only) */
|
||||||
|
|
||||||
|
.fab {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
right: 20px;
|
||||||
|
bottom: calc(var(--bottom-nav-h) + var(--safe-area-bottom) + 16px);
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--gradient-accent);
|
||||||
|
border: none;
|
||||||
|
color: #000;
|
||||||
|
font-size: 24px;
|
||||||
|
z-index: 250;
|
||||||
|
box-shadow: 0 0 0 1px var(--neon-cyan-dim), 0 4px 16px rgba(0, 255, 255, 0.25);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
transition: transform 0.15s var(--ease-out), box-shadow 0.15s var(--ease-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.fab {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fab:active {
|
||||||
|
transform: scale(0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fab__icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Variant: positioned above a music mini-player */
|
||||||
|
.fab--above-player {
|
||||||
|
bottom: calc(var(--bottom-nav-h) + var(--safe-area-bottom) + 16px + 56px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduced motion */
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.fab {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/components/FAB.jsx
Normal file
37
src/components/FAB.jsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { useIsMobile } from '../hooks/useIsMobile';
|
||||||
|
import './FAB.css';
|
||||||
|
|
||||||
|
const PlusIcon = () => (
|
||||||
|
<svg
|
||||||
|
className="fab__icon"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 5v14M5 12h14"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default function FAB({ onClick, icon, label = '액션', className = '' }) {
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
|
if (!isMobile) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`fab ${className}`}
|
||||||
|
onClick={onClick}
|
||||||
|
aria-label={label}
|
||||||
|
>
|
||||||
|
{icon ?? <PlusIcon />}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user