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는 두 시점에 같은 동기화를 수행합니다.

  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

ParameterTypeDescription
depsDependencyListicon의 CSS color에 영향을 주는 의존성 목록입니다. 값이 바뀌면 main thread에서 tint color를 다시 동기화합니다.
options.sourceRefRefObject<MainThread.Element>optional. icon 자체가 아니라 wrapper element의 computed color를 source로 사용할 때 전달합니다.

Return

PropertyTypeDescription
refRefObject<MainThread.Element>icon <image>의 main-thread ref입니다.
main-thread:binduiappear() => voidUI 노드가 appear 될 때 computed colortint-color로 다시 반영하는 main-thread handler입니다.

사용 시 주의사항

  • monochrome icon처럼 native <image tint-color>로 색상을 입히는 icon에 사용합니다.
  • multicolor icon처럼 원본 이미지 색상을 유지해야 하는 경우에는 사용하지 않습니다.
  • deps 누락은 stale tint의 원인이 됩니다. slot className이 바뀌는 상태를 함께 넣어주세요.
  • icon element가 자체 refmain-thread:binduiappear를 필요로 한다면, 해당 slot에서 병합 전략을 별도로 정해야 합니다. SEED Lynx 컴포넌트의 기본 icon slot은 useIconColor가 main-thread ref를 소유합니다.

웹 버전과의 차이

항목Lynx (useIconColor)Web
아이콘 렌더링<image> + native tint-colorSVG / CSS currentColor
색상 source of truthrecipe CSS color의 computed valueCSS cascade / currentColor
동기화 방식main thread에서 computed color를 읽어 attribute로 mirror별도 bridge 불필요
list 초기 렌더binduiappear에서 한 번 더 sync해당 없음

Last updated on

On this page