file: ai-integration/llms-txt.mdx # LLMs.txt 대규모 언어 모델(LLM)이 SEED Design React를 쉽게 이해할 수 있도록 LLMs.txt를 제공합니다. *** title: LLMs.txt description: 대규모 언어 모델(LLM)이 SEED Design React를 쉽게 이해할 수 있도록 LLMs.txt를 제공합니다. ----------------------------------------------------------------------------- ## 구조 다음과 같은 LLMs.txt 파일들을 제공합니다: * [llms.txt](https://seed-design.io/react/llms.txt): LLMs.txt 파일들의 구조를 제공하는 메인 파일입니다. * [llms-full.txt](https://seed-design.io/react/llms-full.txt): SEED Design React의 모든 문서를 포함합니다. * [llms-changelog.txt](https://seed-design.io/react/llms-changelog.txt): 최신 업데이트와 변경사항을 포함하여 버전별 변경 내역을 확인할 수 있습니다. * [llms-components.txt](https://seed-design.io/react/llms-components.txt): 각 컴포넌트의 문서의 진입점입니다. * [llms-components/action-button.txt](https://seed-design.io/react/llms-components/action-button.txt) * [llms-components/chip.txt](https://seed-design.io/react/llms-components/chip.txt) * etc... ## AI 도구와 함께 사용하기 ### Cursor Cursor의 `@Docs` 기능을 사용하여 프로젝트에 LLMs.txt 파일을 포함할 수 있습니다. [Cursor @Docs에 대해 자세히 알아보기](https://docs.cursor.com/context/@-symbols/@-docs) file: ai-integration/mcp.mdx # MCP AI Agent를 활용해 생산성을 높일 수 있는 Model Context Protocol(MCP)를 제공합니다. *** title: MCP description: AI Agent를 활용해 생산성을 높일 수 있는 Model Context Protocol(MCP)를 제공합니다. --------------------------------------------------------------------------- ## 설치 ### Prerequisites * [Bun](https://bun.sh/docs/installation) ### Install MCP Server ```json { "mcpServers": { "SEED Design": { "command": "bunx", // or your package manager's execution command "args": ["-y", "@seed-design/mcp@latest"], "type": "stdio" } } } ``` [Cursor MCP에 대해 자세히 알아보기](https://docs.cursor.com/context/model-context-protocol) ```sh claude mcp add SEED bunx @seed-design/mcp@latest ``` ### Figma [Figma MCP 플러그인](https://www.figma.com/community/plugin/1496384010980477154)을 설치합니다. ## 사용법 ### 웹소켓 서버 실행 ```bash bunx --bun @seed-design/mcp@latest socket ``` ### Figma 플러그인 실행 설치된 SEED Design MCP 플러그인을 실행합니다. 연결이 완료되면, `선택된 노드를 참고해 React로 구현해주세요.` 와 같은 요청을 전달할 수 있습니다. ## 주요 툴 목록 ### `get_selection` 선택한 노드의 id를 반환합니다. ### `get_node_react_code` 노드의 React codegen 결과를 반환합니다. ### `export_node_as_image` 노드의 이미지를 반환합니다. [Playwright MCP](https://github.com/microsoft/playwright-mcp) 등과 통합해 이미지 단위 비교에 활용할 수 있습니다. ### `add_annotations` Figma 파일에 Annotation을 추가합니다. [참고](https://help.figma.com/hc/en-us/articles/20774752502935-Add-measurements-and-annotate-designs) ## 커스텀 설정 사용하기 `--config` 플래그를 통해 커스텀 설정 파일을 로드할 수 있습니다. ```bash bunx --bun @seed-design/mcp@latest --config /path/to/config.ts ``` ### 지원하는 설정 파일 형식 `@seed-design/mcp`는 다음 확장자의 설정 파일을 지원합니다: * `.js` * `.mjs` * `.ts` * `.mts` ### 설정 파일 예시 ```typescript import { type react, defineComponentHandler, createElement } from "@seed-design/figma"; export default { extend: { componentHandlers: [ (_deps: react.ComponentHandlerDeps) => defineComponentHandler( "figma_component_key", ({ componentProperties: props }) => { const tone = props.Tone.value.toLowerCase(); return createElement( "CustomButton", { tone } ); } ) ] }, } satisfies react.CreatePipelineConfig; ``` ### MCP로 ComponentHandler 작성하기 #### 프롬프트 복사 아래 프롬프트를 복사해 파일로 저장합니다. Cursor IDE를 사용하는 경우, [Cursor rule](https://docs.cursor.com/context/rules)로 저장할 수 있습니다. ```markdown # ComponentHandler Implementation Guide ## Initial Context Gathering 1. **Analyze Figma Selection**: - Use \`get_selection()\` to examine the currently selected node(s) - If no selection exists, prompt the user to select a specific component node - Verify the selected node is a component that can be transformed 2. **Retrieve Component Information**: - Use \`get_component_info(nodeId)\` to extract detailed information about the component - Collect the component key, all component properties, and variant definitions - Identify any nested components or instances that might need special handling ## Component Analysis and Planning 3. **Determine Component Structure**: - Analyze the component's visual structure, layout, and behavior patterns - If the target React component implementation is unknown, request an example or props interface - Identify which Figma properties should map to which React props 4. **Define Transformation Strategy**: - Plan how to handle variants, properties, nested components and children - Determine if additional utilities or helper functions are needed - Consider edge cases and special requirements for this component ## Implementation 5. **Create Component Handler**: - Implement the handler using the following pattern: \`\`\`typescript import { createElement, defineComponentHandler, type InferComponentDefinition, type react, } from "@seed-design/figma"; // Define component properties based on Figma definition export type ComponentNameProperties = InferComponentDefinition<{ // Map all component properties from Figma // Example: "PropertyName": { type: "VARIANT" | "TEXT" | "BOOLEAN" | "INSTANCE_SWAP", variantOptions?: string[], // For VARIANT type defaultValue?: string | boolean } }>; // Create and export the handler export const createComponentNameHandler = (_deps: react.ComponentHandlerDeps) => defineComponentHandler( "component-key-from-figma", // Replace with actual component key ({ componentProperties: props }) => { // Transform Figma properties to React props // Use conditionals for variants and property handling return createElement( "ComponentName", // The React component name { // Map properties appropriately propName: props.PropertyName.value, // Add additional props as needed }, [], // Nested elements if any (undefined or omitted if not needed) "Optional comment for accessibility or development notes, use sparingly" ); } ); \`\`\` ## Validation and Testing 6. **Verify Handler Functionality**: - Test the handler with different component variants - Ensure all properties are correctly mapped and transformed - Check that nested components and children are handled properly ## Best Practices - Create reusable helper functions for common transformation patterns - Handle edge cases and optional properties gracefully - Add descriptive comments for complex transformations - Consider performance implications for deeply nested components - Ensure type safety throughout the transformation process ``` #### 프롬프트 실행 저장된 프롬프트 파일과 구현해야 할 컴포넌트 파일을 맥락으로 전달하며 프롬프트를 실행합니다. **예시**: ```bash @CustomButton.tsx @ComponentHandlerRule.md CustomButton 컴포넌트의 ComponentHandler를 구현해주세요. ``` #### 결과 확인 프롬프트 실행 결과로 생성된 ComponentHandler를 확인합니다. **예시** ```typescript import { createElement, defineComponentHandler, type InferComponentDefinition, type react, } from "@seed-design/figma"; export type CustomButtonProperties = InferComponentDefinition<{ tone: { type: "VARIANT"; variantOptions: ["neutral", "brand"]; }; }>; export const createCustomButtonHandler = (_deps: react.ComponentHandlerDeps) => defineComponentHandler( "figma_component_key", ({ componentProperties: props }) => { const tone = props.tone.value.toLowerCase(); return createElement( "CustomButton", { tone } ); } ) ``` #### 설정 파일 적용 생성된 ComponentHandler를 설정 파일에 추가합니다. ```typescript import { type react } from "@seed-design/figma"; import { createCustomButtonHandler } from "./CustomButton"; export default { extend: { componentHandlers: [ createCustomButtonHandler, ] }, } satisfies react.CreatePipelineConfig; ``` file: components/(deprecated)/action-chip.mdx # Action Chip *** ## title: Action Chip ```tsx import { ActionChip } from "@seed-design/react"; export default function ActionChipPreview() { return 라벨; } ``` ## Usage ```tsx import { ActionChip } from "@seed-design/react"; ``` ```tsx ``` ## Props

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Medium ```tsx import { ActionChip } from "@seed-design/react"; export default function ActionChipMedium() { return 라벨; } ``` ### Small ```tsx import { ActionChip } from "@seed-design/react"; export default function ActionChipSmall() { return 라벨; } ``` ### Icon Only ```tsx import { IconPlusFill } from "@karrotmarket/react-monochrome-icon"; import { ActionChip, Icon } from "@seed-design/react"; export default function ActionChipIconOnly() { return ( } /> ); } ``` ### Prefix Icon ```tsx import { IconPlusFill } from "@karrotmarket/react-monochrome-icon"; import { ActionChip, PrefixIcon } from "@seed-design/react"; export default function ActionChipPrefixIcon() { return ( } /> 라벨 ); } ``` ### Suffix Icon ```tsx import { IconChevronDownFill } from "@karrotmarket/react-monochrome-icon"; import { ActionChip, SuffixIcon } from "@seed-design/react"; export default function ActionChipSuffixIcon() { return ( 라벨 } /> ); } ``` file: components/(deprecated)/action-sheet.mdx # Action Sheet *** ## title: Action Sheet ```tsx import { ActionSheetContent, ActionSheetItem, ActionSheetRoot, ActionSheetTrigger, } from "seed-design/ui/action-sheet"; import { ActionButton } from "seed-design/ui/action-button"; const ActionSheetPreview = () => { return ( Open ); }; export default ActionSheetPreview; ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add action-sheet ``` ```bash pnpm dlx @seed-design/cli@latest add action-sheet ``` ```bash yarn dlx @seed-design/cli@latest add action-sheet ``` ```bash bun x @seed-design/cli@latest add action-sheet ``` ## Props ### `ActionSheetRoot`

{"The role of the dialog."}

}, closeOnInteractOutside: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the outside is clicked"}

}, closeOnEscape: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the escape key is pressed"}

}, lazyMount: { "type": "boolean", "default": "false", description: <>

{"Whether to enable lazy mounting"}

}, unmountOnExit: { "type": "boolean", "default": "false", description: <>

{"Whether to unmount on exit."}

}, open: { "type": "boolean", "default": undefined }, defaultOpen: { "type": "boolean", "default": undefined }, onOpenChange: { "type": "((open: boolean) => void)", "default": undefined } }} /> ### `ActionSheetContent`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `ActionSheetItem` ## Examples ### Portalled ``으로 ``를 감싸서 컨텐츠를 원하는 요소에 렌더링할 수 있습니다. Portal은 기본적으로 `document.body`에 렌더링됩니다. ```tsx import { Portal } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { ActionSheetContent, ActionSheetItem, ActionSheetRoot, ActionSheetTrigger, } from "seed-design/ui/action-sheet"; const ActionSheetPortalled = () => { return ( Open ); }; export default ActionSheetPortalled; ``` file: components/(deprecated)/columns.mdx # Columns 여러 열로 구성된 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. *** title: Columns description: 여러 열로 구성된 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. deprecated: 더 이상 사용되지 않습니다. `HStack`과 `wrap` prop을 사용하세요. --------------------------------------------------------- ```tsx import { Column, Columns } from "@seed-design/react"; /** * @deprecated use `HStack` instead. */ export default function ColumnsPreview() { return ( 1 Content Width 2 ); } ``` ## Usage ```tsx import { Columns, Column } from "@seed-design/react"; ``` ```tsx ``` ## Props ### `Columns` ", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, borderColor: { "type": "ScopedColorPalette | (string & {}) | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderTopWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRightWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderBottomWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderLeftWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, width: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, height: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, p: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, px: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, py: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pt: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pr: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pb: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pl: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexDirection: { "type": "\"row\" | \"column\" | \"row-reverse\" | \"column-reverse\" | \"rowReverse\" | \"columnReverse\"", "default": undefined }, flexWrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"If true, flex-wrap will be set to "}{"wrap"}{"."}

}, justifyContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignSelf: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, gap: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; background?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; }", "default": undefined } }} /> ### `Column` ", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "(string & {}) | ScopedColorPalette | ScopedColorBg", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "(string & {}) | ScopedColorPalette | ScopedColorBg", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, borderColor: { "type": "(string & {}) | ScopedColorPalette | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderTopWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRightWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderBottomWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderLeftWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRadius: { "type": "0 | \"full\" | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | \"full\" | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\"", "default": undefined }, borderTopRightRadius: { "type": "0 | \"full\" | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | \"full\" | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | \"full\" | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\"", "default": undefined }, minWidth: { "type": "Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"full\" | (string & {})", "default": undefined }, maxWidth: { "type": "Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"full\" | (string & {})", "default": undefined }, height: { "type": "Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"full\" | (string & {})", "default": undefined }, minHeight: { "type": "Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"full\" | (string & {})", "default": undefined }, maxHeight: { "type": "Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"full\" | (string & {})", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined }, p: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined }, px: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined }, py: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"safeArea\"", "default": undefined }, pt: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined }, pr: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"safeArea\"", "default": undefined }, pb: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined }, pl: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexWrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"If true, flex-wrap will be set to "}{"wrap"}{"."}

}, justifyContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignSelf: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, gap: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: (string & {}) | ScopedColorPalette | ScopedColorBg | undefined; background?: (string & {}) | ScopedColorPalette | ScopedColorBg | undefined; }", "default": undefined } }} /> file: components/(deprecated)/control-chip.mdx # Control Chip *** ## title: Control Chip ```tsx import { ControlChip } from "seed-design/ui/control-chip"; export default function ControlChipPreview() { return 라벨; } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add control-chip ``` ```bash pnpm dlx @seed-design/cli@latest add control-chip ``` ```bash yarn dlx @seed-design/cli@latest add control-chip ``` ```bash bun x @seed-design/cli@latest add control-chip ``` ## Props ### ControlChip.Button

{"Whether the element should be rendered as a child of a slot."}

}, size: { "type": "\"medium\" | \"small\"", "default": "\"medium\"" }, layout: { "type": "\"withText\" | \"iconOnly\"", "default": "\"withText\"" } }} /> ### ControlChip.Toggle ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

}, size: { "type": "\"medium\" | \"small\"", "default": "\"medium\"" }, layout: { "type": "\"withText\" | \"iconOnly\"", "default": "\"withText\"" }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined }, required: { "type": "boolean", "default": undefined }, checked: { "type": "boolean", "default": undefined }, defaultChecked: { "type": "boolean", "default": undefined }, onCheckedChange: { "type": "((checked: boolean) => void)", "default": undefined }, indeterminate: { "type": "boolean", "default": undefined } }} /> ### ControlChip.RadioRoot void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### ControlChip.RadioItem ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

}, size: { "type": "\"medium\" | \"small\"", "default": "\"medium\"" }, layout: { "type": "\"withText\" | \"iconOnly\"", "default": "\"withText\"" }, value: { "type": "string", "default": undefined }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined } }} /> ## Examples ### Medium ```tsx import { ControlChip } from "seed-design/ui/control-chip"; export default function ActionChipMedium() { return 라벨; } ``` ### Small ```tsx import { ControlChip } from "seed-design/ui/control-chip"; export default function ActionChipSmall() { return 라벨; } ``` ### Icon Only ```tsx import { IconPlusFill } from "@karrotmarket/react-monochrome-icon"; import { Icon } from "@seed-design/react"; import { ControlChip } from "seed-design/ui/control-chip"; export default function ControlChipIconOnly() { return ( } /> ); } ``` ### Prefix Icon ```tsx import { IconPlusFill } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { ControlChip } from "seed-design/ui/control-chip"; export default function ControlChipPrefixIcon() { return ( } /> 라벨 ); } ``` ### Suffix Icon ```tsx import { IconChevronDownFill } from "@karrotmarket/react-monochrome-icon"; import { SuffixIcon } from "@seed-design/react"; import { ControlChip } from "seed-design/ui/control-chip"; export default function ControlChipSuffixIcon() { return ( 라벨 } /> ); } ``` file: components/(deprecated)/extended-action-sheet.mdx # Extended Action Sheet *** ## title: Extended Action Sheet ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { ExtendedActionSheetContent, ExtendedActionSheetGroup, ExtendedActionSheetItem, ExtendedActionSheetRoot, ExtendedActionSheetTrigger, } from "seed-design/ui/extended-action-sheet"; const ExtendedActionSheetPreview = () => { return ( Open } /> Action 1 } /> Action 2 } /> Action 3 } /> Action 4 } /> Action 5 ); }; export default ExtendedActionSheetPreview; ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add extended-action-sheet ``` ```bash pnpm dlx @seed-design/cli@latest add extended-action-sheet ``` ```bash yarn dlx @seed-design/cli@latest add extended-action-sheet ``` ```bash bun x @seed-design/cli@latest add extended-action-sheet ``` ## Props ### `ExtendedActionSheetRoot`

{"The role of the dialog."}

}, closeOnInteractOutside: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the outside is clicked"}

}, closeOnEscape: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the escape key is pressed"}

}, lazyMount: { "type": "boolean", "default": "false", description: <>

{"Whether to enable lazy mounting"}

}, unmountOnExit: { "type": "boolean", "default": "false", description: <>

{"Whether to unmount on exit."}

}, open: { "type": "boolean", "default": undefined }, defaultOpen: { "type": "boolean", "default": undefined }, onOpenChange: { "type": "((open: boolean) => void)", "default": undefined } }} /> ### `ExtendedActionSheetTrigger`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `ExtendedActionSheetContent`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `ExtendedActionSheetGroup` ### `ExtendedActionSheetItem`

{"Whether the element should be rendered as a child of a slot."}

}, tone: { "type": "\"neutral\" | \"critical\"", "default": "\"neutral\"" } }} /> file: components/(deprecated)/extended-fab.mdx # Extended FAB *** ## title: Extended FAB ```tsx import { IconBellFill } from "@karrotmarket/react-monochrome-icon"; import { ExtendedFab, PrefixIcon } from "@seed-design/react"; export default function ExtendedFabPreview() { return ( } /> 알림 설정 ); } ``` ## Usage ```tsx import { ExtendedFab, PrefixIcon } from "@seed-design/react"; import { IconPlusLine } from "@karrotmarket/react-monochrome-icon"; ``` ```tsx } /> 라벨 ``` ## Props

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Medium ```tsx import { IconBellFill } from "@karrotmarket/react-monochrome-icon"; import { ExtendedFab, PrefixIcon } from "@seed-design/react"; export default function ExtendedFabMedium() { return ( } /> 알림 설정 ); } ``` ### Small ```tsx import { IconBellFill } from "@karrotmarket/react-monochrome-icon"; import { ExtendedFab, PrefixIcon } from "@seed-design/react"; export default function ExtendedFabSmall() { return ( } /> 알림 설정 ); } ``` ### Neutral Solid ```tsx import { IconBellFill } from "@karrotmarket/react-monochrome-icon"; import { ExtendedFab, PrefixIcon } from "@seed-design/react"; export default function ExtendedFabNeutralSolid() { return ( } /> 알림 설정 ); } ``` ### Layer Floating ```tsx import { IconBellFill } from "@karrotmarket/react-monochrome-icon"; import { ExtendedFab, PrefixIcon } from "@seed-design/react"; export default function ExtendedFabLayerFloating() { return ( } /> 알림 설정 ); } ``` file: components/(deprecated)/fab.mdx # FAB *** ## title: FAB ```tsx import IconPlusLine from "@karrotmarket/react-monochrome-icon/IconPlusLine"; import { Fab, Icon } from "@seed-design/react"; export default function FabPreview() { return ( } /> ); } ``` ## Usage ```tsx import { Fab, Icon } from "@seed-design/react"; import { IconPlusLine } from "@karrotmarket/react-monochrome-icon"; ``` ```tsx } /> ``` ## Props

{"Whether the element should be rendered as a child of a slot."}

} }} /> file: components/(deprecated)/inline-banner.mdx # Inline Banner *** ## title: Inline Banner ```tsx import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add inline-banner ``` ```bash pnpm dlx @seed-design/cli@latest add inline-banner ``` ```bash yarn dlx @seed-design/cli@latest add inline-banner ``` ```bash bun x @seed-design/cli@latest add inline-banner ``` ## Props ### `InlineBanner` ### `ActionableInlineBanner` ### `DismissibleInlineBanner` void)", "default": undefined } }} /> ## Examples ### Content Layout #### With Link Label `linkProps` prop은 `InlineBanner`에서만 제공돼요. ```tsx import { InlineBanner } from "seed-design/ui/inline-banner"; export default function InlineBannerWithLinkLabel() { return ( ); } ``` #### Text Only ```tsx import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerTextOnly() { return ( ); } ``` #### With Icon ```tsx import { IconBellFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerWithIcon() { return ( } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> ); } ``` #### With Title Text ```tsx import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerWithTitleText() { return ( ); } ``` #### With All ```tsx import { IconBellFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerWithAll() { return ( } title="타이틀" description="사업자 정보를 등록해주세요." /> } title="타이틀" description="사업자 정보를 등록해주세요." /> } title="타이틀" description="사업자 정보를 등록해주세요." /> ); } ``` ### Customizable Parts #### Rendering `LinkInlineBanner`’s Link Label as Child ```tsx import { InlineBanner } from "seed-design/ui/inline-banner"; export default function InlineBannerLinkLabelAsChild() { return ( 자세히 보기 ), }} /> ); } ``` ### Variants #### Neutral Weak (Default) ```tsx import { IconBellFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerNeutralWeak() { return ( } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> ); } ``` #### Positive Weak ```tsx import { IconCheckmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerPositiveWeak() { return ( } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> ); } ``` #### Informative Weak ```tsx import { IconILowercaseSerifCircleFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerInformativeWeak() { return ( } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> ); } ``` #### Warning Weak ```tsx import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerWarningWeak() { return ( } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> ); } ``` #### Warning Solid ```tsx import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, DismissibleInlineBanner, InlineBanner, } from "seed-design/ui/inline-banner"; export default function InlineBannerWarningSolid() { return ( } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> ); } ``` #### Critical Weak ```tsx import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableInlineBanner, InlineBanner } from "seed-design/ui/inline-banner"; export default function InlineBannerCriticalWeak() { return ( } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> ); } ``` #### Critical Solid `criticalWeak`과 `criticalSolid` variant는 `InlineBanner`와 `ActionableInlineBanner`에서만 제공돼요. variant가 `criticalWeak`이나 `criticalSolid`인 경우 `position: sticky` 등을 활용하여 화면을 스크롤했을 때도 인라인 배너가 상단에 고정되도록 해 주세요. ```tsx import { ActionableInlineBanner, InlineBanner } from "seed-design/ui/inline-banner"; import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; export default function InlineBannerCriticalSolid() { return ( } description="사업자 정보를 등록해주세요." /> } description="사업자 정보를 등록해주세요." /> ); } ``` ```tsx import * as React from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { InlineBanner, type InlineBannerProps } from "seed-design/ui/inline-banner"; import AppScreen from "@/components/stackflow/ActivityLayout"; import type { ActivityComponentType } from "@stackflow/react/future"; declare module "@stackflow/config" { interface Register { "inline-banner": unknown; } } const InlineBannerActivity: ActivityComponentType<"inline-banner"> = () => { const [variant, setVariant] = React.useState>( "criticalSolid", ); return (
setVariant((prev) => (prev === "criticalSolid" ? "neutralWeak" : "criticalSolid")) } > Toggle tone

Lorem ipsum dolor sit, amet consectetur adipisicing elit. At a eaque fugiat sint sapiente. Id, hic ex, blanditiis totam animi amet delectus temporibus quae fugiat magnam, quos eaque dolorum a? Lorem ipsum dolor, sit amet consectetur adipisicing elit. Possimus labore unde minus temporibus beatae commodi et nesciunt iure in dignissimos suscipit, alias ab voluptatem facilis tempora numquam. Veritatis, dolorum suscipit! Lorem ipsum dolor sit, amet consectetur adipisicing elit. Explicabo fugiat molestias iusto, ipsum distinctio officia ad id ratione esse ducimus architecto deleniti illum reiciendis rerum, at blanditiis molestiae. Cupiditate, nobis? Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab, magni. Aliquid inventore quaerat nemo architecto harum earum quas porro repudiandae explicabo repellat repellendus magni, corporis omnis laborum, velit dicta blanditiis. Lorem ipsum dolor sit, amet consectetur adipisicing elit. Debitis, eveniet quas. Accusamus facere veritatis expedita delectus, asperiores numquam placeat necessitatibus assumenda, nesciunt in dolorem sit provident repellendus, voluptatem earum! Consequatur. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Aut earum asperiores aliquam magnam est delectus veritatis numquam sint porro tenetur dolores nobis, deleniti voluptas quaerat, quia voluptatum soluta autem perspiciatis? Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis possimus eaque aliquam maxime? Quidem enim, sed itaque at veritatis nihil officia esse qui provident ipsa adipisci necessitatibus officiis distinctio laborum!

); }; export default InlineBannerActivity; ```
file: components/(deprecated)/inline.mdx # Inline 인라인 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. *** title: Inline description: 인라인 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. deprecated: 더 이상 사용되지 않습니다. `HStack`과 `wrap` prop을 사용하세요. --------------------------------------------------------- ```tsx import { Box, Inline } from "@seed-design/react"; /** * @deprecated Use `HStack` instead. */ export default function InlinePreview() { return ( 1 2 3 ); } ``` ## Usage ```tsx import { Inline } from "@seed-design/react"; ``` ```tsx ``` ## Props ", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, borderColor: { "type": "ScopedColorPalette | (string & {}) | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderTopWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRightWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderBottomWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderLeftWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, width: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, height: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, p: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, px: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, py: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pt: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pr: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pb: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pl: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexDirection: { "type": "\"row\" | \"column\" | \"row-reverse\" | \"column-reverse\" | \"rowReverse\" | \"columnReverse\"", "default": undefined }, justifyContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignSelf: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, gap: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; background?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; }", "default": undefined } }} /> file: components/(deprecated)/link-content.mdx # Link Content *** ## title: Link Content ```tsx import { IconChevronRightLine } from "@karrotmarket/react-monochrome-icon"; import { LinkContent, SuffixIcon } from "@seed-design/react"; export default function LinkContentPreview() { return ( 새 글 } /> ); } ``` ## Usage ```tsx import { LinkContent, SuffixIcon } from "@seed-design/react"; import { IconChevronRightLine } from "@karrotmarket/react-monochrome-icon"; ``` ```tsx Label } /> ``` ## Props

{"Whether the element should be rendered as a child of a slot."}

}, color: { "type": "ScopedColorFg | ScopedColorPalette | (string & {})", "default": undefined } }} /> ## Examples ### Size ```tsx import { IconChevronRightLine } from "@karrotmarket/react-monochrome-icon"; import { LinkContent, SuffixIcon, VStack } from "@seed-design/react"; export default function LinkContentSize() { return ( 추가 } /> 추가 } /> 추가 } /> ); } ``` ### Color ```tsx import { IconChevronRightLine } from "@karrotmarket/react-monochrome-icon"; import { LinkContent, VStack, SuffixIcon } from "@seed-design/react"; export default function LinkContentColor() { return ( 더보기 } /> 더보기 } /> 더보기 } /> 더보기 } /> ); } ``` file: components/(deprecated)/stack.mdx # Stack 세로로 쌓이는 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. *** title: Stack description: 세로로 쌓이는 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. deprecated: 더 이상 사용되지 않습니다. `VStack` 컴포넌트를 사용하세요. ------------------------------------------------- ```tsx import { Box, Stack } from "@seed-design/react"; /** * @deprecated Use `VStack` instead. */ export default function StackPreview() { return ( 1 2 3 ); } ``` ## Usage ```tsx import { Stack } from "@seed-design/react"; ``` ```tsx ``` ## Props ", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, borderColor: { "type": "ScopedColorPalette | (string & {}) | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderTopWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRightWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderBottomWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderLeftWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, width: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, height: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, p: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, px: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, py: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pt: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pr: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pb: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pl: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexWrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"If true, flex-wrap will be set to "}{"wrap"}{"."}

}, justifyContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignSelf: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, gap: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; background?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; }", "default": undefined }, direction: { "type": "\"row\" | \"column\" | \"row-reverse\" | \"column-reverse\" | \"rowReverse\" | \"columnReverse\"", "default": undefined, description: <>

{"Shorthand for "}{"flexDirection"}{"."}

}, wrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"Shorthand for "}{"flexWrap"}{"."}

}, align: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined, description: <>

{"Shorthand for "}{"alignItems"}{"."}

}, justify: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined, description: <>

{"Shorthand for "}{"justifyContent"}{"."}

}, grow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexGrow"}{"."}

}, shrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexShrink"}{"."}

} }} /> file: components/(foundation)/iconography/composition.mdx # Composition 아이콘을 사용하는 방법을 설명합니다. *** title: Composition description: 아이콘을 사용하는 방법을 설명합니다. --------------------------------- ## 개요 [당근 아이콘 라이브러리](/docs/foundation/iconography/library)는 디자인 시스템에 독립적(agnostic)으로 설계되었으며 SEED Design의 의견이 포함되어 있지 않습니다. 때로는 라이브러리에 없는 커스텀 아이콘을 사용하면서도 아이콘 합성 패턴을 활용해야 하는 경우가 있습니다. 이를 위해 `svg` 속성을 통해 아이콘을 받아 디자인 시스템에 연결하는 유틸리티 컴포넌트를 제공합니다: * `Icon`: 아이콘을 독립적으로 사용하거나 아이콘만 표시하는 컴포넌트에서 사용합니다. * `PrefixIcon`, `SuffixIcon`: 컴포넌트 내에 아이콘과 텍스트를 함께 배치할 때 사용합니다. ## Icon 컴포넌트 `Icon` 컴포넌트는 아이콘을 독립적으로 사용하거나 아이콘만 표시하는 컴포넌트에서 사용합니다. ```jsx import { Icon } from "@seed-design/react"; import { IconHeartFill } from "@karrotmarket/react-monochrome-icon"; // 독립형 아이콘 } /> // 아이콘만 표시하는 버튼 } /> ``` ## PrefixIcon과 SuffixIcon 컴포넌트 내에 아이콘과 텍스트를 함께 배치할 때는 `PrefixIcon`, `SuffixIcon` 컴포넌트를 children으로 배치합니다. ```jsx import { PrefixIcon, SuffixIcon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { IconPlusFill, IconChevronRightFill } from "@karrotmarket/react-monochrome-icon"; // 앞에 아이콘 배치 } /> 라벨 // 뒤에 아이콘 배치 라벨 } /> // 아이콘 양쪽에 배치 } /> 라벨 } /> ``` 이 패턴은 다음과 같은 컴포넌트에서 일관되게 사용됩니다: * `ActionButton`: 버튼 내 아이콘 배치 * `Button`: 일반 버튼 내 아이콘 배치 * `ToggleButton`: 토글 버튼 내 아이콘 배치 * `ActionChip`: 액션 칩 내 아이콘 배치 * `ControlChip`: 컨트롤 칩 내 아이콘 배치 file: components/(foundation)/iconography/library.mdx # Library 리액트 아이콘 패키지는 아이콘을 사용할 때 필요한 컴포넌트를 제공합니다. *** title: Library description: 리액트 아이콘 패키지는 아이콘을 사용할 때 필요한 컴포넌트를 제공합니다. ----------------------------------------------------- import { Sprout } from "lucide-react"; ## Overview }> 아이콘 라이브러리에 포함된 아이콘을 확인합니다. ## Installation npm pnpm yarn bun ```bash npm install @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash pnpm add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash yarn add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash bun add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ## Package * [@karrotmarket/react-monochrome-icon](https://github.com/daangn/seed-icon-v3/pkgs/npm/react-monochrome-icon) * [@karrotmarket/react-multicolor-icon](https://github.com/daangn/seed-icon-v3/pkgs/npm/react-multicolor-icon) file: components/(foundation)/layout/box.mdx # Box Box 컴포넌트는 가장 기초적인 레이아웃 컴포넌트입니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. *** title: Box description: Box 컴포넌트는 가장 기초적인 레이아웃 컴포넌트입니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. --------------------------------------------------------------------------- ```tsx import { Box } from "@seed-design/react"; export default function BoxPreview() { return ( Box Example ); } ``` ## Usage ```tsx import { Box } from "@seed-design/react"; ``` ```tsx ``` ## Props ", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "ScopedColorBg | ScopedColorPalette | (string & {})", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "ScopedColorBg | ScopedColorPalette | (string & {})", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, color: { "type": "ScopedColorPalette | (string & {}) | ScopedColorFg", "default": undefined }, borderColor: { "type": "ScopedColorPalette | (string & {}) | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderTopWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRightWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderBottomWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderLeftWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, width: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, height: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, p: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, px: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, py: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pt: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pr: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pb: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pl: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, display: { "type": "\"block\" | \"flex\" | \"inline-flex\" | \"inline\" | \"inline-block\" | \"none\" | \"inlineFlex\" | \"inlineBlock\"", "default": undefined }, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"visible\" | \"scroll\" | \"auto\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"visible\" | \"scroll\" | \"auto\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexDirection: { "type": "\"row\" | \"column\" | \"row-reverse\" | \"column-reverse\" | \"rowReverse\" | \"columnReverse\"", "default": undefined }, flexWrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"If true, flex-wrap will be set to "}{"wrap"}{"."}

}, justifyContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignSelf: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, gap: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: ScopedColorBg | ScopedColorPalette | (string & {}) | undefined; background?: ScopedColorBg | ScopedColorPalette | (string & {}) | undefined; }", "default": undefined } }} /> ## Examples ### Gradient ```tsx import { Box, VStack } from "@seed-design/react"; export default function BoxGradient() { return ( Box Gradient Box Gradient ); } ``` file: components/(foundation)/layout/flex.mdx # Flex Flex 컴포넌트는 flexbox를 사용하며 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. *** title: Flex description: Flex 컴포넌트는 flexbox를 사용하며 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. -------------------------------------------------------------------- ```tsx import { Flex } from "@seed-design/react"; export default function FlexPreview() { return ( 1 2 3 4 5 ); } ``` ## Props

{"Shorthand for "}{"flexDirection"}{"."}

}, wrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"Shorthand for "}{"flexWrap"}{"."}

}, align: { "type": "\"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"flexStart\" | \"flexEnd\"", "default": undefined, description: <>

{"Shorthand for "}{"alignItems"}{"."}

}, justify: { "type": "\"flex-start\" | \"flex-end\" | \"center\" | \"flexStart\" | \"flexEnd\" | \"space-between\" | \"space-around\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined, description: <>

{"Shorthand for "}{"justifyContent"}{"."}

}, grow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexGrow"}{"."}

}, shrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexShrink"}{"."}

}, color: { "type": "ScopedColorFg | ScopedColorPalette | (string & {})", "default": undefined }, as: { "type": "ElementType", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, borderColor: { "type": "ScopedColorPalette | (string & {}) | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | 1 | (string & {})", "default": undefined }, borderTopWidth: { "type": "0 | 1 | (string & {})", "default": undefined }, borderRightWidth: { "type": "0 | 1 | (string & {})", "default": undefined }, borderBottomWidth: { "type": "0 | 1 | (string & {})", "default": undefined }, borderLeftWidth: { "type": "0 | 1 | (string & {})", "default": undefined }, borderRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, width: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, height: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, p: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, px: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, py: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pt: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pr: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pb: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pl: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexDirection: { "type": "\"row\" | \"column\" | \"row-reverse\" | \"column-reverse\" | \"rowReverse\" | \"columnReverse\"", "default": undefined }, flexWrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"If true, flex-wrap will be set to "}{"wrap"}{"."}

}, justifyContent: { "type": "\"flex-start\" | \"flex-end\" | \"center\" | \"flexStart\" | \"flexEnd\" | \"space-between\" | \"space-around\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"flexStart\" | \"flexEnd\"", "default": undefined }, alignContent: { "type": "\"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"flexStart\" | \"flexEnd\"", "default": undefined }, alignSelf: { "type": "\"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"flexStart\" | \"flexEnd\"", "default": undefined }, gap: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; background?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; }", "default": undefined } }} /> file: components/(foundation)/layout/float.mdx # Float Float 컴포넌트는 특정 위치에 고정된 요소를 배치할 때 사용합니다. *** title: Float description: Float 컴포넌트는 특정 위치에 고정된 요소를 배치할 때 사용합니다. ---------------------------------------------------- ```tsx import { Box, ContextualFloatingButton, Float } from "@seed-design/react"; export default function FloatPreview() { return ( Top Start Top Center Top End Middle Start Middle Center Middle End Bottom Start Bottom Center Bottom End ); } ``` ## Props ", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, borderColor: { "type": "ScopedColorPalette | (string & {}) | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderTopWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRightWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderBottomWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderLeftWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, width: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, height: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, p: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, px: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, py: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pt: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pr: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pb: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pl: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexWrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"If true, flex-wrap will be set to "}{"wrap"}{"."}

}, justifyContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignSelf: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, gap: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; background?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; }", "default": undefined }, direction: { "type": "\"row\" | \"column\" | \"row-reverse\" | \"column-reverse\" | \"rowReverse\" | \"columnReverse\"", "default": undefined, description: <>

{"Shorthand for "}{"flexDirection"}{"."}

}, wrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"Shorthand for "}{"flexWrap"}{"."}

}, align: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined, description: <>

{"Shorthand for "}{"alignItems"}{"."}

}, justify: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined, description: <>

{"Shorthand for "}{"justifyContent"}{"."}

}, grow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexGrow"}{"."}

}, shrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexShrink"}{"."}

} }} /> ## Examples ### Offset X `offsetX` 속성을 사용하면 좌우 방향으로 위치를 조정할 수 있습니다. `start`, `middle`에서는 우측 방향으로 조정되고, `end`에서는 좌측 방향으로 조정됩니다. ```tsx import { Box, ContextualFloatingButton, Float } from "@seed-design/react"; export default function FloatOffsetX() { return ( Middle Start Middle Center Middle End ); } ``` ### Offset Y `offsetY` 속성을 사용하면 상하 방향으로 위치를 조정할 수 있습니다. `top`, `middle`에서는 하측 방향으로 조정되고, `bottom`에서는 상측 방향으로 조정됩니다. ```tsx import { Box, ContextualFloatingButton, Float } from "@seed-design/react"; export default function FloatOffsetY() { return ( Top Center Middle Center Bottom Center ); } ``` file: components/(foundation)/layout/h-stack.mdx # HStack 가로로 쌓이는 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. *** title: HStack description: 가로로 쌓이는 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. ---------------------------------------------------------------- ```tsx import { Box, HStack } from "@seed-design/react"; export default function HStackPreview() { return ( 1 2 3 ); } ``` ## Usage ```tsx import { HStack } from "@seed-design/react"; ``` ```tsx ``` ## Props ", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, borderColor: { "type": "ScopedColorPalette | (string & {}) | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderTopWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRightWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderBottomWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderLeftWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, width: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, height: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, p: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, px: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, py: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pt: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pr: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pb: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pl: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexWrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"If true, flex-wrap will be set to "}{"wrap"}{"."}

}, justifyContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignSelf: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, gap: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; background?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; }", "default": undefined }, direction: { "type": "\"row\" | \"column\" | \"row-reverse\" | \"column-reverse\" | \"rowReverse\" | \"columnReverse\"", "default": undefined, description: <>

{"Shorthand for "}{"flexDirection"}{"."}

}, wrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"Shorthand for "}{"flexWrap"}{"."}

}, align: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined, description: <>

{"Shorthand for "}{"alignItems"}{"."}

}, justify: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined, description: <>

{"Shorthand for "}{"justifyContent"}{"."}

}, grow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexGrow"}{"."}

}, shrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexShrink"}{"."}

} }} /> file: components/(foundation)/layout/v-stack.mdx # VStack 세로로 쌓이는 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. *** title: VStack description: 세로로 쌓이는 레이아웃을 구성합니다. 디자인 토큰을 JSX에서 사용할 수 있도록 도와줍니다. ---------------------------------------------------------------- ```tsx import { Box, VStack } from "@seed-design/react"; export default function VStackPreview() { return ( 1 2 3 ); } ``` ## Usage ```tsx import { VStack } from "@seed-design/react"; ``` ```tsx ``` ## Props ", "default": undefined }, asChild: { "type": "boolean", "default": undefined }, bg: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined, description: <>

{"Shorthand for "}{"background"}{"."}

}, background: { "type": "ScopedColorPalette | (string & {}) | ScopedColorBg", "default": undefined }, bgGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradient"}{"."}

}, backgroundGradient: { "type": "\"fadeLayerFloating\" | \"fadeLayerDefault\" | \"glowMagic\" | \"glowMagicPressed\" | \"shimmerNeutral\" | \"shimmerMagic\" | \"highlightMagicPressed\" | \"highlightMagic\"", "default": undefined }, bgGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"Shorthand for "}{"backgroundGradientDirection"}{".\ne.g. "}{"43deg"}

}, backgroundGradientDirection: { "type": "(string & {}) | \"to right\" | \"to left\" | \"to top\" | \"to bottom\" | \"to top right\" | \"to top left\" | \"to bottom right\" | \"to bottom left\"", "default": undefined, description: <>

{"e.g. "}{"43deg"}

}, borderColor: { "type": "ScopedColorPalette | (string & {}) | ScopedColorStroke", "default": undefined }, borderWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderTopWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRightWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderBottomWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderLeftWidth: { "type": "0 | (string & {}) | 1", "default": undefined }, borderRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderTopRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomRightRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, borderBottomLeftRadius: { "type": "0 | (string & {}) | \"r0_5\" | \"r1\" | \"r1_5\" | \"r2\" | \"r2_5\" | \"r3\" | \"r3_5\" | \"r4\" | \"r5\" | \"r6\" | \"full\"", "default": undefined }, width: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxWidth: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, height: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, minHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, maxHeight: { "type": "(string & {}) | \"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, top: { "type": "0 | (string & {})", "default": undefined }, left: { "type": "0 | (string & {})", "default": undefined }, right: { "type": "0 | (string & {})", "default": undefined }, bottom: { "type": "0 | (string & {})", "default": undefined }, padding: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, p: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"padding"}{"."}

}, paddingX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, px: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingX"}{"."}

}, paddingY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, py: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingY"}{"."}

}, paddingTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pt: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingTop"}{"."}

}, paddingRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pr: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingRight"}{"."}

}, paddingBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined }, pb: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"safeArea\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingBottom"}{"."}

}, paddingLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, pl: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined, description: <>

{"Shorthand for "}{"paddingLeft"}{"."}

}, bleedX: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedTop: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative top margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedRight: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative right margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedBottom: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative bottom margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedLeft: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | \"asPadding\"", "default": undefined, description: <>

{"Negative left margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, position: { "type": "\"relative\" | \"absolute\" | \"fixed\" | \"sticky\"", "default": undefined }, overflowX: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, overflowY: { "type": "\"hidden\" | \"auto\" | \"visible\" | \"scroll\"", "default": undefined }, zIndex: { "type": "number | (string & {})", "default": undefined }, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, flexShrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"If true, flex-shrink will be set to "}{"1"}{"."}

}, flexWrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"If true, flex-wrap will be set to "}{"wrap"}{"."}

}, justifyContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignContent: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, alignSelf: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined }, gap: { "type": "0 | (string & {}) | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\"", "default": undefined }, unstable_transform: { "type": "string", "default": undefined }, _active: { "type": "{ bg?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; background?: ScopedColorPalette | (string & {}) | ScopedColorBg | undefined; }", "default": undefined }, direction: { "type": "\"row\" | \"column\" | \"row-reverse\" | \"column-reverse\" | \"rowReverse\" | \"columnReverse\"", "default": undefined, description: <>

{"Shorthand for "}{"flexDirection"}{"."}

}, wrap: { "type": "true | \"wrap\" | \"wrap-reverse\" | \"nowrap\"", "default": undefined, description: <>

{"Shorthand for "}{"flexWrap"}{"."}

}, align: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined, description: <>

{"Shorthand for "}{"alignItems"}{"."}

}, justify: { "type": "\"center\" | \"flex-start\" | \"flex-end\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined, description: <>

{"Shorthand for "}{"justifyContent"}{"."}

}, grow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexGrow"}{"."}

}, shrink: { "type": "true | 0 | (number & {})", "default": undefined, description: <>

{"Shorthand for "}{"flexShrink"}{"."}

} }} /> file: components/(foundation)/typography/text.mdx # Text 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Text description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { Flex, Text } from "@seed-design/react"; export default function TextPreview() { return ( 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 ); } ``` ## Usage ```tsx import { Text } from "@seed-design/react"; ``` ```tsx ``` ## Props

{"The element to render as"}

}, color: { "type": "ScopedColorFg | ScopedColorPalette | (string & {})", "default": undefined, description: <>

{"The color of the text."}

}, fontSize: { "type": "(string & {}) | \"t1\" | \"t2\" | \"t3\" | \"t4\" | \"t5\" | \"t6\" | \"t7\" | \"t8\" | \"t9\" | \"t10\" | \"t1Static\" | \"t2Static\" | \"t3Static\" | \"t4Static\" | \"t5Static\" | \"t6Static\" | \"t7Static\" | \"t8Static\" | \"t9Static\" | \"t10Static\"", "default": undefined, description: <>

{"The font size of the text. Partially overrides the textStyle."}

}, lineHeight: { "type": "(string & {}) | \"t1\" | \"t2\" | \"t3\" | \"t4\" | \"t5\" | \"t6\" | \"t7\" | \"t8\" | \"t9\" | \"t10\" | \"t1Static\" | \"t2Static\" | \"t3Static\" | \"t4Static\" | \"t5Static\" | \"t6Static\" | \"t7Static\" | \"t8Static\" | \"t9Static\" | \"t10Static\"", "default": undefined, description: <>

{"The line height of the text. Partially overrides the textStyle."}

}, fontWeight: { "type": "\"regular\" | \"medium\" | \"bold\"", "default": undefined, description: <>

{"The font weight of the text. Partially overrides the textStyle."}

}, maxLines: { "type": "number", "default": undefined, description: <>

{"The maximum number of lines to display. If the text overflows, it will be truncated."}

}, align: { "type": "\"left\" | \"center\" | \"right\"", "default": undefined, description: <>

{"The alignment of the text."}

}, textStyle: { "type": "\"screenTitle\" | \"articleBody\" | \"t1Regular\" | \"t1Medium\" | \"t1Bold\" | \"t2Regular\" | \"t2Medium\" | \"t2Bold\" | \"t3Regular\" | \"t3Medium\" | \"t3Bold\" | \"t4Regular\" | \"t4Medium\" | \"t4Bold\" | ... 12 more ...", "default": "\"t5Regular\"" }, textDecorationLine: { "type": "\"none\" | \"line-through\"", "default": "\"none\"" } }} /> ## Examples ### Text Styles Figma의 Text Style과 대응되는 `textStyle` 속성을 사용하는 것이 기본 방법입니다. ```tsx import { Flex, Text } from "@seed-design/react"; export default function TextTextStyles() { return ( 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 ); } ``` ### Font Sizes 세밀한 제어가 필요한 경우 `fontSize` 및 `lineHeight` 속성을 각각 사용할 수 있습니다. `lineHeight` 속성은 `fontSize`에 대응되는 기본값으로 설정되며, `lineHeight` 속성으로 변경이 가능합니다. ```tsx import { Flex, Text } from "@seed-design/react"; export default function TextFontSizes() { return ( 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 ); } ``` ### Font Weights 세밀한 제어가 필요한 경우 `fontWeight` 속성을 사용할 수 있습니다. ```tsx import { Flex, Text } from "@seed-design/react"; export default function TextFontWeights() { return ( 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 다람쥐 헌 쳇바퀴에 타고파 ); } ``` ### Line Through `textDecorationLine` 속성을 사용하여 텍스트에 취소선을 추가할 수 있습니다. ```tsx import { Flex, Text } from "@seed-design/react"; export default function TextLineThrough() { return ( 다람쥐 헌 쳇바퀴에 타고파 ); } ``` file: components/(select-box)/check-select-box.mdx # Check Select Box 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Check Select Box description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { VStack } from "@seed-design/react"; import { CheckSelectBox, CheckSelectBoxGroup } from "seed-design/ui/select-box"; export default function CheckSelectBoxPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add select-box ``` ```bash pnpm dlx @seed-design/cli@latest add select-box ``` ```bash yarn dlx @seed-design/cli@latest add select-box ``` ```bash bun x @seed-design/cli@latest add select-box ``` ## Props ### `CheckSelectBoxGroup`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `CheckSelectBox` ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined }, required: { "type": "boolean", "default": undefined }, checked: { "type": "boolean", "default": undefined }, defaultChecked: { "type": "boolean", "default": undefined }, onCheckedChange: { "type": "((checked: boolean) => void)", "default": undefined }, indeterminate: { "type": "boolean", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### React Hook Form ```tsx import { HStack, VStack } from "@seed-design/react"; import { useCallback, type FormEvent } from "react"; import { useController, useForm } from "react-hook-form"; import { ActionButton } from "seed-design/ui/action-button"; import { CheckSelectBox, CheckSelectBoxGroup } from "seed-design/ui/select-box"; const POSSIBLE_FRUIT_VALUES = ["apple", "melon", "mango"] as const; type FormValues = Record<(typeof POSSIBLE_FRUIT_VALUES)[number], boolean>; export default function CheckSelectBoxReactHookForm() { const { handleSubmit, reset, setValue, control } = useForm({ defaultValues: { apple: false, melon: true, mango: false, }, }); const onValid = useCallback((data: FormValues) => { window.alert(JSON.stringify(data, null, 2)); }, []); const onReset = useCallback( (event: FormEvent) => { event.preventDefault(); reset(); }, [reset], ); return ( {POSSIBLE_FRUIT_VALUES.map((name) => { const { field: { value, ...restProps }, fieldState: { invalid }, } = useController({ name, control }); return ( ); })} 초기화 setValue("mango", true)}> mango 선택 제출 ); } ``` ### Customizing Label ```tsx import { Badge, Box, Flex, VStack } from "@seed-design/react"; import { CheckSelectBox, CheckSelectBoxGroup } from "seed-design/ui/select-box"; export default function CheckSelectBoxCustomizingLabel() { return ( Melon New } description="Elit cupidatat dolore fugiat enim veniam culpa." /> ); } ``` file: components/(select-box)/radio-select-box.mdx # Radio Select Box 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Radio Select Box description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { VStack } from "@seed-design/react"; import { RadioSelectBoxItem, RadioSelectBoxRoot } from "seed-design/ui/select-box"; export default function RadioSelectBoxPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add select-box ``` ```bash pnpm dlx @seed-design/cli@latest add select-box ``` ```bash yarn dlx @seed-design/cli@latest add select-box ``` ```bash bun x @seed-design/cli@latest add select-box ``` ## Props ### `RadioSelectBoxRoot` void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `RadioSelectBoxItem` ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, value: { "type": "string", "default": undefined }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### React Hook Form ```tsx import { HStack, VStack } from "@seed-design/react"; import { useCallback, type FormEvent } from "react"; import { useController, useForm } from "react-hook-form"; import { ActionButton } from "seed-design/ui/action-button"; import { RadioSelectBoxItem, RadioSelectBoxRoot } from "seed-design/ui/select-box"; const POSSIBLE_FRUIT_VALUES = ["apple", "melon", "mango"] as const; interface FormValues { fruit: (typeof POSSIBLE_FRUIT_VALUES)[number]; } export default function RadioSelectBoxReactHookForm() { const { handleSubmit, reset, setValue, control } = useForm({ defaultValues: { fruit: "melon", }, }); const { field } = useController({ name: "fruit", control }); const onValid = useCallback((data: FormValues) => { window.alert(JSON.stringify(data, null, 2)); }, []); const onReset = useCallback( (event: FormEvent) => { event.preventDefault(); reset(); }, [reset], ); return ( {POSSIBLE_FRUIT_VALUES.map((value) => ( ))} 초기화 setValue("fruit", "mango")} > mango 선택 제출 ); } ``` ### Customizing Label ```tsx import { Badge, Box, Flex, VStack } from "@seed-design/react"; import { RadioSelectBoxItem, RadioSelectBoxRoot } from "seed-design/ui/select-box"; export default function RadioSelectBoxCustomizingLabel() { return ( Melon New } description="Elit cupidatat dolore fugiat enim veniam culpa." /> ); } ``` file: components/(tabs)/chip-tabs.mdx # Chip Tabs 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Chip Tabs description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import * as React from "react"; import { ChipTabsList, ChipTabsRoot, ChipTabsTrigger } from "seed-design/ui/chip-tabs"; export default function ChipTabsPreview() { const [value, setValue] = React.useState("1"); return ( <> setValue(value)} > 라벨1 라벨2 라벨3 {value === "1" &&
content 1
} {value === "2" &&
content 2
} {value === "3" &&
content 3
} ); } ```
## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add chip-tabs ``` ```bash pnpm dlx @seed-design/cli@latest add chip-tabs ``` ```bash yarn dlx @seed-design/cli@latest add chip-tabs ``` ```bash bun x @seed-design/cli@latest add chip-tabs ``` ## Props ### `ChipTabsRoot` void)", "default": undefined }, lazyMount: { "type": "boolean", "default": "false", description: <>

{"If "}{"true"}{", the component will be mounted lazily."}

}, unmountOnExit: { "type": "boolean", "default": "false", description: <>

{"If "}{"true"}{", the component will be unmounted when it's not selected."}

}, present: { "type": "boolean", "default": "false", description: <>

{"If "}{"true"}{", the component will be mounted."}

}, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `ChipTabsList`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `ChipTabsTrigger` ### `ChipTabsCarousel` void)", "default": undefined } }} /> ### `ChipTabsContent`

{"Whether the element should be rendered as a child of a slot."}

}, value: { "type": "string", "default": undefined } }} /> ## Examples ### Size=Medium ```tsx import * as React from "react"; import { ChipTabsList, ChipTabsRoot, ChipTabsTrigger } from "seed-design/ui/chip-tabs"; export default function ChipTabsSizeMedium() { const [value, setValue] = React.useState("1"); return ( <> setValue(value)} > 라벨1 라벨2 라벨3 {value === "1" &&
content 1
} {value === "2" &&
content 2
} {value === "3" &&
content 3
} ); } ```
### Size=Large ```tsx import * as React from "react"; import { ChipTabsList, ChipTabsRoot, ChipTabsTrigger } from "seed-design/ui/chip-tabs"; export default function ChipTabsSizeLarge() { const [value, setValue] = React.useState("1"); return ( <> setValue(value)} > 라벨1 라벨2 라벨3 {value === "1" &&
content 1
} {value === "2" &&
content 2
} {value === "3" &&
content 3
} ); } ```
### Variant=Neutral Solid ```tsx import * as React from "react"; import { ChipTabsList, ChipTabsRoot, ChipTabsTrigger } from "seed-design/ui/chip-tabs"; export default function ChipTabsVariantNeutralSolid() { const [value, setValue] = React.useState("1"); return ( <> setValue(value)} > 라벨1 라벨2 라벨3 {value === "1" &&
content 1
} {value === "2" &&
content 2
} {value === "3" &&
content 3
} ); } ```
### Variant=Neutral Outline ```tsx import * as React from "react"; import { ChipTabsList, ChipTabsRoot, ChipTabsTrigger } from "seed-design/ui/chip-tabs"; export default function ChipTabsVariantNeutralOutline() { const [value, setValue] = React.useState("1"); return ( <> setValue(value)} > 라벨1 라벨2 라벨3 {value === "1" &&
content 1
} {value === "2" &&
content 2
} {value === "3" &&
content 3
} ); } ```
### Variant=Brand Solid (Deprecated) brandSolid는 deprecated 됐습니다. neutralSolid, neutralOutline을 사용해주세요. ```tsx import * as React from "react"; import { ChipTabsList, ChipTabsRoot, ChipTabsTrigger } from "seed-design/ui/chip-tabs"; export default function ChipTabsVariantBrandSolid() { const [value, setValue] = React.useState("1"); return ( <> setValue(value)} > 라벨1 라벨2 라벨3 {value === "1" &&
content 1
} {value === "2" &&
content 2
} {value === "3" &&
content 3
} ); } ```
### Notification ```tsx import * as React from "react"; import { ChipTabsList, ChipTabsRoot, ChipTabsTrigger } from "seed-design/ui/chip-tabs"; export default function ChipTabsNotification() { const [value, setValue] = React.useState("1"); return ( <> setValue(value)} > 라벨1 라벨2 라벨3 {value === "1" &&
content 1
} {value === "2" &&
content 2
} {value === "3" &&
content 3
} ); } ```
### Stackflow ```tsx import * as React from "react"; import { ChipTabsList, ChipTabsRoot, ChipTabsTrigger } from "seed-design/ui/chip-tabs"; import AppScreen from "@/components/stackflow/ActivityLayout"; import type { ActivityComponentType } from "@stackflow/react/future"; declare module "@stackflow/config" { interface Register { "chip-tabs-basic": unknown; } } const ChipTabsBasicActivity: ActivityComponentType<"chip-tabs-basic"> = () => { const [value, setValue] = React.useState("1"); const commonStyle = { display: "flex", justifyContent: "center", alignItems: "center", backgroundColor: "#eeeeee", height: "100%", }; return ( setValue(value)} > 라벨1 라벨2 라벨3 {value === "1" &&
content 1
} {value === "2" &&
content 2
} {value === "3" &&
content 3
}
); }; export default ChipTabsBasicActivity; ```
file: components/(tabs)/tabs.mdx # Tabs 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Tabs description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsPreview() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add tabs ``` ```bash pnpm dlx @seed-design/cli@latest add tabs ``` ```bash yarn dlx @seed-design/cli@latest add tabs ``` ```bash bun x @seed-design/cli@latest add tabs ``` ## Props ### `TabsRoot` void)", "default": undefined }, lazyMount: { "type": "boolean", "default": "false", description: <>

{"If "}{"true"}{", the component will be mounted lazily."}

}, unmountOnExit: { "type": "boolean", "default": "false", description: <>

{"If "}{"true"}{", the component will be unmounted when it's not selected."}

}, present: { "type": "boolean", "default": "false", description: <>

{"If "}{"true"}{", the component will be mounted."}

}, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `TabsList`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `TabsTrigger` ### `TabsCarousel` void)", "default": undefined } }} /> ### `TabsContent`

{"Whether the element should be rendered as a child of a slot."}

}, value: { "type": "string", "default": undefined } }} /> ## Examples ### Layout Fill (Default) ```tsx import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsLayoutFill() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Layout Hug ```tsx import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsLayoutHug() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Size Medium ```tsx import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsSizeMedium() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Size Small (Default) ```tsx import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsSizeSmall() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Transition `TabsCarousel` 컴포넌트로 `TabsContent` 컴포넌트들을 감싸면 탭 변경시 컨텐츠가 자연스럽게 전환됩니다. ```tsx import { TabsRoot, TabsList, TabsTrigger, TabsCarousel, TabsContent } from "seed-design/ui/tabs"; export default function TabsTransition() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Swipeable `TabsCarousel` 컴포넌트에 `swipeable` 속성을 추가하면 스와이프 제스처로 탭을 이동할 수 있습니다. ```tsx import { TabsRoot, TabsList, TabsTrigger, TabsCarousel, TabsContent } from "seed-design/ui/tabs"; export default function TabsSwipeable() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Carousel Prevent Drag `Tabs.carouselPreventDrag`를 사용하면 특정 요소가 드래그 제스처에 반응하지 않도록 설정할 수 있습니다. ```tsx import { Box, Tabs } from "@seed-design/react"; import { TabsCarousel, TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsCarouselPreventDrag() { return ( Tab 1 Tab 2 Scrollable area Lorem ipsum dolor sit, amet consectetur adipisicing elit. Reiciendis ab ex accusantium sit. Amet maxime eum molestiae nemo. Beatae sint omnis aut cumque doloremque fugit perspiciatis rerum possimus, reiciendis eaque? Lorem ipsum dolor sit amet consectetur adipisicing elit. ); } ``` ### Disabled ```tsx import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsDisabled() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Notification ```tsx import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsNotification() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Sticky List 탭이 전체화면을 차지하고, Tabs.List가 top에 고정되어 있는 경우 사용하는 예시입니다. ```tsx import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsStickyList() { return ( // 600은 화면 높이라고 가정합니다.
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
); } const Content = (props: React.PropsWithChildren<{ height: string }>) => { const { height, children } = props; return (
{children}
); }; ```
### Standalone TabContent를 사용하지 않고, 컨텐츠 영역을 온전히 소유하고 싶을 때 사용하는 예시입니다. 탭에서 제공하는 Swipe 기능을 사용할 수 없습니다. ```tsx import { useState } from "react"; import { TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsStandalone() { const [activeTab, setActiveTab] = useState("1"); return (
라벨1 라벨2 라벨3 {activeTab === "1" && (
Content 1
)} {activeTab === "2" && (
Content 2
)} {activeTab === "3" && (
Content 3
)}
); } const Content = (props: React.PropsWithChildren) => { return (
{props.children}
); }; ```
### Dynamic Height 각 탭의 높이가 다를 때, 아래의 컨텐츠를 탭 아래에 바로 맞추기 위해서 사용하는 예시입니다. 탭이 자주 바뀌고, 탭에 네트워크 요청이 많은 경우 캐싱을 잘 고려해주세요. ```tsx import { TabsCarousel, TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsDynamicHeight() { return (
라벨1 라벨2 라벨3 Content 1 Content 2 Content 3
아래 컨텐츠
); } const Content = (props: React.PropsWithChildren<{ height: string }>) => { const { height, children } = props; return (
{children}
); }; ```
### Scroll to Top ```tsx import { RefObject, useRef, useState } from "react"; import { TabsCarousel, TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; export default function TabsScrollTop() { const [currentTab, setCurrentTab] = useState("1"); const contentRefs: Record> = { "1": useRef(null), "2": useRef(null), }; const handleTriggerClick = (value: string) => { if (value === currentTab) { contentRefs[value].current?.scrollTo({ top: 0, behavior: "smooth" }); } }; return (
handleTriggerClick("1")} value="1"> 라벨1 handleTriggerClick("2")} value="2"> 라벨2 Content 1 Content 2
); } const Content = (props: React.PropsWithChildren<{ height: string }>) => { const { height, children } = props; return (
{children}
); }; ```
file: components/(text-field)/multiline-text-field.mdx # Multiline Text Field 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Multiline Text Field description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add text-field ``` ```bash pnpm dlx @seed-design/cli@latest add text-field ``` ```bash yarn dlx @seed-design/cli@latest add text-field ``` ```bash bun x @seed-design/cli@latest add text-field ``` ## Props ### `TextField` void)", "default": undefined }, maxGraphemeCount: { "type": "number", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `TextFieldTextarea`

{"If true, the textarea will automatically resize based on its content."}

}, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### State #### Enabled ```tsx import { HStack } from "@seed-design/react"; import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldEnabled() { return ( ); } ``` #### Disabled ```tsx import { HStack } from "@seed-design/react"; import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldDisabled() { return ( ); } ``` #### Read Only ```tsx import { HStack } from "@seed-design/react"; import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldReadOnly() { return ( ); } ``` ### Sizing #### Fixed Height ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldSpecifiedHeight() { return ( ); } ``` #### Auto Height with Constraints ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldConstraints() { return ( ); } ``` ### Customizable Parts #### Required Indicator ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldRequired() { return ( ); } ``` #### Optional Indicator ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldOptional() { return ( ); } ``` #### Grapheme Count ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldGraphemeCount() { return ( ); } ``` ### Size #### XLarge ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldXlarge() { return ( ); } ``` #### Large ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldLarge() { return ( ); } ``` #### Medium ```tsx import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldMedium() { return ( ); } ``` ### Use Cases #### Form ```tsx import { HStack, VStack } from "@seed-design/react"; import { useCallback, useState, type FormEvent } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; interface FormValues { bio: string; address: string; } type FieldErrors = Record; export default function MultilineTextFieldForm() { const [formValues, setFormValues] = useState({ bio: "", address: "", }); const [fieldErrors, setFieldStates] = useState({ bio: null, address: null, }); const validateForm = useCallback((): boolean => { let isValid = true; const newFieldErrors: FieldErrors = { bio: null, address: null, }; // Name validation if (!formValues.bio) { newFieldErrors.bio = "필수 입력 항목입니다"; isValid = false; } if (!formValues.address.startsWith("대한민국")) { newFieldErrors.address = "대한민국으로 시작해주세요"; isValid = false; } if (!formValues.address) { newFieldErrors.address = "필수 입력 항목입니다"; isValid = false; } setFieldStates(newFieldErrors); return isValid; }, [formValues]); const handleSubmit = useCallback( (event: FormEvent) => { event.preventDefault(); if (validateForm()) { window.alert(JSON.stringify(formValues, null, 2)); } }, [formValues, validateForm], ); const handleReset = useCallback((event: FormEvent) => { event.preventDefault(); setFormValues({ bio: "", address: "" }); setFieldStates({ bio: null, address: null }); }, []); const handleNameChange = (value: string) => { setFormValues((prev) => ({ ...prev, bio: value })); setFieldStates((prev) => ({ ...prev, name: null })); }; const handleAddressChange = (value: string) => { setFormValues((prev) => ({ ...prev, address: value })); setFieldStates((prev) => ({ ...prev, address: null })); }; return ( handleNameChange(value)} {...(fieldErrors.bio && { invalid: true, errorMessage: fieldErrors.bio })} > handleAddressChange(slicedValue)} {...(fieldErrors.address && { invalid: true, errorMessage: fieldErrors.address })} > 초기화 제출 ); } ``` #### React Hook Form ```tsx import { HStack, VStack } from "@seed-design/react"; import { useCallback, type FormEvent, type KeyboardEvent } from "react"; import { useController, useForm } from "react-hook-form"; import { ActionButton } from "seed-design/ui/action-button"; import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; interface FormValues { bio: string; address: string; } export default function MultilineTextFieldReactHookForm() { const { handleSubmit, reset, control } = useForm({ defaultValues: { bio: "", address: "", }, shouldFocusError: true, }); const { field: bioField, fieldState: bioFieldState } = useController({ name: "bio", control, rules: { required: "필수 입력 항목입니다", }, }); const { field: { onChange: addressOnChange, ...addressField }, fieldState: addressFieldState, } = useController({ name: "address", control, rules: { required: "필수 입력 항목입니다", pattern: { value: /^대한민국/, message: "대한민국으로 시작해주세요" }, }, }); const onValid = useCallback((data: FormValues) => { window.alert(JSON.stringify(data, null, 2)); }, []); const onReset = useCallback( (event: FormEvent) => { event.preventDefault(); reset(); }, [reset], ); const onMetaReturn = useCallback( (event: KeyboardEvent) => { if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) { event.preventDefault(); handleSubmit(onValid)(); } }, [handleSubmit, onValid], ); return ( addressOnChange(slicedValue)} required {...addressField} > 초기화 제출 ); } ``` #### Formatting ```tsx import { useMemo, useState } from "react"; import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldFormatting() { const [value, setValue] = useState(""); const formattedValue = useMemo( () => value .split("") .filter((char) => char !== " ") .join(""), [value], ); return ( setValue(value)} > ); } ``` #### Slicing ```tsx import { useState } from "react"; import { TextField, TextFieldTextarea } from "seed-design/ui/text-field"; export default function MultilineTextFieldSlicing() { const [value, setValue] = useState(""); return ( setValue(slicedValue)} > ); } ``` file: components/(text-field)/text-field.mdx # Text Field 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Text Field description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add text-field ``` ```bash pnpm dlx @seed-design/cli@latest add text-field ``` ```bash yarn dlx @seed-design/cli@latest add text-field ``` ```bash bun x @seed-design/cli@latest add text-field ``` ## Props ### `TextField` void)", "default": undefined }, maxGraphemeCount: { "type": "number", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `TextFieldInput`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### State #### Enabled ```tsx import { HStack } from "@seed-design/react"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldEnabled() { return ( ); } ``` #### Disabled ```tsx import { HStack } from "@seed-design/react"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldDisabled() { return ( ); } ``` #### Read Only ```tsx import { HStack } from "@seed-design/react"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldReadOnly() { return ( ); } ``` ### Customizable Parts #### Prefix ```tsx import { IconMagnifyingglassLine } from "@karrotmarket/react-monochrome-icon"; import { HStack } from "@seed-design/react"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldPrefix() { return ( } > ); } ``` #### Suffix ```tsx import { IconWonLine } from "@karrotmarket/react-monochrome-icon"; import { HStack } from "@seed-design/react"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldSuffix() { return ( }> ); } ``` #### Both Affixes ```tsx import { IconPlusCircleLine, IconWonLine } from "@karrotmarket/react-monochrome-icon"; import { HStack } from "@seed-design/react"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldSuffix() { return ( } suffixIcon={} > ); } ``` #### Indicator ```tsx import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldIndicator() { return ( ); } ``` #### Grapheme Count ```tsx import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldGraphemeCount() { return ( ); } ``` ### Size #### XLarge ```tsx import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldXlarge() { return ( ); } ``` #### Large ```tsx import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldLarge() { return ( ); } ``` #### Medium ```tsx import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldMedium() { return ( ); } ``` ### Use Cases #### Form ```tsx import { HStack, VStack } from "@seed-design/react"; import { useCallback, useState, type FormEvent } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; interface FormValues { name: string; address: string; } type FieldErrors = Record; export default function TextFieldForm() { const [formValues, setFormValues] = useState({ name: "", address: "", }); const [fieldErrors, setFieldStates] = useState({ name: null, address: null, }); const validateForm = useCallback((): boolean => { let isValid = true; const newFieldErrors: FieldErrors = { name: null, address: null, }; // Name validation if (!formValues.name) { newFieldErrors.name = "필수 입력 항목입니다"; isValid = false; } if (!formValues.address.startsWith("대한민국")) { newFieldErrors.address = "대한민국으로 시작해주세요"; isValid = false; } if (!formValues.address) { newFieldErrors.address = "필수 입력 항목입니다"; isValid = false; } setFieldStates(newFieldErrors); return isValid; }, [formValues]); const handleSubmit = useCallback( (event: FormEvent) => { event.preventDefault(); if (validateForm()) { window.alert(JSON.stringify(formValues, null, 2)); } }, [formValues, validateForm], ); const handleReset = useCallback((event: FormEvent) => { event.preventDefault(); setFormValues({ name: "", address: "" }); setFieldStates({ name: null, address: null }); }, []); const handleNameChange = (value: string) => { setFormValues((prev) => ({ ...prev, name: value })); setFieldStates((prev) => ({ ...prev, name: null })); }; const handleAddressChange = (value: string) => { setFormValues((prev) => ({ ...prev, address: value })); setFieldStates((prev) => ({ ...prev, address: null })); }; return ( handleNameChange(value)} {...(fieldErrors.name && { invalid: true, errorMessage: fieldErrors.name })} > handleAddressChange(slicedValue)} {...(fieldErrors.address && { invalid: true, errorMessage: fieldErrors.address })} > 초기화 제출 ); } ``` #### React Hook Form ```tsx import { HStack, VStack } from "@seed-design/react"; import { useCallback, type FormEvent } from "react"; import { useController, useForm } from "react-hook-form"; import { ActionButton } from "seed-design/ui/action-button"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; interface FormValues { name: string; address: string; } export default function TextFieldReactHookForm() { const { handleSubmit, reset, control } = useForm({ defaultValues: { name: "", address: "", }, }); const { field: nameField, fieldState: nameFieldState } = useController({ name: "name", control, rules: { required: "필수 입력 항목입니다", }, }); const { field: { onChange: addressOnChange, ...addressField }, fieldState: addressFieldState, } = useController({ name: "address", control, rules: { required: "필수 입력 항목입니다", pattern: { value: /^대한민국/, message: "대한민국으로 시작해주세요" }, }, }); const onValid = useCallback((data: FormValues) => { window.alert(JSON.stringify(data, null, 2)); }, []); const onReset = useCallback( (event: FormEvent) => { event.preventDefault(); reset(); }, [reset], ); return ( addressOnChange(slicedValue)} required {...addressField} > 초기화 제출 ); } ``` #### Number Formatting ```tsx import { useMemo, useState } from "react"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldNumberFormatting() { const [value, setValue] = useState("1000"); const formattedValue = useMemo(() => { if (value === "") return value; const number = Number(value.replace(/,/g, "")); if (Number.isNaN(number)) return ""; return number.toLocaleString(); }, [value]); return ( setValue(value)} > ); } ``` #### Slicing ```tsx import { useState } from "react"; import { TextField, TextFieldInput } from "seed-design/ui/text-field"; export default function TextFieldSlicing() { const [value, setValue] = useState(""); return ( setValue(slicedValue)} > ); } ``` file: components/action-button.mdx # Action Button 사용자가 특정 액션을 실행할 수 있도록 도와주는 컴포넌트입니다. *** title: Action Button description: 사용자가 특정 액션을 실행할 수 있도록 도와주는 컴포넌트입니다. ------------------------------------------------ ```tsx import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonPreview() { return 라벨; } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add action-button ``` ```bash pnpm dlx @seed-design/cli@latest add action-button ``` ```bash yarn dlx @seed-design/cli@latest add action-button ``` ```bash bun x @seed-design/cli@latest add action-button ``` ## Props

{"Color of the label and icons inside the button.\nWorks only when "}{"variant"}{" is "}{"ghost"}{"."}

}, variant: { "type": "\"brandSolid\" | \"neutralSolid\" | \"neutralWeak\" | \"criticalSolid\" | \"brandOutline\" | \"neutralOutline\" | \"ghost\"", "default": "\"brandSolid\"" }, size: { "type": "\"xsmall\" | \"small\" | \"medium\" | \"large\"", "default": "\"medium\"" }, layout: { "type": "\"withText\" | \"iconOnly\"", "default": "\"withText\"" }, loading: { "type": "boolean", "default": "false", description: <>

{"버튼에 등록된 비동기 작업이 진행 중임을 사용자에게 알립니다."}

}, disabled: { "type": "boolean", "default": "false", description: <>

{"버튼의 비활성화 여부를 나타냅니다."}

}, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

}, flexGrow: { "type": "true | 0 | 1 | (number & {})", "default": undefined, description: <>

{"If true, flex-grow will be set to "}{"1"}{"."}

}, bleedX: { "type": "0 | \"asPadding\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined, description: <>

{"Negative x-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

}, bleedY: { "type": "0 | \"asPadding\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined, description: <>

{"Negative y-axis margin to extend the element outside its parent.\nIf set to \"asPadding\", it will use the padding value in the same direction."}

} }} /> ## Examples ### Brand Solid ```tsx import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonBrandSolid() { return 라벨; } ``` ### Neutral Solid ```tsx import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonNeutralSolid() { return 라벨; } ``` ### Neutral Weak ```tsx import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonNeutralWeak() { return 라벨; } ``` ### Critical Solid ```tsx import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonCriticalSolid() { return 라벨; } ``` ### Brand Outline ```tsx import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonBrandOutline() { return 라벨; } ``` ### Neutral Outline ```tsx import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonNeutralOutline() { return 라벨; } ``` ### Ghost Ghost variant는 `color` 속성을 사용해 레이블과 아이콘의 색상을 변경할 수 있습니다. ```tsx import { HStack, Text, VStack } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonGhost() { return ( Default Neutral Subtle Brand ); } ``` ### Icon Only ```tsx import { IconPlusFill } from "@karrotmarket/react-monochrome-icon"; import { Icon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonIconOnly() { return ( } /> ); } ``` ### Prefix Icon ```tsx import { IconPlusFill } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonPrefixIcon() { return ( } /> 라벨 ); } ``` ### Suffix Icon ```tsx import { IconChevronRightFill } from "@karrotmarket/react-monochrome-icon"; import { SuffixIcon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonSuffixIcon() { return ( 라벨 } /> ); } ``` ### Disabled ```tsx import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonDisabled() { return 라벨; } ``` ### Loading ```tsx import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonLoading() { const [loading, setLoading] = useState(false); function handleClick() { setLoading(true); setTimeout(() => setLoading(false), 2000); } // 이벤트 핸들링이 필요할 수 있으므로 loading은 disabled를 포함하지 않습니다. 이벤트 발생을 원하지 않는 경우, disabled 속성을 추가해주세요. return ( 시간이 걸리는 액션 ); } ``` ### Bleed `bleedX`, `bleedY` 속성을 사용해 버튼이 레이아웃에서 "빠져나오게" 할 수 있습니다. Ghost variant를 시각적으로 정렬해야 할 때 유용합니다. ```tsx import { HStack, Text, VStack } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; export default function ActionButtonBleed() { return ( Bleed Example Bleed Y Bleed Example Bleed X and Y ); } ``` file: components/alert-dialog.mdx # Alert Dialog 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Alert Dialog description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { ResponsivePair } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, AlertDialogTrigger, } from "seed-design/ui/alert-dialog"; const AlertDialogSingle = () => { return ( // You can set z-index dialog with "--layer-index" custom property. useful for stackflow integration. 열기 주의 이 작업은 되돌릴 수 없습니다. 취소 확인 ); }; export default AlertDialogSingle; ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add alert-dialog ``` ```bash pnpm dlx @seed-design/cli@latest add alert-dialog ``` ```bash yarn dlx @seed-design/cli@latest add alert-dialog ``` ```bash bun x @seed-design/cli@latest add alert-dialog ``` ## Props ### `AlertDialogRoot`

{"The role of the dialog."}

}, closeOnInteractOutside: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the outside is clicked"}

}, closeOnEscape: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the escape key is pressed"}

}, lazyMount: { "type": "boolean", "default": "false", description: <>

{"Whether to enable lazy mounting"}

}, unmountOnExit: { "type": "boolean", "default": "false", description: <>

{"Whether to unmount on exit."}

}, open: { "type": "boolean", "default": undefined }, defaultOpen: { "type": "boolean", "default": undefined }, onOpenChange: { "type": "((open: boolean) => void)", "default": undefined } }} /> ### `AlertDialogTrigger`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `AlertDialogContent`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `AlertDialogHeader`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `AlertDialogTitle`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `AlertDialogDescription`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `AlertDialogFooter`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Responsive Wrapping `` 컴포넌트를 사용해 버튼 컨텐츠가 길어지는 경우 레이아웃을 세로로 접을 수 있습니다. ```tsx import { PrefixIcon, ResponsivePair } from "@seed-design/react"; import { IconCheckFill } from "@seed-design/react-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, AlertDialogTrigger, } from "seed-design/ui/alert-dialog"; const AlertDialogWrap = () => { return ( // You can set z-index dialog with "--layer-index" custom property. useful for stackflow integration. 열기 Wrapping ResponsivePair 컴포넌트를 사용해 버튼 컨텐츠가 길어지는 경우 레이아웃을 세로로 접을 수 있습니다. 취소 } />긴 레이블 예시 ); }; export default AlertDialogWrap; ``` ### Single Action ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, AlertDialogTrigger, } from "seed-design/ui/alert-dialog"; const AlertDialogSingle = () => { // You can set z-index dialog with "--layer-index" custom property. useful for stackflow integration. return ( 열기 제목 단일 선택지를 제공합니다. 확인 ); }; export default AlertDialogSingle; ``` ### Neutral Secondary Action ```tsx import { ResponsivePair } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, AlertDialogTrigger, } from "seed-design/ui/alert-dialog"; const AlertDialogNeutral = () => { return ( // You can set z-index dialog with "--layer-index" custom property. useful for stackflow integration. 열기 제목 중립적인 선택지를 제공합니다. {/* ResponsivePair component wraps layout if button content is too long. */} 취소 확인 ); }; export default AlertDialogNeutral; ``` ### Critical Action ```tsx import { ResponsivePair } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, AlertDialogTrigger, } from "seed-design/ui/alert-dialog"; const AlertDialogCritical = () => { return ( // You can set z-index dialog with "--layer-index" custom property. useful for stackflow integration. 열기 제목 파괴적, 비가역적 작업을 경고합니다. {/* ResponsivePair component wraps layout if button content is too long. */} 취소 확인 ); }; export default AlertDialogCritical; ``` ### Controlled Trigger 외의 방식으로 AlertDialog를 열고 닫을 수 있습니다. 이 경우 `open` prop을 사용하여 AlertDialog의 상태를 제어합니다. ```tsx import { ResponsivePair } from "@seed-design/react"; import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, } from "seed-design/ui/alert-dialog"; const AlertDialogControlled = () => { const [open, setOpen] = useState(false); return ( <> setOpen(true)}>열기 주의 이 작업은 되돌릴 수 없습니다. setOpen(false)}> 취소 setOpen(false)}> 확인 ); }; export default AlertDialogControlled; ``` ### Portalled Portal은 기본적으로 `document.body`에 렌더링됩니다. ```tsx import { ResponsivePair, Portal } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, AlertDialogTrigger, } from "seed-design/ui/alert-dialog"; const AlertDialogPortalled = () => { return ( // You can set z-index dialog with "--layer-index" custom property. useful for stackflow integration. 열기 주의 이 작업은 되돌릴 수 없습니다. 취소 확인 ); }; export default AlertDialogPortalled; ``` ### Stackflow ```tsx import { useActivity } from "@stackflow/react"; import { ActivityComponentType, useFlow } from "@stackflow/react/future"; import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, } from "seed-design/ui/alert-dialog"; declare module "@stackflow/config" { interface Register { "alert-dialog-stackflow": unknown; } } const AlertDialogStackflow: ActivityComponentType<"alert-dialog-stackflow"> = () => { const activity = useActivity(); const { pop } = useFlow(); return ( !open && pop()}> 제목 Stackflow 확인 ); }; export default AlertDialogStackflow; ``` file: components/avatar.mdx # Avatar Avatar는 사용자, 조직과 같은 고유한 아이덴티티를 표현하는 컴포넌트입니다. *** title: Avatar description: Avatar는 사용자, 조직과 같은 고유한 아이덴티티를 표현하는 컴포넌트입니다. --------------------------------------------------------- ```tsx import { Flex } from "@seed-design/react"; import { Avatar, AvatarBadge } from "seed-design/ui/avatar"; import { IdentityPlaceholder } from "seed-design/ui/identity-placeholder"; export default function AvatarPreview() { return ( } >
} /> ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add avatar ``` ```bash pnpm dlx @seed-design/cli@latest add avatar ``` ```bash yarn dlx @seed-design/cli@latest add avatar ``` ```bash bun x @seed-design/cli@latest add avatar ``` ## Props ### `Avatar` void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `AvatarBadge`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `AvatarStack` ## Examples ### Size ```tsx import { Flex } from "@seed-design/react"; import { Avatar } from "seed-design/ui/avatar"; export default function AvatarSize() { return ( ); } ``` ### Badge (Circle) ```tsx import { IdentityPlaceholder } from "seed-design/ui/identity-placeholder"; import { Avatar, AvatarBadge } from "seed-design/ui/avatar"; import { Box } from "@seed-design/react"; export default function AvatarBadgeCircle() { return ( } > ); } ``` ### Badge (Flower) ```tsx import { IdentityPlaceholder } from "seed-design/ui/identity-placeholder"; import { Avatar, AvatarBadge } from "seed-design/ui/avatar"; export default function AvatarBadgeFlower() { return ( } > 뱃지를 설명하는 대체 텍스트를 제공해야 합니다. ); } ``` ### Badge (Shield) ```tsx import { Avatar, AvatarBadge } from "seed-design/ui/avatar"; import { IdentityPlaceholder } from "seed-design/ui/identity-placeholder"; export default function AvatarBadgeShield() { return ( } > 뱃지를 설명하는 대체 텍스트를 제공해야 합니다. ); } ``` ### Stack ```tsx import { Avatar, AvatarStack } from "seed-design/ui/avatar"; import { IdentityPlaceholder } from "seed-design/ui/identity-placeholder"; export default function AvatarStackExample() { return ( } /> } /> } /> } /> ); } ``` file: components/badge.mdx # Badge Badge는 객체의 속성이나 상태를 시각적으로 표현하는 작은 텍스트 라벨입니다. 사용자의 주의를 끌고 콘텐츠의 빠른 인지와 탐색을 돕기 위해 사용됩니다. *** title: Badge description: Badge는 객체의 속성이나 상태를 시각적으로 표현하는 작은 텍스트 라벨입니다. 사용자의 주의를 끌고 콘텐츠의 빠른 인지와 탐색을 돕기 위해 사용됩니다. -------------------------------------------------------------------------------------------------- ```tsx import { Badge } from "@seed-design/react"; export default function BadgePreview() { return 라벨; } ``` ## Usage ```tsx import { Badge } from "@seed-design/react"; ``` ```tsx Badge ``` ## Props

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Truncating Behavior Badge는 긴 텍스트를 잘라내고 생략 부호를 표시합니다. ```tsx import { Badge, VStack } from "@seed-design/react"; export default function BadgeTruncating() { return ( In velit velit deserunt amet veniam incididunt consectetur incididunt Lorem. In velit velit deserunt amet veniam incididunt consectetur incididunt Lorem. ); } ``` ### Tones and Variants #### Neutral ```tsx import { Badge, HStack, VStack } from "@seed-design/react"; export default function BadgeNeutral() { return ( 라벨 라벨 라벨 라벨 라벨 라벨 ); } ``` #### Brand ```tsx import { Badge, HStack, VStack } from "@seed-design/react"; export default function BadgeBrand() { return ( 라벨 라벨 라벨 라벨 라벨 라벨 ); } ``` #### Informative ```tsx import { Badge, HStack, VStack } from "@seed-design/react"; export default function BadgeInformative() { return ( 라벨 라벨 라벨 라벨 라벨 라벨 ); } ``` #### Positive ```tsx import { Badge, HStack, VStack } from "@seed-design/react"; export default function BadgePositive() { return ( 라벨 라벨 라벨 라벨 라벨 라벨 ); } ``` #### Warning ```tsx import { Badge, HStack, VStack } from "@seed-design/react"; export default function BadgeWarning() { return ( 라벨 라벨 라벨 라벨 라벨 라벨 ); } ``` #### Critical ```tsx import { Badge, HStack, VStack } from "@seed-design/react"; export default function BadgeCritical() { return ( 라벨 라벨 라벨 라벨 라벨 라벨 ); } ``` file: components/bottom-sheet.mdx # Bottom Sheet Bottom sheet는 화면 하단에 고정되어 이전 화면과 관련된 콘텐츠를 표시합니다. 사용자에게 추가적인 정보, 작업 또는 메뉴를 제공하는 데 사용됩니다. *** title: Bottom Sheet description: Bottom sheet는 화면 하단에 고정되어 이전 화면과 관련된 콘텐츠를 표시합니다. 사용자에게 추가적인 정보, 작업 또는 메뉴를 제공하는 데 사용됩니다. ---------------------------------------------------------------------------------------------------- ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { BottomSheetBody, BottomSheetContent, BottomSheetFooter, BottomSheetRoot, BottomSheetTrigger, } from "seed-design/ui/bottom-sheet"; const BottomSheetPreview = () => { return ( Open {/* If you need to omit padding, pass px={0}. */} Content 확인 ); }; export default BottomSheetPreview; ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add bottom-sheet ``` ```bash pnpm dlx @seed-design/cli@latest add bottom-sheet ``` ```bash yarn dlx @seed-design/cli@latest add bottom-sheet ``` ```bash bun x @seed-design/cli@latest add bottom-sheet ``` ## Props ### `BottomSheetRoot`

{"The role of the dialog."}

}, closeOnInteractOutside: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the outside is clicked"}

}, closeOnEscape: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the escape key is pressed"}

}, lazyMount: { "type": "boolean", "default": "false", description: <>

{"Whether to enable lazy mounting"}

}, unmountOnExit: { "type": "boolean", "default": "false", description: <>

{"Whether to unmount on exit."}

}, open: { "type": "boolean", "default": undefined }, defaultOpen: { "type": "boolean", "default": undefined }, onOpenChange: { "type": "((open: boolean) => void)", "default": undefined } }} /> ### `BottomSheetTrigger`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `BottomSheetContent`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `BottomSheetBody`

{"Whether the element should be rendered as a child of a slot."}

}, paddingX: { "type": "0 | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined }, height: { "type": "Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"full\"", "default": undefined }, maxHeight: { "type": "Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"full\"", "default": undefined }, minHeight: { "type": "Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {}) | \"full\"", "default": undefined }, justifyContent: { "type": "\"flex-start\" | \"flex-end\" | \"center\" | \"space-between\" | \"space-around\" | \"flexStart\" | \"flexEnd\" | \"spaceBetween\" | \"spaceAround\"", "default": undefined }, alignItems: { "type": "\"flex-start\" | \"flex-end\" | \"center\" | \"flexStart\" | \"flexEnd\" | \"stretch\"", "default": undefined } }} /> ### `BottomSheetFooter`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Trigger ``는 `asChild` 패턴을 사용해 자식 요소가 BottomSheet를 열 수 있도록 합니다. ``는 `BottomSheet`의 `open` 상태에 따라 `aria-expanded` 속성을 자동으로 설정합니다. 이 속성은 스크린 리더와 같은 보조 기술에 유용합니다. ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { BottomSheetBody, BottomSheetContent, BottomSheetFooter, BottomSheetRoot, BottomSheetTrigger, } from "seed-design/ui/bottom-sheet"; const BottomSheetTriggerExample = () => { return ( Open Content 확인 ); }; export default BottomSheetTriggerExample; ``` ### Controlled Trigger 외의 방식으로 BottomSheet를 열고 닫을 수 있습니다. 이 경우 `open` prop을 사용하여 BottomSheet의 상태를 제어합니다. ```tsx import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { BottomSheetBody, BottomSheetContent, BottomSheetFooter, BottomSheetRoot, } from "seed-design/ui/bottom-sheet"; const BottomSheetControlled = () => { const [open, setOpen] = useState(false); const scheduleOpen = () => { setTimeout(() => { setOpen(true); }, 1000); }; return ( <> 1초 후 열기 {/* If you need to omit padding, pass px={0}. */} Content 확인 ); }; export default BottomSheetControlled; ``` ### Max Height ``에 `maxHeight` prop을 전달하여 BottomSheet의 최대 높이를 설정할 수 있습니다. ```tsx import { Box, VStack } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { BottomSheetBody, BottomSheetContent, BottomSheetFooter, BottomSheetRoot, BottomSheetTrigger, } from "seed-design/ui/bottom-sheet"; const BottomSheetMaxHeight = () => { return ( Open {/* If you need to omit padding, pass px={0}. */} 확인 ); }; export default BottomSheetMaxHeight; ``` ### Bottom Inset ``에 `style` prop을 전달하여 아래 여백을 주기 위해 사용합니다. ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { BottomSheetBody, BottomSheetContent, BottomSheetFooter, BottomSheetRoot, BottomSheetTrigger, } from "seed-design/ui/bottom-sheet"; const BottomSheetBottomInset = () => { return ( Open {/* If you need to omit padding, pass px={0}. */} Content 확인 ); }; export default BottomSheetBottomInset; ``` file: components/callout.mdx # Callout 사용자의 주목을 끌어 중요한 정보를 강조하는 컴포넌트에요. *** title: Callout description: 사용자의 주목을 끌어 중요한 정보를 강조하는 컴포넌트에요. --------------------------------------------- ```tsx import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add callout ``` ```bash pnpm dlx @seed-design/cli@latest add callout ``` ```bash yarn dlx @seed-design/cli@latest add callout ``` ```bash bun x @seed-design/cli@latest add callout ``` ## Props ### `Callout` ### `ActionableCallout` ### `DismissibleCallout` void)", "default": undefined } }} /> ## Examples ### Content Layout #### Text Only ```tsx import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutTextOnly() { return ( ); } ``` #### With Icon ```tsx import { IconCalendarFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutWithIcon() { return ( } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> ); } ``` #### With Title Text ```tsx import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutWithTitleText() { return ( ); } ``` #### With Link Label `ActionableCallout`에서는 `linkProps`를 제공하지 않아요. ```tsx import { VStack } from "@seed-design/react"; import { Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutWithLinkLabel() { return ( ); } ``` #### With All ```tsx import { IconCalendarFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutWithAll() { return ( } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." linkProps={{ children: "시도해 보기" }} /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." linkProps={{ children: "시도해 보기" }} /> ); } ``` ### Customizable Parts #### Rendering Link Label as Child ```tsx import { VStack } from "@seed-design/react"; import { Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutLinkLabelAsChild() { return ( 시도해 보기 ), }} /> 시도해 보기 ), }} /> ); } ``` ### Tones #### Neutral (Default) ```tsx import { IconCalendarFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutNeutral() { return ( } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> ); } ``` #### Informative ```tsx import { IconCalendarFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutInformative() { return ( } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> ); } ``` #### Warning ```tsx import { IconCalendarFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutWarning() { return ( } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> ); } ``` #### Critical ```tsx import { IconCalendarFill } from "@karrotmarket/react-monochrome-icon"; import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutCritical() { return ( } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> } description="기능에 대한 안내 또는 유익한 내용을 전달해요. 콜아웃은 꼭 필요한 경우에만 절제하여 사용해요." /> ); } ``` #### Magic ```tsx import { IconSparkle2 } from "@karrotmarket/react-multicolor-icon"; import { VStack } from "@seed-design/react"; import { ActionableCallout, Callout, DismissibleCallout } from "seed-design/ui/callout"; export default function CalloutMagic() { return ( } /> } /> } /> ); } ``` file: components/checkbox.mdx # Checkbox 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Checkbox description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { Checkbox } from "seed-design/ui/checkbox"; export default function CheckboxPreview() { return ; } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add checkbox ``` ```bash pnpm dlx @seed-design/cli@latest add checkbox ``` ```bash yarn dlx @seed-design/cli@latest add checkbox ``` ```bash bun x @seed-design/cli@latest add checkbox ``` ## Props ### `Checkbox` ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, label: { "type": "ReactNode", "default": undefined }, weight: { "type": "\"regular\" | \"bold\" | CheckboxVariantDeprecatedWeightProps", "default": undefined }, size: { "type": "\"large\" | \"medium\"", "default": "\"medium\"" }, variant: { "type": "\"square\" | \"ghost\"", "default": "\"square\"" }, tone: { "type": "\"neutral\" | \"brand\"", "default": "\"brand\"" }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined }, required: { "type": "boolean", "default": undefined }, checked: { "type": "boolean", "default": undefined }, defaultChecked: { "type": "boolean", "default": undefined }, onCheckedChange: { "type": "((checked: boolean) => void)", "default": undefined }, indeterminate: { "type": "boolean", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `Checkmark`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Sizes ```tsx import { HStack, VStack } from "@seed-design/react"; import { Checkbox } from "seed-design/ui/checkbox"; export default function CheckboxSize() { return ( ); } ``` ### Tones and Variants #### Brand ```tsx import { VStack } from "@seed-design/react"; import { Checkbox } from "seed-design/ui/checkbox"; export default function CheckboxBrand() { return ( ); } ``` #### Neutral ```tsx import { VStack } from "@seed-design/react"; import { Checkbox } from "seed-design/ui/checkbox"; export default function CheckboxNeutral() { return ( ); } ``` ### Indeterminate ```tsx import { Checkbox } from "seed-design/ui/checkbox"; export default function CheckboxIndeterminate() { return ; } ``` ### Weights `weight="default"`와 `weight="stronger"`는 더 이상 사용되지 않습니다. 대신 `weight="regular"`와 `weight="bold"`를 사용하세요. ```tsx import { VStack } from "@seed-design/react"; import { Checkbox } from "seed-design/ui/checkbox"; export default function CheckboxWeights() { return ( ); } ``` ### Long Label ```tsx import { VStack } from "@seed-design/react"; import { Checkbox } from "seed-design/ui/checkbox"; export default function CheckboxLongLabel() { return ( ); } ``` ### Disabled ```tsx import { VStack } from "@seed-design/react"; import { Checkbox } from "seed-design/ui/checkbox"; export default function CheckboxDisabled() { return ( ); } ``` ### Use Cases #### React Hook Form ```tsx import { HStack, VStack } from "@seed-design/react"; import { useCallback, type FormEvent } from "react"; import { useController, useForm } from "react-hook-form"; import { ActionButton } from "seed-design/ui/action-button"; import { Checkbox } from "seed-design/ui/checkbox"; const POSSIBLE_FRUIT_VALUES = ["apple", "melon", "mango"] as const; type FormValues = Record<(typeof POSSIBLE_FRUIT_VALUES)[number], boolean>; export default function CheckboxReactHookForm() { const { handleSubmit, reset, setValue, control } = useForm({ defaultValues: { apple: false, melon: true, mango: false, }, }); const onValid = useCallback((data: FormValues) => { window.alert(JSON.stringify(data, null, 2)); }, []); const onReset = useCallback( (event: FormEvent) => { event.preventDefault(); reset(); }, [reset], ); return ( {POSSIBLE_FRUIT_VALUES.map((name) => { const { field: { value, ...restProps }, fieldState: { invalid }, } = useController({ name, control }); return ( ); })} 초기화 setValue("mango", true)} > mango 선택 제출 ); } ``` #### `Checkmark` 활용하기 `Checkmark`는 독립적인 체크 마크 컴포넌트로, 커스텀 레이아웃을 위해 사용할 수 있습니다. ```tsx import { HStack, Text, VStack } from "@seed-design/react"; import { Checkbox } from "@seed-design/react"; import { Checkmark } from "seed-design/ui/checkbox"; function CustomCheckbox({ children, ...props }: Checkbox.RootProps) { return ( {children} ); } export default function CheckboxCheckmark() { return ( regular medium bold ); } ``` file: components/chip.mdx # Chip Chip은 사용자가 선택, 필터링, 전환과 같은 제어 작업을 수행할 수 있도록 돕는 Pill 형태의 컴포넌트입니다. ActionChip과 ControlChip을 통합한 새로운 컴포넌트입니다. *** title: Chip description: Chip은 사용자가 선택, 필터링, 전환과 같은 제어 작업을 수행할 수 있도록 돕는 Pill 형태의 컴포넌트입니다. ActionChip과 ControlChip을 통합한 새로운 컴포넌트입니다. ----------------------------------------------------------------------------------------------------------------------- ```tsx import { HStack, VStack } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; export default function ChipPreview() { return ( Button Chip Toggle Chip Radio Chip 1 Radio Chip 2 ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add chip ``` ```bash pnpm dlx @seed-design/cli@latest add chip ``` ```bash yarn dlx @seed-design/cli@latest add chip ``` ```bash bun x @seed-design/cli@latest add chip ``` ## Props ### `Chip.Button`

{"Whether the element should be rendered as a child of a slot."}

}, variant: { "type": "\"solid\" | \"outlineStrong\" | \"outlineWeak\"", "default": "\"solid\"" }, size: { "type": "\"large\" | \"medium\" | \"small\"", "default": "\"medium\"" }, layout: { "type": "\"iconOnly\" | \"withText\"", "default": "\"withText\"" } }} /> ### `Chip.Toggle` ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

}, variant: { "type": "\"solid\" | \"outlineStrong\" | \"outlineWeak\"", "default": "\"solid\"" }, size: { "type": "\"large\" | \"medium\" | \"small\"", "default": "\"medium\"" }, layout: { "type": "\"iconOnly\" | \"withText\"", "default": "\"withText\"" }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined }, required: { "type": "boolean", "default": undefined }, checked: { "type": "boolean", "default": undefined }, defaultChecked: { "type": "boolean", "default": undefined }, onCheckedChange: { "type": "((checked: boolean) => void)", "default": undefined }, indeterminate: { "type": "boolean", "default": undefined } }} /> ### `Chip.RadioRoot` void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `Chip.RadioItem` ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

}, variant: { "type": "\"solid\" | \"outlineStrong\" | \"outlineWeak\"", "default": "\"solid\"" }, size: { "type": "\"large\" | \"medium\" | \"small\"", "default": "\"medium\"" }, layout: { "type": "\"iconOnly\" | \"withText\"", "default": "\"withText\"" }, value: { "type": "string", "default": undefined }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined } }} /> ## Examples ### Sizes #### Small ```tsx import { HStack, VStack } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; export default function ChipSmall() { return ( Small Button Small Toggle Small Radio 1 Small Radio 2 ); } ``` #### Medium ```tsx import { HStack, VStack } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; export default function ChipMedium() { return ( Medium Button Medium Toggle Medium Radio 1 Medium Radio 2 ); } ``` #### Large ```tsx import { HStack, VStack } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; export default function ChipLarge() { return ( Large Button Large Toggle Large Radio 1 Large Radio 2 ); } ``` ### Variants #### Solid ```tsx import { HStack, VStack } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; export default function ChipSolid() { return ( Solid Button Solid Toggle Solid Radio 1 Solid Radio 2 ); } ``` #### Outline Strong ```tsx import { HStack, VStack } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; export default function ChipOutlineStrong() { return ( Outline Strong Button Outline Strong Toggle Outline Strong Radio 1 Outline Strong Radio 2 ); } ``` #### Outline Weak ```tsx import { HStack, VStack } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; export default function ChipOutlineWeak() { return ( Outline Weak Button Outline Weak Toggle Outline Weak Radio 1 Outline Weak Radio 2 ); } ``` ### Prefix Icon ```tsx import { HStack, VStack, Icon } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; import { IconHeartFill } from "@karrotmarket/react-monochrome-icon"; export default function ChipPrefixIcon() { return ( } /> With Icon Button } /> With Icon Toggle } /> With Icon Radio 1 } /> With Icon Radio 2 ); } ``` ### Suffix Icon ```tsx import { HStack, VStack, Icon } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; import { IconChevronDownLine } from "@karrotmarket/react-monochrome-icon"; export default function ChipSuffixIcon() { return ( Button with Suffix } /> Toggle with Suffix } /> Radio with Suffix 1 } /> Radio with Suffix 2 } /> ); } ``` ### Icon Only ```tsx "use client"; import { HStack, VStack, Icon } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; import { IconArrowClockwiseCircularLine, IconBellLine, IconBellSlashLine, IconTimer_10Line, IconTimer_3Line, } from "@karrotmarket/react-monochrome-icon"; import { useState } from "react"; export default function ChipIconOnly() { const [checked, setChecked] = useState(false); return ( } /> : } /> } /> } /> ); } ``` ### Prefix Avatar [Avatar](/react/components/avatar)와 함께 사용할 수 있습니다. ```tsx import { HStack, VStack } from "@seed-design/react"; import { Chip } from "@/registry/ui/chip"; import { Avatar } from "seed-design/ui/avatar"; import { IdentityPlaceholder } from "seed-design/ui/identity-placeholder"; export default function ChipPrefixAvatar() { return ( } /> With Avatar Button } /> With Avatar Toggle } /> With Avatar Radio 1 } /> With Avatar Radio 2 ); } ``` ## Migrating from ActionChip/ControlChip [Action Chip](/react/components/action-chip)과 [Control Chip](/react/components/control-chip)을 대체합니다. ### ActionChip → Chip.Button ```tsx // Before import { ActionChip } from "@seed-design/react"; Label // After import { Chip } from "@seed-design/react"; Label ``` ### ControlChip → Chip.Toggle ```tsx // Before import { ControlChip } from "@seed-design/react"; Label // After import { Chip } from "@seed-design/react"; Label ``` file: components/concepts/composition.mdx # Composition 컴포넌트를 조합하여 복잡한 UI를 구성하는 방법과 원칙을 설명합니다. *** title: Composition description: 컴포넌트를 조합하여 복잡한 UI를 구성하는 방법과 원칙을 설명합니다. --------------------------------------------------- ## `as` Prop `as` prop은 React 컴포넌트가 렌더링하는 기본 HTML 요소를 변경하는 데 사용됩니다. 컴포넌트의 기능은 유지하면서 기본 요소를 변경할 수 있는 간단한 방법을 제공합니다. ```jsx 단락 텍스트 인라인 텍스트 제목 텍스트 ``` ## `asChild` Prop `asChild` prop은 컴포넌트의 기능을 자식 요소에 합성하는 데 사용됩니다. 이를 활용해 HTML 태그를 변경하거나, 다른 컴포넌트에 기능을 주입할 수 있습니다. [Radix UI](https://www.radix-ui.com/primitives/docs/utilities/slot)에서 제공하는 asChild 패턴과 동일한 기능을 제공합니다. ### 요소 타입 변경하기 ```jsx // FAB는 기본적으로 button 태그를 사용하지만, asChild를 사용해 링크로 변경할 수 있습니다. } /> ``` > 기본 요소 타입을 변경하는 경우, 해당 요소가 접근성을 유지하고 올바르게 작동하는지 확인하는 것은 개발자의 책임입니다. 예를 들어, 버튼을 `div`로 변경하면 더 이상 키보드로 접근할 수 없게 될 수 있습니다. ### React 컴포넌트와 조합하기 ```jsx // 라우터 라이브러리에서 제공하는 Link 컴포넌트에 기능을 합성할 수 있습니다. ``` `asChild`를 사용하여 컴포넌트를 조합할 때는 두 가지 원칙을 따라야 합니다. #### 1. 컴포넌트는 props를 전개해야 합니다 asChild는 기능을 제공하고 접근성을 유지하기 위한 고유의 props와 이벤트 핸들러를 전달합니다. 컴포넌트가 이러한 props를 지원하지 않으면 제대로 작동하지 않습니다. ```jsx // 잘못된 방법 const MyButton = () => {/* [!code highlight] */} alert("보기 클릭됨")} > 보기 ``` [Snippet](/react/components/concepts/snippet)으로 제공되는 `ListButtonItem` 및 `ListLinkItem`는 이 패턴을 쉽게 구현할 수 있도록 돕습니다. ```tsx import { ListButtonItem } from "seed-design/ui/list"; alert("사용자 클릭됨")} title="사용자" detail="항목 6개" suffix={ alert("보기 클릭됨")} > 보기 } /> ``` #### `List.Item`에 `asChild` prop을 사용하는 경우 리스트 항목 전체 영역을 `label`로 만들고, `List.Prefix` 또는 `List.Suffix`에 [Checkmark](/react/components/checkbox#checkmark-활용하기) 또는 [RadioMark](/react/components/radio-group#radiomark-활용하기)를 넣는 경우 활용할 수 있는 패턴입니다. ```tsx import { List as SeedList } from "@seed-design/react"; import { Checkbox } from "@seed-design/react/primitive"; {/* [!code highlight] */} {/* ``` [Snippet](/react/components/concepts/snippet)으로 제공되는 `ListCheckItem` 및 `ListRadioItem`는 이 패턴을 쉽게 구현할 수 있도록 돕습니다. ```tsx import { ListCheckItem } from "seed-design/ui/list"; } /> ``` file: components/manner-temp-badge.mdx # Manner Temp Badge 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Manner Temp Badge description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { VStack } from "@seed-design/react"; import { MannerTempBadge } from "seed-design/ui/manner-temp-badge"; export default function BadgePreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add manner-temp-badge ``` ```bash pnpm dlx @seed-design/cli@latest add manner-temp-badge ``` ```bash yarn dlx @seed-design/cli@latest add manner-temp-badge ``` ```bash bun x @seed-design/cli@latest add manner-temp-badge ``` ## Props

{"The manner temperature of the badge.\nLevel will be calculated based on this value.\nIf level is provided, this will be ignored."}

}, level: { "type": "\"l1\" | \"l2\" | \"l3\" | \"l4\" | \"l5\" | \"l6\"", "default": "\"l1\"" } }} /> file: components/manner-temp.mdx # Manner Temp 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Manner Temp description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { VStack } from "@seed-design/react"; import { MannerTemp } from "seed-design/ui/manner-temp"; export default function MannerTempPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add manner-temp ``` ```bash pnpm dlx @seed-design/cli@latest add manner-temp ``` ```bash yarn dlx @seed-design/cli@latest add manner-temp ``` ```bash bun x @seed-design/cli@latest add manner-temp ``` ## Props

{"The manner temperature of the MannerTemp component.\nLevel will be calculated based on this value.\nIf level is provided, this will be ignored."}

}, level: { "type": "\"l1\" | \"l2\" | \"l3\" | \"l4\" | \"l5\" | \"l6\"", "default": "\"l1\"" } }} /> file: components/menu-sheet.mdx # Menu Sheet Menu Sheet는 사용자가 특정 작업에 관한 선택지뿐만 아니라 추가적인 선택지를 제공할 때 사용하는 시트 형태의 컴포넌트입니다. *** title: Menu Sheet description: Menu Sheet는 사용자가 특정 작업에 관한 선택지뿐만 아니라 추가적인 선택지를 제공할 때 사용하는 시트 형태의 컴포넌트입니다. -------------------------------------------------------------------------------------- ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuSheetContent, MenuSheetGroup, MenuSheetItem, MenuSheetRoot, MenuSheetTrigger, } from "seed-design/ui/menu-sheet"; const MenuSheetPreview = () => { return ( Open } /> Action 1 } /> Action 2 } /> Action 3 } /> Action 4 } /> Action 5 ); }; export default MenuSheetPreview; ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add menu-sheet ``` ```bash pnpm dlx @seed-design/cli@latest add menu-sheet ``` ```bash yarn dlx @seed-design/cli@latest add menu-sheet ``` ```bash bun x @seed-design/cli@latest add menu-sheet ``` ## Props ### `MenuSheetRoot`

{"The role of the dialog."}

}, closeOnInteractOutside: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the outside is clicked"}

}, closeOnEscape: { "type": "boolean", "default": "true", description: <>

{"Whether to close the dialog when the escape key is pressed"}

}, lazyMount: { "type": "boolean", "default": "false", description: <>

{"Whether to enable lazy mounting"}

}, unmountOnExit: { "type": "boolean", "default": "false", description: <>

{"Whether to unmount on exit."}

}, open: { "type": "boolean", "default": undefined }, defaultOpen: { "type": "boolean", "default": undefined }, onOpenChange: { "type": "((open: boolean) => void)", "default": undefined } }} /> ### `MenuSheetTrigger`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `MenuSheetContent`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `MenuSheetGroup` ### `MenuSheetItem`

{"Whether the element should be rendered as a child of a slot."}

}, tone: { "type": "\"neutral\" | \"critical\"", "default": "\"neutral\"" }, labelAlign: { "type": "\"left\" | \"center\"", "default": "\"left\"" } }} /> ## Examples ### With Title ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuSheetContent, MenuSheetGroup, MenuSheetItem, MenuSheetRoot, MenuSheetTrigger, } from "seed-design/ui/menu-sheet"; const MenuSheetWithTitle = () => { return ( Open } /> Action 1 } /> Action 2 } /> Action 3 } /> Action 4 } /> Action 5 ); }; export default MenuSheetWithTitle; ``` ### `labelAlign="left"` (with `PrefixIcon`) ```tsx import { IconEyeSlashLine } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuSheetContent, MenuSheetGroup, MenuSheetItem, MenuSheetRoot, MenuSheetTrigger, } from "seed-design/ui/menu-sheet"; const MenuSheetWithPrefixIcon = () => { return ( Open } /> Action 1 } /> Action 2 } /> Action 3 } /> Action 4 } /> Action 5 ); }; export default MenuSheetWithPrefixIcon; ``` ### `labelAlign="center"` (without `PrefixIcon`) ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { MenuSheetContent, MenuSheetGroup, MenuSheetItem, MenuSheetRoot, MenuSheetTrigger, } from "seed-design/ui/menu-sheet"; const MenuSheetWithoutPrefixIcon = () => { return ( Open Action 1 Action 2 Action 3 Action 4 Action 5 ); }; export default MenuSheetWithoutPrefixIcon; ``` ### Overriding `labelAlign` `MenuSheetContent`에 지정한 `labelAlign`을 `MenuSheetGroup` 또는 `MenuSheetItem`에 지정한 `labelAlign`으로 덮어쓸 수 있습니다. ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { MenuSheetContent, MenuSheetGroup, MenuSheetItem, MenuSheetRoot, MenuSheetTrigger, } from "seed-design/ui/menu-sheet"; const MenuSheetOverridingLabelAlign = () => { return ( Open Action 1 Action 2 Action 3 Action 4 Action 5 ); }; export default MenuSheetOverridingLabelAlign; ``` file: components/page-banner.mdx # Page Banner 페이지 상단에 위치하며 사용자에게 전체적인 상태나 중요한 메시지를 전달하는 상위 레벨 메시지 컴포넌트입니다. *** title: Page Banner description: 페이지 상단에 위치하며 사용자에게 전체적인 상태나 중요한 메시지를 전달하는 상위 레벨 메시지 컴포넌트입니다. ------------------------------------------------------------------------- ```tsx import { VStack } from "@seed-design/react"; import { ActionablePageBanner, DismissiblePageBanner, PageBanner, } from "seed-design/ui/page-banner"; export default function PageBannerPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add page-banner ``` ```bash pnpm dlx @seed-design/cli@latest add page-banner ``` ```bash yarn dlx @seed-design/cli@latest add page-banner ``` ```bash bun x @seed-design/cli@latest add page-banner ``` ## Props ### `PageBanner` ### `PageBannerButton`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `ActionablePageBanner` ### `DismissiblePageBanner` void)", "default": undefined } }} /> ## Examples ### With Button `PageBanner`의 `suffix` prop에 `PageBannerButton`을 전달하여 버튼을 추가할 수 있습니다. ```tsx import { PageBanner, PageBannerButton } from "seed-design/ui/page-banner"; export default function PageBannerWithButton() { return ( 자세히 보기} /> ); } ``` ### Rendering `PageBannerButton` as a Child ```tsx import { PageBanner, PageBannerButton } from "seed-design/ui/page-banner"; export default function PageBannerButtonAsChild() { return ( 새 탭에서 열기 } /> ); } ``` ### Tones and Variants #### Neutral ```tsx import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { ActionablePageBanner, DismissiblePageBanner, PageBanner, PageBannerButton, } from "seed-design/ui/page-banner"; export default function PageBannerNeutral() { return (
} title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." />
); } ```
#### Positive ```tsx import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { ActionablePageBanner, DismissiblePageBanner, PageBanner, PageBannerButton, } from "seed-design/ui/page-banner"; export default function PageBannerPositive() { return (
} title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." />
); } ```
#### Informative ```tsx import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { ActionablePageBanner, DismissiblePageBanner, PageBanner, PageBannerButton, } from "seed-design/ui/page-banner"; export default function PageBannerInformative() { return (
} title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." />
); } ```
#### Warning ```tsx import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { ActionablePageBanner, DismissiblePageBanner, PageBanner, PageBannerButton, } from "seed-design/ui/page-banner"; export default function PageBannerWarning() { return (
} title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." />
); } ```
#### Critical ```tsx import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon"; import { ActionablePageBanner, DismissiblePageBanner, PageBanner, PageBannerButton, } from "seed-design/ui/page-banner"; export default function PageBannerCritical() { return (
} title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." suffix={등록하기} /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." /> } title="미노출" description="사업자 정보를 등록해주세요." />
); } ```
file: components/progress-circle.mdx # Progress Circle 작업이 진행 중임을 알리거나 작업 시간을 시각적으로 나타내는 데 사용됩니다. *** title: Progress Circle description: 작업이 진행 중임을 알리거나 작업 시간을 시각적으로 나타내는 데 사용됩니다. ------------------------------------------------------- ```tsx import { ProgressCircle } from "seed-design/ui/progress-circle"; export default function ProgressCirclePreview() { return ; } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add progress-circle ``` ```bash pnpm dlx @seed-design/cli@latest add progress-circle ``` ```bash yarn dlx @seed-design/cli@latest add progress-circle ``` ```bash bun x @seed-design/cli@latest add progress-circle ``` ## Props

{"The current value of the progress. if undefined, it will be indeterminate."}

}, minValue: { "type": "number", "default": "0", description: <>

{"The minimum value allowed of the progress."}

}, maxValue: { "type": "number", "default": "100", description: <>

{"The maximum value allowed of the progress."}

}, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

}, tone: { "type": "\"inherit\" | \"neutral\" | \"brand\" | \"staticWhite\"", "default": "\"neutral\"" }, size: { "type": "\"inherit\" | \"24\" | \"40\"", "default": "40" } }} /> ## Examples ### Neutral ```tsx import { ProgressCircle } from "seed-design/ui/progress-circle"; export default function ProgressCircleNeutral() { return ; } ``` ### Brand ```tsx import { ProgressCircle } from "seed-design/ui/progress-circle"; export default function ProgressCircleBrand() { return ; } ``` ### Static White ```tsx import { ProgressCircle } from "seed-design/ui/progress-circle"; export default function ProgressCircleStaticWhite() { return (
); } ```
### Size=40 ```tsx import { ProgressCircle } from "seed-design/ui/progress-circle"; export default function ProgressCircle40() { return ; } ``` ### Size=24 ```tsx import { ProgressCircle } from "seed-design/ui/progress-circle"; export default function ProgressCircle24() { return ; } ``` ### Determinate ```tsx import { ProgressCircle } from "seed-design/ui/progress-circle"; export default function ProgressCircleDeterminate() { return ; } ``` ### Indeterminate ```tsx import { ProgressCircle } from "seed-design/ui/progress-circle"; export default function ProgressCirclePreview() { // if you want to show an indeterminate progress circle, you can pass `undefined` or omit the `value` prop return ; } ``` file: components/pull-to-refresh.mdx # Pull To Refresh 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Pull To Refresh description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { AppBar, AppScreen } from "@seed-design/stackflow"; import { ActivityComponentType } from "@stackflow/react/future"; import { VStack } from "@seed-design/react"; import { PullToRefreshContent, PullToRefreshIndicator, PullToRefreshRoot, } from "seed-design/ui/pull-to-refresh"; declare module "@stackflow/config" { interface Register { "pull-to-refresh-preview": unknown; } } const PullToRefreshPreview: ActivityComponentType<"pull-to-refresh-preview"> = () => { // AppScreen is imported from @seed-design/stackflow instead of snippet for demo purpose. // AppScreen snippet is integrating PullToRefresh, so it's not necessary to use it here. return ( Pull To Refresh {}} onPtrRefresh={async () => { await new Promise((resolve) => setTimeout(resolve, 1000)); }} > Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam autem deserunt reprehenderit ducimus sunt. Quod laudantium excepturi tempora fuga repellendus accusantium nam maiores? Quas debitis, neque ullam eligendi minus sit? ); }; export default PullToRefreshPreview; ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add pull-to-refresh ``` ```bash pnpm dlx @seed-design/cli@latest add pull-to-refresh ``` ```bash yarn dlx @seed-design/cli@latest add pull-to-refresh ``` ```bash bun x @seed-design/cli@latest add pull-to-refresh ``` ## Props ### `PullToRefreshRoot`

{"The threshold value to trigger the refresh. (px)"}

}, displacementMultiplier: { "type": "number", "default": "0.5", description: <>

{"The multiplier to calculate displacement from the touch movement."}

}, onPtrPullStart: { "type": "((ctx: PullToRefreshContext) => void)", "default": undefined, description: <>

{"Callback when the pull-to-refresh has started to pull."}

}, onPtrPullMove: { "type": "((ctx: PullToRefreshContext) => void)", "default": undefined, description: <>

{"Callback when the pull-to-refresh is moving during the pull."}

}, onPtrPullEnd: { "type": "((ctx: PullToRefreshContext) => void)", "default": undefined, description: <>

{"Callback when the pull-to-refresh is released.\nIt does not matter if it is ready or not. If you want to handle the refresh, use "}{"onPtrRefresh"}{"."}

}, onPtrReady: { "type": "(() => void)", "default": undefined, description: <>

{"Callback when the pull-to-refresh is pulled over the threshold."}

}, onPtrRefresh: { "type": "(() => Promise)", "default": undefined, description: <>

{"Callback when the pull-to-refresh is released after ready."}

}, disabled: { "type": "boolean", "default": "false", description: <>

{"Whether to disable the pull-to-refresh."}

}, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `PullToRefreshIndicator` ### `PullToRefreshContent`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### PTR in Tabs ```tsx import { VStack } from "@seed-design/react"; import { ActivityComponentType } from "@stackflow/react/future"; import { AppBar, AppBarMain } from "seed-design/ui/app-bar"; import { AppScreen, AppScreenContent } from "seed-design/ui/app-screen"; import { PullToRefreshContent, PullToRefreshIndicator, PullToRefreshRoot, } from "seed-design/ui/pull-to-refresh"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; declare module "@stackflow/config" { interface Register { "pull-to-refresh-tabs": unknown; } } const PullToRefreshTabs: ActivityComponentType<"pull-to-refresh-tabs"> = () => { return ( Pull To Refresh Tab 1 Tab 2 {}} onPtrRefresh={async () => { await new Promise((resolve) => setTimeout(resolve, 1000)); }} > Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam autem deserunt reprehenderit ducimus sunt. Quod laudantium excepturi tempora fuga repellendus accusantium nam maiores? Quas debitis, neque ullam eligendi minus sit? PTR is not available in this tab. ); }; export default PullToRefreshTabs; ``` ### Disabled `disabled` 속성을 사용하여 PTR를 비활성화할 수 있습니다. ```tsx import { Box, HStack, Text } from "@seed-design/react"; import { useState } from "react"; import { PullToRefreshContent, PullToRefreshIndicator, PullToRefreshRoot, } from "seed-design/ui/pull-to-refresh"; import { Switch } from "seed-design/ui/switch"; const PullToRefreshDisabled = () => { const [disabled, setDisabled] = useState(false); return ( {}} onPtrRefresh={async () => { await new Promise((resolve) => setTimeout(resolve, 1000)); }} disabled={disabled} > Disabled ); }; export default PullToRefreshDisabled; ``` file: components/radio-group.mdx # Radio Group Radio Group 컴포넌트는 사용자가 여러 옵션 중 하나를 선택할 수 있도록 합니다. *** title: Radio Group description: "Radio Group 컴포넌트는 사용자가 여러 옵션 중 하나를 선택할 수 있도록 합니다." ---------------------------------------------------------------- ```tsx import { VStack } from "@seed-design/react"; import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; export default function RadioGroupPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add radio-group ``` ```bash pnpm dlx @seed-design/cli@latest add radio-group ``` ```bash yarn dlx @seed-design/cli@latest add radio-group ``` ```bash bun x @seed-design/cli@latest add radio-group ``` ## Props ### `RadioGroup` void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `RadioGroupItem` ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, weight: { "type": "\"regular\" | \"bold\"", "default": "\"regular\"" }, size: { "type": "\"large\" | \"medium\"", "default": "\"medium\"" }, tone: { "type": "\"neutral\" | \"brand\"", "default": "\"brand\"" }, value: { "type": "string", "default": undefined }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `RadioMark`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Sizes ```tsx import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; import { VStack, HStack } from "@seed-design/react"; export default function RadioGroupSize() { return ( ); } ``` ### Tones #### Brand ```tsx import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; import { HStack } from "@seed-design/react"; export default function RadioGroupBrand() { return ( ); } ``` #### Neutral ```tsx import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; import { HStack } from "@seed-design/react"; export default function RadioGroupNeutral() { return ( ); } ``` ### Weights ```tsx import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; import { HStack } from "@seed-design/react"; export default function RadioGroupWeights() { return ( ); } ``` ### Long Label ```tsx import { VStack } from "@seed-design/react"; import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; export default function RadioGroupLongLabel() { return ( ); } ``` ### Disabled ```tsx import { VStack } from "@seed-design/react"; import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; export default function RadioGroupDisabled() { return ( ); } ``` ### Use Cases #### React Hook Form ```tsx import { HStack, VStack } from "@seed-design/react"; import { useCallback, type FormEvent } from "react"; import { useController, useForm } from "react-hook-form"; import { ActionButton } from "seed-design/ui/action-button"; import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; const POSSIBLE_COLORS = ["red", "blue", "green"] as const; interface FormValues { color: (typeof POSSIBLE_COLORS)[number]; } export default function RadioGroupReactHookForm() { const { handleSubmit, reset, setValue, control } = useForm({ defaultValues: { color: "blue", }, }); const { field } = useController({ name: "color", control }); const onValid = useCallback((data: FormValues) => { window.alert(JSON.stringify(data, null, 2)); }, []); const onReset = useCallback( (event: FormEvent) => { event.preventDefault(); reset(); }, [reset], ); return (
setValue("color", value as FormValues["color"])} aria-label="Color selection" > {POSSIBLE_COLORS.map((color) => ( ))} Submit Reset
); } ```
#### `RadioGroupItem`의 레이아웃 `RadioGroup`은 여러 옵션 중 하나만 선택할 수 있는 컴포넌트입니다. 각 옵션은 `RadioGroupItem`으로 구성됩니다. `RadioGroup`은 기본적으로 레이아웃을 제공하지 않습니다. `HStack` 또는 `VStack`과 같은 레이아웃 컴포넌트와 함께 사용해야 합니다. ```tsx import { RadioGroup, RadioGroupItem } from "seed-design/ui/radio-group"; function HorizontalRadioGroup() { const [value, setValue] = useState("option1"); return ( ); } function VerticalRadioGroup() { const [value, setValue] = useState("option1"); return ( ); } ``` #### `RadioMark` 활용하기 `RadioMark`는 독립적인 라디오 마크 컴포넌트로, 커스텀 레이아웃을 위해 사용할 수 있습니다. ```tsx import { HStack, Text, VStack } from "@seed-design/react"; import { RadioMark } from "seed-design/ui/radio-group"; import { RadioGroup } from "@seed-design/react"; function CustomRadioGroupItem({ children, ...props }: RadioGroup.ItemProps) { return ( {children} ); } export default function RadioGroupRadioMark() { return ( regular medium bold ); } ``` file: components/reaction-button.mdx # Reaction Button 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Reaction Button description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { IconFaceSmileCircleFill } from "@karrotmarket/react-monochrome-icon"; import { Count, PrefixIcon } from "@seed-design/react"; import { ReactionButton } from "seed-design/ui/reaction-button"; export default function ReactionButtonPreview() { return ( } /> 도움돼요 1 ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add reaction-button ``` ```bash pnpm dlx @seed-design/cli@latest add reaction-button ``` ```bash yarn dlx @seed-design/cli@latest add reaction-button ``` ```bash bun x @seed-design/cli@latest add reaction-button ``` ## Props

{"버튼에 등록된 비동기 작업이 진행 중임을 사용자에게 알립니다."}

}, disabled: { "type": "boolean", "default": "false", description: <>

{"버튼의 비활성화 여부를 나타냅니다."}

}, pressed: { "type": "boolean", "default": undefined }, defaultPressed: { "type": "boolean", "default": undefined }, onPressedChange: { "type": "((pressed: boolean) => void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Small ```tsx import { IconFaceSmileCircleFill } from "@karrotmarket/react-monochrome-icon"; import { Count, PrefixIcon } from "@seed-design/react"; import { ReactionButton } from "seed-design/ui/reaction-button"; export default function ReactionButtonSmall() { return ( } /> 도움돼요 1 ); } ``` ### Xsmall ```tsx import { IconFaceSmileCircleFill } from "@karrotmarket/react-monochrome-icon"; import { Count, PrefixIcon } from "@seed-design/react"; import { ReactionButton } from "seed-design/ui/reaction-button"; export default function ReactionButtonXsmall() { return ( } /> 도움돼요 1 ); } ``` ### Disabled ```tsx import { IconFaceSmileCircleFill } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { ReactionButton } from "seed-design/ui/reaction-button"; export default function ReactionButtonDisabled() { return ( } /> 비활성 ); } ``` ### Loading ```tsx import { IconFaceSmileCircleFill } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { useState } from "react"; import { ReactionButton } from "seed-design/ui/reaction-button"; export default function ReactionButtonLoading() { const [pressed, setPressed] = useState(false); const [loading, setLoading] = useState(false); function handleToggle() { setLoading(true); setTimeout(() => { setLoading(false); setPressed((prev) => !prev); }, 2000); } // 이벤트 핸들링이 필요할 수 있으므로 loading은 disabled를 포함하지 않습니다. 이벤트 발생을 원하지 않는 경우, disabled 속성을 추가해주세요. return ( } /> 시간이 걸리는 토글 ); } ``` file: components/segmented-control.mdx # Segmented Control 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Segmented Control description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control"; export default function SegmentedControlPreview() { return ( Hot New ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add segmented-control ``` ```bash pnpm dlx @seed-design/cli@latest add segmented-control ``` ```bash yarn dlx @seed-design/cli@latest add segmented-control ``` ```bash bun x @seed-design/cli@latest add segmented-control ``` ## Props ### `SegmentedControl` `value`와 `defaultValue` 중 적어도 하나를 제공해야 합니다. void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `SegmentedControlItem` ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, notification: { "type": "boolean", "default": undefined }, value: { "type": "string", "default": undefined }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Disabled ```tsx import { VStack } from "@seed-design/react"; import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control"; export default function SegmentedControlPreview() { return ( Hot New Marinara Alfredo Pesto Carbonara Bolognese ); } ``` ### Notification ```tsx "use client"; import { ActionButton, VStack } from "@seed-design/react"; import { useState } from "react"; import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control"; export default function SegmentedControlNotification() { const [sortBy, setSortBy] = useState("monthly"); const [hasSeenAnnual, setHasSeenAnnual] = useState(false); return ( { setSortBy(value); if (value === "annual") setHasSeenAnnual(true); }} > Monthly Annual Enterprise Custom setHasSeenAnnual(false)}> Reset Notification ); } ``` ### Long Label ```tsx import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control"; export default function SegmentedControlLongLabel() { return ( 가격 높은 순 할인율 높은 순 인기 많은 순 ); } ``` ### Fixed Width `SegmentedControl`의 `style` prop에 `width`를 제공해서 직접 너비를 설정할 수 있습니다. ```tsx import { VStack } from "@seed-design/react"; import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control"; export default function SegmentedControlFixedWidth() { return ( New Hot One Way Trip Round Trip Multi-City Journey ); } ``` file: components/skeleton.mdx # Skeleton 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Skeleton description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { Skeleton, VStack } from "@seed-design/react"; export default function SkeletonPreview() { return ( ); } ``` ## Usage ```tsx import { Skeleton } from "@seed-design/react"; ``` ```tsx ``` ## Props

{"Whether the element should be rendered as a child of a slot."}

}, height: { "type": "\"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined }, width: { "type": "\"full\" | Dimension | \"spacingX.betweenChips\" | \"spacingX.globalGutter\" | \"spacingY.componentDefault\" | \"spacingY.navToTitle\" | \"spacingY.screenBottom\" | \"spacingY.betweenText\" | (string & {})", "default": undefined } }} /> ## Examples ### Radius ```tsx import { Flex, Skeleton } from "@seed-design/react"; export default function SkeletonRadius() { return ( ); } ``` ### Tone ```tsx import { Box, Skeleton, VStack } from "@seed-design/react"; export default function SkeletonTone() { return ( ); } ``` file: components/snackbar.mdx # Snackbar Snackbar는 사용자 액션의 결과나 프로세스의 결과를 알려주는 일시적인 알림 요소입니다. 화면 하단에 표시되며 자동으로 사라집니다. *** title: Snackbar description: Snackbar는 사용자 액션의 결과나 프로세스의 결과를 알려주는 일시적인 알림 요소입니다. 화면 하단에 표시되며 자동으로 사라집니다. ---------------------------------------------------------------------------------------- ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { Snackbar, SnackbarProvider, useSnackbarAdapter } from "seed-design/ui/snackbar"; function Component() { const adapter = useSnackbarAdapter(); return ( adapter.create({ timeout: 5000, onClose: () => {}, render: () => {}} />, }) } > 실행 ); } export default function SnackbarPreview() { return ( ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add snackbar ``` ```bash pnpm dlx @seed-design/cli@latest add snackbar ``` ```bash yarn dlx @seed-design/cli@latest add snackbar ``` ```bash bun x @seed-design/cli@latest add snackbar ``` ## Props ### `Snackbar`

{"스낵바에 표시할 메시지"}

}, actionLabel: { "type": "string", "default": undefined, description: <>

{"스낵바에 표시할 액션 버튼의 라벨"}

}, onAction: { "type": "(() => void)", "default": undefined, description: <>

{"액션 버튼 클릭 시 호출되는 콜백"}

}, shouldCloseOnAction: { "type": "boolean", "default": "true", description: <>

{"액션 버튼 클릭 시 스낵바를 닫을지 여부"}

}, variant: { "type": "\"default\" | \"positive\" | \"critical\"", "default": "\"default\"" }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### `SnackbarAdapter.create` Parameters (`CreateSnackbarOptions`)

{"The duration the snackbar will be visible"}

}, removeDelay: { "type": "number", "default": "200", description: <>

{"The duration for the snackbar to kept alive before it is removed.\nUseful for exit transitions."}

}, onClose: { "type": "(() => void)", "default": undefined, description: <>

{"Function called when the snackbar has been closed and removed"}

}, render: { "type": "() => ReactNode", "default": undefined, description: <>

{"The content to render in the snackbar region"}

} }} /> ### `SnackbarProvider`

{"Whether to pause the toast when interacted with"}

} }} /> ## Examples ### Variants #### Positive ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { Snackbar, SnackbarProvider, useSnackbarAdapter } from "seed-design/ui/snackbar"; function Component() { const adapter = useSnackbarAdapter(); return ( adapter.create({ timeout: 5000, onClose: () => {}, render: () => ( {}} /> ), }) } > 실행 ); } export default function SnackbarPositive() { return ( ); } ``` #### Critical ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { Snackbar, SnackbarProvider, useSnackbarAdapter } from "seed-design/ui/snackbar"; function Component() { const adapter = useSnackbarAdapter(); return ( adapter.create({ timeout: 50000000, onClose: () => {}, render: () => ( {}} /> ), }) } > 실행 ); } export default function SnackbarNegative() { return ( ); } ``` ### Pause on Interaction 사용자가 Snackbar와 상호작용(hover 및 active) 하는 동안 Snackbar가 timeout으로 인해 dismiss되지 않도록 하려면 `SnackbarProvider`의 `pauseOnInteraction`을 `true`로 설정합니다. * `@seed-design/react@0.1.14`까지: `false`: 명시하지 않는 경우, 상호작용 여부와 관계없이 timeout이 지나면 dismiss됩니다. * 이후 버전: `true`: 명시하지 않는 경우, 사용자가 상호작용하는 동안 timeout이 멈춥니다. ```tsx import { VStack } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { Snackbar, SnackbarProvider, useSnackbarAdapter } from "seed-design/ui/snackbar"; import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control"; import { useState } from "react"; function Component() { const adapter = useSnackbarAdapter(); return ( adapter.create({ timeout: 5000, onClose: () => {}, render: () => {}} />, }) } > 실행 ); } export default function SnackbarPauseOnInteraction() { const [pauseOnInteraction, setPauseOnInteraction] = useState(true); return ( setPauseOnInteraction(value === "true")} > false true ); } ``` ### Avoid Overlap `` 컴포넌트를 사용하여 스낵바가 겹치지 않아야 하는 영역을 지정할 수 있습니다. ``의 자식 컴포넌트는 forwardRef(\~React 18) 혹은 ref prop(React 19\~)으로 ref를 전달받아야 합니다. offset은 다음 상황에서 갱신됩니다. * SnackbarAvoidOverlap의 자식 컴포넌트가 mount될 때 * SnackbarAvoidOverlap의 자식 컴포넌트가 unmount될 때 * SnackbarAvoidOverlap의 자식 컴포넌트의 높이가 변경될 때 * SnackbarRegion의 높이가 변경될 때 ```tsx import { Flex, VStack } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { Snackbar, SnackbarAvoidOverlap, SnackbarProvider, useSnackbarAdapter, } from "seed-design/ui/snackbar"; function Component() { const adapter = useSnackbarAdapter(); return ( adapter.create({ timeout: 5000, onClose: () => {}, render: () => {}} />, }) } > 실행 Snackbar가 이 영역과 겹치지 않게 조정됩니다. 스크롤은 무시합니다. ); } export default function SnackbarPreview() { return ( ); } ``` file: components/stackflow/app-screen.mdx # App Screen 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: App Screen description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add app-screen ``` ```bash pnpm dlx @seed-design/cli@latest add app-screen ``` ```bash yarn dlx @seed-design/cli@latest add app-screen ``` ```bash bun x @seed-design/cli@latest add app-screen ``` ## Props ### App Screen #### `AppScreen`

{"Whether the element should be rendered as a child of a slot."}

}, swipeBackDisplacementRatioThreshold: { "type": "number", "default": "0.4", description: <>

{"The threshold to determine whether the swipe back is intentional."}

}, swipeBackVelocityThreshold: { "type": "number", "default": "1", description: <>

{"The threshold to determine whether the swipe back is intentional."}

}, onSwipeBackStart: { "type": "(() => void)", "default": undefined }, onSwipeBackMove: { "type": "((props: { displacement: number; displacementRatio: number; }) => void)", "default": undefined }, onSwipeBackEnd: { "type": "((props: { swiped: boolean; }) => void)", "default": undefined } }} /> #### `AppScreenContent` void)", "default": undefined }, onPtrRefresh: { "type": "(() => Promise)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ### App Bar #### `AppBar`

{"Whether the element should be rendered as a child of a slot."}

} }} /> #### `AppBarLeft`

{"Whether the element should be rendered as a child of a slot."}

} }} /> #### `AppBarMain`

{"The title of the app bar.\nIf children is provided as ReactElement, this prop will be ignored."}

}, subtitle: { "type": "string", "default": undefined, description: <>

{"The subtitle of the app bar.\nIf children is provided as ReactElement, this prop will be ignored."}

}, layout: { "type": "\"titleOnly\" | \"withSubtitle\"", "default": "\"titleOnly\"" }, theme: { "type": "\"cupertino\" | \"android\"", "default": "\"cupertino\"" }, transitionStyle: { "type": "\"slideFromRightIOS\" | \"fadeFromBottomAndroid\"", "default": "\"slideFromRightIOS\"" }, tone: { "type": "\"layer\" | \"transparent\"", "default": "\"layer\"" } }} /> #### `AppBarRight`

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Transparent App Bar file: components/switch.mdx # Switch 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Switch description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { Switch } from "seed-design/ui/switch"; export default function SwitchPreview() { return ; } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add switch ``` ```bash pnpm dlx @seed-design/cli@latest add switch ``` ```bash yarn dlx @seed-design/cli@latest add switch ``` ```bash bun x @seed-design/cli@latest add switch ``` ## Props ", "default": undefined }, rootRef: { "type": "Ref", "default": undefined }, label: { "type": "ReactNode", "default": undefined }, size: { "type": "\"16\" | \"24\" | \"32\" | SwitchVariantDeprecatedSizeProps", "default": undefined }, tone: { "type": "\"neutral\" | \"brand\"", "default": "\"brand\"" }, disabled: { "type": "boolean", "default": undefined }, invalid: { "type": "boolean", "default": undefined }, required: { "type": "boolean", "default": undefined }, checked: { "type": "boolean", "default": undefined }, defaultChecked: { "type": "boolean", "default": undefined }, onCheckedChange: { "type": "((checked: boolean) => void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Sizes `size="medium"`과 `size="small"`은 더 이상 사용되지 않습니다. 대신 `size="32"`와 `size="16"`을 사용하세요. ```tsx import { VStack } from "@seed-design/react"; import { Switch } from "seed-design/ui/switch"; export default function SwitchSizes() { return ( ); } ``` ### Tones #### Brand ```tsx import { Switch } from "seed-design/ui/switch"; export default function SwitchBrand() { return ; } ``` #### Neutral ```tsx import { Switch } from "seed-design/ui/switch"; export default function SwitchNeutral() { return ; } ``` ### Long Label ```tsx import { VStack } from "@seed-design/react"; import { Switch } from "seed-design/ui/switch"; export default function SwitchLongLabel() { return ( ); } ``` ### Disabled ```tsx import { VStack } from "@seed-design/react"; import { Switch } from "seed-design/ui/switch"; export default function SwitchDisabled() { return ( ); } ``` file: components/toggle-button.mdx # Toggle Button 이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요. *** title: Toggle Button description: "이 문서는 정리 중이에요. 문의 내용은 #\_design\_core 채널을 찾아주세요." --------------------------------------------------------------- ```tsx import { useState } from "react"; import { ToggleButton } from "seed-design/ui/toggle-button"; export default function ToggleButtonPreview() { const [pressed, setPressed] = useState(false); return ( {pressed ? "선택됨" : "미선택"} ); } ``` ## Installation npm pnpm yarn bun ```bash npx @seed-design/cli@latest add toggle-button ``` ```bash pnpm dlx @seed-design/cli@latest add toggle-button ``` ```bash yarn dlx @seed-design/cli@latest add toggle-button ``` ```bash bun x @seed-design/cli@latest add toggle-button ``` ## Props

{"버튼에 등록된 비동기 작업이 진행 중임을 사용자에게 알립니다."}

}, disabled: { "type": "boolean", "default": "false", description: <>

{"버튼의 비활성화 여부를 나타냅니다."}

}, pressed: { "type": "boolean", "default": undefined }, defaultPressed: { "type": "boolean", "default": undefined }, onPressedChange: { "type": "((pressed: boolean) => void)", "default": undefined }, asChild: { "type": "boolean", "default": "false", description: <>

{"Whether the element should be rendered as a child of a slot."}

} }} /> ## Examples ### Brand Solid ```tsx import { useState } from "react"; import { ToggleButton } from "seed-design/ui/toggle-button"; export default function ToggleButtonBrandSolid() { const [pressed, setPressed] = useState(false); return ( {pressed ? "선택됨" : "미선택"} ); } ``` ### Neutral Weak ```tsx import { useState } from "react"; import { ToggleButton } from "seed-design/ui/toggle-button"; export default function ToggleButtonBrandSolid() { const [pressed, setPressed] = useState(false); return ( {pressed ? "선택됨" : "미선택"} ); } ``` ### Small ```tsx import { useState } from "react"; import { ToggleButton } from "seed-design/ui/toggle-button"; export default function ToggleButtonSmall() { const [pressed, setPressed] = useState(false); return ( {pressed ? "선택됨" : "미선택"} ); } ``` ### Xsmall ```tsx import { useState } from "react"; import { ToggleButton } from "seed-design/ui/toggle-button"; export default function ToggleButtonXsmall() { const [pressed, setPressed] = useState(false); return ( {pressed ? "선택됨" : "미선택"} ); } ``` ### Prefix Icon ```tsx import { IconCheckmarkLine, IconPlusLine } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon } from "@seed-design/react"; import { useState } from "react"; import { ToggleButton } from "seed-design/ui/toggle-button"; export default function ToggleButtonPrefixIcon() { const [pressed, setPressed] = useState(false); return ( : } /> {pressed ? "선택됨" : "미선택"} ); } ``` ### Disabled ```tsx import { ToggleButton } from "seed-design/ui/toggle-button"; export default function ToggleButtonDisabled() { return 비활성; } ``` ### Loading ```tsx import { useState } from "react"; import { ToggleButton } from "seed-design/ui/toggle-button"; export default function ToggleButtonLoading() { const [pressed, setPressed] = useState(false); const [loading, setLoading] = useState(false); function handleToggle() { setLoading(true); setTimeout(() => { setLoading(false); setPressed((prev) => !prev); }, 2000); } // 이벤트 핸들링이 필요할 수 있으므로 loading은 disabled를 포함하지 않습니다. 이벤트 발생을 원하지 않는 경우, disabled 속성을 추가해주세요. return ( 시간이 걸리는 토글 ); } ``` file: developer-tools/codemods/available-transforms.mdx # Available Transforms codemod를 통해 실행 가능한 변환 목록입니다. *** title: Available Transforms description: codemod를 통해 실행 가능한 변환 목록입니다. ----------------------------------------- {/* Auto-generated from `scripts/generate-codemod-docs.ts` */} ## replace-custom-seed-design-typography npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-custom-seed-design-typography ``` ```bash pnpm dlx @seed-design/codemod@latest replace-custom-seed-design-typography ``` ```bash yarn dlx @seed-design/codemod@latest replace-custom-seed-design-typography ``` ```bash bun x @seed-design/codemod@latest replace-custom-seed-design-typography ``` ```ts title="basic.input.ts" // @ts-nocheck import { style } from "@vanilla-extract/css"; import { vars } from "@seed-design/css"; import { f, reset } from "@/shared/styles"; import { typography, text } from '@/src/styles/tokens'; export const title = style([ typography.h4, { textAlign: "center", color: vars.$scale.color.gray900, margin: 0, }, ]); export const subtitle = style([ f.typography.title2Bold, { marginBottom: "0.375rem", color: vars.$scale.color.gray900, }, ]); export const smallText = style([ typo.caption2Regular, { color: vars.$scale.color.gray700, }, ]); export const largeTitle = style([ typo.bodyL1Regular, { color: vars.$scale.color.gray900, }, ]); export const button = style([ typography['$semantic.label2Regular'], { width: '100%', paddingTop: rem(14), paddingRight: rem(16), paddingBottom: rem(14), paddingLeft: rem(16), }, ]); export const day = style([ { display: 'flex', flex: 1, alignItems: 'center', justifyContent: 'center', height: rem(30), }, typography['$semantic.caption1Regular'], ]); // Additional test cases for various mappings export const titleBold = style([ typography.title3Bold, { fontWeight: 'bold', }, ]); export const subtitleRegular = style([ f.typography.subtitle2Regular, { color: vars.$scale.color.gray800, }, ]); export const bodyText = style([ typo.bodyM1Regular, { lineHeight: 1.5, }, ]); export const labelText = style([ typography['$semantic.label1Bold'], { textTransform: 'uppercase', }, ]); export const captionBold = style([ typography['$semantic.caption2Bold'], { fontSize: '12px', }, ]); // Test deprecated tokens with alternative export const deprecatedBody = style([ typo.bodyL2Regular, { margin: '8px 0', }, ]); export const deprecatedLabel = style([ typography['$semantic.label6Regular'], { opacity: 0.8, }, ]); // Test multiple token choices (should use first one) export const headerText = style([ typography.h4, { textAlign: 'center', }, ]); export const text = style([ text['$semantic.bodyL2Bold'], ]); ``` ```ts title="basic.output.ts" // @ts-nocheck import { style } from "@vanilla-extract/css"; import { vars } from "@seed-design/css"; import { f, reset } from "@/shared/styles"; import { typography, text } from '@/src/styles/tokens'; export const title = style([ typography.t10Bold, { textAlign: "center", color: vars.$scale.color.gray900, margin: 0, }, ]); export const subtitle = style([ f.typography.t7Bold, { marginBottom: "0.375rem", color: vars.$scale.color.gray900, }, ]); export const smallText = style([ typo.t2Regular, { color: vars.$scale.color.gray700, }, ]); export const largeTitle = style([ typo.articleBody, { color: vars.$scale.color.gray900, }, ]); export const button = style([ typography.t5Regular, { width: '100%', paddingTop: rem(14), paddingRight: rem(16), paddingBottom: rem(14), paddingLeft: rem(16), }, ]); export const day = style([ { display: 'flex', flex: 1, alignItems: 'center', justifyContent: 'center', height: rem(30), }, typography.t3Regular, ]); // Additional test cases for various mappings export const titleBold = style([ typography.t6Bold, { fontWeight: 'bold', }, ]); export const subtitleRegular = style([ f.typography.t4Regular, { color: vars.$scale.color.gray800, }, ]); export const bodyText = style([ typo.t5Regular, { lineHeight: 1.5, }, ]); export const labelText = style([ typography.t6Bold, { textTransform: 'uppercase', }, ]); export const captionBold = style([ typography.t2Bold, { fontSize: '12px', }, ]); // Test deprecated tokens with alternative export const deprecatedBody = style([ typo.t4Regular, { margin: '8px 0', }, ]); export const deprecatedLabel = style([ typography.t1Regular, { opacity: 0.8, }, ]); // Test multiple token choices (should use first one) export const headerText = style([ typography.t10Bold, { textAlign: 'center', }, ]); export const text = style([ text.t4Bold, ]); ``` ## replace-tailwind-typography npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-tailwind-typography ``` ```bash pnpm dlx @seed-design/codemod@latest replace-tailwind-typography ``` ```bash yarn dlx @seed-design/codemod@latest replace-tailwind-typography ``` ```bash bun x @seed-design/codemod@latest replace-tailwind-typography ``` ```tsx title="basic.input.tsx" // @ts-nocheck export function BasicExample() { return (
Primary Background

{formState.content}

Hover Primary Low Background
Focus Primary Low Background
Focus Primary Low Background

{description}

Text with prefix
Another text with prefix

Title with prefix

); } ``` ```tsx title="basic.output.tsx" // @ts-nocheck export function BasicExample() { return (
Primary Background

{formState.content}

Hover Primary Low Background
Focus Primary Low Background
Focus Primary Low Background

{description}

Text with prefix
Another text with prefix

Title with prefix

); } ```
## replace-custom-imported-typography-variable Seed Design V2에서 V3로 마이그레이션 시 import된 타이포그래피 변수를 변환합니다. ### 기능 * 타이포그래피 관련 import 문을 찾아 변수명을 변환합니다. * 변수가 사용된 모든 위치(템플릿 리터럴, 객체 속성 등)를 찾아 업데이트합니다. * typography.mjs의 매핑 정보에 따라 V2 타이포그래피 변수를 V3로 변환합니다. * 같은 V3 토큰으로 변환되는 중복 import를 제거합니다 (예: subtitle1Regular, bodyM1Regular가 모두 t5Regular로 변환되면 t5Regular는 한 번만 import). * 별칭(alias)으로 import된 변수명은 유지합니다 (예: `bodyM1Regular as customTypo`에서 `t5Regular as customTypo`로 변환). npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-custom-imported-typography-variable ``` ```bash pnpm dlx @seed-design/codemod@latest replace-custom-imported-typography-variable ``` ```bash yarn dlx @seed-design/codemod@latest replace-custom-imported-typography-variable ``` ```bash bun x @seed-design/codemod@latest replace-custom-imported-typography-variable ``` ```ts title="basic.input.ts" // @ts-nocheck import { subtitle1Regular, subtitle2Regular, h4, title1Bold, title2Bold, bodyL1Regular, bodyL2Regular, caption1Regular, caption2Regular, label5Regular, } from '@src/constants/typography' import { bodyM1Regular as customTypo } from '@karrot/typography' const S_StoreRequestTitle = styled.h1` ${subtitle1Regular}; margin: 0 0 0.25rem; color: ${vars.$scale.color.gray900}; text-align: center; ` const S_StoreRequestText = styled.p` ${subtitle2Regular}; margin: 0; color: ${vars.$scale.color.gray600}; text-align: center; ` // 추가 테스트 케이스 // screenTitle 매핑 테스트 const S_ScreenHeader = styled.h1` ${h4}; margin-bottom: 1rem; ` // 일반 매핑 테스트 const S_Title = styled.h2` ${title1Bold}; color: ${vars.$scale.color.gray900}; ` // 여러 테스트 케이스를 담은 컴포넌트 const Card = styled.div` // title2Bold 매핑 테스트 h3 { ${title2Bold}; margin-bottom: 8px; } // bodyL1Regular 매핑 테스트 p.description { ${bodyL1Regular}; color: ${vars.$scale.color.gray800}; } // 대체 토큰으로 매핑되는 케이스 p.content { ${bodyL2Regular}; margin: 0; } // 캡션 스타일 p.caption { ${caption1Regular}; color: ${vars.$scale.color.gray600}; } // 작은 텍스트 small { ${caption2Regular}; color: ${vars.$scale.color.gray500}; } // 라벨 스타일 label { ${label5Regular}; margin-right: 4px; } ` // 다른 모듈에서 가져온 타이포그래피 처리 (별칭 유지해야 함) const S_CustomContent = styled.div` ${customTypo}; color: ${vars.$scale.color.gray700}; ` // 변수로 사용하는 경우 const titleStyle = title1Bold; const textStyle = subtitle1Regular; ``` ```ts title="basic.output.ts" // @ts-nocheck import { t5Regular, t4Regular, t10Bold, t9Bold, t7Bold, articleBody, t3Regular, t2Regular, t1Regular, } from '@src/constants/typography'; import { t5Regular as customTypo } from '@karrot/typography' const S_StoreRequestTitle = styled.h1` ${t5Regular}; margin: 0 0 0.25rem; color: ${vars.$scale.color.gray900}; text-align: center; ` const S_StoreRequestText = styled.p` ${t4Regular}; margin: 0; color: ${vars.$scale.color.gray600}; text-align: center; ` // 추가 테스트 케이스 // screenTitle 매핑 테스트 const S_ScreenHeader = styled.h1` ${t10Bold}; margin-bottom: 1rem; ` // 일반 매핑 테스트 const S_Title = styled.h2` ${t9Bold}; color: ${vars.$scale.color.gray900}; ` // 여러 테스트 케이스를 담은 컴포넌트 const Card = styled.div` // title2Bold 매핑 테스트 h3 { ${t7Bold}; margin-bottom: 8px; } // bodyL1Regular 매핑 테스트 p.description { ${articleBody}; color: ${vars.$scale.color.gray800}; } // 대체 토큰으로 매핑되는 케이스 p.content { ${t4Regular}; margin: 0; } // 캡션 스타일 p.caption { ${t3Regular}; color: ${vars.$scale.color.gray600}; } // 작은 텍스트 small { ${t2Regular}; color: ${vars.$scale.color.gray500}; } // 라벨 스타일 label { ${t1Regular}; margin-right: 4px; } ` // 다른 모듈에서 가져온 타이포그래피 처리 (별칭 유지해야 함) const S_CustomContent = styled.div` ${customTypo}; color: ${vars.$scale.color.gray700}; ` // 변수로 사용하는 경우 const titleStyle = t9Bold; const textStyle = t5Regular; ``` ## replace-custom-seed-design-vars npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-custom-seed-design-vars ``` ```bash pnpm dlx @seed-design/codemod@latest replace-custom-seed-design-vars ``` ```bash yarn dlx @seed-design/codemod@latest replace-custom-seed-design-vars ``` ```bash bun x @seed-design/codemod@latest replace-custom-seed-design-vars ``` ```ts title="basic.input.ts" // @ts-nocheck import { vars } from '@/shared/style/vars'; export const date = style({ ...vars.typography.caption1Regular, color: vars.color.gray600, }); export const color1 = style({ color: vars.color.yellow500, }); export const color2 = style({ color: vars.color.blue500, }); export const color3 = style({ color: vars.color.red500, }); export const title = style({ ...vars.typography.bodyM1Bold, color: vars.color.primary, }); export const subtitle = style({ ...vars.typography.bodyM2Regular, color: vars.color.secondary, }); // 배경색 케이스 export const cardBackground = style({ backgroundColor: vars.color.paperSheet, padding: '16px', }); // 테두리 케이스 export const divider = style({ borderTop: `1px solid ${vars.color.divider1}`, marginTop: '8px', marginBottom: '8px', }); // 상태 색상 케이스 export const successMessage = style({ ...vars.typography.bodyM1Bold, color: vars.color.success, backgroundColor: vars.color.successLow, padding: '12px', borderRadius: '4px', }); export const warningMessage = style({ ...vars.typography.bodyM1Bold, color: vars.color.warning, backgroundColor: vars.color.warningLow, padding: '12px', borderRadius: '4px', }); export const errorMessage = style({ ...vars.typography.bodyM1Bold, color: vars.color.danger, backgroundColor: vars.color.dangerLow, padding: '12px', borderRadius: '4px', }); // 다양한 타이포그래피 케이스 export const heading = style({ ...vars.typography.h4, color: vars.color.inkText, }); export const body = style({ ...vars.typography.bodyL1Regular, color: vars.color.inkTextLow, }); export const label = style({ ...vars.typography.label3Bold, color: vars.color.grayActive, }); // 알파 색상 케이스 export const overlay = style({ backgroundColor: vars.color.overlayDim, position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, }); // 복합 케이스와 상호작용 상태 export const button = style({ ...vars.typography.label2Bold, backgroundColor: vars.color.primary, color: vars.color.onPrimary, borderRadius: '4px', padding: '8px 16px', border: 'none', cursor: 'pointer', ':hover': { backgroundColor: vars.color.primaryHover, }, ':active': { backgroundColor: vars.color.primaryPressed, }, }); export const secondaryButton = style({ ...vars.typography.label2Bold, backgroundColor: vars.color.secondaryLow, color: vars.color.secondary, borderRadius: '4px', padding: '8px 16px', border: 'none', cursor: 'pointer', ':hover': { backgroundColor: vars.color.grayHover, }, ':active': { backgroundColor: vars.color.grayPressed, }, }); // 중첩 경로 케이스 export const floatingPanel = style({ backgroundColor: vars.color.paperFloating, boxShadow: `0 2px 8px ${vars.color.overlayLow}`, padding: '20px', borderRadius: '8px', }); export const dialogPanel = style({ backgroundColor: vars.color.paperDialog, padding: '24px', boxShadow: `0 4px 16px ${vars.color.overlayDim}`, borderRadius: '12px', }); // 정적 색상 케이스 export const staticColors = style({ color: vars.color.staticBlack, backgroundColor: vars.color.staticWhite, border: `1px solid ${vars.color.staticBlackAlpha200}`, }); // 정적 색상 케이스 (명시적으로 static 프리픽스 테스트) export const staticExplicitColors = style({ color: vars.color.staticBlack, backgroundColor: vars.color.staticWhite, boxShadow: `0 2px 4px ${vars.color.staticBlackAlpha500}`, outline: `1px solid ${vars.color.staticBlackAlpha200}`, }); export const specialBackground = style({ background: `linear-gradient(to bottom, ${vars.color.staticWhiteAlpha50}, ${vars.color.staticWhiteAlpha200})`, backdropFilter: 'blur(8px)', }); // 복합 스타일 및 다중 속성 케이스 export const multiProperty = style({ ...vars.typography.title2Bold, color: vars.color.accent, borderLeft: `4px solid ${vars.color.accent}`, borderRight: `4px solid ${vars.color.accent}`, boxShadow: `inset 0 0 0 1px ${vars.color.divider2}, 0 2px 4px ${vars.color.overlayLow}`, padding: '16px', backgroundColor: vars.color.paperDefault, }); // 믹스인 스타일 케이스 export const mixinStyle = { primary: { background: vars.color.primary, color: vars.color.onPrimary, }, secondary: { background: vars.color.secondary, }, accent: { background: vars.color.accent, color: vars.color.onGrayOverlay50, }, }; // 특수 속성 및 스케일 색상 케이스 export const scaleColors = style({ fill: vars.color.carrot500, stroke: vars.color.gray400, stopColor: vars.color.blue400, floodColor: vars.color.red400, lightingColor: vars.color.green400, }); // 특수 타이포그래피 케이스 export const specialTypographies = { title: vars.typography.title1Bold, subtitle: vars.typography.subtitle1Regular, label: vars.typography.label5Regular, caption: vars.typography.caption2Bold, }; // 다양한 경로를 가진 컬러 토큰 export const colorContexts = style({ // 일반 색상 color: vars.color.primaryLow, // 배경 색상 backgroundColor: vars.color.paperBackground, // 테두리 색상 borderColor: vars.color.divider3, // 호버 색상 ':hover': { backgroundColor: vars.color.primaryLowHover, borderColor: vars.color.primaryLowActive, }, }); // 복잡한 다중 경로와 중첩된 객체 export const nestedStyleObject = { button: { default: { backgroundColor: vars.color.paperAccent, color: vars.color.inkText, border: `1px solid ${vars.color.carrot300}`, }, hover: { backgroundColor: vars.color.carrot100, borderColor: vars.color.carrot400, }, active: { backgroundColor: vars.color.carrot200, color: vars.color.inkTextLow, }, }, panel: { header: { ...vars.typography.subtitle2Bold, color: vars.color.blue600, borderBottom: `1px solid ${vars.color.blue200}`, }, body: { ...vars.typography.bodyM2Regular, color: vars.color.inkTextLow, backgroundColor: vars.color.blue50, }, footer: { backgroundColor: vars.color.blue100, borderTop: `1px solid ${vars.color.blue200}`, }, }, }; // 테두리 속성 매핑 테스트 export const borderMapping = style({ // stroke 토큰으로 매핑될 속성 borderColor: vars.color.divider2, // stroke 토큰이 없어서 fg 토큰으로 대체되는 케이스 borderTopColor: vars.color.primary, borderBottomColor: vars.color.accent, // stroke 또는 fg 토큰으로 대체 boxShadow: `0 0 0 1px ${vars.color.primary}, 0 2px 4px ${vars.color.overlayLow}`, // 복합 속성 border: `1px solid ${vars.color.secondary}`, }); ``` ```ts title="basic.output.ts" // @ts-nocheck import { vars } from "@/shared/style/vars"; export const date = style({ ...vars.typography.t3Regular, color: vars.color.palette.gray700, }); export const color1 = style({ color: vars.color.palette.yellow700, }); export const color2 = style({ color: vars.color.palette.blue600, }); export const color3 = style({ color: vars.color.palette.red700, }); export const title = style({ ...vars.typography.t5Bold, color: vars.color.fg.brand, }); export const subtitle = style({ ...vars.typography.t4Regular, color: vars.color.palette.gray900, }); // 배경색 케이스 export const cardBackground = style({ backgroundColor: vars.color.bg.layerFloating, padding: "16px", }); // 테두리 케이스 export const divider = style({ borderTop: `1px solid ${vars.color.stroke.neutralSubtle}`, marginTop: "8px", marginBottom: "8px", }); // 상태 색상 케이스 export const successMessage = style({ ...vars.typography.t5Bold, color: vars.color.fg.positive, backgroundColor: vars.color.bg.positiveWeak, padding: "12px", borderRadius: "4px", }); export const warningMessage = style({ ...vars.typography.t5Bold, color: vars.color.bg.warningSolid, backgroundColor: vars.color.bg.warningWeak, padding: "12px", borderRadius: "4px", }); export const errorMessage = style({ ...vars.typography.t5Bold, color: vars.color.fg.critical, backgroundColor: vars.color.bg.criticalWeak, padding: "12px", borderRadius: "4px", }); // 다양한 타이포그래피 케이스 export const heading = style({ ...vars.typography.t10Bold, color: vars.color.fg.neutral, }); export const body = style({ ...vars.typography.articleBody, color: vars.color.fg.neutralSubtle, }); export const label = style({ ...vars.typography.t4Bold, color: vars.color.fg.neutralMuted, }); // 알파 색상 케이스 export const overlay = style({ backgroundColor: vars.color.bg.overlay, position: "absolute", top: 0, left: 0, right: 0, bottom: 0, }); // 복합 케이스와 상호작용 상태 export const button = style({ ...vars.typography.t5Bold, backgroundColor: vars.color.bg.brandSolid, color: vars.color.palette.staticWhite, borderRadius: "4px", padding: "8px 16px", border: "none", cursor: "pointer", ":hover": { backgroundColor: vars.color.bg.brandSolidPressed, }, ":active": { backgroundColor: vars.color.bg.brandSolidPressed, }, }); export const secondaryButton = style({ ...vars.typography.t5Bold, backgroundColor: vars.color.bg.neutralWeak, color: vars.color.palette.gray900, borderRadius: "4px", padding: "8px 16px", border: "none", cursor: "pointer", ":hover": { backgroundColor: vars.color.bg.neutralWeakPressed, }, ":active": { backgroundColor: vars.color.bg.neutralWeakPressed, }, }); // 중첩 경로 케이스 export const floatingPanel = style({ backgroundColor: vars.color.bg.layerFloating, boxShadow: `0 2px 8px ${vars.color.bg.overlayMuted}`, padding: "20px", borderRadius: "8px", }); export const dialogPanel = style({ backgroundColor: vars.color.bg.layerFloating, padding: "24px", boxShadow: `0 4px 16px ${vars.color.bg.overlay}`, borderRadius: "12px", }); // 정적 색상 케이스 export const staticColors = style({ color: vars.color.palette.staticBlack, backgroundColor: vars.color.palette.staticWhite, border: `1px solid ${vars.color.palette.staticBlackAlpha200}`, }); // 정적 색상 케이스 (명시적으로 static 프리픽스 테스트) export const staticExplicitColors = style({ color: vars.color.palette.staticBlack, backgroundColor: vars.color.palette.staticWhite, boxShadow: `0 2px 4px ${vars.color.palette.staticBlackAlpha500}`, outline: `1px solid ${vars.color.palette.staticBlackAlpha200}`, }); export const specialBackground = style({ background: `linear-gradient(to bottom, ${vars.color.palette.staticWhiteAlpha50}, ${vars.color.palette.staticWhiteAlpha200})`, backdropFilter: "blur(8px)", }); // 복합 스타일 및 다중 속성 케이스 export const multiProperty = style({ ...vars.typography.t7Bold, color: vars.color.fg.informative, borderLeft: `4px solid ${vars.color.fg.informative}`, borderRight: `4px solid ${vars.color.fg.informative}`, boxShadow: `inset 0 0 0 1px ${vars.color.stroke.neutral}, 0 2px 4px ${vars.color.bg.overlayMuted}`, padding: "16px", backgroundColor: vars.color.bg.layerDefault, }); // 믹스인 스타일 케이스 export const mixinStyle = { primary: { background: vars.color.bg.brandSolid, color: vars.color.palette.staticWhite, }, secondary: { background: vars.color.palette.gray900, }, accent: { background: vars.color.bg.informativeSolid, color: vars.color.stroke.onImage, }, }; // 특수 속성 및 스케일 색상 케이스 export const scaleColors = style({ fill: vars.color.palette.carrot600, stroke: vars.color.palette.gray500, stopColor: vars.color.palette.blue400, floodColor: vars.color.palette.red600, lightingColor: vars.color.palette.green500, }); // 특수 타이포그래피 케이스 export const specialTypographies = { title: vars.typography.t9Bold, subtitle: vars.typography.t5Regular, label: vars.typography.t1Regular, caption: vars.typography.t2Bold, }; // 다양한 경로를 가진 컬러 토큰 export const colorContexts = style({ // 일반 색상 color: vars.color.palette.carrot100, // 배경 색상 backgroundColor: vars.color.bg.layerBasement, // 테두리 색상 borderColor: vars.color.palette.gray400, // 호버 색상 ":hover": { backgroundColor: vars.color.palette.carrot200, borderColor: vars.color.palette.carrot100, }, }); // 복잡한 다중 경로와 중첩된 객체 export const nestedStyleObject = { button: { default: { backgroundColor: vars.color.palette.carrot100, color: vars.color.fg.neutral, border: `1px solid ${vars.color.palette.carrot400}`, }, hover: { backgroundColor: vars.color.palette.carrot200, borderColor: vars.color.palette.carrot500, }, active: { backgroundColor: vars.color.palette.carrot300, color: vars.color.fg.neutralSubtle, }, }, panel: { header: { ...vars.typography.t4Bold, color: vars.color.palette.blue600, borderBottom: `1px solid ${vars.color.palette.blue300}`, }, body: { ...vars.typography.t4Regular, color: vars.color.fg.neutralSubtle, backgroundColor: vars.color.palette.blue100, }, footer: { backgroundColor: vars.color.palette.blue200, borderTop: `1px solid ${vars.color.palette.blue300}`, }, }, }; // 테두리 속성 매핑 테스트 export const borderMapping = style({ // stroke 토큰으로 매핑될 속성 borderColor: vars.color.stroke.neutral, // stroke 토큰이 없어서 fg 토큰으로 대체되는 케이스 borderTopColor: vars.color.fg.brand, borderBottomColor: vars.color.fg.informative, // stroke 또는 fg 토큰으로 대체 boxShadow: `0 0 0 1px ${vars.color.bg.brandSolid}, 0 2px 4px ${vars.color.bg.overlayMuted}`, // 복합 속성 border: `1px solid ${vars.color.palette.gray900}`, }); ``` ## replace-stitches-styled-typography npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-stitches-styled-typography ``` ```bash pnpm dlx @seed-design/codemod@latest replace-stitches-styled-typography ``` ```bash yarn dlx @seed-design/codemod@latest replace-stitches-styled-typography ``` ```bash bun x @seed-design/codemod@latest replace-stitches-styled-typography ``` ```tsx title="basic.input.tsx" // @ts-nocheck const ContentText = styled('p', { ...userSelectText, overflow: 'hidden', whiteSpace: 'pre-wrap', wordBreak: 'break-word', color: '$gray900', variants: { size: { medium: { $text: 'bodyM1Regular', }, large: { $text: 'bodyL1Regular', }, xlarge: { $text: "h4", }, }, }, }); const ContentText2 = styled('p', { ...userSelectText, overflow: 'hidden', whiteSpace: 'pre-wrap', wordBreak: 'break-word', color: '$gray900', variants: { size: { medium: { $typography: 'bodyM1Regular', }, large: { $typography: 'bodyL1Regular', }, xlarge: { $typography: "h4", }, }, }, }); ``` ```tsx title="basic.output.tsx" // @ts-nocheck const ContentText = styled('p', { ...userSelectText, overflow: 'hidden', whiteSpace: 'pre-wrap', wordBreak: 'break-word', color: '$gray900', variants: { size: { medium: { $text: "t5Regular", }, large: { $text: "articleBody", }, xlarge: { $text: "t10Bold", }, }, }, }); const ContentText2 = styled('p', { ...userSelectText, overflow: 'hidden', whiteSpace: 'pre-wrap', wordBreak: 'break-word', color: '$gray900', variants: { size: { medium: { $typography: "t5Regular", }, large: { $typography: "articleBody", }, xlarge: { $typography: "t10Bold", }, }, }, }); ``` ## replace-stitches-theme-color npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-stitches-theme-color ``` ```bash pnpm dlx @seed-design/codemod@latest replace-stitches-theme-color ``` ```bash yarn dlx @seed-design/codemod@latest replace-stitches-theme-color ``` ```bash bun x @seed-design/codemod@latest replace-stitches-theme-color ``` ```tsx title="basic.input.tsx" // @ts-nocheck import { theme } from "@src/stitches/stitches.config"; const semanticColors = { primary: theme.colors["primary-semantic"].computedValue, onPrimary: theme.colors["onPrimary-semantic"].computedValue, primaryLow: theme.colors["primaryLow-semantic"].computedValue, success: theme.colors["success-semantic"].computedValue, warning: theme.colors["warning-semantic"].computedValue, danger: theme.colors["danger-semantic"].computedValue, paperDefault: theme.colors["paperDefault-semantic"].computedValue, paperContents: theme.colors["paperContents-semantic"].computedValue, paperDialog: theme.colors["paperDialog-semantic"].computedValue, inkText: theme.colors["inkText-semantic"].computedValue, inkTextLow: theme.colors["inkTextLow-semantic"].computedValue, divider1: theme.colors["divider1-semantic"].computedValue, divider2: theme.colors["divider2-semantic"].computedValue, overlayDim: theme.colors["overlayDim-semantic"].computedValue, accent: theme.colors["accent-semantic"].computedValue, }; const scaleColors = { gray00: theme.colors.gray00.computedValue, gray100: theme.colors.gray100.computedValue, gray200: theme.colors.gray200.computedValue, gray300: theme.colors.gray300.computedValue, gray400: theme.colors.gray400.computedValue, gray500: theme.colors.gray500.computedValue, gray600: theme.colors.gray600.computedValue, gray700: theme.colors.gray700.computedValue, gray800: theme.colors.gray800.computedValue, gray900: theme.colors.gray900.computedValue, carrot100: theme.colors.carrot100.computedValue, carrot500: theme.colors.carrot500.computedValue, carrot900: theme.colors.carrot900.computedValue, carrotAlpha50: theme.colors.carrotAlpha50.computedValue, carrotAlpha100: theme.colors.carrotAlpha100.computedValue, carrotAlpha200: theme.colors.carrotAlpha200.computedValue, blue300: theme.colors.blue300.computedValue, blue600: theme.colors.blue600.computedValue, red500: theme.colors.red500.computedValue, }; const staticColors = { white: theme.colors["white-static"].computedValue, black: theme.colors["black-static"].computedValue, blackAlpha200: theme.colors["blackAlpha200-static"].computedValue, whiteAlpha200: theme.colors["whiteAlpha200-static"].computedValue, gray900: theme.colors["gray900-static"].computedValue, carrot50: theme.colors["carrot50-static"].computedValue, carrot800: theme.colors["carrot800-static"].computedValue, blue50: theme.colors["blue50-static"].computedValue, blue800: theme.colors["blue800-static"].computedValue, red50: theme.colors["red50-static"].computedValue, red800: theme.colors["red800-static"].computedValue, }; const Component = () => { return (
안내사항 중요
); }; const Dialog = ({ isOpen, onClose }) => { const styles = { overlay: { backgroundColor: theme.colors["overlayDim-semantic"].computedValue, }, container: { backgroundColor: theme.colors["paperDialog-semantic"].computedValue, borderColor: theme.colors.gray300.computedValue, }, header: { borderBottom: `1px solid ${theme.colors["divider1-semantic"].computedValue}`, }, title: { color: theme.colors.gray900.computedValue, }, content: { color: theme.colors.gray700.computedValue, backgroundColor: theme.colors["paperContents-semantic"].computedValue, }, footer: { borderTop: `1px solid ${theme.colors["divider2-semantic"].computedValue}`, }, closeButton: { color: theme.colors.gray500.computedValue, }, submitButton: { backgroundColor: theme.colors.blue600.computedValue, color: theme.colors["white-static"].computedValue, }, }; return isOpen ? (

다이얼로그 제목

다이얼로그 내용
) : null; }; export { semanticColors, scaleColors, staticColors, Component, Dialog }; ``` ```tsx title="basic.output.tsx" // @ts-nocheck import { theme } from "@src/stitches/stitches.config"; const semanticColors = { primary: theme.colors["bg-brand-solid"].computedValue, onPrimary: theme.colors["palette-static-white"].computedValue, primaryLow: theme.colors["palette-carrot-100"].computedValue, success: theme.colors["bg-positive-solid"].computedValue, warning: theme.colors["bg-warning-solid"].computedValue, danger: theme.colors["bg-critical-solid"].computedValue, paperDefault: theme.colors["bg-layer-default"].computedValue, paperContents: theme.colors["bg-layer-fill"].computedValue, paperDialog: theme.colors["bg-layer-floating"].computedValue, inkText: theme.colors["fg-neutral"].computedValue, inkTextLow: theme.colors["fg-neutral-subtle"].computedValue, divider1: theme.colors["stroke-neutral-subtle"].computedValue, divider2: theme.colors["stroke-neutral-muted"].computedValue, overlayDim: theme.colors["bg-overlay"].computedValue, accent: theme.colors["bg-informative-solid"].computedValue, }; const scaleColors = { gray00: theme.colors["palette-gray-00"].computedValue, gray100: theme.colors["palette-gray-200"].computedValue, gray200: theme.colors["palette-gray-300"].computedValue, gray300: theme.colors["palette-gray-400"].computedValue, gray400: theme.colors["palette-gray-500"].computedValue, gray500: theme.colors["palette-gray-600"].computedValue, gray600: theme.colors["palette-gray-700"].computedValue, gray700: theme.colors["palette-gray-800"].computedValue, gray800: theme.colors["palette-gray-900"].computedValue, gray900: theme.colors["palette-gray-1000"].computedValue, carrot100: theme.colors["palette-carrot-200"].computedValue, carrot500: theme.colors["palette-carrot-600"].computedValue, carrot900: theme.colors["palette-carrot-800"].computedValue, carrotAlpha50: theme.colors["palette-carrot-100"].computedValue, carrotAlpha100: theme.colors["palette-carrot-200"].computedValue, carrotAlpha200: theme.colors["palette-carrot-200"].computedValue, blue300: theme.colors["palette-blue-400"].computedValue, blue600: theme.colors["palette-blue-600"].computedValue, red500: theme.colors["palette-red-700"].computedValue, }; const staticColors = { white: theme.colors["palette-static-white"].computedValue, black: theme.colors["palette-static-black"].computedValue, blackAlpha200: theme.colors["palette-static-black-alpha-500"].computedValue, whiteAlpha200: theme.colors["palette-static-white-alpha-300"].computedValue, gray900: theme.colors["palette-static-black"].computedValue, carrot50: theme.colors["palette-carrot-100"].computedValue, carrot800: theme.colors["palette-carrot-700"].computedValue, blue50: theme.colors["palette-blue-100"].computedValue, blue800: theme.colors["palette-blue-700"].computedValue, red50: theme.colors["palette-red-100"].computedValue, red800: theme.colors["palette-red-700"].computedValue, }; const Component = () => { return (
안내사항 중요
); }; const Dialog = ({ isOpen, onClose }) => { const styles = { overlay: { backgroundColor: theme.colors["bg-overlay"].computedValue, }, container: { backgroundColor: theme.colors["bg-layer-floating"].computedValue, borderColor: theme.colors["palette-gray-400"].computedValue, }, header: { borderBottom: `1px solid ${theme.colors["stroke-neutral-subtle"].computedValue}`, }, title: { color: theme.colors["palette-gray-1000"].computedValue, }, content: { color: theme.colors["palette-gray-800"].computedValue, backgroundColor: theme.colors["bg-layer-fill"].computedValue, }, footer: { borderTop: `1px solid ${theme.colors["stroke-neutral-muted"].computedValue}`, }, closeButton: { color: theme.colors["palette-gray-600"].computedValue, }, submitButton: { backgroundColor: theme.colors["palette-blue-600"].computedValue, color: theme.colors["palette-static-white"].computedValue, }, }; return isOpen ? (

다이얼로그 제목

다이얼로그 내용
) : null; }; export { semanticColors, scaleColors, staticColors, Component, Dialog }; ```
## replace-css-seed-design-color-variable npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-css-seed-design-color-variable ``` ```bash pnpm dlx @seed-design/codemod@latest replace-css-seed-design-color-variable ``` ```bash yarn dlx @seed-design/codemod@latest replace-css-seed-design-color-variable ``` ```bash bun x @seed-design/codemod@latest replace-css-seed-design-color-variable ``` ```css title="basic.input.css" :root[data-seed] { --seed-alert-dialog-backdrop-background: var(--seed-semantic-color-overlay-dim); --seed-alert-dialog-content-background: var(--seed-semantic-color-paper-dialog); --seed-alert-dialog-title-color: var(--seed-scale-color-gray-900); --seed-alert-dialog-description-color: var(--seed-scale-color-gray-900); --seed-box-button-focus-border: 2px solid var(--seed-scale-color-blue-600); box-shadow: 0 0 0 2px var(--seed-scale-color-blue-600); background: linear-gradient(to bottom, var(--seed-scale-color-blue-600), var(--seed-scale-color-blue-700)); } ``` ```css title="basic.output.css" :root[data-seed] { --seed-alert-dialog-backdrop-background: var(--seed-color-bg-overlay); --seed-alert-dialog-content-background: var(--seed-color-bg-layer-floating); --seed-alert-dialog-title-color: var(--seed-color-palette-gray-1000); --seed-alert-dialog-description-color: var(--seed-color-palette-gray-1000); --seed-box-button-focus-border: 2px solid var(--seed-color-palette-blue-600); box-shadow: 0 0 0 2px var(--seed-color-palette-blue-600); background: linear-gradient(to bottom, var(--seed-color-palette-blue-600), var(--seed-color-palette-blue-800)); } ``` ## replace-react-icon npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-react-icon ``` ```bash pnpm dlx @seed-design/codemod@latest replace-react-icon ``` ```bash yarn dlx @seed-design/codemod@latest replace-react-icon ``` ```bash bun x @seed-design/codemod@latest replace-react-icon ``` ```tsx title="basic.input.tsx" // @ts-nocheck import { IconSellRegular, IconListFill, IconAddFill as AddIconAlias, } from "@seed-design/react-icon"; import IconSellFill from "@seed-design/react-icon/IconSellFill"; import IconAddThin from '@karrotmarket/karrot-ui-icon/lib/react/IconAddThin'; import IconCloseThin from '@karrotmarket/karrot-ui-icon/lib/react/IconCloseThin'; import IconCarRegular from '@karrotmarket/karrot-ui-icon/lib/react/IconCarRegular'; function App() { console.log(IconSellRegular); return ( <> ); } ``` ```tsx title="basic.output.tsx" // @ts-nocheck import { IconPlusSquareLine, IconDothorizline3VerticalFill, IconPlusFill as AddIconAlias, } from "@karrotmarket/react-monochrome-icon"; import IconPlusSquareFill from "@karrotmarket/react-monochrome-icon/IconPlusSquareFill"; import IconPlusLine from "@karrotmarket/react-monochrome-icon/IconPlusLine"; import IconXmarkLine from "@karrotmarket/react-monochrome-icon/IconXmarkLine"; import IconCarFrontsideLine from "@karrotmarket/react-monochrome-icon/IconCarFrontsideLine"; function App() { console.log(IconPlusSquareLine); return ( <> ); } ``` ## replace-seed-design-token-vars npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-seed-design-token-vars ``` ```bash pnpm dlx @seed-design/codemod@latest replace-seed-design-token-vars ``` ```bash yarn dlx @seed-design/codemod@latest replace-seed-design-token-vars ``` ```bash bun x @seed-design/codemod@latest replace-seed-design-token-vars ``` ```tsx title="basic.input.tsx" import { vars as legacyVars } from "@seed-design/design-token"; import { vars } from "@seed-design/css/vars"; import { vars as typoVars } from "@seed-design/css/vars/component/typography"; const color = vars.$color.palette.gray600; const typography = typoVars.textStyleT5Bold.enabled.root; const legacyColor = legacyVars.$static.color.staticWhiteAlpha50; ``` ```tsx title="basic.output.tsx" import { vars as legacyVars } from "@seed-design/design-token"; import { vars } from "@seed-design/css/vars"; import { vars as typoVars } from "@seed-design/css/vars/component/typography"; const color = vars.$color.palette.gray600; const typography = typoVars.textStyleT5Bold.enabled.root; const legacyColor = legacyVars.$static.color.staticWhiteAlpha50; ``` ## replace-semantic-stroke-color 시맨틱 stroke 컬러 토큰을 v0.2.0에 맞춰 마이그레이션하는 transform입니다. ### 목적 @seed-design/css v0.2.0에서 업데이트된 시맨틱 stroke 컬러 토큰을 자동으로 마이그레이션합니다. 이전 버전의 stroke 토큰들을 새로운 네이밍 규칙에 맞게 변환합니다. ### 변환 매핑 #### 우선 순위 변환 (1차) ⚠️ **중요**: 다음 변환은 반드시 다른 변환보다 먼저 처리됩니다. | 기존 토큰 | 신규 토큰 | 비고 | | --------------------------------- | ---------------------------------- | ------------------ | | `vars.$color.stroke.neutralMuted` | `vars.$color.stroke.neutralSubtle` | 가장 먼저 마이그레이션해야 합니다 | #### 일반 변환 (2차) | 기존 토큰 | 신규 토큰 | | --------------------------------- | ------------------------------------ | | `vars.$color.stroke.onImage` | `vars.$color.stroke.neutralSubtle` | | `vars.$color.stroke.neutral` | `vars.$color.stroke.neutralMuted` | | `vars.$color.stroke.fieldFocused` | `vars.$color.stroke.neutralContrast` | | `vars.$color.stroke.control` | `vars.$color.stroke.neutralWeak` | | `vars.$color.stroke.field` | `vars.$color.stroke.neutralWeak` | | `vars.$color.stroke.brand` | `vars.$color.stroke.brandWeak` | | `vars.$color.stroke.positive` | `vars.$color.stroke.positiveWeak` | | `vars.$color.stroke.informative` | `vars.$color.stroke.informativeWeak` | | `vars.$color.stroke.warning` | `vars.$color.stroke.warningWeak` | | `vars.$color.stroke.critical` | `vars.$color.stroke.criticalWeak` | ### 지원하는 파일 형식 * TypeScript (`.ts`) * TypeScript JSX (`.tsx`) ### 변환 예시 #### 기본 사용 ```typescript // Before import { vars } from "@seed-design/css/vars"; const borderColor = vars.$color.stroke.neutralMuted; const outlineColor = vars.$color.stroke.neutral; // After import { vars } from "@seed-design/css/vars"; const borderColor = vars.$color.stroke.neutralSubtle; const outlineColor = vars.$color.stroke.neutralMuted; ``` #### React 컴포넌트에서의 사용 ```tsx // Before const Component = () => (
); // After const Component = () => (
); ``` ### 우선 순위의 중요성 이 transform은 **2-pass 방식**으로 동작합니다: 1. **1차 변환**: `neutralMuted` → `neutralSubtle`을 먼저 처리 2. **2차 변환**: `neutral` → `neutralMuted` 등 나머지 변환들을 처리 이 순서가 중요한 이유는 연쇄 변환을 방지하기 위해서입니다. 만약 순서가 바뀌면 `neutralMuted`가 `neutralSubtle`로 변환되기 전에 `neutral`이 `neutralMuted`로 변환될 수 있어 예상치 못한 결과가 나올 수 있습니다. ### 변환되지 않는 토큰들 다음 토큰들은 이미 v3 형식이므로 변환되지 않습니다: * `vars.$color.stroke.brandWeak` * `vars.$color.stroke.brandSolid` * `vars.$color.stroke.neutralSubtle` * `vars.$color.stroke.neutralContrast` * `vars.$color.stroke.neutralWeak` * 기타 `-weak`, `-solid` 접미사를 가진 토큰들 ### 로깅 transform 실행 시 다음과 같은 로그가 생성됩니다: * `.report/replace-semantic-stroke-color-success.log`: 성공한 변환들 * `.report/replace-semantic-stroke-color-issues.log`: 경고 및 실패 * `.report/replace-semantic-stroke-color-debug.log`: 디버그 정보 npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-semantic-stroke-color ``` ```bash pnpm dlx @seed-design/codemod@latest replace-semantic-stroke-color ``` ```bash yarn dlx @seed-design/codemod@latest replace-semantic-stroke-color ``` ```bash bun x @seed-design/codemod@latest replace-semantic-stroke-color ``` ```tsx title="basic.input.tsx" // @ts-nocheck import React from "react"; import { vars } from "@seed-design/css/vars"; // 인라인 스타일에서 stroke 토큰 사용 const Component1 = () => (
); // 객체 스타일에서 사용 const styles = { container: { borderColor: vars.$color.stroke.control, border: `1px solid ${vars.$color.stroke.field}`, }, button: { borderColor: vars.$color.stroke.brand, outlineColor: vars.$color.stroke.positive, }, input: { borderColor: vars.$color.stroke.informative, "&:focus": { borderColor: vars.$color.stroke.warning, }, }, error: { borderColor: vars.$color.stroke.critical, }, }; // 삼항 연산자에서 사용 const ConditionalComponent = ({ isActive }: { isActive: boolean }) => (
); // 새로운 토큰들 (변경되지 않아야 함) const NewTokensComponent = () => (
); ``` ```tsx title="basic.output.tsx" // @ts-nocheck import React from "react"; import { vars } from "@seed-design/css/vars"; // 인라인 스타일에서 stroke 토큰 사용 const Component1 = () => (
); // 객체 스타일에서 사용 const styles = { container: { borderColor: vars.$color.stroke.neutralWeak, border: `1px solid ${vars.$color.stroke.neutralWeak}`, }, button: { borderColor: vars.$color.stroke.brandWeak, outlineColor: vars.$color.stroke.positiveWeak, }, input: { borderColor: vars.$color.stroke.informativeWeak, "&:focus": { borderColor: vars.$color.stroke.warningWeak, }, }, error: { borderColor: vars.$color.stroke.criticalWeak, }, }; // 삼항 연산자에서 사용 const ConditionalComponent = ({ isActive }: { isActive: boolean }) => (
); // 새로운 토큰들 (변경되지 않아야 함) const NewTokensComponent = () => (
); ``` ## replace-custom-seed-design-text-component npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-custom-seed-design-text-component ``` ```bash pnpm dlx @seed-design/codemod@latest replace-custom-seed-design-text-component ``` ```bash yarn dlx @seed-design/codemod@latest replace-custom-seed-design-text-component ``` ```bash bun x @seed-design/codemod@latest replace-custom-seed-design-text-component ``` ```tsx title="basic.input.tsx" // @ts-nocheck import Text from 'components/Base/Text'; const Component = () => { return (
{/* 기존 variant prop 케이스 */} 광고 노출 기준 앱 내 최근 활동 이력을 분석하여 이용자의 관심사와 관련성이 높은 게시글을 노출해요. {/* typography prop + color prop 케이스 */} 앱 내 최근 활동 이력을 분석하여 이용자의 관심사와 관련성이 높은 게시글을 노출해요. 지역 선택하기 지표별 성과 {/* 다양한 typography prop 형태 */} 접두사 없는 토큰 또 다른 토큰 {/* 다양한 color prop 형태 */} 시맨틱 컬러 스태틱 컬러 textColor prop {/* 조건부 표현식 케이스 */} 조건부 variant 조건부 color {/* JSX 표현식 컨테이너 케이스 */} 표현식 컨테이너
); }; ``` ```tsx title="basic.output.tsx" // @ts-nocheck import { Text } from "@seed-design/react"; const Component = () => { return (
{/* 기존 variant prop 케이스 */} 광고 노출 기준 앱 내 최근 활동 이력을 분석하여 이용자의 관심사와 관련성이 높은 게시글을 노출해요. {/* typography prop + color prop 케이스 */} 앱 내 최근 활동 이력을 분석하여 이용자의 관심사와 관련성이 높은 게시글을 노출해요. 지역 선택하기 지표별 성과 {/* 다양한 typography prop 형태 */} 접두사 없는 토큰 또 다른 토큰 {/* 다양한 color prop 형태 */} 시맨틱 컬러 스태틱 컬러 textColor prop {/* 조건부 표현식 케이스 */} 조건부 variant 조건부 color {/* JSX 표현식 컨테이너 케이스 */} 표현식 컨테이너
); }; ```
## replace-seed-design-token-typography-classname npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-seed-design-token-typography-classname ``` ```bash pnpm dlx @seed-design/codemod@latest replace-seed-design-token-typography-classname ``` ```bash yarn dlx @seed-design/codemod@latest replace-seed-design-token-typography-classname ``` ```bash bun x @seed-design/codemod@latest replace-seed-design-token-typography-classname ``` ```tsx title="basic.input.tsx" // @ts-nocheck import { classNames } from "@seed-design/design-token"; import { style } from "@vanilla-extract/css"; const typography = { one: classNames.$semantic.typography.title2Regular, two: classNames.$semantic.typography.label3Regular, three: classNames.$semantic.typography.label5Regular, four: classNames.$semantic.typography.label6Regular, } export const footer = style([ classNames.$semantic.typography.caption1Regular, { padding: "16px", marginTop: "12px", color: vars.$scale.color.gray700, backgroundColor: vars.$semantic.color.paperContents, }, ]); ``` ```tsx title="basic.output.tsx" // @ts-nocheck import { text } from "@seed-design/css/recipes/text"; import { style } from "@vanilla-extract/css"; const typography = { one: text({ textStyle: "t7Regular" }), two: text({ textStyle: "t4Regular" }), three: text({ textStyle: "t1Regular" }), four: text({ textStyle: "t1Regular" }), } export const footer = style([ text({ textStyle: "t3Regular" }), { padding: "16px", marginTop: "12px", color: vars.$scale.color.gray700, backgroundColor: vars.$semantic.color.paperContents, }, ]); ``` ## replace-stitches-styled-color Stitches로 스타일링된 컴포넌트의 색상을 V3 형식으로 변환해요. ### 변환 내용 * Stitches `styled()` 함수에서 사용된 Seed Design V2 색상 토큰을 V3 색상 토큰으로 변환합니다. * 모든 색상 관련 스타일 속성(color, backgroundColor, borderColor 등)을 지원합니다. * 상태 변이(variants)에 적용된 색상 변경도 함께 변환합니다. ### 대상 파일 * `.tsx`, `.jsx`, `.ts`, `.js` 파일에서 Stitches 스타일링 사용 부분 ### 주의사항 * 기존 코드의 구조와 포맷을 최대한 유지하면서 색상 값만 변경합니다. * 커스텀 색상 값이나 CSS 변수는 변환하지 않습니다. npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-stitches-styled-color ``` ```bash pnpm dlx @seed-design/codemod@latest replace-stitches-styled-color ``` ```bash yarn dlx @seed-design/codemod@latest replace-stitches-styled-color ``` ```bash bun x @seed-design/codemod@latest replace-stitches-styled-color ``` ```tsx title="basic.input.tsx" // @ts-nocheck const SemanticColorTestComponent = styled("div", { // Semantic Color 테스트 color: "$primary-semantic", color: "$onPrimary-semantic", color: "$primaryLow-semantic", color: "$secondary-semantic", color: "$secondaryLow-semantic", color: "$success-semantic", color: "$successLow-semantic", color: "$warning-semantic", color: "$warningLow-semantic", color: "$danger-semantic", color: "$dangerLow-semantic", color: "$overlayDim-semantic", color: "$overlayLow-semantic", color: "$paperSheet-semantic", color: "$paperDialog-semantic", color: "$paperFloating-semantic", color: "$paperContents-semantic", color: "$paperDefault-semantic", color: "$paperBackground-semantic", color: "$paperAccent-semantic", color: "$primaryHover-semantic", color: "$primaryPressed-semantic", color: "$primaryLowHover-semantic", color: "$primaryLowActive-semantic", color: "$primaryLowPressed-semantic", color: "$grayHover-semantic", color: "$grayPressed-semantic", color: "$onPrimaryOverlay50-semantic", color: "$onPrimaryOverlay200-semantic", color: "$onPrimaryLowOverlay50-semantic", color: "$onPrimaryLowOverlay100-semantic", color: "$onPrimaryLowOverlay200-semantic", color: "$onGrayOverlay50-semantic", color: "$onGrayOverlay100-semantic", color: "$divider1-semantic", color: "$divider2-semantic", color: "$divider3-semantic", color: "$accent-semantic", color: "$inkText-semantic", color: "$inkTextLow-semantic", color: "$grayActive-semantic", }); const ScaleColorTestComponent = styled("div", { // Scale Color Gray 테스트 color: "$gray00", color: "$gray50", color: "$gray100", color: "$gray200", color: "$gray300", color: "$gray400", color: "$gray500", color: "$gray600", color: "$gray700", color: "$gray800", color: "$gray900", color: "$grayAlpha50", color: "$grayAlpha100", color: "$grayAlpha200", color: "$grayAlpha500", // Scale Color Carrot 테스트 color: "$carrot50", color: "$carrot100", color: "$carrot200", color: "$carrot300", color: "$carrot400", color: "$carrot500", color: "$carrot600", color: "$carrot700", color: "$carrot800", color: "$carrot900", color: "$carrot950", color: "$carrotAlpha50", color: "$carrotAlpha100", color: "$carrotAlpha200", // Scale Color Blue 테스트 color: "$blue50", color: "$blue100", color: "$blue200", color: "$blue300", color: "$blue400", color: "$blue500", color: "$blue600", color: "$blue700", color: "$blue800", color: "$blue900", color: "$blue950", color: "$blueAlpha50", color: "$blueAlpha100", color: "$blueAlpha200", // Scale Color Red 테스트 color: "$red50", color: "$red100", color: "$red200", color: "$red300", color: "$red400", color: "$red500", color: "$red600", color: "$red700", color: "$red800", color: "$red900", color: "$red950", color: "$redAlpha50", color: "$redAlpha100", color: "$redAlpha200", // Scale Color Green 테스트 color: "$green50", color: "$green100", color: "$green200", color: "$green300", color: "$green400", color: "$green500", color: "$green600", color: "$green700", color: "$green800", color: "$green900", color: "$green950", color: "$greenAlpha50", color: "$greenAlpha100", color: "$greenAlpha200", // Scale Color Yellow 테스트 color: "$yellow50", color: "$yellow100", color: "$yellow200", color: "$yellow300", color: "$yellow400", color: "$yellow500", color: "$yellow600", color: "$yellow700", color: "$yellow800", color: "$yellow900", color: "$yellow950", color: "$yellowAlpha50", color: "$yellowAlpha100", color: "$yellowAlpha200", // Scale Color Purple 테스트 color: "$purple50", color: "$purple100", color: "$purple200", color: "$purple300", color: "$purple400", color: "$purple500", color: "$purple600", color: "$purple700", color: "$purple800", color: "$purple900", color: "$purple950", }); const StaticColorTestComponent = styled("div", { // Static Color 테스트 color: "$black-static", color: "$white-static", color: "$gray900-static", color: "$carrot50-static", color: "$carrot800-static", color: "$green50-static", color: "$green800-static", color: "$yellow50-static", color: "$yellow800-static", color: "$red50-static", color: "$red800-static", color: "$blue50-static", color: "$blue800-static", color: "$blackAlpha200-static", color: "$blackAlpha500-static", color: "$whiteAlpha50-static", color: "$whiteAlpha200-static", }); // 복합 속성 테스트 const ComplexPropertyTestComponent = styled("div", { border: "1px solid $gray700", boxShadow: "0 0 10px $overlayDim-semantic", outline: "2px solid $accent-semantic", textDecoration: "underline $danger-semantic", // 네스팅된 속성 테스트 "&:before": { borderBottom: "1px solid $divider1-semantic", background: "$paperContents-semantic", }, // 변형 테스트 variants: { theme: { primary: { background: "$primary-semantic", color: "$onPrimary-semantic", }, secondary: { background: "$secondaryLow-semantic", color: "$inkText-semantic", }, danger: { background: "$danger-semantic", color: "$white-static", }, }, }, }); // 복합 속성 (색상 토큰이 앞에 있는 경우) 테스트 const BorderAndColorTestComponent = styled("div", { color: "$scale-red500 solid 1px", color: "$red600 dashed 2px", color: "$scale-blue400 dotted 3px", color: "$scale-green600 double 4px", color: "$scale-yellow500 groove 2px", outlineColor: "$scale-purple500", }); const ImportantTest = styled("div", { color: "$primary-semantic !important", color: "$onPrimary-semantic !important", color: "$primaryLow-semantic !important", color: "$gray00 !important", color: "$gray50 !important", color: "$gray100 !important", css: { color: "$scale-gray600 !important", borderColor: "$scale-gray400 !important", backgroundColor: "$scale-gray100 !important", }, }); const Li_FieldItem = styled("li", { borderBottom: `${rem(1)} solid $semantic-divider1`, borderBottom: `0.5rem solid $semantic-paperBackground`, border: check ? "1px solid $semantic-divider1" : "0.5rem solid $semantic-paperBackground", }); ``` ```tsx title="basic.output.tsx" // @ts-nocheck const SemanticColorTestComponent = styled("div", { // Semantic Color 테스트 color: "$fg-brand", color: "$palette-static-white", color: "$palette-carrot-100", color: "$palette-gray-900", color: "$bg-neutral-weak", color: "$fg-positive", color: "$bg-positive-weak", color: "$bg-warning-solid", color: "$bg-warning-weak", color: "$fg-critical", color: "$bg-critical-weak", color: "$bg-overlay", color: "$bg-overlay-muted", color: "$bg-layer-floating", color: "$bg-layer-floating", color: "$bg-layer-floating", color: "$bg-layer-fill", color: "$bg-layer-default", color: "$bg-layer-basement", color: "$palette-carrot-100", color: "$bg-brand-solid-pressed", color: "$bg-brand-solid-pressed", color: "$palette-carrot-200", color: "$palette-carrot-100", color: "$palette-carrot-200", color: "$bg-neutral-weak-pressed", color: "$bg-neutral-weak-pressed", color: "$onPrimaryOverlay50-semantic", color: "$onPrimaryOverlay200-semantic", color: "$onPrimaryLowOverlay50-semantic", color: "$onPrimaryLowOverlay100-semantic", color: "$onPrimaryLowOverlay200-semantic", color: "$stroke-neutral-subtle", color: "$onGrayOverlay100-semantic", color: "$stroke-neutral-subtle", color: "$stroke-neutral-muted", color: "$palette-gray-400", color: "$fg-informative", color: "$fg-neutral", color: "$fg-neutral-subtle", color: "$fg-neutral-muted", }); const ScaleColorTestComponent = styled("div", { // Scale Color Gray 테스트 color: "$palette-gray-00", color: "$palette-gray-100", color: "$palette-gray-200", color: "$palette-gray-300", color: "$palette-gray-400", color: "$palette-gray-500", color: "$palette-gray-600", color: "$palette-gray-700", color: "$palette-gray-800", color: "$palette-gray-900", color: "$palette-gray-1000", color: "$palette-gray-200", color: "$palette-gray-300", color: "$palette-gray-500", color: "$palette-gray-700", // Scale Color Carrot 테스트 color: "$palette-carrot-100", color: "$palette-carrot-200", color: "$palette-carrot-300", color: "$palette-carrot-400", color: "$palette-carrot-500", color: "$palette-carrot-600", color: "$palette-carrot-600", color: "$palette-carrot-700", color: "$palette-carrot-700", color: "$palette-carrot-800", color: "$palette-carrot-800", color: "$palette-carrot-100", color: "$palette-carrot-200", color: "$palette-carrot-200", // Scale Color Blue 테스트 color: "$palette-blue-100", color: "$palette-blue-200", color: "$palette-blue-300", color: "$palette-blue-400", color: "$palette-blue-400", color: "$palette-blue-600", color: "$palette-blue-600", color: "$palette-blue-800", color: "$palette-blue-900", color: "$palette-blue-900", color: "$palette-blue-1000", color: "$palette-blue-100", color: "$palette-blue-100", color: "$palette-blue-200", // Scale Color Red 테스트 color: "$palette-red-100", color: "$palette-red-200", color: "$palette-red-300", color: "$palette-red-400", color: "$palette-red-600", color: "$palette-red-700", color: "$palette-red-700", color: "$palette-red-800", color: "$palette-red-900", color: "$palette-red-900", color: "$palette-red-900", color: "$palette-red-100", color: "$palette-red-200", color: "$palette-red-300", // Scale Color Green 테스트 color: "$palette-green-100", color: "$palette-green-200", color: "$palette-green-300", color: "$palette-green-400", color: "$palette-green-500", color: "$palette-green-600", color: "$palette-green-700", color: "$palette-green-800", color: "$palette-green-900", color: "$palette-green-900", color: "$palette-green-900", color: "$palette-green-100", color: "$palette-green-200", color: "$palette-green-200", // Scale Color Yellow 테스트 color: "$palette-yellow-100", color: "$palette-yellow-200", color: "$palette-yellow-300", color: "$palette-yellow-400", color: "$palette-yellow-500", color: "$palette-yellow-700", color: "$palette-yellow-700", color: "$palette-yellow-800", color: "$palette-yellow-800", color: "$palette-yellow-900", color: "$palette-yellow-900", color: "$palette-yellow-100", color: "$palette-yellow-100", color: "$palette-yellow-100", // Scale Color Purple 테스트 color: "$palette-purple-100", color: "$palette-purple-300", color: "$palette-purple-400", color: "$palette-purple-400", color: "$palette-purple-500", color: "$palette-purple-600", color: "$palette-purple-700", color: "$palette-purple-800", color: "$palette-purple-900", color: "$palette-purple-900", color: "$palette-purple-1000", }); const StaticColorTestComponent = styled("div", { // Static Color 테스트 color: "$palette-static-black", color: "$palette-static-white", color: "$palette-static-black", color: "$palette-carrot-100", color: "$palette-carrot-700", color: "$palette-green-100", color: "$palette-green-700", color: "$palette-yellow-100", color: "$palette-yellow-700", color: "$palette-red-100", color: "$palette-red-700", color: "$palette-blue-100", color: "$palette-blue-700", color: "$palette-static-black-alpha-500", color: "$palette-static-black-alpha-700", color: "$palette-static-white-alpha-50", color: "$palette-static-white-alpha-300", }); // 복합 속성 테스트 const ComplexPropertyTestComponent = styled("div", { border: "1px solid $palette-gray-800", boxShadow: "0 0 10px $bg-overlay", outline: "2px solid $fg-informative", textDecoration: "underline $fg-critical", // 네스팅된 속성 테스트 "&:before": { borderBottom: "1px solid $stroke-neutral-subtle", background: "$bg-layer-fill", }, // 변형 테스트 variants: { theme: { primary: { background: "$bg-brand-solid", color: "$palette-static-white", }, secondary: { background: "$bg-neutral-weak", color: "$fg-neutral", }, danger: { background: "$bg-critical-solid", color: "$palette-static-white", }, }, }, }); // 복합 속성 (색상 토큰이 앞에 있는 경우) 테스트 const BorderAndColorTestComponent = styled("div", { color: "$palette-red-700 solid 1px", color: "$palette-red-700 dashed 2px", color: "$palette-blue-400 dotted 3px", color: "$palette-green-700 double 4px", color: "$palette-yellow-700 groove 2px", outlineColor: "$palette-purple-600", }); const ImportantTest = styled("div", { color: "$fg-brand !important", color: "$palette-static-white !important", color: "$palette-carrot-100 !important", color: "$palette-gray-00 !important", color: "$palette-gray-100 !important", color: "$palette-gray-200 !important", css: { color: "$palette-gray-700 !important", borderColor: "$palette-gray-500 !important", backgroundColor: "$palette-gray-200 !important", }, }); const Li_FieldItem = styled("li", { borderBottom: `${rem(1)} solid $stroke-neutral-subtle`, borderBottom: `0.5rem solid $bg-layer-basement`, border: check ? "1px solid $stroke-neutral-subtle" : "0.5rem solid $bg-layer-basement", }); ``` ## replace-custom-text-component-color-prop npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-custom-text-component-color-prop ``` ```bash pnpm dlx @seed-design/codemod@latest replace-custom-text-component-color-prop ``` ```bash yarn dlx @seed-design/codemod@latest replace-custom-text-component-color-prop ``` ```bash bun x @seed-design/codemod@latest replace-custom-text-component-color-prop ``` ```tsx title="basic.input.tsx" // @ts-nocheck const Component = () => { return ( <> ); }; ``` ```tsx title="basic.output.tsx" // @ts-nocheck const Component = () => { return ( <> ); }; ``` ## replace-alpha-color Seed Design V3에서 V3로 알파 컬러 토큰을 업데이트하는 transform입니다. 이 transform은 다음과 같은 알파 컬러 토큰들을 새로운 값으로 변경합니다: * `staticBlackAlpha50` → `staticBlackAlpha200` * `staticBlackAlpha200` → `staticBlackAlpha500` * `staticBlackAlpha500` → `staticBlackAlpha700` * `staticWhiteAlpha200` → `staticWhiteAlpha300` ### 주의사항 * 이 transform은 JavaScript/TypeScript 파일과 CSS 파일을 모두 자동으로 처리합니다. * **한 번만 실행**: 동일한 파일에 여러 번 실행하면 연쇄 변환이 발생할 수 있습니다 * **V3 → V3 마이그레이션**: 이미 V3를 사용 중인 프로젝트에서만 사용하세요 * **백업 권장**: 변환 전에 코드를 백업하는 것을 권장합니다 * **순서 중요**: 큰 번호부터 작은 번호 순으로 변환하여 연쇄 변환을 방지합니다 npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-alpha-color ``` ```bash pnpm dlx @seed-design/codemod@latest replace-alpha-color ``` ```bash yarn dlx @seed-design/codemod@latest replace-alpha-color ``` ```bash bun x @seed-design/codemod@latest replace-alpha-color ``` ```tsx title="basic.input.tsx" // @ts-nocheck import { vars } from "@seed-design/css/vars"; export const Component = () => { const styles = { overlay: { backgroundColor: vars.$color.palette.staticBlackAlpha50, }, shadow: { backgroundColor: vars.$color.palette.staticBlackAlpha200, }, darkOverlay: { backgroundColor: vars.$color.palette.staticBlackAlpha500, }, lightOverlay: { backgroundColor: vars.$color.palette.staticWhiteAlpha200, }, }; return (
Light overlay
Shadow
Dark overlay
Light overlay
Direct usage
); }; ``` ```tsx title="basic.output.tsx" // @ts-nocheck import { vars } from "@seed-design/css/vars"; export const Component = () => { const styles = { overlay: { backgroundColor: vars.$color.palette.staticBlackAlpha200, }, shadow: { backgroundColor: vars.$color.palette.staticBlackAlpha500, }, darkOverlay: { backgroundColor: vars.$color.palette.staticBlackAlpha700, }, lightOverlay: { backgroundColor: vars.$color.palette.staticWhiteAlpha300, }, }; return (
Light overlay
Shadow
Dark overlay
Light overlay
Direct usage
); }; ```
## replace-custom-seed-design-color 커스텀 Seed Design 컬러 토큰을 V3 형식으로 변환하는 트랜스폼 npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-custom-seed-design-color ``` ```bash pnpm dlx @seed-design/codemod@latest replace-custom-seed-design-color ``` ```bash yarn dlx @seed-design/codemod@latest replace-custom-seed-design-color ``` ```bash bun x @seed-design/codemod@latest replace-custom-seed-design-color ``` ```ts title="basic.input.ts" // @ts-nocheck import { style } from "@vanilla-extract/css"; import { color, backgroundColor, background } from "@/shared/styles"; export const container = style({ backgroundColor: color.gray100, color: color.gray900, borderColor: color.carrot500, }); export const box = style({ background: color.gray50, color: color.red500, border: `1px solid ${color.gray300}`, }); export const alert = style({ backgroundColor: color.red50, color: color.red900, }); export const button = style({ backgroundColor: background.gray100, color: color.gray900, }); export const highlight = style({ color: color.carrot500, backgroundColor: backgroundColor.primary, }); export const primary = style({ color: color.primary, }); ``` ```ts title="basic.output.ts" // @ts-nocheck import { style } from "@vanilla-extract/css"; import { color, backgroundColor, background } from "@/shared/styles"; export const container = style({ backgroundColor: color.palette.gray200, color: color.palette.gray1000, borderColor: color.palette.carrot600, }); export const box = style({ background: color.palette.gray100, color: color.palette.red700, border: `1px solid ${color.palette.gray400}`, }); export const alert = style({ backgroundColor: color.palette.red100, color: color.palette.red900, }); export const button = style({ backgroundColor: background.palette.gray200, color: color.palette.gray1000, }); export const highlight = style({ color: color.palette.carrot600, backgroundColor: backgroundColor.bg.brandSolid, }); export const primary = style({ color: color.fg.brand, }); ``` ## replace-custom-color-to-seed-design-vars-color npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-custom-color-to-seed-design-vars-color ``` ```bash pnpm dlx @seed-design/codemod@latest replace-custom-color-to-seed-design-vars-color ``` ```bash yarn dlx @seed-design/codemod@latest replace-custom-color-to-seed-design-vars-color ``` ```bash bun x @seed-design/codemod@latest replace-custom-color-to-seed-design-vars-color ``` ```ts title="basic.input.ts" // @ts-nocheck import { color, bg, typography, mode } from '@/src/styles/tokens'; export const container = style({ backgroundColor: color['$semantic.paperDefault'], color: color['$scale.gray900'], borderColor: color['$scale.carrot500'], }); export const box = style({ background: color['$scale.gray50'], color: color['$scale.red500'], border: `1px solid ${color['$scale.gray300']}`, }); export const alert = style({ backgroundColor: color['$scale.red50'], color: color['$scale.red900'], }); export const button = style({ backgroundColor: color['$scale.gray100'], color: color['$scale.gray900'], }); export const highlight = style({ color: color['$scale.carrot500'], backgroundColor: color['$semantic.primary'], }); export const primary = style({ color: color['$semantic.primary'], }); // Additional test cases for various mappings export const semanticColors = style({ backgroundColor: color['$semantic.primary'], color: color['$semantic.inkText'], borderColor: color['$semantic.divider1'], }); export const scaleColors = style({ background: color['$scale.gray100'], color: color['$scale.carrot600'], border: `1px solid ${color['$scale.blue500']}`, }); export const staticColors = style({ backgroundColor: color['$static.staticWhite'], color: color['$static.staticBlack'], borderColor: color['$static.staticBlackAlpha200'], }); // Test deprecated tokens with alternative export const deprecatedColors = style({ backgroundColor: color['$semantic.paperContents'], color: color['$semantic.inkTextLow'], }); // Test multiple token choices (should use first one) export const multipleChoices = style({ backgroundColor: color['$semantic.success'], color: color['$semantic.warning'], }); export const icon = { color: color['$scale.gray600'], bg: bg['$scale.gray100'], }; ``` ```ts title="basic.output.ts" // @ts-nocheck import { color, bg, typography, mode } from "@/src/styles/tokens"; export const container = style({ backgroundColor: color["bg.layerDefault"], color: color["palette.gray1000"], borderColor: color["palette.carrot600"], }); export const box = style({ background: color["palette.gray100"], color: color["palette.red700"], border: `1px solid ${color["palette.gray400"]}`, }); export const alert = style({ backgroundColor: color["palette.red100"], color: color["palette.red900"], }); export const button = style({ backgroundColor: color["palette.gray200"], color: color["palette.gray1000"], }); export const highlight = style({ color: color["palette.carrot600"], backgroundColor: color["bg.brandSolid"], }); export const primary = style({ color: color["fg.brand"], }); // Additional test cases for various mappings export const semanticColors = style({ backgroundColor: color["bg.brandSolid"], color: color["fg.neutral"], borderColor: color["stroke.neutralSubtle"], }); export const scaleColors = style({ background: color["palette.gray200"], color: color["palette.carrot600"], border: `1px solid ${color["palette.blue600"]}`, }); export const staticColors = style({ backgroundColor: color["palette.staticWhite"], color: color["palette.staticBlack"], borderColor: color["palette.staticBlackAlpha500"], }); // Test deprecated tokens with alternative export const deprecatedColors = style({ backgroundColor: color["bg.layerFill"], color: color["fg.neutralSubtle"], }); // Test multiple token choices (should use first one) export const multipleChoices = style({ backgroundColor: color["bg.positiveSolid"], color: color["bg.warningSolid"], }); export const icon = { color: color["palette.gray700"], bg: bg["palette.gray200"], }; ``` ## replace-css-seed-design-typography-variable npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-css-seed-design-typography-variable ``` ```bash pnpm dlx @seed-design/codemod@latest replace-css-seed-design-typography-variable ``` ```bash yarn dlx @seed-design/codemod@latest replace-css-seed-design-typography-variable ``` ```bash bun x @seed-design/codemod@latest replace-css-seed-design-typography-variable ``` ```css title="basic.input.css" /* Radio Label */ .seed-radio-group[data-size="small"] [data-part="radio-label"] { margin-inline-start: var(--seed-radio-small-label-margin-inline-start); margin-block-start: var(--seed-radio-small-label-margin-block-start); font-size: var(--seed-semantic-typography-label4-regular-font-size); font-weight: var(--seed-semantic-typography-label4-regular-font-weight); line-height: var(--seed-semantic-typography-label4-regular-line-height); letter-spacing: var(--seed-semantic-typography-label4-regular-letter-spacing); } .seed-radio-group[data-size="medium"] [data-part="radio-label"] { margin-inline-start: var(--seed-radio-medium-label-margin-inline-start); margin-block-start: var(--seed-radio-medium-label-margin-block-start); font-size: var(--seed-semantic-typography-label3-regular-font-size); font-weight: var(--seed-semantic-typography-label3-regular-font-weight); line-height: var(--seed-semantic-typography-label3-regular-line-height); letter-spacing: var(--seed-semantic-typography-label3-regular-letter-spacing); } .seed-radio-group[data-size="large"] [data-part="radio-label"] { margin-inline-start: var(--seed-radio-large-label-margin-inline-start); margin-block-start: var(--seed-radio-large-label-margin-block-start); font-size: var(--seed-semantic-typography-label2-regular-font-size); font-weight: var(--seed-semantic-typography-label2-regular-font-weight); line-height: var(--seed-semantic-typography-label2-regular-line-height); letter-spacing: var(--seed-semantic-typography-label2-regular-letter-spacing); } ``` ```css title="basic.output.css" /* Radio Label */ .seed-radio-group[data-size="small"] [data-part="radio-label"] { margin-inline-start: var(--seed-radio-small-label-margin-inline-start); margin-block-start: var(--seed-radio-small-label-margin-block-start); font-size: var(--seed-font-size-t2); font-weight: var(--seed-font-weight-regular); line-height: var(--seed-line-height-t2); letter-spacing: normal; } .seed-radio-group[data-size="medium"] [data-part="radio-label"] { margin-inline-start: var(--seed-radio-medium-label-margin-inline-start); margin-block-start: var(--seed-radio-medium-label-margin-block-start); font-size: var(--seed-font-size-t4); font-weight: var(--seed-font-weight-regular); line-height: var(--seed-line-height-t4); letter-spacing: normal; } .seed-radio-group[data-size="large"] [data-part="radio-label"] { margin-inline-start: var(--seed-radio-large-label-margin-inline-start); margin-block-start: var(--seed-radio-large-label-margin-block-start); font-size: var(--seed-font-size-t5); font-weight: var(--seed-font-weight-regular); line-height: var(--seed-line-height-t5); letter-spacing: normal; } ``` ## replace-tailwind-color Tailwind CSS 색상 클래스를 Seed Design V3 형식으로 변환해요. ### 변환 내용 * Seed Design V2의 색상 클래스 네이밍을 V3 형식으로 변환합니다. * `text-`, `bg-`, `border-` 등의 접두사를 가진 Tailwind 색상 클래스를 변환합니다. * 색상 강도(shade)에 따른 변환 매핑을 적용합니다. ### 변환 예시 * `text-carrot-500` → `text-static-orange-base` * `bg-salmon-100` → `bg-static-red-light` * `border-navy-900` → `border-static-blue-dark` ### 대상 파일 * `.tsx`, `.jsx`, `.ts`, `.js`, `.html`, `.css` 파일에서 Tailwind 클래스를 사용하는 부분 ### 주의사항 * className 문자열, 템플릿 리터럴, 배열 형태 모두 지원합니다. * Tailwind 동적 클래스 조합(`clsx`, `cx`, `classnames` 등)도 변환됩니다. npm pnpm yarn bun ```bash npx @seed-design/codemod@latest replace-tailwind-color ``` ```bash pnpm dlx @seed-design/codemod@latest replace-tailwind-color ``` ```bash yarn dlx @seed-design/codemod@latest replace-tailwind-color ``` ```bash bun x @seed-design/codemod@latest replace-tailwind-color ``` ```tsx title="basic.input.tsx" // @ts-nocheck export function BackgroundExample() { return (
Primary Background
Primary Low Background
Hover Primary Low Background
Focus Primary Low Background
Active Primary Low Background
Scale Background
Scale Carrot Low Background
Scale Carrot Mid Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Static Black Background
Static White Background
Static Gray900 Background
); } export function SeedBackgroundExample() { return (
Primary Background
Primary Low Background
Hover Primary Low Background
Focus Primary Low Background
Active Primary Low Background
Scale Background
Scale Carrot Low Background
Scale Carrot Mid Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Static Black Background
Static White Background
Static Gray900 Background
); } // Class Variance Authority Example import { cva } from "class-variance-authority"; // Button component with variants const buttonVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors", { variants: { variant: { default: "bg-primary text-staticWhite hover:bg-primaryLow", destructive: "bg-danger text-staticWhite hover:bg-dangerLow", outline: "border border-gray300 bg-staticWhite text-gray900 hover:bg-gray100", secondary: "bg-seed-secondaryLow text-seed-secondary hover:bg-seed-gray200", ghost: "text-seed-primary hover:bg-seed-primaryLow", link: "text-seed-primary underline-offset-4 hover:underline", }, size: { default: "h-10 px-4 py-2", sm: "h-9 rounded-md px-3", lg: "h-11 rounded-md px-8", icon: "h-10 w-10", }, }, defaultVariants: { variant: "default", size: "default", }, } ); ``` ```tsx title="basic.output.tsx" // @ts-nocheck export function BackgroundExample() { return (
Primary Background
Primary Low Background
Hover Primary Low Background
Focus Primary Low Background
Active Primary Low Background
Scale Background
Scale Carrot Low Background
Scale Carrot Mid Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Static Black Background
Static White Background
Static Gray900 Background
); } export function SeedBackgroundExample() { return (
Primary Background
Primary Low Background
Hover Primary Low Background
Focus Primary Low Background
Active Primary Low Background
Scale Background
Scale Carrot Low Background
Scale Carrot Mid Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Scale Carrot High Background
Static Black Background
Static White Background
Static Gray900 Background
); } // Class Variance Authority Example import { cva } from "class-variance-authority"; // Button component with variants const buttonVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors", { variants: { variant: { default: "bg-bg-brand-solid text-palette-static-white hover:bg-palette-carrot-100", destructive: "bg-bg-critical-solid text-palette-static-white hover:bg-bg-critical-weak", outline: "border border-palette-gray-400 bg-palette-static-white text-palette-gray-1000 hover:bg-palette-gray-200", secondary: "bg-bg-neutral-weak text-palette-gray-900 hover:bg-palette-gray-300", ghost: "text-fg-brand hover:bg-palette-carrot-100", link: "text-fg-brand underline-offset-4 hover:underline", }, size: { default: "h-10 px-4 py-2", sm: "h-9 rounded-md px-3", lg: "h-11 rounded-md px-8", icon: "h-10 w-10", }, }, defaultVariants: { variant: "default", size: "default", }, } ); ```
file: developer-tools/codemods/introduction.mdx # Introduction @seed-design/codemod는 Seed Design V2에서 V3로 마이그레이션하기 위한 코드 변환 도구예요. *** title: Introduction description: "@seed-design/codemod는 Seed Design V2에서 V3로 마이그레이션하기 위한 코드 변환 도구예요." --------------------------------------------------------------------------------- import { Terminal } from "lucide-react"; ## 사용 방법 npm pnpm yarn bun ```bash npx @seed-design/codemod@latest <옵션> ``` ```bash pnpm dlx @seed-design/codemod@latest <옵션> ``` ```bash yarn dlx @seed-design/codemod@latest <옵션> ``` ```bash bun x @seed-design/codemod@latest <옵션> ``` 사용 가능한 transform 목록을 확인하려면 다음 명령어를 실행해요. npm pnpm yarn bun ```bash npx @seed-design/codemod@latest --list ``` ```bash pnpm dlx @seed-design/codemod@latest --list ``` ```bash yarn dlx @seed-design/codemod@latest --list ``` ```bash bun x @seed-design/codemod@latest --list ``` } href="/react/developer-tools/codemods/available-transforms"> 사용 가능한 변환 목록을 확인합니다. 스크립트 실행을 위해서는 **Node.js 20.16.0 이상**의 버전이 필요해요. 버전 요구사항을 만족시키지 않으면 안내 문구가 표시돼요. nvm을 사용한다면 codemod 실행을 위해 Node.js 버전을 잠시 변경할 수 있어요. ```shell nvm install 20.16 ``` ## 옵션 * `--list` * 사용 가능한 transform 목록을 보여줘요. * `--log` * 로그를 파일로 저장해요. * `./`에 `combined.log`와 `warnings.log` 파일이 생성돼요. * `--parser` * jscodeshift가 사용할 파서를 지정해요 * `babel` | `babylon` | `flow` | `ts` | `tsx` * 기본값: `tsx` * 예시: `--parser=babel` * `--extensions` * 변환할 파일 확장자를 지정해요. * 지정하지 않으면 `<경로>` 안의 `js,jsx,ts,tsx` 파일을 변환해요. (`d.ts`는 제외) * 예시: `--extensions="ts,tsx"` * `--ignore-config` * 변환하지 않을 파일 패턴이 정의된 파일을 지정해요. * 예시: `--ignore-config=".gitignore"` file: developer-tools/figma-integration/codegen.mdx # Codegen Figma 디자인으로부터 React 코드를 생성하는 플러그인을 제공합니다. *** title: Codegen description: Figma 디자인으로부터 React 코드를 생성하는 플러그인을 제공합니다. ------------------------------------------------------ ## 설치 [SEED Design Codegen](https://www.figma.com/community/plugin/1469592983561656263) 플러그인을 설치합니다. ## 사용법 Figma 디자인을 열고, Dev mode에서 코드 생성을 원하는 디자인 요소를 선택합니다. ![Figma Codegen](/docs/figma-codegen-preview.png) Codegen 플러그인은 작은 단위의 코드 생성 및 작업에 적합합니다. 복잡한 작업은 [MCP](/react/ai-integration/mcp)를 활용하는 것을 권장합니다. ## 관련 문서 * [Figma Learn](https://help.figma.com/hc/en-us/articles/15023202277399-Use-code-snippets-in-Dev-Mode) file: getting-started/cli/commands.mdx # Commands @seed-design/cli 패키지를 사용하여 seed-design을 더 쉽게 사용할 수 있어요. *** title: Commands description: "@seed-design/cli 패키지를 사용하여 seed-design을 더 쉽게 사용할 수 있어요." ---------------------------------------------------------------------- import { File } from "lucide-react"; ## init `seed-design.json` 파일을 생성하기 위한 명령어에요. } title="Configuration" href="/react/getting-started/cli/configuration#옵션"> `seed-design.json` 파일에 대해 알아봐요. ### init 명령어 입력하기 npm pnpm yarn bun ```bash npx @seed-design/cli@latest init ``` ```bash pnpm dlx @seed-design/cli@latest init ``` ```bash yarn dlx @seed-design/cli@latest init ``` ```bash bun x @seed-design/cli@latest init ``` ### seed-design 설정 ```sh ◇ TypeScript를 사용중이신가요? │ Yes │ ◇ React Server Components를 사용중이신가요? │ No │ ◇ seed-design 폴더 경로를 입력해주세요. (기본값은 프로젝트 루트에 생성됩니다.) │ ./seed-design ``` ### 옵션 ```sh copy Usage: $ seed-design init Options: -c, --cwd 작업 디렉토리. 기본값은 현재 디렉토리. -y, --yes 모든 질문에 대해 기본값으로 답변합니다. -h, --help Display this message ``` ## add 컴포넌트를 추가하기 위한 명령어에요. npm pnpm yarn bun ```bash npx @seed-design/cli@latest add [...components] ``` ```bash pnpm dlx @seed-design/cli@latest add [...components] ``` ```bash yarn dlx @seed-design/cli@latest add [...components] ``` ```bash bun x @seed-design/cli@latest add [...components] ``` 컴포넌트를 입력하지 않고 명령어를 입력하게 되면 받을 수 있는 모든 컴포넌트를 볼 수 있어요. npm pnpm yarn bun ```bash npx @seed-design/cli@latest add ``` ```bash pnpm dlx @seed-design/cli@latest add ``` ```bash yarn dlx @seed-design/cli@latest add ``` ```bash bun x @seed-design/cli@latest add ``` ```sh copy ◆ Select all components to add │ ◻ action-button │ ◻ alert-dialog │ ◻ tabs │ ◻ callout │ ◻ switch │ ◻ checkbox │ ◻ text-field │ ◻ ... └ ``` 혹은 여러 컴포넌트를 입력해서 추가할 수도 있어요. npm pnpm yarn bun ```bash npx @seed-design/cli@latest add action-button alert-dialog ``` ```bash pnpm dlx @seed-design/cli@latest add action-button alert-dialog ``` ```bash yarn dlx @seed-design/cli@latest add action-button alert-dialog ``` ```bash bun x @seed-design/cli@latest add action-button alert-dialog ``` ### 옵션 ```sh copy Usage: $ seed-design add [...components] Options: -a, --all Add all components (default: false) --include-deprecated Include deprecated components when used with `--all` (default: false) -c, --cwd the working directory. defaults to the current directory. -u, --baseUrl the base url of the registry. defaults to the current directory. -h, --help Display this message Examples: seed-design add action-button seed-design add alert-dialog ``` file: getting-started/cli/configuration.mdx # Configuration seed-design.json 파일을 통해 CLI를 사용할 때 필요한 설정을 명시해요. *** title: Configuration description: seed-design.json 파일을 통해 CLI를 사용할 때 필요한 설정을 명시해요. ------------------------------------------------------------- import { Terminal } from "lucide-react"; ## 설정 `seed-design.json` 파일은 CLI로 생성하거나 직접 추가할 수 있어요. } title="CLI" href="/react/getting-started/cli#init"> CLI로 seed-design을 추가하는 방법을 알아봐요. 아래 파일을 프로젝트 루트에 생성해주세요. ```json title="seed-design.json" { "rsc": false, "tsx": true, "path": "./seed-design" } ``` ## 옵션 ### path `path`는 생성되는 컴포넌트의 기본 경로를 설정해요. seed-design이 필요로 하는 폴더나 파일들은 `path`로 지정된 경로의 하위에 생겨요. `seed-design`의 root 폴더는 유저가 입력할 수 있게 하되, 그 내부에 생성되는 폴더나 파일들은 고정되는 형식이에요. ```json title="seed-design.json" { "path": "./seed-design" } ``` 만약 위와 같이 설정했다면, `./seed-design` 폴더가 생성이 되고, 그 안에 `ui`, `utils`, `hooks`와 같은 폴더들이 생기게 될거에요. ### rsc 리액트 서버 컴포넌트를 사용할지 여부를 설정해요. `true`로 설정하면 컴포넌트에 `use client` directive가 추가돼요. ```json title="seed-design.json" { "rsc": true | false (default: false) } ``` ### tsx 타입스크립트를 사용할지 여부를 설정해요. `true`로 설정하면 컴포넌트에 `.tsx` 확장자이고, `false`로 설정하면 `.jsx` 확장자로 생성돼요. ```json title="seed-design.json" { "tsx": true | false (default: true) } ``` ### $schema 준비중이에요. file: getting-started/installation/manual.mdx # Manual Seed Design을 번들러 통합 없이 설치하고 사용하는 방법을 알아봅니다. *** title: Manual description: Seed Design을 번들러 통합 없이 설치하고 사용하는 방법을 알아봅니다. -------------------------------------------------------- ### 의존성 설치 필요한 의존성들을 설치해요. npm pnpm yarn bun ```bash npm install @seed-design/react @seed-design/css ``` ```bash pnpm add @seed-design/react @seed-design/css ``` ```bash yarn add @seed-design/react @seed-design/css ``` ```bash bun add @seed-design/react @seed-design/css ``` ### index.html 수정하기 Seed Design의 컬러 토큰은 `` 태그의 `data-seed-color-mode`, `data-seed-user-color-scheme` 속성을 통해 라이트/다크모드 전환을 해요. ```tsx title="index.html" ``` ```tsx title="index.html" ``` ```tsx title="index.html" ``` ### all.css import하기 스타일시트 크기를 줄이기 위해 `base.css` 및 각 컴포넌트의 스타일시트를 따로 import할 수 있어요. 번들러를 사용하는 경우 문서 상단의 번들러 가이드를 통해 컴포넌트 스타일시트를 자동으로 로드할 수 있어요. ```ts title="index.tsx" import "@seed-design/css/all.css"; ``` ### seed-design.json 생성하기 ### init 명령어 입력하기 ```sh npx @seed-design/cli@latest init ``` ### seed-design 설정 ```sh ◇ TypeScript를 사용중이신가요? │ Yes │ ◇ React Server Components를 사용중이신가요? │ No │ ◇ seed-design 폴더 경로를 입력해주세요. (기본값은 프로젝트 루트에 생성됩니다.) │ ./seed-design ``` 아래 파일을 프로젝트 루트에 생성해주세요. ```json title="seed-design.json" { "rsc": false, "tsx": true, "path": "./seed-design" } ``` ### 컴포넌트를 한번 사용해볼까요? ```sh npx @seed-design/cli@latest add action-button ``` ### tsconfig.json 설정하기 ```json title="tsconfig.json" { "compilerOptions": { // your options "paths": { // [!code highlight] "seed-design/ui/*": [ // [!code highlight] "./seed-design/ui/*" // [!code highlight] ] // [!code highlight] } // [!code highlight] } } ``` file: getting-started/installation/vite.mdx # Vite Vite 프로젝트에서 Seed Design을 설치하고 사용하는 방법을 알아봅니다. *** title: Vite description: Vite 프로젝트에서 Seed Design을 설치하고 사용하는 방법을 알아봅니다. ---------------------------------------------------------- ### 의존성 설치 필요한 의존성들을 설치해요. npm pnpm yarn bun ```bash npm install @seed-design/react @seed-design/css ``` ```bash pnpm add @seed-design/react @seed-design/css ``` ```bash yarn add @seed-design/react @seed-design/css ``` ```bash bun add @seed-design/react @seed-design/css ``` ### base.css import하기 ```ts title="index.tsx" import "@seed-design/css/base.css"; ``` ### seed-design.json 생성하기 ### init 명령어 입력하기 ```sh npx @seed-design/cli@latest init ``` ### seed-design 설정 ```sh ◇ TypeScript를 사용중이신가요? │ Yes │ ◇ React Server Components를 사용중이신가요? │ No │ ◇ seed-design 폴더 경로를 입력해주세요. (기본값은 프로젝트 루트에 생성됩니다.) │ ./seed-design ``` 아래 파일을 프로젝트 루트에 생성해주세요. ```json title="seed-design.json" { "rsc": false, "tsx": true, "path": "./seed-design" } ``` ### tsconfig.json 설정하기 위에서 설정한 [seed-design.json path](/react/getting-started/cli/configuration#path)의 경로와 동일해야 해요. ```json title="tsconfig.app.json" { "compilerOptions": { // your options "paths": { // [!code highlight] "seed-design/ui/*": [ // [!code highlight] "./seed-design/ui/*" // [!code highlight] ] // [!code highlight] } // [!code highlight] } } ``` ### vite config 수정하기 npm pnpm yarn bun ```bash npm install -D @seed-design/vite-plugin vite-tsconfig-paths ``` ```bash pnpm add -D @seed-design/vite-plugin vite-tsconfig-paths ``` ```bash yarn add --dev @seed-design/vite-plugin vite-tsconfig-paths ``` ```bash bun add --dev @seed-design/vite-plugin vite-tsconfig-paths ``` * `seedDesignPlugin`은 theming 관련, CSS 파일 자동 로드 등을 담당해요. * `tsconfigPaths`는 tsconfig.json의 경로를 자동으로 인식해요. ```ts title="vite.config.ts" import react from "@vitejs/plugin-react" import { defineConfig } from "vite" import { seedDesignPlugin } from '@seed-design/vite-plugin'; // [!code highlight] import tsconfigPaths from 'vite-tsconfig-paths'; // [!code highlight] export default defineConfig({ plugins: [ react(), seedDesignPlugin(), // [!code highlight] tsconfigPaths(), // [!code highlight] ], }) ``` ### 컴포넌트를 한번 사용해볼까요? ```sh npx @seed-design/cli@latest add action-button ``` file: getting-started/installation/webpack.mdx # Webpack Webpack 프로젝트에서 Seed Design을 설치하고 사용하는 방법을 알아봅니다. *** title: Webpack description: Webpack 프로젝트에서 Seed Design을 설치하고 사용하는 방법을 알아봅니다. ------------------------------------------------------------- ### 의존성 설치 필요한 의존성들을 설치해요. npm pnpm yarn bun ```bash npm install @seed-design/react @seed-design/css @seed-design/webpack-plugin ``` ```bash pnpm add @seed-design/react @seed-design/css @seed-design/webpack-plugin ``` ```bash yarn add @seed-design/react @seed-design/css @seed-design/webpack-plugin ``` ```bash bun add @seed-design/react @seed-design/css @seed-design/webpack-plugin ``` ### base.css import하기 ```ts title="index.tsx" import "@seed-design/css/base.css"; ``` ### webpack config 설정하기 ```ts title="vite.config.ts" +import { SeedDesignPlugin } from '@seed-design/webpack-plugin'; export default defineConfig({ plugins: [ + new SeedDesignPlugin() ] }) ``` ### seed-design.json 생성하기 ### init 명령어 입력하기 ```sh npx @seed-design/cli@latest init ``` ### seed-design 설정 ```sh ◇ TypeScript를 사용중이신가요? │ Yes │ ◇ React Server Components를 사용중이신가요? │ No │ ◇ seed-design 폴더 경로를 입력해주세요. (기본값은 프로젝트 루트에 생성됩니다.) │ ./seed-design ``` 아래 파일을 프로젝트 루트에 생성해주세요. ```json title="seed-design.json" { "rsc": false, "tsx": true, "path": "./seed-design" } ``` ### 컴포넌트를 한번 사용해볼까요? ```sh npx @seed-design/cli@latest add action-button ``` ### tsconfig.json 설정하기 ```json title="tsconfig.json" { "compilerOptions": { // your options "paths": { // [!code highlight] "seed-design/ui/*": [ // [!code highlight] "./seed-design/ui/*" // [!code highlight] ] // [!code highlight] } // [!code highlight] } } ``` file: migration/guide.mdx # Guide Seed Design V2에서 V3로 마이그레이션하기 위해 필요한 작업들을 안내합니다. *** title: Guide description: Seed Design V2에서 V3로 마이그레이션하기 위해 필요한 작업들을 안내합니다. ------------------------------------------------------------- ## 마이그레이션 개요 V2에서 V3로 넘어가기 위해서는 크게 아래와 같은 순서로 진행됩니다. 1. 이전 버전 용례 분석 2. V3 설치 3. 파운데이션 마이그레이션 (일괄 적용 권장) 4. 컴포넌트 마이그레이션 (화면별로 적용 권장 및 점진적 적용 가능) 기본적으로 파운데이션까지는 프로젝트 전체에 일괄 교체를 진행합니다. 컴포넌트는 그 이후에 화면별로 적용하거나, 컴포넌트 별로 적용하는 것과 같이 점진적 적용이 가능합니다. ## V3 설치 V3를 사용하기 위한 기반 작업들을 먼저 진행합니다. 아래 작업들이 끝나면 V3 사용이 가능합니다. ### 의존성 설치 필요한 의존성들을 설치해요. npm pnpm yarn bun ```bash npm install @seed-design/react @seed-design/css ``` ```bash pnpm add @seed-design/react @seed-design/css ``` ```bash yarn add @seed-design/react @seed-design/css ``` ```bash bun add @seed-design/react @seed-design/css ``` * `@seed-design/react`는 리액트 컴포넌트 라이브러리가 전부 포함되어 있습니다. * 기존 `sprout` 패키지들을 대체합니다. * 컴포넌트 마이그레이션 전까지는 기존 패키지들을 사용해주세요. * `@seed-design/css`는 스타일 관련된 모든 것이 포함되어 있습니다. (vars, theming, recipe, css, etc.) * 기존 `@seed-design/stylesheet` 라이브러리를 대체합니다. * 기존 `@seed-design/design-token` 라이브러리를 대체합니다. * 파운데이션 마이그레이션 전까지는 기존 패키지들을 사용해주세요. {/* ----------------------------------------------------------------------- */} {/* ----------------------------------------------------------------------- */} ### CSS import V2 `@seed-design/stylesheet` 패키지의 `global.css`와 상호운용이 가능합니다. 번들러 플러그인([webpack](https://github.com/daangn/seed-design/tree/dev/packages/webpack-plugin), [vite](https://github.com/daangn/seed-design/tree/dev/packages/vite-plugin), [rsbuild](https://github.com/daangn/seed-design/tree/dev/packages/rsbuild-plugin))을 사용하는 경우에는 `all.css` 대신 `base.css`를 사용해주세요. ```ts title="index.tsx" import "@seed-design/css/all.css"; // [!code ++] ``` V3 스타일시트 사용법은 [Installation의 css import](/react/getting-started/installation/manual#allcss-import하기) 설명을 참고해주세요. ### Theme 적용 #### 변경사항 기존 V2에서 사용되던 data-attribute가 바뀌었습니다. ```html ``` * `data-seed`: Seed Design 전역 테마 적용 (V3에서 그대로 유지) * `data-seed-color-mode`: Seed Design 테마 강제 적용 * `light-only`, `dark-only`, `system` 중 하나를 선택할 수 있습니다. * `data-seed-user-color-scheme`: 유저 기기의 설정 * `light`, `dark` 중 하나의 값을 가집니다. * v2에서 `data-seed-scale-color` 속성을 사용하던 코드가 있다면 `data-seed-user-color-scheme` 속성으로 변경해주세요. 해당 속성들을 직접 적용하는 방법도 있지만 `플러그인 적용` 방식을 권장합니다. 지원되지 않는 번들러를 사용하는 경우 직접 `스크립트 적용` 방식을 사용해서 적용해주세요. #### 플러그인 적용 Vite, Rsbuild, Webpack 등의 번들러를 사용하는 프로젝트에서는 플러그인을 추가하면 바로 Theming을 적용할 수 있습니다. Vite 사용 시 * [@seed-design/vite-plugin](https://github.com/daangn/seed-design/tree/dev/packages/vite-plugin) npm pnpm yarn bun ```bash npm install @seed-design/vite-plugin ``` ```bash pnpm add @seed-design/vite-plugin ``` ```bash yarn add @seed-design/vite-plugin ``` ```bash bun add @seed-design/vite-plugin ``` Rsbuild 사용 시 * [@seed-design/rsbuild-plugin](https://github.com/daangn/seed-design/tree/dev/packages/rsbuild-plugin) npm pnpm yarn bun ```bash npm install @seed-design/rsbuild-plugin ``` ```bash pnpm add @seed-design/rsbuild-plugin ``` ```bash yarn add @seed-design/rsbuild-plugin ``` ```bash bun add @seed-design/rsbuild-plugin ``` Webpack 사용 시 * [@seed-design/webpack-plugin](https://github.com/daangn/seed-design/tree/dev/packages/webpack-plugin) npm pnpm yarn bun ```bash npm install @seed-design/webpack-plugin ``` ```bash pnpm add @seed-design/webpack-plugin ``` ```bash yarn add @seed-design/webpack-plugin ``` ```bash bun add @seed-design/webpack-plugin ``` #### 스크립트 적용 `@seed-design/css/theming` 패키지에서 제공하는 `generateThemingScript` 함수를 사용해서 스크립트를 생성해요. ```ts title="index.tsx" import { generateThemingScript } from "@seed-design/css/theming"; ``` 생성된 스크립트를 직접 적용해주세요. ```html ``` 혹은 직접 스크립트를 작성하실 수도 있습니다. ```html ``` ## 파운데이션 마이그레이션 파운데이션 마이그레이션에는 크게 `Color`와 `Typography` 두 가지에 대해서 작업이 필요합니다. ### 용례 분석하기 우선 현재 프로젝트에서 `@seed-design/design-token` 패키지를 사용하는 용례를 분석해야합니다. * `@seed-design/design-token` 패키지의 vars를 사용하는 용례 * `@seed-design/design-token` 패키지의 vars를 확장해서 사용하는 컴포넌트 * 위 컴포넌트를 사용중인 코드 용례 * `@seed-design/stylesheet` 패키지를 사용하는 용례 * `--seed-` prefix로 시작하는 CSS Variable을 사용하는 용례 * 사용중인 CSS 라이브러리와 `@seed-design/design-token` 패키지와 결합해서 사용하는 용례 아래의 프롬프트를 이용해서 현재 프로젝트에서 사용중인 용례를 분석할 수도 있습니다. ```text title="prompt" Seed Design System의 디자인 토큰을 새로운 토큰으로 마이그레이션 할건데 코드 어디 부분들을 변경해야 하는지 보고서를 써줘. 1. `@seed-design/design-token` 패키지의 vars 변수를 사용하는 용례 2. `@seed-design/design-token` 패키지의 vars 변수를 확장해서 사용하는 컴포넌트 3. 2번 컴포넌트를 사용중인 코드 용례 4. `@seed-design/styleesheet` 패키지를 사용하는 용례 5. `--seed-` prefix로 시작하는 CSS Variable을 사용하는 용례 6. 사용중인 CSS 라이브러리와 `@seed-design/design-token` 패키지와 결합해서 사용하는 용례 위와 같은 사례들말고도 네가 더 분석해서 추가적으로 마이그레이션 해야하는 부분들도 알려줘. ``` ### 마이그레이션 전략 * 만약 여러 패키지를 사용하는 경우에는 공통 패키지 먼저 마이그레이션 합니다. * 전처리해서 사용하는 경우에는 전처리 코드 자체를 V3로 마이그레이션 한 후 나머지 코드들을 Codemod로 마이그레이션 하는게 좋습니다. * Color와 Typography 각각 진행해도 되지만, Color와 Typography 마이그레이션을 동시에 진행 후 한번에 QA를 진행하는게 더 간결합니다. ### Typography Preset 많은 프로젝트에서 기존 타이포그래피 토큰을 이용해서 유틸리티 함수를 만들어서 사용하는 경우가 있습니다. 이런 경우에는 아래의 코드를 참고해서 전처리를 진행 후 코드들을 그에 맞게 변경해주세요. * [replace-custom-seed-design-typography](https://seed-design.io/react/developer-tools/codemods/available-transforms#replace-custom-seed-design-typography) 커스텀 transform을 사용해서 마이그레이션 할 수 있습니다. ```ts title="typography.ts" import type { TextVariant } from '@seed-design/css/recipes/text'; import { vars as typographyVars } from '@seed-design/css/vars/component/typography'; /** * @see https://seed-design.io/docs/foundation/typography/overview * @example * typography.t1Bold * typography.t2Regular * typography.t3Bold * typography.t4Regular * typography.t5Bold * typography.t6Bold * typography.t7Bold * typography.screenTitle * ... */ export const typography = Object.entries(typographyVars).reduce( (acc, [key, value]) => { const withoutPrefix = key.replace('textStyle', ''); const firstChar = withoutPrefix.charAt(0).toLowerCase(); const restOfString = withoutPrefix.slice(1); const name = (firstChar + restOfString) as TextVariant['textStyle']; acc[name] = value.enabled.root; return acc; }, {} as Record< TextVariant['textStyle'], { fontSize: string; fontWeight: string; lineHeight: string; } >, ); ``` ### Codemod 기본적으로 마이그레이션은 [Codemod](/react/developer-tools/codemods/introduction)를 이용해 진행합니다. npm pnpm yarn bun ```bash npx @seed-design/codemod@latest <옵션> ``` ```bash pnpm dlx @seed-design/codemod@latest <옵션> ``` ```bash yarn dlx @seed-design/codemod@latest <옵션> ``` ```bash bun x @seed-design/codemod@latest <옵션> ``` * Codemod는 기본적으로 `color`와 `typography` transform을 분리해서 제공합니다. * 현재는 Tailwind CSS, Stitches 혹은 Emotion, Vanilla Extract CSS와 같은 CSS-in-JS 라이브러리에 대한 transform을 제공합니다. * 각팀에서 커스텀으로 제공되는 transform의 경우에는 `replace-custom-`의 prefix로 제공됩니다. * 커스텀 transform의 변경 예시를 살펴보고 프로젝트와 상황이 같다면 사용할 수 있습니다. * 추가로 특정 라이브러리의 transform이 필요하거나, 필요한 경우 커스텀 transform을 만들 수 있습니다. (디자인코어 팀에 문의) #### Tailwind CSS * Tailwind V3 플러그인을 제공합니다. * [@seed-design/tailwind3-plugin](https://github.com/daangn/seed-design/tree/dev/packages/tailwind3-plugin) * [@seed-design/tailwind4-theme](https://github.com/daangn/seed-design/tree/dev/packages/tailwind4-theme) * Tailwind transform은 [replace-tailwind-typography](/react/developer-tools/codemods/available-transforms#replace-tailwind-typography), [replace-tailwind-color](/react/developer-tools/codemods/available-transforms#replace-tailwind-color) 두 개가 제공됩니다. * Tailwind 같은 경우는 각 프로젝트에서 커스텀 플러그인을 작성해서 사용중인 경우가 많기 때문에 Codemod가 정확하게 맞지 않을 수 있습니다. * Codemod 페이지에서 변경 예시를 살펴보고 프로젝트와 상황이 같다면 사용할 수 있습니다. * 예시와 맞지 않다면 디자인코어팀에 문의해주세요. #### Stitches CSS * Stitches는 [replace-stitches-styled-typography](/react/developer-tools/codemods/available-transforms#replace-stitches-styled-typography), [replace-stitches-styled-color](/react/developer-tools/codemods/available-transforms#replace-stitches-styled-color), [replace-stitches-theme-color](/react/developer-tools/codemods/available-transforms#replace-stitches-theme-color) 의 형태로 제공합니다. * 자세한 내용은 [Codemod](/react/developer-tools/codemods/introduction) 페이지를 참고해주세요. #### Emotion, Vanilla Extract CSS, (CSS-in-JS) * Emotion, Vanilla Extract CSS와 같은 CSS-in-JS 라이브러리는 `@seed-design/design-token`을 사용하는 경우가 대부분입니다. * [replace-seed-design-token-vars](/react/developer-tools/codemods/available-transforms#replace-seed-design-token-vars) transform을 사용해서 일괄적으로 마이그레이션 할 수 있습니다. * 해당 transform은 `color`와 `typography` 두 개 동시에 변경합니다. #### Native CSS * 기본적으로 `--seed-` prefix가 붙은 CSS Variable을 사용하는 경우가 있습니다. * [replace-css-seed-design-color-variable](/react/developer-tools/codemods/available-transforms#replace-css-seed-design-color-variable) CSS transform도 제공합니다. ### Codemod 사용 시 주의사항 Codemod는 다수의 파일을 변경하기 때문에 주의가 필요합니다. * 변경사항 추적과 히스토리 관리를 위해서 별도의 브랜치를 사용할 것을 권장합니다. * transform에 따라 커밋을 나누는 것을 권장합니다. * Codemod 실행 후 `lint`와 `test`를 진행해주세요. ### Codemod Log 파일 Codemod 실행 시 디버깅에 도움을 주는 로그 파일을 생성할 수 있습니다. * `--log` 옵션을 추가해주세요. * 로그 파일은 Codemod 실행 경로에 `.report` 폴더에 생성됩니다. * 로그 파일은 변경사항을 추적하고 히스토리 관리에 도움을 줍니다. #### debug.log * 디버깅 정보를 기록합니다. * 변경 시도한 파일 경로와 시간을 기록합니다. ```log title="debug.log" 2025-03-28 19:17:36 [DEBUG]: Starting transformation of /Project/src/component1.tsx 2025-03-28 19:17:36 [DEBUG]: Starting transformation of /Project/src/component2.tsx 2025-03-28 19:17:36 [DEBUG]: Starting transformation of /Project/src/component3.tsx 2025-03-28 19:17:36 [DEBUG]: Starting transformation of /Project/src/component4.tsx ``` #### issues.log * 확인이 필요한 변경사항을 기록합니다. * 문제가 있는 파일 경로와 라인 번호를 기록합니다. * 문제가 있는 이유를 기록합니다. * 매핑이 없는 경우를 제외하고는 이미 변경된 상태입니다. ```log title="issues.log" 2025-03-28 18:46:55 [WARN]: /Project/src/component1.tsx (line: 171) ↳ reason: $gray900-static static에서 palette로 변경되는 색상으로 용도 파악 필요 2025-03-28 18:46:55 [WARN]: /Project/src/component2.tsx (line: 194) ↳ reason: $gray900-static static에서 palette로 변경되는 색상으로 용도 파악 필요 2025-03-28 18:46:55 [WARN]: /Project/src/component3.tsx (line: 147) ↳ reason: $gray900-static static에서 palette로 변경되는 색상으로 용도 파악 필요 2025-03-28 18:46:56 [WARN]: /Project/src/component4.tsx (line: 242) ↳ reason: $gray900-static static에서 palette로 변경되는 색상으로 용도 파악 필요 ``` 자주 발생하는 문제들은 제일 아래 [issues.log 파일에 생긴 문제들은 어떻게 해결해야 하나요?](#issueslog-파일에-생긴-문제들은-어떻게-해결해야-하나요)에 정리해두었습니다. #### success.log * 변경사항 추적에 도움을 줍니다. * 변경된 파일 경로와 라인 번호를 기록합니다 * 변경된 토큰을 기록합니다. * CSS 파일을 변경하는 transform의 경우는 토큰을 일일이 기록하지 않습니다. * tailwind 같은 경우는 변경된 className을 기록합니다. ```log title="success.log" 2025-03-28 18:46:54 /Project/src/hooks/hook1.tsx (line: 149): $gray900 → $palette-gray-1000 (line 149) 2025-03-28 18:46:54 /Project/src/hooks/hook2.tsx (line: 155): $gray700 → $palette-gray-800 (line 155) 2025-03-28 18:46:54 /Project/src/components/component1.tsx (line: 54): $divider1-semantic → $stroke-neutral-muted (line 54) 2025-03-28 18:46:54 /Project/src/components/component2.tsx (line: 60): $paperDefault-semantic → $bg-layer-default (line 60) ``` ### V2 V3 Compatibility Color, Typography 마이그레이션이 끝나고 나면 기존 Sprout (V2) 컴포넌트와의 호환성 문제가 있을 수 있습니다. Sprout 내부에 V2 토큰을 V3 토큰으로 전부 교체한 Compatibility 버전을 제공합니다. 여기까지 진행해야 파운데이션 마이그레이션이 끝난 것으로 간주할 수 있습니다. [Sprout Compatibility 버전](https://github.com/daangn/sprout/pkgs/npm/sprout-components-button) 페이지에서 `-v3-compat` 태그가 붙은 버전중에 최신 버전으로 모든 컴포넌트를 전부 교체해주시면 됩니다. (모든 컴포넌트 동일한 버전을 제공합니다.) 주의할 점: 너무 예전의 버전을 사용하는 경우 컴포넌트 내부에서 breaking changes가 있을 수 있습니다. V2 V3 Compatibility 버전까지 설치가 되었다면 파운데이션 마이그레이션이 끝난 것으로 간주할 수 있습니다. 이론상 이때부터는 `@seed-design/design-token` 패키지와 `@seed-design/stylesheet` 패키지를 제거할 수 있습니다. 또한 V3 컴포넌트를 점진적 사용이 가능합니다. ### V3 Compat Script 제거 ```html ``` 기존에 25.10.0 앱버전 이상에서 V2 백그라운드 색상을 V3로 변경하기 위해 추가했던 스크립트는 마이그레이션이 끝나고 제거해도 됩니다. ## 컴포넌트 마이그레이션 TBD ## 자주 묻는 질문 ### issues.log 파일에 생긴 문제들은 어떻게 해결해야 하나요? #### 토큰 매핑이 안되는 경우 (컬러, 타이포그래피) * V3에서 지원하지 않는 토큰을 사용하는 경우입니다. (주로 alpha 색상 토큰이거나 너무 작거나 큰 타이포 토큰입니다.) * 토큰 매핑을 확인할 수 있는 방법은 [설명](#파운데이션-토큰-매핑은-어디서-확인할-수-있나요)을 참고해주세요. * 해당 경우는 디자이너분과 상의 후 다른 적절한 토큰으로 직접 매핑해주세요. * 결정에 어려움이 있는 경우 디자인코어팀에 문의해주세요. #### alpha 토큰이 사라진 경우 (컬러) * alpha가 들어간 토큰은 대부분의 경우 더 이상 사용되지 않습니다. * 직접 CSS에 `alpha` 채널을 적용해주세요. (opacity 속성을 사용하거나, rgba 형식으로 직접 적용) #### static 토큰이 palette로 변경된 경우 (컬러) * V3에서 static 컬러 토큰은 웬만해서는 `white`, `black` 두 가지만 지원합니다. * 나머지 색상 (yellow, green, blue, red, gray) 등은 palette 토큰으로 변경되었습니다. * 다크모드와 라이트모드에 따라 색상이 달라질 수 있기 때문에 확인이 필요합니다. * 배경은 변하는데 텍스트 색상이 변하지 않거나, 그 반대의 상황이 나올 수 있습니다. * 대부분의 경우는 static 토큰이 필요한 경우가 아니기 때문에 palette 토큰으로 변경되었습니다. * 이 경우는 디자이너분과 상의 후 기존 static 토큰을 다른 적절한 palette 토큰으로 직접 매핑해주세요. #### 선택지가 두개인 토큰으로 매핑된 경우 (컬러) * 컬러 토큰의 경우 대체 토큰이 두 가지인 경우가 있습니다. (ex. `primary` -> `bg.brand-solid`, `fg.brand`) * `fg`는 텍스트, 아이콘 등 UI의 전경 요소에 사용되는 색상입니다. (color, fill, etc.) * `bg`는 전체 화면 또는 UI의 배경에 사용하는 색상입니다. (backgroundColor, etc.) * 변경되어야 하는 토큰을 Codemod가 판단하기 어려울 수 있습니다. * 이 경우는 직접 적절한 토큰으로 매핑해주세요. #### alternate 토큰으로 변경된 경우 (타이포그래피) * 기본적으로 [Mapping](/docs/migration/migration-reference)은 1:1 매핑을 지원합니다. * 하지만 V3에서 Deprecated 된 토큰인 경우, 대체 토큰으로 매핑 될 수 있습니다. * 그런 경우 font size나 line height가 변경되었을 수 있습니다. * 이 경우는 직접 UI를 확인해야 합니다. ### 파운데이션 토큰 매핑은 어디서 확인할 수 있나요? [Migration Reference](/docs/migration/migration-reference)에서 토큰 매핑을 확인할 수 있습니다. ## Known Issues ### Vanilla Extract CSS + Vite + V3 사용시 * `@vanilla-extract/vite-plugin`와 `@seed-design/vite-plugin`을 같이 사용하는 경우 빌드가 실패할 수 있습니다. * `@vanilla-extract/vite-plugin`의 버전을 `5` 이상으로 업그레이드 해주세요. file: migration/migrating-icons.mdx # Migrating Icons SEED V2 아이콘을 V3 아이콘으로 쉽게 마이그레이션해요. *** title: Migrating Icons description: SEED V2 아이콘을 V3 아이콘으로 쉽게 마이그레이션해요. ----------------------------------------------- import { Terminal } from "lucide-react"; ## 업그레이드 방법 현재 아이콘을 사용하고 있는 방법에 따라 적용할 수 있는 2가지 방법이 있어요. ### Codemod 스크립트 아래 3개 아이콘 패키지를 사용하고 있다면, 제공되는 codemod 스크립트를 사용해서 리뉴얼된 아이콘 패키지로 손쉽게 업그레이드할 수 있어요. * [`@seed-deesign/react-icon`](https://www.npmjs.com/package/@seed-design/react-icon) * [`@seed-design/icon`](https://www.npmjs.com/package/@seed-design/icon) (deprecated) * [`@karrotmarket/karrot-ui-icon`](https://www.npmjs.com/package/@karrotmarket/karrot-ui-icon) (deprecated) (React 컴포넌트를 사용하는 경우) 3개 패키지에서 사용하고 있는 아이콘은 [`@karrotmarket/react-monochrome-icon`](https://github.com/daangn/seed-icon-v3/pkgs/npm/react-monochrome-icon)의 아이콘으로 대체돼요. ### 수동 업그레이드 다음과 같은 경우에는 수동으로 업그레이드해야 해요. * PNG, SVG 등의 파일로 기존 아이콘을 사용하는 경우 * [`@karrotmarket/karrot-ui-icon`](https://www.npmjs.com/package/@karrotmarket/karrot-ui-icon) (deprecated)에서 제공되는 SVG 파일을 사용하는 경우 * 다음 패키지를 사용하는 경우 * [`@seed-design/vue2-icon`](https://www.npmjs.com/package/@seed-design/vue2-icon) → [`@daangn/vue2-monochrome-icon`](https://github.com/daangn/seed-icon-v3/pkgs/npm/vue2-monochrome-icon)으로 대체돼요. * [`@seed-design/vue3-icon`](https://www.npmjs.com/package/@seed-design/vue3-icon) → [`@daangn/vue3-monochrome-icon`](https://github.com/daangn/seed-icon-v3/pkgs/npm/vue3-monochrome-icon)으로 대체돼요. ## 작업 순서 많은 변경사항이 발생하게 되므로, 커밋하지 않은 변경사항이 없는지 확인하고 시작하는 것이 좋아요. ### Codemod 스크립트 #### 리뉴얼된 아이콘 패키지 설치 npm pnpm yarn bun ```bash npm install @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash pnpm add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash yarn add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash bun add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` 2개 패키지 중 필요한 패키지만 설치해요. * [`@karrotmarket/react-monochrome-icon`](https://github.com/daangn/seed-icon-v3/pkgs/npm/react-monochrome-icon) * 단색 아이콘 패키지에요. **일반** 아이콘, **카테고리** 아이콘, **서비스** 아이콘이 포함되어 있어요. * 이 패키지에서 제공되는 서비스 아이콘은 검은색으로만 사용할 수 있어요. * codemod 실행 시, 기존 패키지들의 아이콘은 모두 이 패키지의 아이콘으로 대체돼요. * [`@karrotmarket/react-multicolor-icon`](https://github.com/daangn/seed-icon-v3/pkgs/npm/react-multicolor-icon) * 멀티컬러 아이콘 패키지에요. **카테고리** 아이콘과 **서비스** 아이콘이 포함되어 있어요. * 이 패키지에서 제공되는 카테고리 아이콘과 서비스 아이콘은 패키지에서 제공되는 색상 그대로만 사용할 수 있어요. * 기존에 SVG로 사용하던 멀티컬러 아이콘들을 이 패키지로 직접 대체할 수 있어요. 따라서, 필요한 경우에만 설치해도 좋아요. #### Codemod 스크립트 실행 `replace-react-icon` transform을 실행해요. ```shell npx @seed-design/codemod@latest replace-react-icon ``` }> 해당 transform에 대해 자세히 알아봅니다. #### 결과 확인 문제 없이 모든 변환이 완료된 경우 다음과 같은 결과가 표시돼요. ``` All done. Results: 0 errors // [!code highlight] 439 unmodified 1 skipped 27 ok Time elapsed: 43.376seconds ``` * `errors`: 파싱 오류 등으로 인해, 아이콘을 참조하는 코드가 있는지 확인하지 못한 파일의 수에요. * 에러가 발생한 파일에 이전 아이콘을 참조하는 코드가 없다면, 해당 파일에서 발생하는 에러는 무시해도 좋아요. * 이전 아이콘을 참조하는 코드가 있다면, 문제가 발생한 부분을 수정하고 다시 스크립트를 실행하거나, 해당 파일의 아이콘 마이그레이션을 직접 진행해주세요. * `unmodified`: 아이콘을 참조하는 코드가 없어, 아무 변환도 이루어지지 않은 파일의 수에요. * `skipped`: 빈 파일 등 변환 대상이 아니어서, 아무 변환도 이루어지지 않은 파일의 수에요. * `ok`: 변환이 이루어진 파일의 수에요. ``` ERR /Users/seed/foo/bar.js Transformation error (Unexpected reserved word 'package'. (3:3)) ``` codemod 스크립트 실행 중 파싱 오류가 발생할 수 있어요. 파싱 오류는 다음과 같은 이유로 발생해요. * `assert`를 사용한 [import assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html#import-attributes)과 같은, deprecated된 문법이 있는 경우 * `package`와 같은 예약어를 변수 이름으로 사용한 경우 등 #### 코드 포맷 프로젝트에서 사용하는 포매터를 사용해서 코드를 포맷해요. #### 이전 패키지 제거 이전 아이콘이 모두 대체된 것을 확인하고, 이전 패키지를 제거해요. npm pnpm yarn bun ```bash npm uninstall @seed-design/icon @seed-design/react-icon @karrotmarket/karrot-ui-icon ``` ```bash pnpm remove @seed-design/icon @seed-design/react-icon @karrotmarket/karrot-ui-icon ``` ```bash yarn remove @seed-design/icon @seed-design/react-icon @karrotmarket/karrot-ui-icon ``` ```bash bun remove @seed-design/icon @seed-design/react-icon @karrotmarket/karrot-ui-icon ``` #### 사이드 이펙트 확인 * [사이드 이펙트](#발생-가능한-사이드-이펙트)가 발생했는지 확인하여 의도한 대로 변경이 이루어졌는지 검토해요. * 디자인 QA 과정에서, 자동으로 변경된 아이콘이 아닌 새로운 아이콘을 사용하도록 결정되었을 수 있어요. 이러한 경우, Figma 디자인 파일을 참고하여 코드에 반영해요. * 멀티컬러 아이콘 사용이 필요한 곳에는 [멀티컬러 아이콘 패키지](https://github.com/daangn/seed-icon-v3/pkgs/npm/react-multicolor-icon)를 사용해주세요. ### 수동 업그레이드 #### 이전 패키지 제거 이전 아이콘 패키지들을 제거해요. npm pnpm yarn bun ```bash npm uninstall @seed-design/icon @seed-design/react-icon @karrotmarket/karrot-ui-icon @seed-design/vue2-icon @seed-design/vue3-icon ``` ```bash pnpm remove @seed-design/icon @seed-design/react-icon @karrotmarket/karrot-ui-icon @seed-design/vue2-icon @seed-design/vue3-icon ``` ```bash yarn remove @seed-design/icon @seed-design/react-icon @karrotmarket/karrot-ui-icon @seed-design/vue2-icon @seed-design/vue3-icon ``` ```bash bun remove @seed-design/icon @seed-design/react-icon @karrotmarket/karrot-ui-icon @seed-design/vue2-icon @seed-design/vue3-icon ``` #### 리뉴얼된 패키지 설치 ##### React npm pnpm yarn bun ```bash npm install @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash pnpm add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash yarn add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ```bash bun add @karrotmarket/react-monochrome-icon @karrotmarket/react-multicolor-icon ``` ##### Vue 2 npm pnpm yarn bun ```bash npm install @daangn/vue2-monochrome-icon @daangn/vue2-multicolor-icon ``` ```bash pnpm add @daangn/vue2-monochrome-icon @daangn/vue2-multicolor-icon ``` ```bash yarn add @daangn/vue2-monochrome-icon @daangn/vue2-multicolor-icon ``` ```bash bun add @daangn/vue2-monochrome-icon @daangn/vue2-multicolor-icon ``` ##### Vue 3 npm pnpm yarn bun ```bash npm install @daangn/vue3-monochrome-icon @daangn/vue3-multicolor-icon ``` ```bash pnpm add @daangn/vue3-monochrome-icon @daangn/vue3-multicolor-icon ``` ```bash yarn add @daangn/vue3-monochrome-icon @daangn/vue3-multicolor-icon ``` ```bash bun add @daangn/vue3-monochrome-icon @daangn/vue3-multicolor-icon ``` 2개 패키지 중 필요한 패키지만 설치해요. * `@daangn/*-monochrome-icon` * 단색 아이콘 패키지에요. **일반** 아이콘, **카테고리** 아이콘, **서비스** 아이콘이 포함되어 있어요. * 이 패키지에서 제공되는 서비스 아이콘은 검은색으로만 사용할 수 있어요. * codemod 실행 시, 기존 패키지들의 아이콘은 모두 이 패키지의 아이콘으로 대체돼요. * `@daangn/*-multicolor-icon` * 멀티컬러 아이콘 패키지에요. **카테고리** 아이콘과 **서비스** 아이콘이 포함되어 있어요. * 이 패키지에서 제공되는 카테고리 아이콘과 서비스 아이콘은 패키지에서 제공되는 색상 그대로만 사용할 수 있어요. * 기존에 SVG로 사용하던 멀티컬러 아이콘들을 이 패키지로 직접 대체할 수 있어요. 따라서, 필요한 경우에만 설치해도 좋아요. #### 아이콘 이름 변경 [V2 V3 아이콘 맵핑](/docs/migration/migration-reference#iconography) 문서를 참고하여 리뉴얼된 패키지를 사용하도록 코드를 수정해요. * 기존 아이콘의 `IconHome*`은 신규 아이콘에서 `IconHouse*`로 이름이 바뀌었어요. * 기존 아이콘의 `IconHouse*`는 신규 아이콘에서 `IconWindow4House*`로 이름이 바뀌었어요. 따라서, 수동 마이그레이션 시 `IconHome*`이 `IconWindow4House*`로 잘못 변경되지 않게 주의해야 해요. **`IconHouse*`를 먼저 마이그레이션**하고, `IconHome*`을 마이그레이션하는 것을 추천해요. #### 사이드 이펙트 확인 * [사이드 이펙트](#발생-가능한-사이드-이펙트)가 발생했는지 확인하여 의도한 대로 변경이 이루어졌는지 검토해요. * 디자인 QA 과정에서, [V2 V3 아이콘 맵핑](/docs/migration/migration-reference#iconography)에 따른 아이콘이 아닌 새로운 아이콘을 사용하도록 결정되었을 수 있어요. 이러한 경우, Figma 디자인 파일을 참고하여 코드에 반영해요. * 멀티컬러 아이콘 사용이 필요한 곳에는 [멀티컬러 아이콘 패키지](https://github.com/daangn/seed-icon-v3/pkgs/npm/react-multicolor-icon)를 사용해주세요. ## 발생 가능한 사이드 이펙트 ### 정확히 대응되는 리뉴얼된 아이콘이 없는 경우 * 이전 아이콘 중 아래 5개 아이콘(총 15개 variant)은 리뉴얼된 아이콘 패키지에 시각적으로 정확히 대응되는 항목이 없어요. * codemod 스크립트 실행 시 **추천되는 아이콘으로 변환되지만**, 시각적인 차이가 크기 때문에 변경 후 확인이 필요해요. | 이전 아이콘 이름 | 리뉴얼된 아이콘 이름 | | --------------------------------------- | ---------------------------------------------------------------------------------------- | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * codemod 스크립트 사용 시, 5개 아이콘(총 15개 variant)이 사용된 경우 터미널에 메시지가 출력돼요. ``` REP ...을 ...로 변경했지만, 변경된 아이콘이 적절한지 확인이 필요해요 ``` * codemod 스크립트를 `--log` flag와 함께 사용 시, 사용된 내역이 `migrate-icons-warnings.log`에 기록돼요. * 다음을 활용하여 코드를 직접 검색할 수 있어요. ```regex tab="정규 표현식" (IconBold|IconCobuying|IconDelivery|IconSuggest|IconWriteStory)(Thin|Regular|Fill)|(IconTUppercaseSerif|IconShoppingbag2Stacked|IconTruck|IconLightbulbDot5|IconHorizline2VerticalChatbubbleRight)(Line|Fill) ``` ```shell tab="git grep" git grep -E '(IconBold|IconCobuying|IconDelivery|IconSuggest|IconWriteStory)(Thin|Regular|Fill)|(IconTUppercaseSerif|IconShoppingbag2Stacked|IconTruck|IconLightbulbDot5|IconHorizline2VerticalChatbubbleRight)(Line|Fill)' ``` ### 여러 이전 아이콘이 하나의 리뉴얼된 아이콘으로 대체되는 경우 **이전 아이콘과 리뉴얼된 아이콘은 `n:1`로 대응돼요.** 따라서, 같은 페이지에 표시되었던 서로 다른 여러 개의 아이콘이, 동일한 리뉴얼된 아이콘으로 대체되는 경우가 있어요. 의도한 목적대로 아이콘이 표시되는지 확인해요. * 한 이전 아이콘의 3개 variant 중 `Thin` variant와 `Regular` variant는 리뉴얼된 아이콘에서 모두 `Line` variant로 대체돼요. * 예를 들면, `IconForwardThin`, `IconForwardRegular`는 모두 [`IconArrowRightLine`](/docs/foundation/iconography/library?icon=icon_arrow_right_line)으로 대체돼요. * 이전 아이콘의 `Fill` variant는 리뉴얼된 아이콘에서도 `Fill` variant로 대체돼요. * 여러 개의 이전 아이콘이 하나의 리뉴얼된 아이콘으로 대체되는 경우도 있어요. * 예를 들면, `IconHeadphoneRegular`, `IconHelpcenterRegular`, `IconHelperRegular`는 모두 [`IconHeadsetLine`](/docs/foundation/iconography/library?icon=icon_headset_line)으로 대체돼요. file: updates/changelog.mdx # Changelog 최신 업데이트와 변경사항을 기록합니다. *** title: Changelog description: 최신 업데이트와 변경사항을 기록합니다. ---------------------------------- ## 2025.09.12 [`afdd1ee`](https://github.com/daangn/seed-design/commit/afdd1ee825168fbf76bd5a7b718d982cda36bcc9) Figma Codegen을 위한 컴포넌트 핸들러를 업데이트합니다. * List, Checkmark, RadioMark, Radio, Tabs, ChipTabs 지원 * Chip, Divider, HelpBubble, Switch, Checkbox 업데이트 [`8ebe8a5`](https://github.com/daangn/seed-design/commit/8ebe8a57d6ca64ec862e918d9be30dca94ec6643) Switch, Checkmark, Radio Mark의 스타일을 업데이트합니다. * tone=neutral variant를 추가합니다. * Switch의 thumb 크기를 조정합니다. Checkbox와 Radio의 weight variant를 default, stronger에서 regular, bold로 수정합니다. [`f61b80d`](https://github.com/daangn/seed-design/commit/f61b80d31f71524d29233b501be609350e5d3528) 다크 모드에서의 색상 대비 보장을 위해 시맨틱 색상을 수정하고 컴포넌트에서의 색상을 변경합니다. * **$color.bg.warning-solid**: theme-dark에서 $color.palette.yellow-600 → $color.palette.yellow-800 * **$color.bg.warning-solid-pressed**: theme-dark에서 $color.palette.yellow-700 → $color.palette.yellow-900 * Badge, Page Banner의 tone=warning, variant=solid variant에서 전경 항목 색상 변경: $color.fg.neutral → $color.palette.static-black-alpha-900 [`ce047f5`](https://github.com/daangn/seed-design/commit/ce047f502d9ccff5cb48e94de47bfa0c5b60d29f) Tabs.Carousel의 reInit 이벤트 시 탭 인덱스가 변경되지 않는 문제를 수정합니다. ### Version Updates * [@seed-design/css@0.2.4](https://npmjs.com/package/@seed-design/css/v/0.2.4) * [@seed-design/figma@0.2.4](https://npmjs.com/package/@seed-design/figma/v/0.2.4) * [@seed-design/react@0.2.4](https://npmjs.com/package/@seed-design/react/v/0.2.4) * [@seed-design/react-tabs@0.0.9](https://npmjs.com/package/@seed-design/react-tabs/v/0.0.9) * [@seed-design/rootage-artifacts@0.1.3](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.1.3) ## 2025.09.08 [`a22b8b9`](https://github.com/daangn/seed-design/commit/a22b8b9b21e0072220b78c604f17b86c06251b45) ChipTabs 컴포넌트 Variant, Size 변경 및 디자인 수정 * variant `neutralOutline` 추가 * variant `brandSolid` deprecated * size(`medium(default)` | `large`) 추가 [`5836976`](https://github.com/daangn/seed-design/commit/583697689d0c1e6d6c1695411dee4c889eac5408) text-field의 value slot이 input의 size attribute로 인해 기본적으로 width를 가지는 문제를 해결합니다. [`12faf5a`](https://github.com/daangn/seed-design/commit/12faf5a50ea4fb109b90378d264e1301f0d61c29) List 컴포넌트를 추가하고, Checkbox 및 Radio 컴포넌트를 개선합니다. * List 컴포넌트를 제공하여, 정보를 구조화된 목록 형태로 표시할 수 있도록 합니다. * Checkbox와 Radio의 컨트롤 영역만을 표시하는 Checkmark와 RadioMark를 제공합니다. * Select Box에서 컨트롤 영역을 Checkmark와 RadioMark로 교체합니다. * RadioGroup 컴포넌트를 제공합니다. ### Version Updates * [@seed-design/css@0.2.3](https://npmjs.com/package/@seed-design/css/v/0.2.3) * [@seed-design/react@0.2.3](https://npmjs.com/package/@seed-design/react/v/0.2.3) * [@seed-design/rootage-artifacts@0.1.2](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.1.2) ## 2025.09.05 [`9d93518`](https://github.com/daangn/seed-design/commit/9d935189cff6c528338d9a00b103a7be5366eb18) Text 컴포넌트의 fontSize, lineHeight, color 속성에 string도 사용 가능하도록 변경했습니다. [`91952e4`](https://github.com/daangn/seed-design/commit/91952e408d31d919b6c6f1a77739b04e7164e61b) `replace-semantic-stroke-color` transform을 추가합니다. * `@seed-design/css` v0.2.0에 맞춰 `replace-semantic-stroke-color` transform을 추가합니다. * `@seed-design/css/vars`에서 사용한 stroke 토큰을 업데이트하는 마이그레이션 코드모드를 추가합니다. ### Version Updates * [@seed-design/codemod@0.0.31](https://npmjs.com/package/@seed-design/codemod/v/0.0.31) * [@seed-design/react@0.2.2](https://npmjs.com/package/@seed-design/react/v/0.2.2) ## 2025.09.04 [`35984d0`](https://github.com/daangn/seed-design/commit/35984d05ac4cd9677526152e975d3daf2c4c345d) Chip 컴포넌트를 업데이트합니다. * 아이콘에 트랜지션 효과가 적용되지 않던 현상을 수정합니다. * Button, Toggle 등 사용되는 방식에 따라 적절한 data prop을 받도록 수정합니다. [`c5bed96`](https://github.com/daangn/seed-design/commit/c5bed9674a1c036bd0c84acf9e81ebed72215b79) Divider 컴포넌트가 `$color.stroke.neutral-muted` 색상을 기본값으로 사용하도록 수정합니다. ### Version Updates * [@seed-design/css@0.2.1](https://npmjs.com/package/@seed-design/css/v/0.2.1) * [@seed-design/react@0.2.1](https://npmjs.com/package/@seed-design/react/v/0.2.1) * [@seed-design/rootage-artifacts@0.1.1](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.1.1) ## 2025.09.03 [`8448880`](https://github.com/daangn/seed-design/commit/8448880aa424edcd3af8e78a5c3ff5a0f142ae8d) 시맨틱 stroke 컬러 토큰을 업데이트합니다. **이름이 변경되는 stroke 토큰** * [Color Role 규칙](https://seed-design.io/docs/foundation/color/color-role)에 맞춰 일관적인 토큰 이름을 유지할 수 있도록 업데이트합니다. * 이름이 변경되는 stroke 토큰을 사용하고 있는 경우, 간단한 Find & Replace 마이그레이션이 필요합니다. | 기존 | 신규 | 비고 | | ------------------------------- | ------------------------------- | ------------------- | | **$color.stroke.neutral-muted** | $color.stroke.neutral-subtle | 가장 먼저 마이그레이션해야 합니다. | | $color.stroke.on-image | $color.stroke.neutral-subtle | | | $color.stroke.neutral | **$color.stroke.neutral-muted** | | | $color.stroke.field-focused | $color.stroke.neutral-contrast | | | $color.stroke.control | $color.stroke.neutral-weak | | | $color.stroke.field | $color.stroke.neutral-weak | | | $color.stroke.brand | $color.stroke.brand-weak | | | $color.stroke.positive | $color.stroke.positive-weak | | | $color.stroke.informative | $color.stroke.informative-weak | | | $color.stroke.warning | $color.stroke.warning-weak | | | $color.stroke.critical | $color.stroke.critical-weak | | **색상이 변경되는 stroke 토큰 (마이그레이션 불필요)** `$color.stroke.neutral-contrast` (이름 변경 전 `$color.stroke.field-focused`) 모든 theme mode에서 `$color.palette.gray-800` → `$color.palette.gray-1000`로 변경되었습니다. **신규 stroke 토큰 (마이그레이션 불필요)** | 신규 | | ------------------------------- | | $color.stroke.neutral-solid | | $color.stroke.brand-solid | | $color.stroke.positive-solid | | $color.stroke.informative-solid | | $color.stroke.warning-solid | | $color.stroke.critical-solid | ### Version Updates * [@seed-design/css@0.2.0](https://npmjs.com/package/@seed-design/css/v/0.2.0) * [@seed-design/migration-index@0.0.31](https://npmjs.com/package/@seed-design/migration-index/v/0.0.31) * [@seed-design/rootage-artifacts@0.2.0](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.2.0) * [@seed-design/tailwind3-plugin@0.2.0](https://npmjs.com/package/@seed-design/tailwind3-plugin/v/0.2.0) * [@seed-design/tailwind4-theme@0.2.0](https://npmjs.com/package/@seed-design/tailwind4-theme/v/0.2.0) ## 2025.08.28 [`c51a261`](https://github.com/daangn/seed-design/commit/c51a261858087bc4a7a572af52bd0ebcacc69d49) font-size, line-height 토큰에 static variant를 추가합니다. * `--seed-font-size-t1-static` \~ `--seed-font-size-t10-static` * `--seed-line-height-t1-static` \~ `--seed-line-height-t10-static` [`5f2ee39`](https://github.com/daangn/seed-design/commit/5f2ee39374372be285e6679e3aa08b822b0ef938) CSS 최적화 도구(e.g. cssnano)가 CSS variable로 정의된 longhand declaration을 병합하지 않도록 합니다. (workaround, [관련 issue](https://github.com/cssnano/cssnano/issues/1472)) [`8299ba9`](https://github.com/daangn/seed-design/commit/8299ba91f2f77ee3a226b8059d56a7c1c2317232) Snackbar 컴포넌트를 업데이트합니다. * root 영역에 maxWidth 스펙을 추가합니다. * `pauseOnInteraction`의 기본값을 `false`에서 `true`로 변경합니다. [`d497166`](https://github.com/daangn/seed-design/commit/d497166f648952a68bfef445a39f9822f2cfa44d) 플랫폼별 조건부 폰트 스케일링 제한 (iOS: 135%, Android: 150%) 적용 * CSS 변수 `--seed-{font-size|line-height}-limit-{min|max}` 도입 * 빌드 타임 basePx 계산을 런타임 static 토큰 참조로 대체 * global.ts에 폰트 스케일링 변수 통합 [`9a3c76a`](https://github.com/daangn/seed-design/commit/9a3c76a74eec244736f8bc7807d3629b4d5328c5) Divider 컴포넌트를 업데이트합니다. * `orientation`을 지정할 수 있습니다. * Divider를 `li`로 렌더링하여 `ol`, `ul` 내부에서 사용할 수 있습니다. * Divider를 `div` 또는 `li`로 렌더링하는 경우에도 `role="separator"`를 지정하여 스크린 리더가 Divider를 읽도록 할 수 있습니다. ### Version Updates * [@seed-design/css@0.1.15](https://npmjs.com/package/@seed-design/css/v/0.1.15) * [@seed-design/react@0.1.15](https://npmjs.com/package/@seed-design/react/v/0.1.15) * [@seed-design/react-snackbar@0.0.6](https://npmjs.com/package/@seed-design/react-snackbar/v/0.0.6) * [@seed-design/rootage-artifacts@0.0.6](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.0.6) * [@seed-design/tailwind3-plugin@0.1.15](https://npmjs.com/package/@seed-design/tailwind3-plugin/v/0.1.15) * [@seed-design/tailwind4-theme@0.1.15](https://npmjs.com/package/@seed-design/tailwind4-theme/v/0.1.15) ## 2025.08.22 [`f806356`](https://github.com/daangn/seed-design/commit/f806356f0ca5d419647c9672426e14ca3350f479) Page Banner 컴포넌트를 추가합니다. Inline Banner 컴포넌트를 deprecate합니다. * Inline Banner 컴포넌트 대비 모든 `tone`에서 모든 `variant`를 지원하며, 내부 Button의 충분한 터치 영역을 보장합니다. ```tsx 새 탭에서 열기 } /> ``` 시맨틱 색상 토큰을 추가하고 수정합니다. * `$color.bg.positive-solid-pressed`: theme-dark에서 `$color.palette.green-500` → `$color.palette.green-600` * `$color.bg.warning-solid-pressed` 추가 [`1982494`](https://github.com/daangn/seed-design/commit/198249432e62bcc693c469aa233fabe6a6b23532) Badge 컴포넌트를 업데이트합니다. * `tone=warning` variant를 추가합니다. * `maxWidth` 스펙을 추가합니다. 신규 시맨틱 색상 토큰을 추가합니다. * `$color.fg.warning` * `$color.stroke.warning` * `$color.fg.brand-contrast` * `$color.bg.brand-weak` * `$color.bg.brand-weak-pressed` ### Version Updates * [@seed-design/css@0.1.14](https://npmjs.com/package/@seed-design/css/v/0.1.14) * [@seed-design/figma@0.1.14](https://npmjs.com/package/@seed-design/figma/v/0.1.14) * [@seed-design/react@0.1.14](https://npmjs.com/package/@seed-design/react/v/0.1.14) * [@seed-design/rootage-artifacts@0.0.5](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.0.5) * [@seed-design/tailwind3-plugin@0.1.14](https://npmjs.com/package/@seed-design/tailwind3-plugin/v/0.1.14) * [@seed-design/tailwind4-theme@0.1.14](https://npmjs.com/package/@seed-design/tailwind4-theme/v/0.1.14) ## 2025.08.20 [`0be9b00`](https://github.com/daangn/seed-design/commit/0be9b00baad2502eb4ea32e641c5c1d8c3f3eb4c) Avatar, Avatar Stack 컴포넌트에 `size=108` variant를 추가합니다. ### Version Updates * [@seed-design/css@0.1.13](https://npmjs.com/package/@seed-design/css/v/0.1.13) * [@seed-design/rootage-artifacts@0.0.4](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.0.4) ## 2025.08.12 #2 [`62094b6`](https://github.com/daangn/seed-design/commit/62094b6e6d445edd1fbd7085f80a8e1cc4da03bf) Help Bubble의 스타일 문제를 수정합니다. * `placement=left-*` / `placement=right-*`에서 arrow가 content와 떨어져 표시되는 문제를 수정합니다. ### Version Updates * [@seed-design/css@0.1.12](https://npmjs.com/package/@seed-design/css/v/0.1.12) * [@seed-design/react@0.1.12](https://npmjs.com/package/@seed-design/react/v/0.1.12) * [@seed-design/react-popover@0.0.8](https://npmjs.com/package/@seed-design/react-popover/v/0.0.8) ## 2025.08.12 [`9993e0e`](https://github.com/daangn/seed-design/commit/9993e0ea799258e88a5d81777ab7785e21cafa97) 레이아웃 컴포넌트를 사용할 때 `flexGrow`, `flexShrink`, `flexWrap`에도 `true`를 사용할 수 있도록 수정합니다. Figma 레이어가 이미지 Fill을 가지고 있는 경우 `` 요소를 prepend합니다. ### Version Updates * [@seed-design/figma@0.1.11](https://npmjs.com/package/@seed-design/figma/v/0.1.11) * [@seed-design/react@0.1.11](https://npmjs.com/package/@seed-design/react/v/0.1.11) ## 2025.08.11 [`ef91c21`](https://github.com/daangn/seed-design/commit/ef91c21da109e74405fc57f0fd0246af63dcd1a9) Bottom Sheet의 스타일 문제를 수정해요. * Close Button에 브라우저 기본 스타일이 표시되는 문제를 수정해요. [`aa40f66`](https://github.com/daangn/seed-design/commit/aa40f66e33a6d050d4728cce4d749f56a79e7975) Figma 컴포넌트 정보 및 핸들러를 최신화하고 codegen을 업데이트합니다. * Instance에 오버라이드한 내용이 있는 경우 주석으로 알립니다. ### Version Updates * [@seed-design/css@0.1.10](https://npmjs.com/package/@seed-design/css/v/0.1.10) * [@seed-design/figma@0.1.10](https://npmjs.com/package/@seed-design/figma/v/0.1.10) ## 2025.08.07 [`5a025b7`](https://github.com/daangn/seed-design/commit/5a025b7b12b7d288bc07dbea88e26cfb41d5b661) Switch 컴포넌트를 업데이트합니다. * size: medium → 32, small → 16으로 rename합니다. * (React) `size="medium"`으로 `32`, `size="small"`로 `16`을 사용할 수 있습니다. (deprecated) * size: 24를 추가합니다. * 모든 size에 대해 레이블 스타일을 추가합니다. (기존: small에만 존재) [`f9379e0`](https://github.com/daangn/seed-design/commit/f9379e09d64d047136383ca4b16a704a5d82268e) Figma 컴포넌트 핸들러 정보를 최신화하고 정확한 prop을 생성하도록 수정합니다. * Chip, Progress Circle, Switch 컴포넌트 핸들러를 업데이트합니다. * `grow` 대신 `flexGrow`가 생성되도록, `borderWidth`가 `string`으로 생성되도록 수정합니다. [`ac35731`](https://github.com/daangn/seed-design/commit/ac35731de335a06b4aa2f87bf03ebce002e61e2b) Chip.Root `position: relative` 속성 추가 * 이제 Chip.Toggle을 사용해도 예상치 못한 스크롤이 발생하지 않습니다. [`f9041e9`](https://github.com/daangn/seed-design/commit/f9041e9cf4ee90acef8e52be1dc483d01438e0e2) `CheckSelectBox`, `RadioSelectBox`의 `label`, `description` 영역을 수정합니다. * `span` 대신 `div`를 렌더링합니다. * 기본적으로 grow하도록 만들어 Badge 등 추가 요소를 넣기 쉽게 만듭니다. ### Version Updates * [@seed-design/css@0.1.9](https://npmjs.com/package/@seed-design/css/v/0.1.9) * [@seed-design/figma@0.1.9](https://npmjs.com/package/@seed-design/figma/v/0.1.9) * [@seed-design/react@0.1.9](https://npmjs.com/package/@seed-design/react/v/0.1.9) * [@seed-design/rootage-artifacts@0.0.3](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.0.3) ## 2025.08.04 [`2e2cc53`](https://github.com/daangn/seed-design/commit/2e2cc530648f5d10432f23fa8169e3c4225f6315) - Figma 컴포넌트 핸들러 및 스타일 정보를 최신화합니다. * normalize 과정에서 그라디언트 정보를 포함하도록 수정합니다. [`609b8f3`](https://github.com/daangn/seed-design/commit/609b8f3b69bc98f0b3a2c971f17409559811f376) iOS의 `더 큰 텍스트` 기능에 제한을 둡니다. * iOS는 7단계(XS \~ XXXL)의 텍스트 크기 조절 이외에도, 보다 더 큰 텍스트를 위한 `더 큰 텍스트` 기능을 제공합니다. * iOS 네이티브에서는 `더 큰 텍스트`의 UI 레이아웃 대응이 어렵다고 결정하여, XXXL(135%) 이상의 텍스트 크기 조절을 지원하지 않습니다. * 웹뷰도 iOS와 동일한 제한을 위한 기능이 추가되었습니다. [`99e7f2c`](https://github.com/daangn/seed-design/commit/99e7f2c693ac2a4d433791719b25d4818bc41170) figma-extractor (Figma REST API 호출 결과를 파일로 저장하는 CLI 툴) 설정 파일 작성 방법을 개선합니다. * 사용자가 직접 API 호출부터 파일 저장까지의 파이프라인을 작성할 수 있습니다. ### Version Updates * [@seed-design/css@0.1.8](https://npmjs.com/package/@seed-design/css/v/0.1.8) * [@seed-design/figma@0.1.8](https://npmjs.com/package/@seed-design/figma/v/0.1.8) * [@seed-design/figma-extractor@0.0.5](https://npmjs.com/package/@seed-design/figma-extractor/v/0.0.5) ## 2025.08.01 [`4afe80b`](https://github.com/daangn/seed-design/commit/4afe80b81e6845ec917426039ef8d7817e67e7ec) MultilineTextField의 스타일 문제를 수정합니다. * 스크롤바가 요소 끝에 표시되도록 수정합니다. ### Version Updates * [@seed-design/css@0.1.7](https://npmjs.com/package/@seed-design/css/v/0.1.7) ## 2025.07.31 [`235147d`](https://github.com/daangn/seed-design/commit/235147def530d1d2ab6441f0e5b965efb1d67e43) action-button: `size=medium, layout=withText` variant에서 gap을 1 → 1.5로 수정합니다. [`3c13ad7`](https://github.com/daangn/seed-design/commit/3c13ad76a32bbf909b44f4ffbca1277d6d0f1d7a) `highlight-magic-pressed` 그라디언트 토큰을 추가합니다. ### Version Updates * [@seed-design/css@0.1.6](https://npmjs.com/package/@seed-design/css/v/0.1.6) * [@seed-design/rootage-artifacts@0.0.2](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.0.2) * [@seed-design/tailwind3-plugin@0.1.6](https://npmjs.com/package/@seed-design/tailwind3-plugin/v/0.1.6) * [@seed-design/tailwind4-theme@0.1.6](https://npmjs.com/package/@seed-design/tailwind4-theme/v/0.1.6) ## 2025.07.29 [`a059fb0`](https://github.com/daangn/seed-design/commit/a059fb02b051fc4ca8fd0c79c5706dec90448097) Menu Sheet 컴포넌트를 추가하는 동시에 Action Sheet과 Extended Action Sheet 컴포넌트를 deprecate합니다. * [Menu Sheet React 문서](https://seed-design.io/react/components/menu-sheet) * Menu Sheet는 기존 Extended Action Sheet의 모든 기능을 포함하는 동시에, `labelAlign` prop으로 `MenuSheetItem`를 `left` 또는 `center`로 정렬할 수 있습니다. [`3889eb6`](https://github.com/daangn/seed-design/commit/3889eb6c82915c6ae4df05c815841f0ad54d27a6) Inline Banner의 스타일 문제를 수정합니다. * `title`과 `description`이 `inline-flex`로 레이아웃되던 문제를 해결합니다. * `title`과 `description` 간의 간격을 조정합니다. * 닫기 버튼(Dismissible)과 `suffix icon`, `link label`이 상단으로 레이아웃되던 문제를 해결합니다. Callout의 스타일 문제를 수정합니다. * `title`과 `description` 간의 간격을 조정합니다. Chip의 스타일 문제를 수정합니다. * `Chip.Button`의 `label`이 의도한 글꼴로 표시되도록 수정합니다. ### Version Updates * [@seed-design/css@0.1.5](https://npmjs.com/package/@seed-design/css/v/0.1.5) * [@seed-design/react@0.1.5](https://npmjs.com/package/@seed-design/react/v/0.1.5) * [@seed-design/rootage-artifacts@0.0.1](https://npmjs.com/package/@seed-design/rootage-artifacts/v/0.0.1) ## 2025.07.28 [`9b271d6`](https://github.com/daangn/seed-design/commit/9b271d613f2067c8cc8cbc517cd1d334f4e04e92) snippet의 deprecated 여부를 기록합니다. cli add 명령 실행 시 snippet 목록에서 deprecate 여부를 표시하고, `--all`로 모든 스니펫 추가 시 기본적으로 deprecated snippet을 제외합니다. ```sh seed-design add --all # deprecated snippet 제외 ``` ```sh seed-design add --all --include-deprecated # deprecated snippet 포함 ``` ### Version Updates * [@seed-design/cli@0.0.3](https://npmjs.com/package/@seed-design/cli/v/0.0.3) ## 2025.07.23 [`0ffcd48`](https://github.com/daangn/seed-design/commit/0ffcd481d3be71cff6a7cfea6985a7c063086ff7) Chip 컴포넌트가 추가되고, ActionChip, ControlChip 컴포넌트가 Deprecated 되었습니다. * [Chip 컴포넌트](https://seed-design.io/react/components/chip) * Chip 컴포넌트는 버튼과 토글 컴포넌트를 모두 포함하고 있습니다. [`56e03ca`](https://github.com/daangn/seed-design/commit/56e03cad0841e4a77e284da12d63e81d412e84b9) Layout 컴포넌트 `pb`, `pt`, `paddingBottom`, `paddingTop` 속성에 `safeArea` 값을 지정할 수 있도록 지원 ```tsx ``` ### Version Updates * [@seed-design/css@0.1.4](https://npmjs.com/package/@seed-design/css/v/0.1.4) * [@seed-design/react@0.1.4](https://npmjs.com/package/@seed-design/react/v/0.1.4) ## 2025.07.11 [`cdc0930`](https://github.com/daangn/seed-design/commit/cdc09303deb05db51455c779b72c148b975014c5) `@seed-design/stackflow` 백스와이프 애니메이션 개선 * iOS 스타일 화면 전환 애니메이션의 지속 시간과 타이밍 함수가 `300ms`에서 `350ms`로 조정되어 더 부드러운 전환 효과를 제공합니다. * 스와이프 백 제스처 시 애니메이션이 보다 자연스럽고 일관되게 표현됩니다. * 스와이프 백 종료 시 CSS 변수를 활용해 전환 상태를 명확히 하여 사용자 경험이 개선되었습니다. [`946faf7`](https://github.com/daangn/seed-design/commit/946faf79c824b435da30e4cf6162b7ba4dba49ec) 그라디언트 토큰 추가 및 변경 * `fade-layer-floating`, `fade-layer-default` 토큰이 추가되었습니다. * `$gradient.shimmer-magic` 토큰 stop color가 변경되었습니다. [`71c58fd`](https://github.com/daangn/seed-design/commit/71c58fd22901d6296f09a852082839e1b2888e31) iOS Font Scaling * iOS 기기에서 시스템 폰트 크기 설정에 따라 동적으로 폰트 크기와 줄 높이를 조정하는 폰트 스케일링 옵션이 추가되었습니다. * 플러그인(webpack, vite, rsbuild)에서 `fontScaling` 옵션을 통해 폰트 스케일링 기능을 활성화할 수 있습니다. * `data-seed-font-scaling='enabled'` 일 때, 폰트 크기를 조정합니다. ### Version Updates * [@seed-design/css@0.1.3](https://npmjs.com/package/@seed-design/css/v/0.1.3) * [@seed-design/rsbuild-plugin@0.1.3](https://npmjs.com/package/@seed-design/rsbuild-plugin/v/0.1.3) * [@seed-design/stackflow@0.1.3](https://npmjs.com/package/@seed-design/stackflow/v/0.1.3) * [@seed-design/tailwind3-plugin@0.1.3](https://npmjs.com/package/@seed-design/tailwind3-plugin/v/0.1.3) * [@seed-design/tailwind4-theme@0.1.3](https://npmjs.com/package/@seed-design/tailwind4-theme/v/0.1.3) * [@seed-design/vite-plugin@0.1.3](https://npmjs.com/package/@seed-design/vite-plugin/v/0.1.3) * [@seed-design/webpack-plugin@0.1.3](https://npmjs.com/package/@seed-design/webpack-plugin/v/0.1.3) ## 2025.07.01 그라디언트 토큰 및 AI 관련 컴포넌트 업데이트 * AI용 magic 테마와 중립적인 테마의 다양한 그라디언트(Shimmer, Fade, Glow, Highlight) 컬러 토큰이 추가되었습니다. * `` 컴포넌트의 `tone="magic"` 스타일이 변경되었습니다. * `` 컴포넌트에 `tone` prop이 추가되어 `neutral`과 `magic` 옵션을 제공합니다. * 모든 Layout 컴포넌트(Box, VStack, HStack 등)에서 `bg/bgGradient` 속성을 통해 그라디언트를 지정할 수 있습니다. * `` 컴포넌트에 `textDecorationLine` 옵션이 추가되었습니다. * `` 컴포넌트의 arrow가 상위 요소의 font-size에 영향받지 않도록 수정되었습니다. * `` 컴포넌트의 description font-size가 t6에서 t5로 변경되었습니다. * 기존 보라색 계열 magic 관련 시맨틱 색상들(`fg/magic`, `fg/magic-contrast`, `bg/magic-solid`)이 삭제되었습니다. ### Version Updates * [@seed-design/css@0.1.0](https://npmjs.com/package/@seed-design/css/v/0.1.0) * [@seed-design/figma@0.1.0](https://npmjs.com/package/@seed-design/figma/v/0.1.0) * [@seed-design/mcp@0.1.0](https://npmjs.com/package/@seed-design/mcp/v/0.1.0) * [@seed-design/react@0.1.0](https://npmjs.com/package/@seed-design/react/v/0.1.0) * [@seed-design/rsbuild-plugin@0.1.0](https://npmjs.com/package/@seed-design/rsbuild-plugin/v/0.1.0) * [@seed-design/stackflow@0.1.0](https://npmjs.com/package/@seed-design/stackflow/v/0.1.0) * [@seed-design/vite-plugin@0.1.0](https://npmjs.com/package/@seed-design/vite-plugin/v/0.1.0) * [@seed-design/webpack-plugin@0.1.0](https://npmjs.com/package/@seed-design/webpack-plugin/v/0.1.0) ## 2025.06.24 Alpha 컬러 업데이트 * White와 black의 alpha 색상이 새롭게 추가되었습니다. (staticWhiteAlpha50 \~ staticWhiteAlpha1000, staticBlackAlpha100 \~ staticBlackAlpha1000) * stroke 색상에도 alpha 색상이 추가되었습니다. * 기존 alpha 색상 값들의 매핑이 변경되었습니다: * `staticBlackAlpha500` → `staticBlackAlpha700` * `staticBlackAlpha200` → `staticBlackAlpha500` * `staticBlackAlpha50` → `staticBlackAlpha200` * `staticWhiteAlpha200` → `staticWhiteAlpha300` * `npx @seed-design/codemod@latest replace-alpha-color` 코드모드를 제공합니다. ### Version Updates * [@seed-design/codemod@0.0.28](https://npmjs.com/package/@seed-design/codemod/v/0.0.28) * [@seed-design/css@0.0.39](https://npmjs.com/package/@seed-design/css/v/0.0.39) * [@seed-design/figma@0.0.39](https://npmjs.com/package/@seed-design/figma/v/0.0.39) * [@seed-design/mcp@0.0.39](https://npmjs.com/package/@seed-design/mcp/v/0.0.39) * [@seed-design/migration-index@0.0.28](https://npmjs.com/package/@seed-design/migration-index/v/0.0.28) * [@seed-design/react@0.0.39](https://npmjs.com/package/@seed-design/react/v/0.0.39) * [@seed-design/rsbuild-plugin@0.0.39](https://npmjs.com/package/@seed-design/rsbuild-plugin/v/0.0.39) * [@seed-design/stackflow@0.0.39](https://npmjs.com/package/@seed-design/stackflow/v/0.0.39) * [@seed-design/tailwind3-plugin@0.0.39](https://npmjs.com/package/@seed-design/tailwind3-plugin/v/0.0.39) * [@seed-design/tailwind4-theme@0.0.39](https://npmjs.com/package/@seed-design/tailwind4-theme/v/0.0.39) * [@seed-design/vite-plugin@0.0.39](https://npmjs.com/package/@seed-design/vite-plugin/v/0.0.39) * [@seed-design/webpack-plugin@0.0.39](https://npmjs.com/package/@seed-design/webpack-plugin/v/0.0.39) file: updates/v3-improvements.mdx # V3 Improvements Seed Design V3의 개선사항을 안내합니다. *** title: V3 Improvements description: Seed Design V3의 개선사항을 안내합니다. ----------------------------------------- ## Composition V3에서는 컴포넌트를 조합하여 복잡한 UI를 구성하는 방법과 원칙을 제공합니다. as Prop, asChild Prop, 슬롯 등을 통해 컴포넌트를 조합할 수 있습니다. [Composition](/react/components/concepts/composition) 페이지에서 자세히 설명합니다. ```tsx title="Composition" // Text 컴포넌트는 기본적으로 span 태그를 사용하지만, as Prop을 사용해 다른 태그로 변경할 수 있습니다. 단락 텍스트 인라인 텍스트 제목 텍스트 // FAB는 기본적으로 button 태그를 사용하지만, asChild를 사용해 링크로 변경할 수 있습니다. } /> ``` ## Snippet V3에서는 자주 사용되는 UI 패턴을 스니펫으로 제공하여 개발 효율성을 높이는 방법을 제공합니다. Compound Components 패턴과 Snippet의 조합을 통해 복잡한 컴포넌트를 쉽게 구현할 수 있습니다. [Snippet](/react/components/concepts/snippet) 페이지에서 자세히 설명합니다. ```tsx title="Snippet" Click me ``` ## Icon Usage V3에서의 아이콘 사용 방식이 달라졌습니다. [Icon Usage](/react/components/concepts/composition) 페이지에서 자세히 설명합니다. ```tsx title="Icon Usage" import { IconPlusFill } from "@karrotmarket/react-monochrome-icon"; import { PrefixIcon, SuffixIcon, Icon } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; // snippet 제공 import { ActionChip } from "seed-design/ui/action-chip"; // snippet 제공 export default function ActionButtonPrefixIcon() { return ( <> } /> } /> } /> Prefix Icon } /> Suffix Icon } /> ); } ``` ## Avatar 컴포넌트 변경 ```tsx // [!code --] import { Avatar } from "@daangn/sprout-components-avatar"; // [!code ++] import { Avatar } from "seed-design/ui/avatar"; // snippet 제공 ``` * `size` 옵션 확장: `"20" | "24" | "36" | "48" | "64" | "80" | "96"` * 이미지 로딩 실패 시 대체 콘텐츠를 위한 `fallback` prop 제공 * 슬롯 기반 구조 추가: `Root`, `Image`, `Fallback` * [V3 컴포넌트 보러가기 (Avatar)](/react/components/avatar) ## AlertDialog 관련 컴포넌트 변경 V2의 Dialog와 AlertDialog는 V3에서 각각 별도의 컴포넌트로 제공돼요. ```tsx // [!code --] import { Dialog, DialogContainer, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@daangn/sprout-components-dialog"; // [!code ++] import { AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogRoot, AlertDialogTitle, AlertDialogTrigger } from "seed-design/ui/alert-dialog"; // snippet 제공 ``` * 기존에 `DialogHeader`로만 구조화되어 있던 부분들 조금 더 세분화 (`AlertDialogContent`, `AlertDialogHeader`, `AlertDialogFooter`) * 액션에 관한 슬롯 추가 `AlertDialogAction` * `AlertDialogTrigger`로 명시적으로 trigger를 제공하거나 혹은 `open` prop을 통해 외부에서 제어 가능 * [V3 컴포넌트 보러가기 (AlertDialog)](/react/components/alert-dialog) ## 버튼 관련 컴포넌트 변경 ### BoxButton, TextButton → ActionButton V2의 [BoxButton](https://sprout-storybook.vercel.app/?path=/docs/components-buttons-boxbutton--docs), [TextButton](https://sprout-storybook.vercel.app/?path=/docs/components-buttons-textbutton--docs)을 대체하는 통합 버튼 컴포넌트 ```tsx // [!code --] import { BoxButton, TextButton } from "@daangn/sprout-components-button"; // [!code ++] import { ActionButton } from "seed-design/ui/action-button"; // snippet 제공 ``` * `xlarge` size 제거 * 전체적인 variant 명칭 변경 * `Primary` → `Neutral Solid` * `Primary low` → `Neutral Weak` * `Secondary` → `Neutral Weak` * `Danger` → `Critical Solid` * 추가된 variant: `Neutral Outline` * `isLoading`이 `loading`으로 변경 * `layout` prop 추가 (`withText`, `iconOnly`) * `prefix`, `suffix`: 아이콘 배치 방식이 `children`으로 통합 * [V3 컴포넌트 보러가기 (ActionButton)](/react/components/action-button) ### BoxToggleButton, CapsuleToggleButton → ToggleButton, ReactionButton V2의 [BoxToggleButton](https://sprout-storybook.vercel.app/?path=/docs/components-buttons-boxtogglebutton--docs), [CapsuleToggleButton](https://sprout-storybook.vercel.app/?path=/docs/components-buttons-capsuletogglebutton--docs)은 V3에서 각각 ToggleButton, ReactionButton으로 변경되었어요. ```tsx // [!code --] import { BoxToggleButton, CapsuleToggleButton } from "@daangn/sprout-components-button"; // [!code ++] import { ToggleButton } from "seed-design/ui/toggle-button"; // snippet 제공 // [!code ++] import { ReactionButton } from "seed-design/ui/reaction-button"; // snippet 제공 ``` **ToggleButton 변경사항** * size 변경: V2의 `xSmall`, `small`, `medium`, `large` → V3의 `xsmall`, `small`로 통합 * variant 명칭 변경 * `primaryLow` → `neutralWeak` * `secondary` → `neutralWeak` * `primary` → `brandSolid` * State 관련 명칭 변경 (Selected + State 조합) * [V3 컴포넌트 보러가기 (ToggleButton)](/react/components/toggle-button) **ReactionButton 변경사항** * CapsuleToggleButton V2의 `small`, `xsmall` 크기만 지원 * 좋아요 버튼 등 반응형 버튼에 특화된 컴포넌트 * V3에서는 `size` 옵션으로 `xsmall`, `small` 제공 * selected 상태일 때 스타일 변경 (브랜드 색상으로 강조) * [V3 컴포넌트 보러가기 (ReactionButton)](/react/components/reaction-button) ## Chips 관련 컴포넌트 변경 V2에서는 `@daangn/sprout-components-chips` 패키지에서 여러 칩 관련 컴포넌트들을 제공했어요. V3에서는 이러한 컴포넌트들이 목적에 따라 재구성되었어요. ### ChipButton → ActionChip V2의 [ChipButton](https://sprout-storybook.vercel.app/?path=/docs/components-chips-chipbutton--docs)은 V3에서 ActionChip으로 변경되었어요. ```tsx // [!code --] import { ChipButton } from "@daangn/sprout-components-chips"; // [!code ++] import { ActionChip } from "seed-design/ui/action-chip"; // snippet 제공 ``` * `layout` prop 추가 (`withText`, `iconOnly`) * `prefix`, `suffix` prop 대신 `children`으로 아이콘 전달 * `count` prop 제거 * [V3 컴포넌트 보러가기 (ActionChip)](/react/components/action-chip) ### ChipToggleButton, ChipRadio, ChipRadioGroup → ControlChip V2의 [ChipToggleButton](https://sprout-storybook.vercel.app/?path=/docs/components-chips-chiptogglebutton--docs)과 [ChipRadio, ChipRadioGroup](https://sprout-storybook.vercel.app/?path=/docs/components-chips-chipradiogroup--docs)는 V3에서 ControlChip으로 통합되었어요. ```tsx // [!code --] import { ChipToggleButton, ChipRadio, ChipRadioGroup } from "@daangn/sprout-components-chips"; // [!code ++] import { ControlChip } from "seed-design/ui/control-chip"; // snippet 제공 ``` * `ControlChip.Radio`와 `ControlChip.RadioGroup` 또는 `ControlChip.Toggle`로 사용 * `layout` prop 추가 (`withText`, `iconOnly`) * `prefix`, `suffix` prop 대신 `children`으로 아이콘 전달 * [V3 컴포넌트 보러가기 (ControlChip)](/react/components/control-chip) ### ChipFilter → 제거됨 V2의 [ChipFilter](https://sprout-storybook.vercel.app/?path=/docs/components-chips-chipfilter--docs)는 V3에서 제거되었어요. 필요한 경우 ActionChip이나 ControlChip으로 대체할 수 있어요. ## Checkbox 관련 컴포넌트 변경 ```tsx // [!code --] import { Checkbox } from "@daangn/sprout-components-checkbox"; // [!code ++] import { Checkbox } from "seed-design/ui/checkbox"; // snippet 제공 ``` * `variant` 옵션이 `shape` prop으로 변경 (`square`, `ghost`) * `circle` variant가 제거되었으며 대신 `square`를 사용 * `size` 변경: `small` 크기가 제거되고 `medium`, `large`만 제공 * `bold` 속성은 `weight` prop으로 변경 (`default` | `stronger`) * [V3 컴포넌트 보러가기 (Checkbox)](/react/components/checkbox) ## TextField 관련 컴포넌트 변경 V2에서는 TextField, MultilineTextField 컴포넌트를 따로 제공했지만, V3에서는 조합형 컴포넌트로 통합되었어요. ```tsx // [!code --] import { TextField, MultilineTextField } from "@daangn/sprout-components-text-field"; // [!code ++] import { TextField, TextFieldInput, TextFieldTextarea } from "seed-design/ui/text-field"; // snippet 제공 ``` * 크기 매핑 변경 * V2 `large` → V3 `xlarge` * V2 `medium` → V3 `large` * V2 `small` → V3 `medium` * `TextFieldInput`은 텍스트 입력 컴포넌트로 사용 * `TextFieldTextarea`는 다중 라인 입력 컴포넌트로 사용 * `maxGraphemeCount` prop 추가 (기존 `maxLength` prop을 override해서 사용하던걸 명시적으로 표현) * [V3 컴포넌트 보러가기 (TextField)](/react/components/text-field) * [V3 컴포넌트 보러가기 (MultilineTextField)](/react/components/multiline-text-field) ## InlineAlert 관련 컴포넌트 변경 V2에서는 `@daangn/sprout-components-inline-alert` 패키지에서 여러 배너 관련 컴포넌트들을 제공했어요. V3에서는 `InlineBanner` 컴포넌트로 제공되고 있어요. ```tsx // [!code --] import { InlineBanner, ActionableInlineBanner, DismissibleInlineBanner } from "@daangn/sprout-components-banner"; // [!code ++] import { InlineBanner, ActionableInlineBanner, DismissibleInlineBanner } from "seed-design/ui/inline-banner"; // snippet 제공 ``` * Variant 명칭 변경 * `normal` → `neutralWeak (default)` * `info` → `informativeWeak` * `warning` → `warningWeak` * `danger` → `criticalWeak` * 각 `neutral` 제외하고 `solid` variant 추가 (`informativeSolid`, `warningSolid`, `criticalSolid`) * `criticalWeak`, `criticalSolid` variant는 `dismissible` prop 사용 불가 * [V3 컴포넌트 보러가기 (InlineBanner)](/react/components/inline-banner) ## Callout 관련 컴포넌트 변경 V2에서는 `@daangn/sprout-components-callout` 패키지에서 여러 Callout 관련 컴포넌트들을 제공했어요. V3에서도 `Callout` 컴포넌트로 제공되고 있어요. ```tsx // [!code --] import { Callout, ActionableCallout, DismissibleCallout } from "@daangn/sprout-components-callout"; // [!code ++] import { Callout, ActionableCallout, DismissibleCallout } from "seed-design/ui/callout"; // snippet 제공 ``` * `variant` -> `tone`으로 변경 * `normal` → `neutral` * `info` → `informative` * `danger` → `critical` * `warning` → `warning` (유지) * `magic` -> `magic` (유지) * [V3 컴포넌트 보러가기 (Callout)](/react/components/callout) ## SelectBox 관련 컴포넌트 변경 V2에서는 `@daangn/sprout-components-select-box` 패키지에서 여러 SelectBox 관련 컴포넌트들을 제공했어요. V3에서는 이러한 컴포넌트들이 목적에 따라 재구성되었어요. ### SelectBoxCheck -> CheckSelectBox, CheckSelectBoxGroup V2의 RadioSelectBox와 CheckSelectBox는 V3에서 하나의 SelectBox 컴포넌트로 통합되었어요. ```tsx // [!code --] import { SelectBoxCheck } from "@daangn/sprout-components-select-box"; // [!code ++] import { CheckSelectBox, CheckSelectBoxGroup } from "seed-design/ui/select-box"; // snippet 제공 ``` * `SelectBoxCheck` -> `CheckSelectBox` * 그룹 컴포넌트 추가: `CheckSelectBoxGroup` * [V3 컴포넌트 보러가기 (CheckSelectBox)](/react/components/check-select-box) ### SelectBoxRadio, SelectBoxRadioGroup -> RadioSelectBoxItem, RadioSelectBoxRoot ```tsx // [!code --] import { SelectBoxRadio, SelectBoxRadioGroup } from "@daangn/sprout-components-select-box"; // [!code ++] import { RadioSelectBoxItem, RadioSelectBoxRoot } from "seed-design/ui/select-box"; // snippet 제공 ``` * `SelectBoxRadio` -> `RadioSelectBoxItem` * `SelectBoxRadioGroup` -> `RadioSelectBoxRoot` * [V3 컴포넌트 보러가기 (RadioSelectBox)](/react/components/radio-select-box) ## Tabs 관련 컴포넌트 변경 ### Tabs ```tsx // [!code --] import { Tabs, TabList, Tab, TabPanelGroup, TabPanel } from "@daangn/sprout-components-tabs"; // [!code ++] import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "seed-design/ui/tabs"; // snippet 제공 ``` **Tabs 변경사항** * size 추가: `small`, `medium` * 탭 내 알림 표시 옵션 제공 (`dot` -> `notification`) * `stickyList` prop 추가: 스크롤 시 탭 목록 고정 가능 * `layout` -> `triggerLayout` 으로 변경 (`fill`, `hug`) * 컨텐츠의 layout도 조절 가능 (`contentLayout`) * 렌더링 관련 prop 변경 * `isLazy` -> `lazyMount` * `lazyMode` (unmount, keepMounted) -> `unmountOnExit` (boolean) * [V3 컴포넌트 보러가기 (Tabs)](/react/components/tabs) ### ChipTabs (신규) ```tsx // [!code ++] import { ChipTabsRoot, ChipTabsList, ChipTabsTrigger, ChipTabsContent, ChipTabsCarousel } from "seed-design/ui/chip-tabs"; // snippet 제공 ``` * V3 Tabs와 동일한 인터페이스 * [V3 컴포넌트 보러가기 (ChipTabs)](/react/components/chip-tabs) ## Switch 컴포넌트 변경 ```tsx // [!code --] import { Switch } from "@daangn/sprout-components-switch"; // [!code ++] import { Switch } from "seed-design/ui/switch"; // snippet 제공 ``` * 크기 기본값 `small` 추가 제공 (기존에는 `medium`만 제공) * children으로 제공되던 label 대신 `label` prop 추가 * [V3 컴포넌트 보러가기 (Switch)](/react/components/switch) ## Spinner 컴포넌트 변경 ```tsx // [!code --] import { Spinner } from "@daangn/sprout-components-spinner"; // [!code ++] import { ProgressCircle } from "seed-design/ui/progress-circle"; // snippet 제공 ``` * `Spinner`에서 `ProgressCircle`로 이름 변경 * `size` 옵션: `"24" | "40" | "inherit"` * `tone` 옵션: `"neutral" | "brand" | "staticWhite" | "inherit"` * 결정 상태(`value` prop 제공)와 미결정(로팅) 상태(`indeterminate` prop) 모두 지원 * [V3 컴포넌트 보러가기 (ProgressCircle)](/react/components/progress-circle) ## Snackbar 컴포넌트 변경 ```tsx // [!code --] import { SnackBar, useSnackbarAdapter } from "@daangn/sprout-components-snackbar"; // [!code ++] import { Snackbar, SnackbarProvider, useSnackbar } from "seed-design/ui/snackbar"; // snippet 제공 ``` * `variant` 옵션: `"default" | "positive" | "critical"` 으로 변경 * `SnackbarProvider`와 `useSnackbar` hook을 통한 편리한 선언적 사용 방식 지원 (기존과 동일) * [V3 컴포넌트 보러가기 (Snackbar)](/react/components/snackbar) ## HelpBubble 컴포넌트 변경 ```tsx // [!code --] import { HelpBubbleAnchor, HelpBubbleTrigger } from "@daangn/sprout-components-help-bubble"; // [!code ++] import { HelpBubbleTrigger, HelpBubbleAnchor } from "seed-design/ui/help-bubble"; // snippet 제공 ``` * 두 가지 사용 방식 제공: `HelpBubbleTrigger`(클릭 시 표시) 및 `HelpBubbleAnchor`(요소에 앵커링) * `title`, `description` prop으로 내용 구성 * `showCloseButton` prop으로 닫기 버튼 표시 여부 설정 * `strategy` (absolute, fixed) prop으로 포지셔닝 전략 선택 가능 * `gutter` prop으로 팝업 주변 여백 조절 가능 * `arrowPadding` prop으로 화살표 주변 여백 조절 가능 * `overflowPadding` prop으로 팝업 주변 여백 조절 가능 * [V3 컴포넌트 보러가기 (HelpBubble)](/react/components/help-bubble) ## FAB(Floating Action Button) 컴포넌트 변경 ### FAB ```tsx // [!code --] import { FloatingActionButton } from "@daangn/sprout-components-floating-action-button"; // [!code ++] import { FAB } from "seed-design/ui/fab"; // snippet 제공 import { ExtendedFAB } from "seed-design/ui/extended-fab"; // snippet 제공 ``` * [V3 컴포넌트 보러가기 (FAB)](/react/components/fab) ### ExtendedFAB ```tsx // [!code ++] import { ExtendedFab } from "@daangn/sprout-components-fab"; // [!code ++] import { ExtendedFAB } from "seed-design/react"; ``` * `size` 옵션: `"small" | "medium"` * `variant` 옵션: `"neutralSolid" | "layerFloating"` * [V3 컴포넌트 보러가기 (ExtendedFAB)](/react/components/extended-fab) ## 새로운 컴포넌트 ### AppScreen Stackflow AppScreen 컴포넌트 ```tsx // [!code ++] import { AppScreen } from "seed-design/ui/app-screen"; // snippet 제공 ``` * `theme` prop: `"cupertino" | "android"` * `transitionStyle` prop: `"slideFromRightIOS" | "fadeFromBottomAndroid"` * `layerOffsetTop` prop: `"none" | "safeArea" | "appBar"` * `layerOffsetBottom` prop: `"none" | "safeArea"` * [V3 컴포넌트 보러가기 (AppScreen)](/react/components/stackflow/app-screen) ### BottomSheet, ActionSheet, ExtendedActionSheet V3에서는 BottomSheet와 ActionSheet가 새로 추가되었어요. ```tsx // [!code ++] import { BottomSheet } from "seed-design/ui/bottom-sheet"; // snippet 제공 import { ActionSheet } from "seed-design/ui/action-sheet"; // snippet 제공 import { ExtendedActionSheet } from "seed-design/ui/extended-action-sheet"; // snippet 제공 ``` * `BottomSheet`: 커스텀 콘텐츠를 담을 수 있는 바텀 시트 * `ActionSheet`: 액션 목록을 표시하는 바텀 시트 * `ExtendedActionSheet`: 확장된 기능을 가진 액션 시트 * 모바일 환경에 최적화된 상호작용 패턴 지원 * 접근성이 개선된 API 구조 * [V3 컴포넌트 보러가기 (BottomSheet)](/react/components/bottom-sheet) * [V3 컴포넌트 보러가기 (ActionSheet)](/react/components/action-sheet) * [V3 컴포넌트 보러가기 (ExtendedActionSheet)](/react/components/extended-action-sheet) ### PullToRefresh PullToRefresh 컴포넌트 ```tsx // [!code ++] import { PullToRefresh } from "seed-design/ui/pull-to-refresh"; // snippet 제공 ``` * 모바일 앱과 같은 당겨서 새로고침 기능 제공 * [V3 컴포넌트 보러가기 (PullToRefresh)](/react/components/pull-to-refresh) ### SegmentedControl 세그먼트 컨트롤 컴포넌트 ```tsx // [!code ++] import { SegmentedControl } from "seed-design/ui/segmented-control"; // snippet 제공 ``` * 여러 옵션 중 하나를 선택할 수 있는 컴포넌트 * `size` 옵션: `"large" | "medium"` * 커스텀 스타일과 접근성을 고려한 구조 제공 * [V3 컴포넌트 보러가기 (SegmentedControl)](/react/components/segmented-control) ### LinkContent 텍스트 링크 컴포넌트 ```tsx // [!code ++] import { LinkContent } from "seed-design/ui/link-content"; // snippet 제공 ``` * 기존 TextButton 컴포넌트의 용도를 대체하는 컴포넌트 * 다양한 색상과 크기를 지원하는 텍스트 링크 컴포넌트 * `size` 옵션: `"small" | "medium" | "large"` * `color` 옵션: `"neutral" | "brand" | "information" | "positive" | "notice" | "critical" | "white"` * 외부 링크, 다운로드 링크 등을 표현하는 데 유용 * [V3 컴포넌트 보러가기 (LinkContent)](/react/components/link-content) ### Skeleton 콘텐츠 로딩 상태를 표시하는 스켈레톤 컴포넌트 ```tsx // [!code ++] import { Skeleton } from "seed-design/ui/skeleton"; // snippet 제공 ``` * 다양한 반경(radius) 옵션을 제공하는 로딩 플레이스홀더 * 콘텐츠 로드 전 레이아웃을 미리 보여줘 사용자 경험 향상 * 애니메이션 효과로 로딩 중임을 시각적으로 표현 * [V3 컴포넌트 보러가기 (Skeleton)](/react/components/skeleton) ### MannerTempBadge 매너온도 뱃지 컴포넌트 ```tsx // [!code ++] import { MannerTempBadge } from "seed-design/ui/manner-temp-badge"; // snippet 제공 ``` * 당근마켓의 매너온도를 시각적으로 표현하는 뱃지 * 온도에 따른 다양한 색상 및 아이콘 변화 지원 * 매너온도 표시에 특화된 컴포넌트 * [V3 컴포넌트 보러가기 (MannerTempBadge)](/react/components/manner-temp-badge) ### Badge ```tsx // [!code ++] import { Badge } from "@seed-design/react"; ``` * 정보를 강조하여 표시하는 뱃지 컴포넌트 * `size` 옵션: `"medium" | "large"` * `variant` 옵션: `"weak" | "solid" | "outline"` * `tone` 옵션: `"neutral" | "brand" | "informative" | "positive" | "critical"` * `asChild` prop을 통해 다른 요소에 뱃지 스타일 적용 가능 * [V3 컴포넌트 보러가기 (Badge)](/react/components/badge) ### Error State ```tsx // [!code ++] import { ErrorState } from "seed-design/ui/error-state"; // snippet 제공 ``` * 사용자에게 오류 혹은 조회 결과가 없음을 알리는 컴포넌트 * `variant` 옵션: `"basement"` * 콘텐츠가 없거나 오류가 발생한 상황에서 사용자에게 적절한 피드백 제공 * [V3 컴포넌트 보러가기 (ErrorState)](/react/components/error-state) ### Identity Placeholder ```tsx // [!code ++] import { IdentityPlaceholder } from "seed-design/ui/identity-placeholder"; // snippet 제공 ``` * 사용자나 항목의 신원을 표현하는 플레이스홀더 컴포넌트 * 사용자 아바타나 항목 이미지의 로딩 전 상태를 시각적으로 표현 * 콘텐츠 로드 전 일관된 사용자 인터페이스 제공 * [V3 컴포넌트 보러가기 (IdentityPlaceholder)](/react/components/identity-placeholder) ### 레이아웃 관련 컴포넌트 V3에서는 레이아웃 구성을 위한 다양한 컴포넌트를 제공해요. ```tsx // [!code ++] import { Box, Flex, VStack, HStack } from "@seed-design/react"; ``` * `Box`: 기본 레이아웃 컨테이너 * `Flex`: Flex 레이아웃을 구성하기 위한 컴포넌트 * `VStack`: 수직 방향으로 요소를 쌓는 레이아웃 * `HStack`: 수평 방향으로 요소를 쌓는 레이아웃 * [V3 컴포넌트 보러가기 (Box)](/react/components/layout/box) * [V3 컴포넌트 보러가기 (Flex)](/react/components/layout/flex) * [V3 컴포넌트 보러가기 (VStack)](/react/components/layout/v-stack) * [V3 컴포넌트 보러가기 (HStack)](/react/components/layout/h-stack)