Contextual Floating Button
화면 위에 떠 있으며 특정 상황에서만 나타나는 보조적인 동작을 위한 버튼입니다.
npm install @seed-design/lynx-react @seed-design/lynx-css
pnpm add @seed-design/lynx-react @seed-design/lynx-css
yarn add @seed-design/lynx-react @seed-design/lynx-css
bun add @seed-design/lynx-react @seed-design/lynx-css
import IconBellFill from "@karrotmarket/lynx-monochrome-icon/IconBellFill";
import { ContextualFloatingButton, PrefixIcon } from "@seed-design/lynx-react";
export default function Example() {
return (
<ContextualFloatingButton>
<PrefixIcon icon={<IconBellFill />} />
알림 설정
</ContextualFloatingButton>
);
}
style?CSSProperties | undefined
children?React.ReactNode
className?string | undefined
bindtap?EventHandler<BaseTouchEvent<Target>> | undefined
main-thread:bindtap?EventHandler<BaseTouchEvent<Element>> | undefined
Lynx에는 Float 컴포넌트가 없으므로 기준 frame의 position="relative"와 외부 Box의 native absolute bottom-center 배치로 같은 결과를 만듭니다.
import IconBellFill from "@karrotmarket/lynx-monochrome-icon/IconBellFill";
import { Box, ContextualFloatingButton, PrefixIcon } from "@seed-design/lynx-react";
export default function Example() {
return (
<Box
position="relative"
width="300px"
height="500px"
borderWidth={1}
borderColor="stroke.neutralMuted"
>
<Box position="absolute" width="full" bottom="x4" display="flex" justifyContent="center">
<ContextualFloatingButton>
<PrefixIcon icon={<IconBellFill />} />
알림 설정
</ContextualFloatingButton>
</Box>
</Box>
);
}
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { ContextualFloatingButton, PrefixIcon } from "@seed-design/lynx-react";
export default function Example() {
return (
<ContextualFloatingButton variant="solid">
<PrefixIcon icon={<IconPlusLine />} />
Solid Variant
</ContextualFloatingButton>
);
}
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { ContextualFloatingButton, PrefixIcon } from "@seed-design/lynx-react";
export default function Example() {
return (
<ContextualFloatingButton variant="layer">
<PrefixIcon icon={<IconPlusLine />} />
Layer Variant
</ContextualFloatingButton>
);
}
layout="iconOnly"에는 스크린 리더가 읽을 accessibility-label을 함께 지정하세요.
import IconPlusFill from "@karrotmarket/lynx-monochrome-icon/IconPlusFill";
import { ContextualFloatingButton, Icon } from "@seed-design/lynx-react";
export default function Example() {
return (
<ContextualFloatingButton layout="iconOnly" accessibility-label="추가">
<Icon icon={<IconPlusFill />} />
</ContextualFloatingButton>
);
}
탭하면 loading 상태가 즉시 시작되고 2초 뒤에 원래 상태로 돌아옵니다. Loading 중에는 탭할 수 없습니다.
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { useState } from "@lynx-js/react";
import { ContextualFloatingButton, PrefixIcon } from "@seed-design/lynx-react";
export default function Example() {
const [loading, setLoading] = useState(false);
function handleTap() {
"background only";
setLoading(true);
setTimeout(() => setLoading(false), 2000);
}
return (
<ContextualFloatingButton loading={loading} bindtap={handleTap}>
<PrefixIcon icon={<IconPlusLine />} />
시간이 걸리는 액션
</ContextualFloatingButton>
);
}
- 이벤트 핸들링:
onClick 대신 bindtap 또는 main-thread:bindtap을 사용합니다.
- 렌더링 요소: HTML
<button> 대신 네이티브 <view>와 <text> 요소를 렌더링합니다. HTML form props와 asChild는 지원하지 않습니다.
- 접근성:
aria-label 대신 native accessibility-label을 사용합니다.
- 아이콘: 웹 SVG 대신 native icon asset을
PrefixIcon 또는 Icon child slot으로 전달합니다. recipe 색상은 native icon tint로 동기화됩니다.
- Loading: 두 플랫폼 모두 spinner를 absolute로 얹고 content를 숨겨 버튼 폭을 유지합니다. Lynx는 loading 중 tap을 차단하지만, React는 loading만으로
onClick을 차단하지 않습니다.
- Scale Feedback: root의
transform은 Scale Feedback hook이 소유합니다. 위치를 transform으로 조정해야 할 때는 버튼 root가 아닌 외부 wrapper에 적용하세요.