"use client"; import type { ReactNode, Ref } from "react"; import { cx } from "../../utils"; export type FoxIconButtonType = "default" | "ghost" | "overlay"; export type FoxIconButtonSize = "lg" | "md" | "sm" | "xsm"; export interface FoxIconButtonProps { type?: FoxIconButtonType; size: FoxIconButtonSize; /** 네이티브 `type` — prop의 `type`이 시각 계열을 쓰므로 분리했다. */ htmlType?: "button" | "submit" | "reset"; /** 배치 조정용. 모양이 달라야 하면 여기 말고 `type`을 추가한다. */ className?: string; /** `currentColor`로 그린 SVG여야 계열별 색이 적용된다. 크기는 슬롯이 정한다. */ icon: ReactNode; /** 글자가 보이지 않으므로 `aria-label`이 된다. 무엇을 하는 버튼인지 적는다. */ label: string; /** * 주면 토글 버튼이 된다(`aria-pressed`). 생략하면 일반 아이콘 버튼이다. * 호출부가 소유한다 — 버튼이 스스로 뒤집지 않는다. */ active?: boolean; disabled?: boolean; /** 참이면 렌더하지 않는다(DOM에 남지 않는다). */ hidden?: boolean; onAction?: () => void; /** 포인터가 올라오면 `true`, 벗어나면 `false`. */ onHoverChange?: (hovered: boolean) => void; ref?: Ref; } const TYPE_CLASS: Record = { default: "fox-icon-button--default", ghost: "fox-icon-button--ghost", overlay: "fox-icon-button--overlay", }; const SIZE_CLASS: Record = { lg: "fox-icon-button--lg", md: "fox-icon-button--md", sm: "fox-icon-button--sm", xsm: "fox-icon-button--xsm", }; /** * @fox 아이콘 버튼. 상태를 갖지 않는다. * * `active`를 주면 토글로 동작한다 — 시안의 btn-ico와 btn-ico-toggle이 계열·크기·모양이 * 같고 켜짐 상태만 다르므로 한 컴포넌트로 둔다. * * ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"` * (또는 개별 파티셜)로 한 번 불러와야 한다. */ export function FoxIconButton({ type = "default", size, htmlType = "button", className, icon, label, active, disabled = false, hidden = false, onAction, onHoverChange, ref, }: FoxIconButtonProps) { if (hidden) { return null; } return ( ); }