From 2f28f46aefbffd7ea1c826dc0a7cd64dec7c3e9b Mon Sep 17 00:00:00 2001 From: Joo Chanhwi <56245920+te6-in@users.noreply.github.com> Date: Fri, 24 Jan 2025 21:42:29 +0900 Subject: [PATCH 1/6] feat(figma-extractor): sort imports --- tools/figma-extractor/CHANGELOG.md | 6 ++++++ tools/figma-extractor/package.json | 2 +- tools/figma-extractor/src/services/component-sets.ts | 3 ++- tools/figma-extractor/src/services/components.ts | 3 ++- tools/figma-extractor/src/services/styles.ts | 5 ++++- tools/figma-extractor/src/services/variables.ts | 3 ++- 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tools/figma-extractor/CHANGELOG.md b/tools/figma-extractor/CHANGELOG.md index 5ce1d08b2..578b9695f 100644 --- a/tools/figma-extractor/CHANGELOG.md +++ b/tools/figma-extractor/CHANGELOG.md @@ -1,5 +1,11 @@ # @seed-design/figma-extractor +## 0.0.3 + +### Patch Changes + +- Sort exports + ## 0.0.2 ### Patch Changes diff --git a/tools/figma-extractor/package.json b/tools/figma-extractor/package.json index b27481835..d201ac84e 100644 --- a/tools/figma-extractor/package.json +++ b/tools/figma-extractor/package.json @@ -1,6 +1,6 @@ { "name": "@seed-design/figma-extractor", - "version": "0.0.2", + "version": "0.0.3", "repository": { "type": "git", "url": "git+https://github.com/daangn/seed-design.git", diff --git a/tools/figma-extractor/src/services/component-sets.ts b/tools/figma-extractor/src/services/component-sets.ts index d0eaf488d..1a8d2cecc 100644 --- a/tools/figma-extractor/src/services/component-sets.ts +++ b/tools/figma-extractor/src/services/component-sets.ts @@ -18,7 +18,8 @@ export async function generateComponentSetMetadata({ const componentSetsMetadata = (await getComponentSetMetadataItemsInFile({ fileKey })) .filter(filter) - .map(transform); + .map(transform) + .sort((a, b) => a.name.localeCompare(b.name)); if (componentSetsMetadata.length === 0) { console.error("추출할 component set 메타데이터가 없습니다."); diff --git a/tools/figma-extractor/src/services/components.ts b/tools/figma-extractor/src/services/components.ts index 23d242f8f..3b1ca3ac7 100644 --- a/tools/figma-extractor/src/services/components.ts +++ b/tools/figma-extractor/src/services/components.ts @@ -18,7 +18,8 @@ export async function generateComponentMetadata({ const componentsMetadata = (await getComponentMetadataItemsInFile({ fileKey })) .filter(filter) - .map(transform); + .map(transform) + .sort((a, b) => a.name.localeCompare(b.name)); if (componentsMetadata.length === 0) { console.error("추출할 component 메타데이터가 없습니다."); diff --git a/tools/figma-extractor/src/services/styles.ts b/tools/figma-extractor/src/services/styles.ts index dd7ef418b..fd427f004 100644 --- a/tools/figma-extractor/src/services/styles.ts +++ b/tools/figma-extractor/src/services/styles.ts @@ -20,7 +20,10 @@ export async function generateStyleMetadata({ }) { console.log("style 메타데이터 생성 중"); - const stylesMetadata = (await getStylesMetadataInFile({ fileKey })).filter(filter).map(transform); + const stylesMetadata = (await getStylesMetadataInFile({ fileKey })) + .filter(filter) + .map(transform) + .sort((a, b) => a.name.localeCompare(b.name)); if (stylesMetadata.length === 0) { console.error("추출할 style 메타데이터가 없습니다."); diff --git a/tools/figma-extractor/src/services/variables.ts b/tools/figma-extractor/src/services/variables.ts index 620651518..ef2278244 100644 --- a/tools/figma-extractor/src/services/variables.ts +++ b/tools/figma-extractor/src/services/variables.ts @@ -22,7 +22,8 @@ export async function generateVariableMetadata({ const variablesMetadata = (await getVariableMetadataItemsInFile({ fileKey })) .filter(filter) - .map(transform); + .map(transform) + .sort((a, b) => a.name.localeCompare(b.name)); if (variablesMetadata.length === 0) { console.error("추출할 variable 메타데이터가 없습니다."); From 480bc203c353b6439503990bfc9b0f77e1e270bb Mon Sep 17 00:00:00 2001 From: Joo Chanhwi <56245920+te6-in@users.noreply.github.com> Date: Fri, 24 Jan 2025 22:10:41 +0900 Subject: [PATCH 2/6] feat: support codegen for ErrorState, MannerTempBadge & 2 sheets --- .../docs/react/components/action-sheet.mdx | 11 +- .../components/extended-action-sheet.mdx | 11 +- tools/figma-codegen/package.json | 2 +- .../src/codegen/component/index.ts | 217 +++++++++++++++++- .../src/codegen/component/type.ts | 67 ++++++ .../data/component-sets/error-state.d.ts | 32 +++ .../data/component-sets/error-state.mjs | 32 +++ .../component-sets/extended-action-sheet.d.ts | 10 +- .../component-sets/extended-action-sheet.mjs | 10 +- .../codegen/data/component-sets/index.d.ts | 67 +++--- .../src/codegen/data/component-sets/index.mjs | 67 +++--- yarn.lock | 4 +- 12 files changed, 440 insertions(+), 90 deletions(-) create mode 100644 tools/figma-codegen/src/codegen/data/component-sets/error-state.d.ts create mode 100644 tools/figma-codegen/src/codegen/data/component-sets/error-state.mjs diff --git a/docs/content/docs/react/components/action-sheet.mdx b/docs/content/docs/react/components/action-sheet.mdx index c9b52180a..283d04544 100644 --- a/docs/content/docs/react/components/action-sheet.mdx +++ b/docs/content/docs/react/components/action-sheet.mdx @@ -11,14 +11,21 @@ description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core ## Props -### ActionSheetRoot +### `ActionSheetRoot` -### ActionSheetItem +### `ActionSheetContent` + + + +### `ActionSheetItem` -### ExtendedActionSheetItem +### `ExtendedActionSheetContent` + + + +### `ExtendedActionSheetItem` = { count: Number(props["Count#7185:21"].value), }), }; - return createElement("ChipButton", commonProps, children); + return createElement("ActionChip", commonProps, children); + }, +}; + +const actionSheetHandler: ComponentHandler = { + key: metadata.actionSheet.key, + codegen: (node) => { + const { componentProperties: props } = node; + + const contentProps = match(props.Header.value) + .with("None", () => ({ + title: undefined, + description: undefined, + })) + .with("Title Only", () => ({ + title: props["Title#15641:37"].value, + description: undefined, + })) + .with("Description Only", () => ({ + title: undefined, + description: props["Description#15641:70"].value, + })) + .with("Title With Description", () => ({ + title: props["Title#15641:37"].value, + description: props["Description#15641:70"].value, + })) + .exhaustive(); + + const items = node.findAll( + (child) => + child.type === "INSTANCE" && + ((child.mainComponent?.parent?.type === "COMPONENT_SET" && + child.mainComponent?.parent.key === actionSheetItemHandler.key) || + child.mainComponent?.key === actionSheetItemHandler.key), + ) as (InstanceNode & { componentProperties: ActionSheetItemProperties })[]; + + const contentChildren = items.map(actionSheetItemHandler.codegen); + + console.log(contentProps, contentChildren); + + const content = createElement( + "ActionSheetContent", + contentProps, + contentChildren, + contentProps.title + ? "" + : "title을 제공하지 않는 경우 aria-label이나 aria-labelledby 중 하나를 제공해야 합니다.", + ); + + const trigger = createElement( + "ActionSheetTrigger", + { asChild: true }, + createElement("ActionButton", undefined, "열기", "ActionSheet을 여는 요소를 제공해주세요."), + ); + + return createElement("ActionSheet", undefined, [trigger, content]); + }, +}; + +const actionSheetItemHandler: ComponentHandler = { + key: "c3cafd3a3fdcd45fecb6971019d88eaf39a2e381", + codegen: ({ componentProperties: props }) => { + const states = props.State.value.split("-"); + + const commonProps = { + label: props["Label#15420:4"].value, + tone: camelCase(props.Tone.value), + ...(states.includes("Disabled") && { + disabled: true, + }), + }; + + return createElement("ActionSheetItem", commonProps); }, }; @@ -155,7 +234,10 @@ const avatarHandler: ComponentHandler = { codegen: (node) => { const placeholder = node.findOne( (child) => - child.type === "INSTANCE" && child.mainComponent?.key === identityPlaceholderHandler.key, + child.type === "INSTANCE" && + (child.mainComponent?.parent?.type === "COMPONENT_SET" + ? child.mainComponent.parent.key === identityPlaceholderHandler.key + : child.mainComponent?.key === identityPlaceholderHandler.key), ) as (InstanceNode & { componentProperties: IdentityPlaceholderProperties }) | null; const { componentProperties: props } = node; @@ -445,6 +527,117 @@ const controlChipHandler: ComponentHandler = { }, }; +const errorStateHandler: ComponentHandler = { + key: metadata.errorState.key, + codegen: (node) => { + const props = node.componentProperties; + + const actionButtonNode = node.findOne( + (child) => + child.type === "INSTANCE" && + ((child.mainComponent?.parent?.type === "COMPONENT_SET" && + child.mainComponent?.parent.key === actionButtonHandler.key) || + child.mainComponent?.key === actionButtonHandler.key), + ) as InstanceNode & { componentProperties: ActionButtonProperties }; + + const commonProps = { + variant: camelCase(props.Variant.value), + ...(props.Layout.value === "With Title" && { + title: props["Title#16237:0"].value, + }), + description: props["Description#16237:5"].value, + ...(actionButtonNode && { + primaryActionProps: { + children: actionButtonHandler.codegen(actionButtonNode).children[0], + }, + secondaryActionProps: { + children: props["Secondary Action Label#17042:0"].value, + }, + }), + }; + + return createElement("ErrorState", commonProps); + }, +}; + +const extendedActionSheetHandler: ComponentHandler = { + key: metadata.extendedActionSheet.key, + codegen: (node) => { + const { componentProperties: props } = node; + + const groups = node.findAll( + (child) => + child.type === "INSTANCE" && + ((child.mainComponent?.parent?.type === "COMPONENT_SET" && + child.mainComponent?.parent.key === extendedActionSheetGroupHandler.key) || + child.mainComponent?.key === extendedActionSheetGroupHandler.key), + ) as (InstanceNode & { componentProperties: ExtendedActionSheetGroupProperties })[]; + + const contentChildren = groups.map(extendedActionSheetGroupHandler.codegen); + + const title = props["Show Title#17043:12"].value ? props["Title#14599:0"].value : undefined; + + const content = createElement( + "ExtendedActionSheetContent", + { title }, + contentChildren, + title + ? "" + : "title을 제공하지 않는 경우 aria-label이나 aria-labelledby 중 하나를 제공해야 합니다.", + ); + + const trigger = createElement( + "ExtendedActionSheetTrigger", + { asChild: true }, + createElement( + "ActionButton", + undefined, + "열기", + "ExtendedActionSheet을 여는 요소를 제공해주세요.", + ), + ); + + return createElement("ExtendedActionSheet", undefined, [trigger, content]); + }, +}; + +const extendedActionSheetGroupHandler: ComponentHandler = { + key: "2a504a1c6b7810d5e652862dcba2cb7048f9eb16", + codegen: (node) => { + const items = node.findAll( + (child) => + child.type === "INSTANCE" && + ((child.mainComponent?.parent?.type === "COMPONENT_SET" && + child.mainComponent?.parent.key === extendedActionSheetItemHandler.key) || + child.mainComponent?.key === extendedActionSheetItemHandler.key), + ) as (InstanceNode & { componentProperties: ExtendedActionSheetItemProperties })[]; + + const contentChildren = items.map(extendedActionSheetItemHandler.codegen); + + return createElement("ExtendedActionSheetGroup", undefined, contentChildren); + }, +}; + +const extendedActionSheetItemHandler: ComponentHandler = { + key: "057083e95466da59051119eec0b41d4ad5a07f8f", + codegen: ({ componentProperties: props }) => { + const states = props.State.value.split("-"); + + const commonProps = { + tone: camelCase(props.Tone.value), + label: props["Label#55905:8"].value, + ...(props["Show Prefix Icon#17043:5"].value && { + prefixIcon: createElement(createIconTagNameFromId(props["Prefix Icon#55948:0"].value)), + }), + ...(states.includes("Disabled") && { + disabled: true, + }), + }; + + return createElement("ExtendedActionSheetItem", commonProps); + }, +}; + const extendedFabHandler: ComponentHandler = { key: metadata.extendedFloatingActionButton.key, codegen: ({ componentProperties: props }) => { @@ -609,6 +802,19 @@ const inlineBannerHandler: ComponentHandler = { }, }; +const mannerTempBadgeHandler: ComponentHandler = { + key: metadata.mannerTempBadge.key, + codegen: ({ children }) => { + const textNode = children.find((child) => child.type === "TEXT"); + + const commonProps = { + temperature: Number(textNode?.characters.replace(/[^\d.-]/g, "") ?? "-1"), + }; + + return createElement("MannerTempBadge", commonProps); + }, +}; + const multilineTextFieldHandler: ComponentHandler = { key: metadata.multilineTextField.key, codegen: ({ componentProperties: props }) => { @@ -1252,6 +1458,7 @@ const toggleButtonHandler: ComponentHandler = { const componentHandlers = [ actionButtonHandler, actionChipHandler, + actionSheetHandler, avatarHandler, avatarStackHandler, badgeHandler, @@ -1259,16 +1466,20 @@ const componentHandlers = [ checkboxHandler, chipTabsHandler, controlChipHandler, + errorStateHandler, + extendedActionSheetHandler, extendedFabHandler, fabHandler, helpBubbleHandler, identityPlaceholderHandler, inlineBannerHandler, + mannerTempBadgeHandler, multilineTextFieldHandler, progressCircleHandler, reactionButtonHandler, segmentedControlHandler, selectBoxGroupHandler, + selectBoxHandler, skeletonHandler, snackbarHandler, switchHandler, diff --git a/tools/figma-codegen/src/codegen/component/type.ts b/tools/figma-codegen/src/codegen/component/type.ts index b0265656f..f86719256 100644 --- a/tools/figma-codegen/src/codegen/component/type.ts +++ b/tools/figma-codegen/src/codegen/component/type.ts @@ -9,6 +9,27 @@ export type ActionChipProperties = InferFromDefinition< typeof metadata.actionChip.componentPropertyDefinitions >; +export type ActionSheetProperties = InferFromDefinition< + typeof metadata.actionSheet.componentPropertyDefinitions +>; + +export type ActionSheetItemProperties = InferFromDefinition<{ + "Label#15420:4": { + type: "TEXT"; + defaultValue: "액션 버튼"; + }; + Tone: { + type: "VARIANT"; + defaultValue: "Default"; + variantOptions: ["Default", "Critical"]; + }; + State: { + type: "VARIANT"; + defaultValue: "Enabled"; + variantOptions: ["Enabled", "Enabled-Pressed", "Disabled"]; + }; +}>; + export type AvatarProperties = InferFromDefinition< typeof metadata.avatar.componentPropertyDefinitions >; @@ -61,6 +82,48 @@ export type ControlChipProperties = InferFromDefinition< typeof metadata.controlChip.componentPropertyDefinitions >; +export type ErrorStateProperties = InferFromDefinition< + typeof metadata.errorState.componentPropertyDefinitions +>; + +export type ExtendedActionSheetProperties = InferFromDefinition< + typeof metadata.extendedActionSheet.componentPropertyDefinitions +>; + +export type ExtendedActionSheetGroupProperties = InferFromDefinition<{ + "Action Count": { + type: "VARIANT"; + defaultValue: "8"; + variantOptions: ["1", "2", "3", "4", "5", "6", "7", "8"]; + }; +}>; + +export type ExtendedActionSheetItemProperties = InferFromDefinition<{ + "Show Prefix Icon#17043:5": { + type: "BOOLEAN"; + defaultValue: true; + }; + "Label#55905:8": { + type: "TEXT"; + defaultValue: "액션 버튼"; + }; + "Prefix Icon#55948:0": { + type: "INSTANCE_SWAP"; + defaultValue: "17024:100799"; + preferredValues: []; + }; + Tone: { + type: "VARIANT"; + defaultValue: "Neutral"; + variantOptions: ["Neutral", "Critical"]; + }; + State: { + type: "VARIANT"; + defaultValue: "Enabled"; + variantOptions: ["Enabled", "Enabled-Pressed", "Disabled"]; + }; +}>; + export type ExtendedFabProperties = InferFromDefinition< typeof metadata.extendedFloatingActionButton.componentPropertyDefinitions >; @@ -81,6 +144,10 @@ export type InlineBannerProperties = InferFromDefinition< typeof metadata.inlineBanner.componentPropertyDefinitions >; +export type MannerTempBadgeProperties = InferFromDefinition< + typeof metadata.mannerTempBadge.componentPropertyDefinitions +>; + export type MultilineTextFieldProperties = InferFromDefinition< typeof metadata.multilineTextField.componentPropertyDefinitions >; diff --git a/tools/figma-codegen/src/codegen/data/component-sets/error-state.d.ts b/tools/figma-codegen/src/codegen/data/component-sets/error-state.d.ts new file mode 100644 index 000000000..842c60ff1 --- /dev/null +++ b/tools/figma-codegen/src/codegen/data/component-sets/error-state.d.ts @@ -0,0 +1,32 @@ +export declare const metadata: { + "name": "🟢 Error State", + "key": "39b4ecd0b5b4d35f4dc5791765ca04aa062a5172", + "componentPropertyDefinitions": { + "Secondary Action Label#17042:0": { + "type": "TEXT" + }, + "Title#16237:0": { + "type": "TEXT" + }, + "Description#16237:5": { + "type": "TEXT" + }, + "Show Buttons#9080:5": { + "type": "BOOLEAN" + }, + "Variant": { + "type": "VARIANT", + "variantOptions": [ + "Default", + "Basement" + ] + }, + "Layout": { + "type": "VARIANT", + "variantOptions": [ + "With Title", + "Description Only" + ] + } + } +}; diff --git a/tools/figma-codegen/src/codegen/data/component-sets/error-state.mjs b/tools/figma-codegen/src/codegen/data/component-sets/error-state.mjs new file mode 100644 index 000000000..0347951a5 --- /dev/null +++ b/tools/figma-codegen/src/codegen/data/component-sets/error-state.mjs @@ -0,0 +1,32 @@ +export const metadata = { + "name": "🟢 Error State", + "key": "39b4ecd0b5b4d35f4dc5791765ca04aa062a5172", + "componentPropertyDefinitions": { + "Secondary Action Label#17042:0": { + "type": "TEXT" + }, + "Title#16237:0": { + "type": "TEXT" + }, + "Description#16237:5": { + "type": "TEXT" + }, + "Show Buttons#9080:5": { + "type": "BOOLEAN" + }, + "Variant": { + "type": "VARIANT", + "variantOptions": [ + "Default", + "Basement" + ] + }, + "Layout": { + "type": "VARIANT", + "variantOptions": [ + "With Title", + "Description Only" + ] + } + } +}; diff --git a/tools/figma-codegen/src/codegen/data/component-sets/extended-action-sheet.d.ts b/tools/figma-codegen/src/codegen/data/component-sets/extended-action-sheet.d.ts index 1564c7f5a..7acbe34fc 100644 --- a/tools/figma-codegen/src/codegen/data/component-sets/extended-action-sheet.d.ts +++ b/tools/figma-codegen/src/codegen/data/component-sets/extended-action-sheet.d.ts @@ -2,6 +2,9 @@ export declare const metadata: { "name": "🟢 Extended Action Sheet", "key": "cd4cf8a850bf3de87b79080b36b421a649bf3fcb", "componentPropertyDefinitions": { + "Show Title#17043:12": { + "type": "BOOLEAN" + }, "OS Indicator (Figma Only)#81637:129": { "type": "BOOLEAN" }, @@ -18,13 +21,6 @@ export declare const metadata: { "Destructive" ] }, - "Header": { - "type": "VARIANT", - "variantOptions": [ - "True", - "False" - ] - }, "Action Group Count": { "type": "VARIANT", "variantOptions": [ diff --git a/tools/figma-codegen/src/codegen/data/component-sets/extended-action-sheet.mjs b/tools/figma-codegen/src/codegen/data/component-sets/extended-action-sheet.mjs index 63c3ce95f..0b49d20df 100644 --- a/tools/figma-codegen/src/codegen/data/component-sets/extended-action-sheet.mjs +++ b/tools/figma-codegen/src/codegen/data/component-sets/extended-action-sheet.mjs @@ -2,6 +2,9 @@ export const metadata = { "name": "🟢 Extended Action Sheet", "key": "cd4cf8a850bf3de87b79080b36b421a649bf3fcb", "componentPropertyDefinitions": { + "Show Title#17043:12": { + "type": "BOOLEAN" + }, "OS Indicator (Figma Only)#81637:129": { "type": "BOOLEAN" }, @@ -18,13 +21,6 @@ export const metadata = { "Destructive" ] }, - "Header": { - "type": "VARIANT", - "variantOptions": [ - "True", - "False" - ] - }, "Action Group Count": { "type": "VARIANT", "variantOptions": [ diff --git a/tools/figma-codegen/src/codegen/data/component-sets/index.d.ts b/tools/figma-codegen/src/codegen/data/component-sets/index.d.ts index 39312f2fe..8e7bc05c9 100644 --- a/tools/figma-codegen/src/codegen/data/component-sets/index.d.ts +++ b/tools/figma-codegen/src/codegen/data/component-sets/index.d.ts @@ -1,44 +1,45 @@ -export { metadata as chipTablist } from "./chip-tablist"; -export { metadata as bottomSheet } from "./bottom-sheet"; -export { metadata as rangeSlider } from "./range-slider"; -export { metadata as identityPlaceholder } from "./identity-placeholder"; -export { metadata as extendedFloatingActionButton } from "./extended-floating-action-button"; -export { metadata as toggleButton } from "./toggle-button"; -export { metadata as switch } from "./switch"; -export { metadata as divider } from "./divider"; -export { metadata as checkbox } from "./checkbox"; -export { metadata as helpBubble } from "./help-bubble"; -export { metadata as textButton } from "./text-button"; -export { metadata as multilineTextField } from "./multiline-text-field"; -export { metadata as slider } from "./slider"; -export { metadata as selectBoxGroup } from "./select-box-group"; +export { metadata as bottomFixedBar } from "./bottom-fixed-bar"; export { metadata as buttonGroup } from "./button-group"; +export { metadata as selectBoxGroup } from "./select-box-group"; +export { metadata as actionButton } from "./action-button"; export { metadata as actionChip } from "./action-chip"; +export { metadata as actionSheet } from "./action-sheet"; +export { metadata as avatar } from "./avatar"; +export { metadata as avatarStack } from "./avatar-stack"; export { metadata as badge } from "./badge"; -export { metadata as mannerTempBar } from "./manner-temp-bar"; -export { metadata as reactionButton } from "./reaction-button"; -export { metadata as topNavigationMainGlobal } from "./top-navigation-main-global"; +export { metadata as bottomNavigationGlobal } from "./bottom-navigation-global"; +export { metadata as bottomNavigationKr } from "./bottom-navigation-kr"; +export { metadata as bottomSheet } from "./bottom-sheet"; +export { metadata as callout } from "./callout"; +export { metadata as checkbox } from "./checkbox"; +export { metadata as chipTablist } from "./chip-tablist"; export { metadata as controlChip } from "./control-chip"; -export { metadata as tablist } from "./tablist"; +export { metadata as divider } from "./divider"; +export { metadata as errorState } from "./error-state"; +export { metadata as extendedActionSheet } from "./extended-action-sheet"; +export { metadata as extendedFloatingActionButton } from "./extended-floating-action-button"; +export { metadata as floatingActionButton } from "./floating-action-button"; +export { metadata as helpBubble } from "./help-bubble"; +export { metadata as identityPlaceholder } from "./identity-placeholder"; +export { metadata as inlineBanner } from "./inline-banner"; +export { metadata as mannerTemp } from "./manner-temp"; +export { metadata as mannerTempBar } from "./manner-temp-bar"; export { metadata as mannerTempBadge } from "./manner-temp-badge"; +export { metadata as multilineTextField } from "./multiline-text-field"; export { metadata as progressCircle } from "./progress-circle"; -export { metadata as actionSheet } from "./action-sheet"; -export { metadata as bottomNavigationKr } from "./bottom-navigation-kr"; -export { metadata as inlineBanner } from "./inline-banner"; export { metadata as radio } from "./radio"; -export { metadata as avatarStack } from "./avatar-stack"; -export { metadata as avatar } from "./avatar"; -export { metadata as actionButton } from "./action-button"; +export { metadata as rangeSlider } from "./range-slider"; +export { metadata as reactionButton } from "./reaction-button"; export { metadata as segmentedControl } from "./segmented-control"; -export { metadata as topNavigationMainKr } from "./top-navigation-main-kr"; -export { metadata as floatingActionButton } from "./floating-action-button"; -export { metadata as bottomNavigationGlobal } from "./bottom-navigation-global"; -export { metadata as callout } from "./callout"; -export { metadata as skeleton } from "./skeleton"; export { metadata as selectBox } from "./select-box"; -export { metadata as bottomFixedBar } from "./bottom-fixed-bar"; -export { metadata as extendedActionSheet } from "./extended-action-sheet"; +export { metadata as skeleton } from "./skeleton"; +export { metadata as slider } from "./slider"; export { metadata as snackbar } from "./snackbar"; -export { metadata as mannerTemp } from "./manner-temp"; -export { metadata as topNavigation } from "./top-navigation"; +export { metadata as switch } from "./switch"; +export { metadata as tablist } from "./tablist"; +export { metadata as textButton } from "./text-button"; export { metadata as textField } from "./text-field"; +export { metadata as toggleButton } from "./toggle-button"; +export { metadata as topNavigation } from "./top-navigation"; +export { metadata as topNavigationMainGlobal } from "./top-navigation-main-global"; +export { metadata as topNavigationMainKr } from "./top-navigation-main-kr"; diff --git a/tools/figma-codegen/src/codegen/data/component-sets/index.mjs b/tools/figma-codegen/src/codegen/data/component-sets/index.mjs index d96f7d133..14a5c800d 100644 --- a/tools/figma-codegen/src/codegen/data/component-sets/index.mjs +++ b/tools/figma-codegen/src/codegen/data/component-sets/index.mjs @@ -1,44 +1,45 @@ -export { metadata as chipTablist } from "./chip-tablist.mjs"; -export { metadata as bottomSheet } from "./bottom-sheet.mjs"; -export { metadata as rangeSlider } from "./range-slider.mjs"; -export { metadata as identityPlaceholder } from "./identity-placeholder.mjs"; -export { metadata as extendedFloatingActionButton } from "./extended-floating-action-button.mjs"; -export { metadata as toggleButton } from "./toggle-button.mjs"; -export { metadata as switch } from "./switch.mjs"; -export { metadata as divider } from "./divider.mjs"; -export { metadata as checkbox } from "./checkbox.mjs"; -export { metadata as helpBubble } from "./help-bubble.mjs"; -export { metadata as textButton } from "./text-button.mjs"; -export { metadata as multilineTextField } from "./multiline-text-field.mjs"; -export { metadata as slider } from "./slider.mjs"; -export { metadata as selectBoxGroup } from "./select-box-group.mjs"; +export { metadata as bottomFixedBar } from "./bottom-fixed-bar.mjs"; export { metadata as buttonGroup } from "./button-group.mjs"; +export { metadata as selectBoxGroup } from "./select-box-group.mjs"; +export { metadata as actionButton } from "./action-button.mjs"; export { metadata as actionChip } from "./action-chip.mjs"; +export { metadata as actionSheet } from "./action-sheet.mjs"; +export { metadata as avatar } from "./avatar.mjs"; +export { metadata as avatarStack } from "./avatar-stack.mjs"; export { metadata as badge } from "./badge.mjs"; -export { metadata as mannerTempBar } from "./manner-temp-bar.mjs"; -export { metadata as reactionButton } from "./reaction-button.mjs"; -export { metadata as topNavigationMainGlobal } from "./top-navigation-main-global.mjs"; +export { metadata as bottomNavigationGlobal } from "./bottom-navigation-global.mjs"; +export { metadata as bottomNavigationKr } from "./bottom-navigation-kr.mjs"; +export { metadata as bottomSheet } from "./bottom-sheet.mjs"; +export { metadata as callout } from "./callout.mjs"; +export { metadata as checkbox } from "./checkbox.mjs"; +export { metadata as chipTablist } from "./chip-tablist.mjs"; export { metadata as controlChip } from "./control-chip.mjs"; -export { metadata as tablist } from "./tablist.mjs"; +export { metadata as divider } from "./divider.mjs"; +export { metadata as errorState } from "./error-state.mjs"; +export { metadata as extendedActionSheet } from "./extended-action-sheet.mjs"; +export { metadata as extendedFloatingActionButton } from "./extended-floating-action-button.mjs"; +export { metadata as floatingActionButton } from "./floating-action-button.mjs"; +export { metadata as helpBubble } from "./help-bubble.mjs"; +export { metadata as identityPlaceholder } from "./identity-placeholder.mjs"; +export { metadata as inlineBanner } from "./inline-banner.mjs"; +export { metadata as mannerTemp } from "./manner-temp.mjs"; +export { metadata as mannerTempBar } from "./manner-temp-bar.mjs"; export { metadata as mannerTempBadge } from "./manner-temp-badge.mjs"; +export { metadata as multilineTextField } from "./multiline-text-field.mjs"; export { metadata as progressCircle } from "./progress-circle.mjs"; -export { metadata as actionSheet } from "./action-sheet.mjs"; -export { metadata as bottomNavigationKr } from "./bottom-navigation-kr.mjs"; -export { metadata as inlineBanner } from "./inline-banner.mjs"; export { metadata as radio } from "./radio.mjs"; -export { metadata as avatarStack } from "./avatar-stack.mjs"; -export { metadata as avatar } from "./avatar.mjs"; -export { metadata as actionButton } from "./action-button.mjs"; +export { metadata as rangeSlider } from "./range-slider.mjs"; +export { metadata as reactionButton } from "./reaction-button.mjs"; export { metadata as segmentedControl } from "./segmented-control.mjs"; -export { metadata as topNavigationMainKr } from "./top-navigation-main-kr.mjs"; -export { metadata as floatingActionButton } from "./floating-action-button.mjs"; -export { metadata as bottomNavigationGlobal } from "./bottom-navigation-global.mjs"; -export { metadata as callout } from "./callout.mjs"; -export { metadata as skeleton } from "./skeleton.mjs"; export { metadata as selectBox } from "./select-box.mjs"; -export { metadata as bottomFixedBar } from "./bottom-fixed-bar.mjs"; -export { metadata as extendedActionSheet } from "./extended-action-sheet.mjs"; +export { metadata as skeleton } from "./skeleton.mjs"; +export { metadata as slider } from "./slider.mjs"; export { metadata as snackbar } from "./snackbar.mjs"; -export { metadata as mannerTemp } from "./manner-temp.mjs"; -export { metadata as topNavigation } from "./top-navigation.mjs"; +export { metadata as switch } from "./switch.mjs"; +export { metadata as tablist } from "./tablist.mjs"; +export { metadata as textButton } from "./text-button.mjs"; export { metadata as textField } from "./text-field.mjs"; +export { metadata as toggleButton } from "./toggle-button.mjs"; +export { metadata as topNavigation } from "./top-navigation.mjs"; +export { metadata as topNavigationMainGlobal } from "./top-navigation-main-global.mjs"; +export { metadata as topNavigationMainKr } from "./top-navigation-main-kr.mjs"; diff --git a/yarn.lock b/yarn.lock index 38e9b6314..19f43f8da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7752,7 +7752,7 @@ __metadata: "@create-figma-plugin/tsconfig": "npm:^3.0.2" "@create-figma-plugin/utilities": "npm:^3.0.2" "@figma/plugin-typings": "npm:^1.107.0-beta.1" - "@seed-design/figma-extractor": "npm:^0.0.2" + "@seed-design/figma-extractor": "npm:^0.0.3" change-case: "npm:^5.2.0" ts-pattern: "npm:^5.2.0" typescript: "npm:^5.4.5" @@ -7785,7 +7785,7 @@ __metadata: languageName: unknown linkType: soft -"@seed-design/figma-extractor@npm:^0.0.2, @seed-design/figma-extractor@workspace:tools/figma-extractor": +"@seed-design/figma-extractor@npm:^0.0.3, @seed-design/figma-extractor@workspace:tools/figma-extractor": version: 0.0.0-use.local resolution: "@seed-design/figma-extractor@workspace:tools/figma-extractor" dependencies: From 8b4522ec91cbe333c5c966cdd8a8bb848c0723ed Mon Sep 17 00:00:00 2001 From: malangcat Date: Sun, 26 Jan 2025 23:51:11 +0900 Subject: [PATCH 3/6] refactor: root layout as server component --- docs/app/layout.tsx | 9 +++------ docs/components/theme-sync.tsx | 10 ++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 docs/components/theme-sync.tsx diff --git a/docs/app/layout.tsx b/docs/app/layout.tsx index a69957008..ac0cdfc4a 100644 --- a/docs/app/layout.tsx +++ b/docs/app/layout.tsx @@ -1,5 +1,3 @@ -"use client"; - import "@seed-design/stylesheet/base.css"; import "@seed-design/stylesheet/global.css"; import "@seed-design/stylesheet/token.css"; @@ -8,19 +6,17 @@ import "@stackflow/plugin-basic-ui/index.css"; import "simple-reveal/index.css"; import "./global.css"; -import { useThemeSync } from "@/hooks/useThemeSync"; +import GoogleAnalytics from "@/components/google-analytics"; +import ThemeSync from "@/components/theme-sync"; import { RootProvider } from "fumadocs-ui/provider"; import { Inter } from "next/font/google"; import type { ReactNode } from "react"; -import GoogleAnalytics from "@/components/google-analytics"; const inter = Inter({ subsets: ["latin"], }); export default function Layout({ children }: { children: ReactNode }) { - useThemeSync(); - return ( + {children} diff --git a/docs/components/theme-sync.tsx b/docs/components/theme-sync.tsx new file mode 100644 index 000000000..f3aa92ba9 --- /dev/null +++ b/docs/components/theme-sync.tsx @@ -0,0 +1,10 @@ +"use client"; + +import { useThemeSync } from "@/hooks/useThemeSync"; + +function ThemeSync() { + useThemeSync(); + + return null; +} +export default ThemeSync; From a40e62162d58b6ff4bea27829d9b8db2b992dee5 Mon Sep 17 00:00:00 2001 From: malangcat Date: Mon, 27 Jan 2025 00:04:08 +0900 Subject: [PATCH 4/6] feat: cleanup sanity --- .gitignore | 1 + docs/app/(home)/page.tsx | 13 +-- docs/app/blog/[[...slug]]/page.tsx | 102 ------------------ docs/app/blog/[slug]/page.tsx | 98 +++++++++++++++++ docs/app/blog/layout.tsx | 8 +- docs/app/docs/[[...slug]]/page.tsx | 31 +++++- docs/components/mdx/mdx-components.ts | 2 - docs/components/sanity/client.tsx | 8 -- docs/components/sanity/sanity-content.tsx | 68 ------------ .../docs/design/components/action-button.mdx | 2 - .../docs/design/components/action-chip.mdx | 2 - .../docs/design/components/alert-dialog.mdx | 2 - .../content/docs/design/components/avatar.mdx | 2 - docs/content/docs/design/components/badge.mdx | 2 - .../docs/design/components/bottom-sheet.mdx | 2 - .../docs/design/components/callout.mdx | 2 - .../docs/design/components/control-chip.mdx | 2 - .../docs/design/components/extended-fab.mdx | 2 - docs/content/docs/design/components/fab.mdx | 2 - .../docs/design/components/inline-banner.mdx | 2 - .../design/components/progress-circle.mdx | 2 - .../design/components/reaction-button.mdx | 2 - .../design/components/segmented-control.mdx | 2 - .../docs/design/components/select-box.mdx | 2 - .../docs/design/components/text-button.mdx | 2 - .../docs/design/components/text-field.mdx | 2 - .../docs/design/components/toggle-button.mdx | 2 - .../docs/design/components/top-navigation.mdx | 2 - .../foundation/iconography/overview.mdx | 2 - .../design/foundation/iconography/usage.mdx | 2 - .../content/docs/design/foundation/radius.mdx | 2 - .../docs/design/guidelines/loading.mdx | 2 - docs/sanity.config.ts | 1 - docs/sanity/lib/client.tsx | 9 ++ .../sanity => sanity/lib}/do-dont.tsx | 0 .../sanity => sanity/lib}/external-image.tsx | 0 .../sanity => sanity/lib}/image-text-half.tsx | 4 +- .../sanity => sanity/lib}/image.tsx | 11 +- docs/sanity/lib/queries.ts | 24 +++++ docs/sanity/lib/sanity-content.tsx | 66 ++++++++++++ .../sanity => sanity/lib}/table.tsx | 2 - .../sanity => sanity/lib}/types.ts | 0 42 files changed, 239 insertions(+), 255 deletions(-) delete mode 100644 docs/app/blog/[[...slug]]/page.tsx create mode 100644 docs/app/blog/[slug]/page.tsx delete mode 100644 docs/components/sanity/client.tsx delete mode 100644 docs/components/sanity/sanity-content.tsx create mode 100644 docs/sanity/lib/client.tsx rename docs/{components/sanity => sanity/lib}/do-dont.tsx (100%) rename docs/{components/sanity => sanity/lib}/external-image.tsx (100%) rename docs/{components/sanity => sanity/lib}/image-text-half.tsx (92%) rename docs/{components/sanity => sanity/lib}/image.tsx (90%) create mode 100644 docs/sanity/lib/queries.ts create mode 100644 docs/sanity/lib/sanity-content.tsx rename docs/{components/sanity => sanity/lib}/table.tsx (98%) rename docs/{components/sanity => sanity/lib}/types.ts (100%) diff --git a/.gitignore b/.gitignore index 892eef53f..2a97b1a84 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ **/node_modules/ lib +!docs/**/lib \ No newline at end of file diff --git a/docs/app/(home)/page.tsx b/docs/app/(home)/page.tsx index b76d9fd76..4838a3b60 100644 --- a/docs/app/(home)/page.tsx +++ b/docs/app/(home)/page.tsx @@ -1,5 +1,6 @@ -import { client } from "@/components/sanity/client"; -import { SanityImage } from "@/components/sanity/image"; +import { client } from "@/sanity/lib/client"; +import { SanityImage } from "@/sanity/lib/image"; +import { BLOG_QUERY } from "@/sanity/lib/queries"; import type { SanityImageAsset } from "@sanity/asset-utils"; import Link from "next/link"; @@ -14,14 +15,6 @@ interface Blog { publishedAt: string; } -const BLOG_QUERY = `*[_type == "blog"] { - title, - description, - thumbnail, - slug, - publishedAt, -}`; - export default async function HomePage() { const blogs = await client.fetch( BLOG_QUERY, diff --git a/docs/app/blog/[[...slug]]/page.tsx b/docs/app/blog/[[...slug]]/page.tsx deleted file mode 100644 index 805f7c30a..000000000 --- a/docs/app/blog/[[...slug]]/page.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { client } from "@/components/sanity/client"; -import { SanityImage } from "@/components/sanity/image"; -import { PortableContent } from "@/components/sanity/sanity-content"; -import { SanityImageAsset } from "@sanity/asset-utils"; -import { DocsBody, DocsDescription, DocsPage, DocsTitle } from "fumadocs-ui/page"; -import { Metadata } from "next"; -import { notFound } from "next/navigation"; - -interface Blog { - title: string; - description: string; - thumbnail: SanityImageAsset; - slug: { - current: string; - _type: "slug"; - }; - publishedAt: string; - // biome-ignore lint/suspicious/noExplicitAny: - content: any; -} - -const BLOG_QUERY = `*[_type == "blog"] { - title, - description, - thumbnail, - slug, - publishedAt, - content - }`; - -const SINGLE_BLOG_QUERY = `*[_type == "blog" && slug.current == $slug][0] { - title, - description, - thumbnail, - slug, - publishedAt, - content - }`; - -export default async function Page({ - params, -}: { - params: { slug?: string[] }; -}) { - if (!params.slug) notFound(); - - const blog = await client.fetch(SINGLE_BLOG_QUERY, { - slug: params.slug[0], - }); - - if (!blog) { - return ( - - - - ); - } - - return ( - - {blog.title} - {blog.description} - - - - - - ); -} - -export async function generateStaticParams() { - const blogs = await client.fetch( - BLOG_QUERY, - {}, - { - perspective: "published", - }, - ); - - const slugs = blogs.map((blog) => { - return { slug: [blog.slug.current] }; - }); - - return slugs; -} - -export async function generateMetadata({ params }: { params: { slug?: string[] } }) { - const blogs = await client.fetch( - BLOG_QUERY, - {}, - { - perspective: "published", - }, - ); - - const page = blogs.find((blog) => blog.slug.current === params.slug?.[0]); - - return { - title: page?.title, - description: page?.description, - } satisfies Metadata; -} diff --git a/docs/app/blog/[slug]/page.tsx b/docs/app/blog/[slug]/page.tsx new file mode 100644 index 000000000..541fd6c1a --- /dev/null +++ b/docs/app/blog/[slug]/page.tsx @@ -0,0 +1,98 @@ +import { client } from "@/sanity/lib/client"; +import { SanityImage } from "@/sanity/lib/image"; +import { BLOG_QUERY, SINGLE_BLOG_QUERY } from "@/sanity/lib/queries"; +import { PortableContent } from "@/sanity/lib/sanity-content"; +import { SanityImageAsset } from "@sanity/asset-utils"; +import { DocsBody, DocsDescription, DocsPage, DocsTitle } from "fumadocs-ui/page"; +import { Metadata } from "next"; +import { notFound } from "next/navigation"; +import { PortableTextBlock } from "sanity"; + +interface Blog { + title: string; + description: string; + thumbnail: SanityImageAsset; + slug: { + current: string; + _type: "slug"; + }; + publishedAt: string; + content: PortableTextBlock | PortableTextBlock[]; + toc?: { + _key: string; + level: number; + }[]; +} + +export default async function Page({ + params, +}: { + params: { slug?: string }; +}) { + const page = await client.fetch(SINGLE_BLOG_QUERY, { + slug: params.slug, + }); + + if (!page) { + notFound(); + } + + const toc = page.toc?.map((item) => { + return { + depth: item.level ?? 0, + title: ( + + ), + url: `#${item._key}`, + }; + }); + + return ( + + {page.title} + {page.description} + + + + + + ); +} + +export async function generateStaticParams() { + const blogs = await client.fetch( + BLOG_QUERY, + {}, + { + perspective: "published", + }, + ); + + const slugs = blogs.map((blog) => { + return { slug: blog.slug.current }; + }); + + return slugs; +} + +export async function generateMetadata({ params }: { params: { slug?: string } }) { + const blogs = await client.fetch( + BLOG_QUERY, + {}, + { + perspective: "published", + }, + ); + + const page = blogs.find((blog) => blog.slug.current === params.slug); + + return { + title: page?.title, + description: page?.description, + } satisfies Metadata; +} diff --git a/docs/app/blog/layout.tsx b/docs/app/blog/layout.tsx index 045551d6f..f50d637c4 100644 --- a/docs/app/blog/layout.tsx +++ b/docs/app/blog/layout.tsx @@ -1,11 +1,7 @@ import { DocsLayout } from "fumadocs-ui/layouts/docs"; -import { Suspense, type ReactNode } from "react"; +import { type ReactNode } from "react"; import { docsOptions } from "../layout.config"; export default function Layout({ children }: { children: ReactNode }) { - return ( - - {children} - - ); + return {children}; } diff --git a/docs/app/docs/[[...slug]]/page.tsx b/docs/app/docs/[[...slug]]/page.tsx index d11c25d8e..53a28d55f 100644 --- a/docs/app/docs/[[...slug]]/page.tsx +++ b/docs/app/docs/[[...slug]]/page.tsx @@ -1,8 +1,12 @@ import { source } from "@/app/source"; import { mdxComponents } from "@/components/mdx/mdx-components"; +import { client } from "@/sanity/lib/client"; +import { GUIDELINE_QUERY } from "@/sanity/lib/queries"; +import { PortableContent } from "@/sanity/lib/sanity-content"; import { DocsBody, DocsDescription, DocsPage, DocsTitle } from "fumadocs-ui/page"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; +import { PortableTextBlock } from "sanity"; export default async function Page({ params, @@ -14,11 +18,36 @@ export default async function Page({ const MDX = page.data.body; + const guideline = params.slug?.includes("design") + ? await client.fetch(GUIDELINE_QUERY, { title: page.data.title }) + : null; + + const guidelineToc = + guideline?.toc?.map((item: PortableTextBlock) => { + return { + depth: item.level ?? 0, + title: ( + + ), + url: `#${item._key}`, + }; + }) ?? []; + return ( - + {page.data.title} {page.data.description} + {guideline && } diff --git a/docs/components/mdx/mdx-components.ts b/docs/components/mdx/mdx-components.ts index 5e5782c9b..3762ca652 100644 --- a/docs/components/mdx/mdx-components.ts +++ b/docs/components/mdx/mdx-components.ts @@ -1,7 +1,6 @@ import { ComponentExample } from "@/components/component-example"; import { ComponentSpecBlock } from "@/components/component-spec-block"; import { Installation } from "@/components/installation"; -import { SanityGuideline } from "@/components/sanity/sanity-content"; import { StackflowExample } from "@/components/stackflow-example"; import { File, Files, Folder } from "fumadocs-ui/components/files"; import { Step, Steps } from "fumadocs-ui/components/steps"; @@ -19,7 +18,6 @@ export const mdxComponents = { ComponentExample, TokenReference, ComponentSpecBlock, - SanityGuideline, Tab, Tabs, Step, diff --git a/docs/components/sanity/client.tsx b/docs/components/sanity/client.tsx deleted file mode 100644 index fe658e8b7..000000000 --- a/docs/components/sanity/client.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { createClient } from "@sanity/client"; - -export const client = createClient({ - projectId: "mokd6dka", - dataset: "production", - apiVersion: "2024-01-01", - useCdn: true, -}); diff --git a/docs/components/sanity/sanity-content.tsx b/docs/components/sanity/sanity-content.tsx deleted file mode 100644 index 8b524c175..000000000 --- a/docs/components/sanity/sanity-content.tsx +++ /dev/null @@ -1,68 +0,0 @@ -"use client"; - -import { PortableText } from "@portabletext/react"; -import type { SanityDocument } from "next-sanity"; -import { client } from "./client"; - -import { ImageTextHalfPreview } from "@/components/sanity/image-text-half"; -import { useEffect, useState } from "react"; -import ErrorBoundary from "../error-boundary"; -import { DoDont } from "./do-dont"; -import { ExternalImage } from "./external-image"; -import { PortableImage } from "./image"; -import { Table } from "./table"; - -interface SanityGuidelineProps { - title: string; -} - -const GUIDELINE_QUERY = `*[_type == "guideline" && title == $title][0] { - title, - content, - publishedAt -}`; - -export const SanityGuideline = ({ title }: SanityGuidelineProps) => { - const [data, setData] = useState(null); - - useEffect(() => { - const fetchData = async () => { - const data = await client.fetch(GUIDELINE_QUERY, { title }); - setData(data); - }; - fetchData(); - }, [title]); - - if (!data) { - return null; - } - - return ( - - - - ); -}; - -// biome-ignore lint/suspicious/noExplicitAny: -export const PortableContent = ({ content }: { content: any }) => { - return ( - , - tabelContainer: Table, - imageWithText: ImageTextHalfPreview, - externalImageLink: ExternalImage, - doDont: DoDont, - }, - block: { - normal: (props) =>

