useIconColor
Lynx image 아이콘의 CSS color를 native tint-color로 동기화하는 훅입니다.
Import
import { useIconColor } from "@seed-design/lynx-react";useIconColor는 @seed-design/lynx-react 패키지에 포함되어 있습니다. 주로 SEED Lynx 컴포넌트가 monochrome icon을 슬롯에 주입할 때 사용합니다.
Usage
기본 사용
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 (
<view main-thread:ref={wrapperRef} className="my-icon-slot">
{cloneElement(icon, {
...iconColorProps,
style: { width: "100%", height: "100%" },
})}
</view>
);
}useIconColor가 반환하는 객체는 icon element에 그대로 주입할 수 있는 props입니다. sourceRef를 전달하면 wrapper의 computed color를 읽어 icon <image>의 tint-color에 반영합니다. 기존처럼 sourceRef 없이 쓰면 icon element 자신의 computed color를 읽습니다.
상태 의존성
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은 내부적으로 <image>를 렌더링하고, 실제 아이콘 색상은 native tint-color attribute로 적용됩니다. 반면 SEED recipe는 slot className에 CSS color를 선언합니다.
.seed-action-button__icon {
color: var(--seed-color-palette-static-white);
}웹에서는 SVG나 CSS currentColor 패턴으로 이 색상을 자연스럽게 사용할 수 있지만, Lynx <image>의 tint-color 경로에서는 CSS variable 문자열을 직접 넣는 방식이 안정적으로 동작하지 않습니다. 따라서 useIconColor는 main thread에서 computed color를 읽고, resolved color를 tint-color attribute에 반영합니다.
동작 방식
useIconColor는 두 시점에 같은 동기화를 수행합니다.
deps가 바뀐 뒤 React effect에서runOnMainThread로 동기화합니다.- 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 전용
keyremount나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<MainThread.Element> | optional. icon 자체가 아니라 wrapper element의 computed color를 source로 사용할 때 전달합니다. |
Return
| Property | Type | Description |
|---|---|---|
ref | RefObject<MainThread.Element> | icon <image>의 main-thread ref입니다. |
main-thread:binduiappear | () => void | UI 노드가 appear 될 때 computed color를 tint-color로 다시 반영하는 main-thread handler입니다. |
사용 시 주의사항
- monochrome icon처럼 native
<image tint-color>로 색상을 입히는 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 |
|---|---|---|
| 아이콘 렌더링 | <image> + 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 | 해당 없음 |
Last updated on