# useIconColor
URL: /lynx/hooks/use-icon-color
Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/hooks/use-icon-color.mdx
Lynx image 아이콘의 CSS color를 native tint-color로 동기화하는 훅입니다.
사용 가능 버전: @seed-design/lynx-react@0.1.0
## Import
```ts
import { useIconColor } from "@seed-design/lynx-react";
```
`useIconColor`는 `@seed-design/lynx-react` 패키지에 포함되어 있습니다. 주로 SEED Lynx 컴포넌트가 monochrome icon을 슬롯에 주입할 때 사용합니다.
## Usage
### 기본 사용
```tsx
import { cloneElement, isValidElement, type ReactElement } from "react";
import { useMainThreadRef } from "@lynx-js/react";
import { useIconColor } from "@seed-design/lynx-react";
function IconSlot({ icon, variant, disabled }: {
icon: ReactElement;
variant: string;
disabled: boolean;
}) {
const wrapperRef = useMainThreadRef(null);
const iconColorProps = useIconColor([variant, disabled], { sourceRef: wrapperRef });
if (!isValidElement(icon)) return null;
return (
{cloneElement(icon, {
...iconColorProps,
style: { width: "100%", height: "100%" },
})}
);
}
```
`useIconColor`가 반환하는 객체는 icon element에 그대로 주입할 수 있는 props입니다. `sourceRef`를 전달하면 wrapper의 computed `color`를 읽어 icon ``의 `tint-color`에 반영합니다. 기존처럼 `sourceRef` 없이 쓰면 icon element 자신의 computed `color`를 읽습니다.
### 상태 의존성
```tsx
const iconColorProps = useIconColor([
variant,
disabled,
loading,
checked,
pressed,
tone,
size,
]);
```
`deps`에는 icon의 CSS `color`에 영향을 줄 수 있는 값을 모두 포함합니다. 예를 들어 ActionButton은 `variant`, `disabled`, `loading`을 포함하고, Checkbox와 RadioGroup indicator는 `checked`, `pressed`, `tone`, `size`처럼 indicator 색상에 영향을 주는 상태를 함께 포함합니다.
## 왜 필요한가
Lynx의 monochrome icon은 내부적으로 ``를 렌더링하고, 실제 아이콘 색상은 native `tint-color` attribute로 적용됩니다. 반면 SEED recipe는 slot className에 CSS `color`를 선언합니다.
```css
.seed-action-button__icon {
color: var(--seed-color-palette-static-white);
}
```
웹에서는 SVG나 CSS `currentColor` 패턴으로 이 색상을 자연스럽게 사용할 수 있지만, Lynx ``의 `tint-color` 경로에서는 CSS variable 문자열을 직접 넣는 방식이 안정적으로 동작하지 않습니다. 따라서 `useIconColor`는 main thread에서 computed `color`를 읽고, resolved color를 `tint-color` attribute에 반영합니다.
## 동작 방식
`useIconColor`는 두 시점에 같은 동기화를 수행합니다.
1. `deps`가 바뀐 뒤 React effect에서 `runOnMainThread`로 동기화합니다.
2. icon의 UI 노드가 appear 될 때 `main-thread:binduiappear`에서 한 번 더 동기화합니다.
두 번째 동기화는 특히 `list` / `list-item` 내부에서 중요합니다. `VariantTable`처럼 list 기반으로 많은 preview를 렌더링하는 화면에서는 background thread의 effect가 실행되는 시점과 main thread UI 노드가 실제로 attach되어 computed style을 읽을 수 있는 시점이 어긋날 수 있습니다. `binduiappear`는 polling이나 timer retry 없이, UI 노드가 보이는 생명주기에서 같은 sync를 한 번 더 실행하기 위한 장치입니다.
## 설계 결정
`useIconColor`는 색상 의미를 JS에서 다시 해석하지 않습니다. SEED semantic token 이름이나 palette token 값을 `@seed-design/lynx-react` 안에 복제하지 않고, qvism recipe와 page/root에 주입된 CSS variable이 색상의 source of truth가 되도록 둡니다.
이 결정은 다음 이유 때문입니다.
- 사용자가 `#123144`, `rgb(...)`, theme별 semantic token 등 어떤 색을 쓰더라도 CSS computed value를 기준으로 처리할 수 있어야 합니다.
- React 패키지에 semantic color table을 두면 theme, token, recipe 변경과 쉽게 어긋납니다.
- `tint-color`에 CSS variable 문자열을 직접 넣는 방식은 Lynx image 경로에서 충분히 안정적이지 않습니다.
- `setTimeout`이나 frame retry를 늘리는 방식은 list 초기 렌더 타이밍 문제를 가릴 수는 있어도, 원인을 코드에 설명하기 어렵고 성능 리스크가 커집니다.
- catalog 전용 `key` remount나 `recyclable={false}` workaround는 컴포넌트 패키지의 실제 문제를 숨길 수 있습니다.
결론적으로 `useIconColor`는 “CSS computed color를 native image tint에 반영하는 얇은 bridge”입니다. 색상 계산은 recipe와 CSS가 담당하고, hook은 그 결과를 Lynx native attribute로 전달하는 책임만 가집니다.
## API
### Parameters
| Parameter | Type | Description |
| ------------------- | ------------------------------- | -------------------------------------------------------------------------------- |
| `deps` | `DependencyList` | icon의 CSS `color`에 영향을 주는 의존성 목록입니다. 값이 바뀌면 main thread에서 tint color를 다시 동기화합니다. |
| `options.sourceRef` | `RefObject` | optional. icon 자체가 아니라 wrapper element의 computed `color`를 source로 사용할 때 전달합니다. |
### Return
| Property | Type | Description |
| -------------------------- | ------------------------------- | --------------------------------------------------------------------------------- |
| `ref` | `RefObject` | icon ``의 main-thread ref입니다. |
| `main-thread:binduiappear` | `() => void` | UI 노드가 appear 될 때 computed `color`를 `tint-color`로 다시 반영하는 main-thread handler입니다. |
## 사용 시 주의사항
- monochrome icon처럼 native ``로 색상을 입히는 icon에 사용합니다.
- multicolor icon처럼 원본 이미지 색상을 유지해야 하는 경우에는 사용하지 않습니다.
- `deps` 누락은 stale tint의 원인이 됩니다. slot className이 바뀌는 상태를 함께 넣어주세요.
- icon element가 자체 `ref`나 `main-thread:binduiappear`를 필요로 한다면, 해당 slot에서 병합 전략을 별도로 정해야 합니다. SEED Lynx 컴포넌트의 기본 icon slot은 `useIconColor`가 main-thread ref를 소유합니다.
## 웹 버전과의 차이
| 항목 | Lynx (`useIconColor`) | Web |
| ------------------ | -------------------------------------------------- | ---------------------------- |
| 아이콘 렌더링 | `` + native `tint-color` | SVG / CSS `currentColor` |
| 색상 source of truth | recipe CSS `color`의 computed value | CSS cascade / `currentColor` |
| 동기화 방식 | main thread에서 computed color를 읽어 attribute로 mirror | 별도 bridge 불필요 |
| list 초기 렌더 | `binduiappear`에서 한 번 더 sync | 해당 없음 |