임동욱 임동욱 08-18
feat: 카드·모달에 그림이 들어가는 예시 추가
카드는 이미 그림 슬롯이 있어 예시만 넣었고, 모달은 contents에 들어온
그림이 폭을 채우도록 규칙을 더했다. 자리표시 그림은 인라인 SVG로 둬서
@fox가 앱 이미지 경로에 기대지 않게 했다.

Co-Authored-By: Claude Opus 5 
@c9417c608a35407c1d325225f1998415c3cd6844
@fox/dev-test/component-registry.tsx
--- @fox/dev-test/component-registry.tsx
+++ @fox/dev-test/component-registry.tsx
@@ -607,17 +607,21 @@
   withUtility = false,
   withActions = true,
   closable = true,
+  withImage = false,
+  openLabel,
 }: {
   size: "sm" | "md" | "lg" | "full";
   title?: string;
   withUtility?: boolean;
   withActions?: boolean;
   closable?: boolean;
+  withImage?: boolean;
+  openLabel?: string;
 }) {
   const [open, setOpen] = useState(false);
   return (
     <>
-      <FoxButton size="md" type="secondary" label={`${size} 열기`} onAction={() => setOpen(true)} />
+      <FoxButton size="md" type="secondary" label={openLabel ?? `${size} 열기`} onAction={() => setOpen(true)} />
       <FoxModal
         open={open}
         onClose={() => setOpen(false)}
@@ -638,12 +642,33 @@
           ) : undefined
         }
       >
+        {/* 시안의 contents 슬롯에는 그림이 들어간 예가 있다 — 슬롯이라 무엇이든 놓을 수 있다. */}
+        {withImage && <DemoThumb />}
         <p>
           대화 상자는 사용자에게 작업에 대해 알리고 중요한 정보를 포함하거나 결정이 필요하거나
           여러 작업을 포함할 수 있습니다.
         </p>
       </FoxModal>
     </>
+  );
+}
+
+/**
+ * 그림 자리 확인용 도형. 실제 사진 대신 쓴다 — `@fox`는 앱의 이미지 경로를 참조하지 않고
+ * (다른 프로젝트로 통째로 복사되어야 한다), 카탈로그가 외부 파일에 기대지도 않게 한다.
+ * 토큰 색을 그대로 쓰므로 라이트·다크에서 함께 바뀐다.
+ */
+function DemoThumb() {
+  return (
+    <svg viewBox="0 0 320 180" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
+      <rect width="320" height="180" fill="var(--fox-color-surface-neutral-gray-strong)" />
+      <circle cx="232" cy="52" r="26" fill="var(--fox-color-element-theme-primary)" opacity="0.35" />
+      <path
+        d="M0 148l72-52 54 38 60-46 134 92v0H0z"
+        fill="var(--fox-color-element-neutral-default)"
+        opacity="0.45"
+      />
+    </svg>
   );
 }
 
@@ -3365,6 +3390,15 @@
         ),
       },
       {
+        label: "그림이 들어갈 때 — contents는 슬롯이라 무엇이든 놓입니다",
+        node: (
+          <div className={styles.demoRow}>
+            <ModalDemo size="md" title="타이틀" withImage openLabel="그림 있는 모달 열기" />
+            <ModalDemo size="lg" title="타이틀" withImage openLabel="lg 그림 모달 열기" />
+          </div>
+        ),
+      },
+      {
         label: "아래쪽 왼편 (utility) — 시안의 체크박스 자리",
         node: (
           <div className={styles.demoRow}>
@@ -3436,6 +3470,24 @@
       "Figma 시안(card 441:6006)을 옮겼습니다. 크기 넷은 여백과 모서리만 바꿉니다 — 폭은 놓이는 자리가 정합니다(시안은 320px 자리에 뒀습니다). 그림은 16:9로 잘리고 상자가 모서리를 넘지 않게 자릅니다.",
     variants: [
       {
+        label: "그림이 있을 때 — 16:9로 잘리고 위쪽 모서리를 넘지 않습니다",
+        node: (
+          <div className={styles.demoRow}>
+            {(["xlg", "md"] as const).map((size) => (
+              <div key={size} style={{ inlineSize: 320 }}>
+                <FoxCard
+                  size={size}
+                  image={<DemoThumb />}
+                  title="타이틀 영역"
+                  description="간단한 설명이 들어가는 영역입니다."
+                  actions={<FoxTextButton size="md" label="액션1" />}
+                />
+              </div>
+            ))}
+          </div>
+        ),
+      },
+      {
         label: "크기 — xlg · lg · md · sm (여백과 모서리가 달라집니다)",
         node: (
           <div className={styles.demoRow}>
@fox/styles/_fox-modal.scss
--- @fox/styles/_fox-modal.scss
+++ @fox/styles/_fox-modal.scss
@@ -132,6 +132,14 @@
     font-weight: fox.font-weight(regular);
     line-height: 1.5;
     letter-spacing: -0.025em;
+
+    // 그림이 들어오면 폭을 채운다 — 시안의 contents 슬롯에 든 것도 폭 100%다.
+    > img,
+    > svg,
+    > picture {
+      inline-size: 100%;
+      block-size: auto;
+    }
   }
 
   // ── 아래쪽 ────────────────────────────────────────────────────────────────
Add a comment
List