, - h3: (props) =>

, - description: (props) => , - }, - }} - value={content} - /> - ); -}; diff --git a/docs/content/docs/design/components/action-button.mdx b/docs/content/docs/design/components/action-button.mdx index d36125d81..7c9ad181b 100644 --- a/docs/content/docs/design/components/action-button.mdx +++ b/docs/content/docs/design/components/action-button.mdx @@ -3,8 +3,6 @@ title: Action Button description: 사용자가 특정 액션을 실행할 수 있도록 도와주는 컴포넌트입니다. --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/action-chip.mdx b/docs/content/docs/design/components/action-chip.mdx index a003dcfe5..0beb130b0 100644 --- a/docs/content/docs/design/components/action-chip.mdx +++ b/docs/content/docs/design/components/action-chip.mdx @@ -3,8 +3,6 @@ title: Action Chip description: 사용자가 특정 액션을 실행할 수 있도록 도와주는 Pill 형태의 컴포넌트입니다. --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/alert-dialog.mdx b/docs/content/docs/design/components/alert-dialog.mdx index c2a0b2a58..da0bd89c5 100644 --- a/docs/content/docs/design/components/alert-dialog.mdx +++ b/docs/content/docs/design/components/alert-dialog.mdx @@ -3,8 +3,6 @@ title: Alert Dialog description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/avatar.mdx b/docs/content/docs/design/components/avatar.mdx index 9b11fbefb..31faefef9 100644 --- a/docs/content/docs/design/components/avatar.mdx +++ b/docs/content/docs/design/components/avatar.mdx @@ -3,8 +3,6 @@ title: Avatar description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 (Avatar) diff --git a/docs/content/docs/design/components/badge.mdx b/docs/content/docs/design/components/badge.mdx index 84861326d..8c71fd07f 100644 --- a/docs/content/docs/design/components/badge.mdx +++ b/docs/content/docs/design/components/badge.mdx @@ -3,8 +3,6 @@ title: Badge description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/bottom-sheet.mdx b/docs/content/docs/design/components/bottom-sheet.mdx index d9eeceb0f..cdc48000e 100644 --- a/docs/content/docs/design/components/bottom-sheet.mdx +++ b/docs/content/docs/design/components/bottom-sheet.mdx @@ -3,8 +3,6 @@ title: Bottom Sheet description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/callout.mdx b/docs/content/docs/design/components/callout.mdx index bffbd2aac..14450dab7 100644 --- a/docs/content/docs/design/components/callout.mdx +++ b/docs/content/docs/design/components/callout.mdx @@ -3,8 +3,6 @@ title: Callout description: 사용자의 주목을 끌어 중요한 정보를 강조하는 컴포넌트입니다. --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/control-chip.mdx b/docs/content/docs/design/components/control-chip.mdx index e0abb7cd0..4a19b7f63 100644 --- a/docs/content/docs/design/components/control-chip.mdx +++ b/docs/content/docs/design/components/control-chip.mdx @@ -3,8 +3,6 @@ title: Control Chip description: Control Chip은 사용자가 선택, 필터링, 전환과 같은 제어 작업을 수행할 수 있도록 돕는 Pill 형태의 컴포넌트입니다. --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/extended-fab.mdx b/docs/content/docs/design/components/extended-fab.mdx index 95d287bad..1c2ba4f42 100644 --- a/docs/content/docs/design/components/extended-fab.mdx +++ b/docs/content/docs/design/components/extended-fab.mdx @@ -3,8 +3,6 @@ title: Extended FAB description: 사용자가 특정 액션을 실행할 수 있도록 도와주는 컴포넌트입니다. --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/fab.mdx b/docs/content/docs/design/components/fab.mdx index 1bf2d62cb..500a67500 100644 --- a/docs/content/docs/design/components/fab.mdx +++ b/docs/content/docs/design/components/fab.mdx @@ -3,8 +3,6 @@ title: FAB description: 사용자가 특정 액션을 실행할 수 있도록 도와주는 컴포넌트입니다. --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/inline-banner.mdx b/docs/content/docs/design/components/inline-banner.mdx index 93bd962cf..1b5987baf 100644 --- a/docs/content/docs/design/components/inline-banner.mdx +++ b/docs/content/docs/design/components/inline-banner.mdx @@ -3,8 +3,6 @@ title: Inline Banner description: 사용자가 꼭 알아야 하는 경고 메시지나 현재 상태를 전달하는 컴포넌트입니다. --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/progress-circle.mdx b/docs/content/docs/design/components/progress-circle.mdx index 8fc9b0c54..d5bf34bf8 100644 --- a/docs/content/docs/design/components/progress-circle.mdx +++ b/docs/content/docs/design/components/progress-circle.mdx @@ -3,8 +3,6 @@ title: Progress Circle description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/reaction-button.mdx b/docs/content/docs/design/components/reaction-button.mdx index b2a4055f9..0d2ab3882 100644 --- a/docs/content/docs/design/components/reaction-button.mdx +++ b/docs/content/docs/design/components/reaction-button.mdx @@ -3,8 +3,6 @@ title: Reaction Button description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/segmented-control.mdx b/docs/content/docs/design/components/segmented-control.mdx index 9e8a5a11a..e9fed80c7 100644 --- a/docs/content/docs/design/components/segmented-control.mdx +++ b/docs/content/docs/design/components/segmented-control.mdx @@ -3,8 +3,6 @@ title: Segmented Control description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 (Segment) diff --git a/docs/content/docs/design/components/select-box.mdx b/docs/content/docs/design/components/select-box.mdx index 4b664fd69..e4f226ca6 100644 --- a/docs/content/docs/design/components/select-box.mdx +++ b/docs/content/docs/design/components/select-box.mdx @@ -3,8 +3,6 @@ title: Select Box description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/text-button.mdx b/docs/content/docs/design/components/text-button.mdx index 17b248b13..fe7152a67 100644 --- a/docs/content/docs/design/components/text-button.mdx +++ b/docs/content/docs/design/components/text-button.mdx @@ -3,8 +3,6 @@ title: Text Button description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/text-field.mdx b/docs/content/docs/design/components/text-field.mdx index d1cd9a6e2..358ca3bb6 100644 --- a/docs/content/docs/design/components/text-field.mdx +++ b/docs/content/docs/design/components/text-field.mdx @@ -3,8 +3,6 @@ title: Text Field description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/toggle-button.mdx b/docs/content/docs/design/components/toggle-button.mdx index 7c96f10c8..e19cbbac8 100644 --- a/docs/content/docs/design/components/toggle-button.mdx +++ b/docs/content/docs/design/components/toggle-button.mdx @@ -3,8 +3,6 @@ title: Toggle Button description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/components/top-navigation.mdx b/docs/content/docs/design/components/top-navigation.mdx index e0aeb416d..d4ce73a85 100644 --- a/docs/content/docs/design/components/top-navigation.mdx +++ b/docs/content/docs/design/components/top-navigation.mdx @@ -3,8 +3,6 @@ title: Top Navigation description: "이 문서는 정리 중이에요. 문의 내용은 #_design_core 채널을 찾아주세요." --- - - ## 개요 ### 옵션 테이블 diff --git a/docs/content/docs/design/foundation/iconography/overview.mdx b/docs/content/docs/design/foundation/iconography/overview.mdx index 8e655b1c6..b5ed3076e 100644 --- a/docs/content/docs/design/foundation/iconography/overview.mdx +++ b/docs/content/docs/design/foundation/iconography/overview.mdx @@ -2,5 +2,3 @@ title: Overview description: 아이콘은 사용자가 복잡한 정보나 기능을 빠르게 이해할 수 있도록 도와주는 디자인 요소입니다. --- - - diff --git a/docs/content/docs/design/foundation/iconography/usage.mdx b/docs/content/docs/design/foundation/iconography/usage.mdx index 291f8c31f..0fae620fd 100644 --- a/docs/content/docs/design/foundation/iconography/usage.mdx +++ b/docs/content/docs/design/foundation/iconography/usage.mdx @@ -2,5 +2,3 @@ title: Usage description: 아이콘과 다른 디자인 요소 간의 상호작용 및 아이콘 사용 방법에 대해 설명합니다. --- - - diff --git a/docs/content/docs/design/foundation/radius.mdx b/docs/content/docs/design/foundation/radius.mdx index 10169ac41..613447153 100644 --- a/docs/content/docs/design/foundation/radius.mdx +++ b/docs/content/docs/design/foundation/radius.mdx @@ -3,8 +3,6 @@ title: Radius description: Radius는 컴포넌트 혹은 콘텐츠 모서리의 둥글기를 표현합니다. --- - - ### Radius Tokens diff --git a/docs/content/docs/design/guidelines/loading.mdx b/docs/content/docs/design/guidelines/loading.mdx index 304aefd21..84b8274d9 100644 --- a/docs/content/docs/design/guidelines/loading.mdx +++ b/docs/content/docs/design/guidelines/loading.mdx @@ -2,5 +2,3 @@ title: Loading description: 로딩을 관리하는 데 필요한 요소, 시간에 따른 적합한 선택지와 단계별로 사용자 경험을 최적화하는 방법에 대해 소개합니다. --- - - diff --git a/docs/sanity.config.ts b/docs/sanity.config.ts index 3b9ff3da0..3ac1d74d2 100644 --- a/docs/sanity.config.ts +++ b/docs/sanity.config.ts @@ -18,7 +18,6 @@ import { schema } from "./sanity/schemaTypes"; import { table } from "@sanity/table"; export default defineConfig({ - basePath: "/studio", projectId, dataset, // Add and edit the content schema in the './sanity/schemaTypes' folder diff --git a/docs/sanity/lib/client.tsx b/docs/sanity/lib/client.tsx new file mode 100644 index 000000000..5cd7d7f7e --- /dev/null +++ b/docs/sanity/lib/client.tsx @@ -0,0 +1,9 @@ +import { createClient } from "@sanity/client"; +import { apiVersion, dataset, projectId } from "../env"; + +export const client = createClient({ + projectId: projectId, + dataset: dataset, + apiVersion: apiVersion, + useCdn: false, +}); diff --git a/docs/components/sanity/do-dont.tsx b/docs/sanity/lib/do-dont.tsx similarity index 100% rename from docs/components/sanity/do-dont.tsx rename to docs/sanity/lib/do-dont.tsx diff --git a/docs/components/sanity/external-image.tsx b/docs/sanity/lib/external-image.tsx similarity index 100% rename from docs/components/sanity/external-image.tsx rename to docs/sanity/lib/external-image.tsx diff --git a/docs/components/sanity/image-text-half.tsx b/docs/sanity/lib/image-text-half.tsx similarity index 92% rename from docs/components/sanity/image-text-half.tsx rename to docs/sanity/lib/image-text-half.tsx index 210e298a6..1b93191f9 100644 --- a/docs/components/sanity/image-text-half.tsx +++ b/docs/sanity/lib/image-text-half.tsx @@ -1,11 +1,11 @@ "use client"; -import { PortableContent } from "@/components/sanity/sanity-content"; -import { PortableTextBlock } from "@portabletext/react"; +import { PortableTextBlock } from "sanity"; import { SanityImageAsset } from "@sanity/asset-utils"; import imageUrlBuilder from "@sanity/image-url"; import { useCallback } from "react"; import { client } from "./client"; +import { PortableContent } from "./sanity-content"; const builder = imageUrlBuilder(client); diff --git a/docs/components/sanity/image.tsx b/docs/sanity/lib/image.tsx similarity index 90% rename from docs/components/sanity/image.tsx rename to docs/sanity/lib/image.tsx index 97660dc2c..6d1934498 100644 --- a/docs/components/sanity/image.tsx +++ b/docs/sanity/lib/image.tsx @@ -1,14 +1,13 @@ "use client"; -import imageUrlBuilder from "@sanity/image-url"; -import { client } from "./client"; - import type { PortableTextTypeComponentProps } from "@portabletext/react"; import { getImageDimensions, SanityImageAsset } from "@sanity/asset-utils"; -import { SanityImageType } from "./types"; +import imageUrlBuilder from "@sanity/image-url"; import clsx from "clsx"; +import { client } from "./client"; +import { SanityImageType } from "./types"; -const { projectId, dataset } = client.config(); +const builder = imageUrlBuilder(client); interface ImageProps { value: SanityImageAsset; @@ -20,7 +19,6 @@ export const SanityImage = ({ value, className }: ImageProps) => { return
; } - const builder = imageUrlBuilder({ projectId: projectId!, dataset: dataset! }); const cdnUrl = builder .image(value) .width(1000) @@ -48,7 +46,6 @@ export const PortableImage = ({ value }: PortableTextTypeComponentProps const { aspectRatio } = getImageDimensions(value as any); - const builder = imageUrlBuilder({ projectId: projectId!, dataset: dataset! }); // Sanity CDN URL 생성 const cdnUrl = builder diff --git a/docs/sanity/lib/queries.ts b/docs/sanity/lib/queries.ts new file mode 100644 index 000000000..f8c903836 --- /dev/null +++ b/docs/sanity/lib/queries.ts @@ -0,0 +1,24 @@ +export const BLOG_QUERY = `*[_type == "blog"] { + title, + description, + thumbnail, + slug, + publishedAt, +}`; + +export const SINGLE_BLOG_QUERY = `*[_type == "blog" && slug.current == $slug][0] { + title, + description, + thumbnail, + slug, + publishedAt, + content, + "toc": content[style in ["h1", "h2", "h3", "h4", "h5", "h6"]] +}`; + +export const GUIDELINE_QUERY = `*[_type == "guideline" && title == $title][0] { + title, + content, + publishedAt, + "toc": content[style in ["h1", "h2", "h3", "h4", "h5", "h6"]] +}`; diff --git a/docs/sanity/lib/sanity-content.tsx b/docs/sanity/lib/sanity-content.tsx new file mode 100644 index 000000000..76c71e3e5 --- /dev/null +++ b/docs/sanity/lib/sanity-content.tsx @@ -0,0 +1,66 @@ +"use client"; + +import { PortableText } from "@portabletext/react"; +import { Heading } from "fumadocs-ui/components/heading"; +import { PortableTextBlock } from "sanity"; +import { DoDont } from "./do-dont"; +import { ExternalImage } from "./external-image"; +import { PortableImage } from "./image"; +import { ImageTextHalfPreview } from "./image-text-half"; +import { Table } from "./table"; + +export const PortableContent = ({ + content, +}: { content: PortableTextBlock | PortableTextBlock[] }) => { + return ( + ( +

+ {children} +

+ ), + h1: ({ value, children }) => ( + + {children} + + ), + h2: ({ value, children }) => ( + + {children} + + ), + h3: ({ value, children }) => ( + + {children} + + ), + h4: ({ value, children }) => ( + + {children} + + ), + h5: ({ value, children }) => ( + + {children} + + ), + description: ({ value, children }) => ( + + {children} + + ), + }, + }} + value={content} + /> + ); +}; diff --git a/docs/components/sanity/table.tsx b/docs/sanity/lib/table.tsx similarity index 98% rename from docs/components/sanity/table.tsx rename to docs/sanity/lib/table.tsx index 120ea8e3f..682515a34 100644 --- a/docs/components/sanity/table.tsx +++ b/docs/sanity/lib/table.tsx @@ -1,5 +1,3 @@ -"use client"; - import type { PortableTextTypeComponentProps } from "@portabletext/react"; interface TableContainerProps { diff --git a/docs/components/sanity/types.ts b/docs/sanity/lib/types.ts similarity index 100% rename from docs/components/sanity/types.ts rename to docs/sanity/lib/types.ts From a909bfc6f46bdaeffdf84a64b9d26e18a6158d2a Mon Sep 17 00:00:00 2001 From: malangcat Date: Mon, 27 Jan 2025 00:04:31 +0900 Subject: [PATCH 5/6] feat: add mainDocuments to presentation tool --- docs/sanity.config.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/sanity.config.ts b/docs/sanity.config.ts index 3ac1d74d2..fbab51fe8 100644 --- a/docs/sanity.config.ts +++ b/docs/sanity.config.ts @@ -8,7 +8,7 @@ import { visionTool } from "@sanity/vision"; import { defineConfig } from "sanity"; import { structure } from "./sanity/structure"; import { structureTool } from "sanity/structure"; -import { presentationTool, defineLocations } from "sanity/presentation"; +import { presentationTool, defineLocations, defineDocuments } from "sanity/presentation"; import * as changeCase from "change-case"; // Go to https://www.sanity.io/docs/api-versioning to learn how API versioning works @@ -26,6 +26,10 @@ export default defineConfig({ structureTool({ structure }), presentationTool({ resolve: { + // TODO: add design guidelines to mainDocuments + mainDocuments: defineDocuments([ + { route: "/blog/:slug", filter: `_type == "blog" && slug.current == $slug` }, + ]), locations: { contents: defineLocations({ select: { From 3f065f2720ee2ce903edb100522c054200da24e4 Mon Sep 17 00:00:00 2001 From: malangcat Date: Mon, 27 Jan 2025 00:06:18 +0900 Subject: [PATCH 6/6] feat: studio layout as server component --- docs/app/(studio)/admin/page.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/app/(studio)/admin/page.tsx b/docs/app/(studio)/admin/page.tsx index 06351f8d9..a60ba1caa 100644 --- a/docs/app/(studio)/admin/page.tsx +++ b/docs/app/(studio)/admin/page.tsx @@ -1,5 +1,3 @@ -"use client"; - /** * This route is responsible for the built-in authoring environment using Sanity Studio. * All routes under your studio path is handled by this file using Next.js' catch-all routes: @@ -14,7 +12,7 @@ import config from "../../../sanity.config"; export const dynamic = "force-static"; -export { viewport } from "next-sanity/studio"; +export { viewport, metadata } from "next-sanity/studio"; export default function StudioPage() { return ;