Used in projects like React

Most frontend frameworks/libraries can seamlessly use custom elements, such as assigning Attributes/Properties and registering events. However, directly using custom elements lacks type hints, so DuoyunUI has been re-exported to perfectly adapt to React/Vue/Svelte.

React

NOTE

React 19 supports custom elements. Please ensure you have React 19 installed.

Use DuoyunUI just like any other React component library:

import { useRef, useState } from 'react'; import Layout from '../components/layout'; import type { DyColorPickerMethods } from 'duoyun-ui/react/DyColorPicker'; import DyActionText, { DuoyunActionTextElement } from 'duoyun-ui/react/DyActionText' import DyActiveLink, { DuoyunActiveLinkElement } from 'duoyun-ui/react/DyActiveLink' import DyAlert, { DuoyunAlertElement } from 'duoyun-ui/react/DyAlert' import DyAreaChart, { DuoyunAreaChartElement } from 'duoyun-ui/react/DyAreaChart' import DyAvatar, { DuoyunAvatarElement } from 'duoyun-ui/react/DyAvatar' import DyAvatarGroup, { DuoyunAvatarGroupElement } from 'duoyun-ui/react/DyAvatarGroup' import DyBanner, { DuoyunBannerElement } from 'duoyun-ui/react/DyBanner' import DyBarChart, { DuoyunBarChartElement } from 'duoyun-ui/react/DyBarChart' import DyBreadcrumbs, { DuoyunBreadcrumbsElement } from 'duoyun-ui/react/DyBreadcrumbs' import DyButton, { DuoyunButtonElement } from 'duoyun-ui/react/DyButton' import DyCalendar, { DuoyunCalendarElement } from 'duoyun-ui/react/DyCalendar' import DyCard, { DuoyunCardElement } from 'duoyun-ui/react/DyCard' import DyCarousel, { DuoyunCarouselElement } from 'duoyun-ui/react/DyCarousel' import DyCascader, { DuoyunCascaderElement } from 'duoyun-ui/react/DyCascader' import DyCascaderPicker, { DuoyunCascaderPickerElement } from 'duoyun-ui/react/DyCascaderPicker' import DyChartTooltip, { DuoyunChartTooltipElement } from 'duoyun-ui/react/DyChartTooltip' import DyChartZoom, { DuoyunChartZoomElement } from 'duoyun-ui/react/DyChartZoom' import DyCheckbox, { DuoyunCheckboxElement } from 'duoyun-ui/react/DyCheckbox' import DyCheckboxGroup, { DuoyunCheckboxGroupElement } from 'duoyun-ui/react/DyCheckboxGroup' import DyCoachMark, { DuoyunCoachMarkElement } from 'duoyun-ui/react/DyCoachMark' import DyCodeBlock, { DuoyunCodeBlockElement } from 'duoyun-ui/react/DyCodeBlock' import DyCollapse, { DuoyunCollapseElement } from 'duoyun-ui/react/DyCollapse' import DyCollapsePanel, { DuoyunCollapsePanelElement } from 'duoyun-ui/react/DyCollapsePanel' import DyContextmenu, { DuoyunContextmenuElement } from 'duoyun-ui/react/DyContextmenu' import DyColorPanel, { DuoyunColorPanelElement } from 'duoyun-ui/react/DyColorPanel' import DyColorPicker, { DuoyunColorPickerElement } from 'duoyun-ui/react/DyColorPicker' import DyCompartment, { DuoyunCompartmentElement } from 'duoyun-ui/react/DyCompartment' import DyCopy, { DuoyunCopyElement } from 'duoyun-ui/react/DyCopy' import DyDatePanel, { DuoyunDatePanelElement } from 'duoyun-ui/react/DyDatePanel' import DyDatePicker, { DuoyunDatePickerElement } from 'duoyun-ui/react/DyDatePicker' import DyDateRangePanel, { DuoyunDateRangePanelElement } from 'duoyun-ui/react/DyDateRangePanel' import DyDateRangePicker, { DuoyunDateRangePickerElement } from 'duoyun-ui/react/DyDateRangePicker' import DyDivider, { DuoyunDividerElement } from 'duoyun-ui/react/DyDivider' import DyDonutChart, { DuoyunDonutChartElement } from 'duoyun-ui/react/DyDonutChart' import DyDrawer, { DuoyunDrawerElement } from 'duoyun-ui/react/DyDrawer' import DyDropArea, { DuoyunDropAreaElement } from 'duoyun-ui/react/DyDropArea' import DyEmpty, { DuoyunEmptyElement } from 'duoyun-ui/react/DyEmpty' import DyFilePicker, { DuoyunFilePickerElement } from 'duoyun-ui/react/DyFilePicker' import DyFlow, { DuoyunFlowElement } from 'duoyun-ui/react/DyFlow' import DyFlowCanvas, { DuoyunFlowCanvasElement } from 'duoyun-ui/react/DyFlowCanvas' import DyForm, { DuoyunFormElement } from 'duoyun-ui/react/DyForm' import DyFormItem, { DuoyunFormItemElement } from 'duoyun-ui/react/DyFormItem' import DyFormItemInlineGroup, { DuoyunFormItemInlineGroupElement } from 'duoyun-ui/react/DyFormItemInlineGroup' import DyGesture, { DuoyunGestureElement } from 'duoyun-ui/react/DyGesture' import DyHeading, { DuoyunHeadingElement } from 'duoyun-ui/react/DyHeading' import DyHelpText, { DuoyunHelpTextElement } from 'duoyun-ui/react/DyHelpText' import DyIcons, { DuoyunIconsElement } from 'duoyun-ui/react/DyIcons' import DyImagePreview, { DuoyunImagePreviewElement } from 'duoyun-ui/react/DyImagePreview' import DyInput, { DuoyunInputElement } from 'duoyun-ui/react/DyInput' import DyInputCapture, { DuoyunInputCaptureElement } from 'duoyun-ui/react/DyInputCapture' import DyInputGroup, { DuoyunInputGroupElement } from 'duoyun-ui/react/DyInputGroup' import DyKeyboardAccess, { DuoyunKeyboardAccessElement } from 'duoyun-ui/react/DyKeyboardAccess' import DyLegend, { DuoyunLegendElement } from 'duoyun-ui/react/DyLegend' import DyLightRoute, { DuoyunLightRouteElement } from 'duoyun-ui/react/DyLightRoute' import DyLineChart, { DuoyunLineChartElement } from 'duoyun-ui/react/DyLineChart' import DyLink, { DuoyunLinkElement } from 'duoyun-ui/react/DyLink' import DyList, { DuoyunListElement } from 'duoyun-ui/react/DyList' import DyListItem, { DuoyunListItemElement } from 'duoyun-ui/react/DyListItem' import DyLoading, { DuoyunLoadingElement } from 'duoyun-ui/react/DyLoading' import DyMap, { DuoyunMapElement } from 'duoyun-ui/react/DyMap' import DyMeter, { DuoyunMeterElement } from 'duoyun-ui/react/DyMeter' import DyModal, { DuoyunModalElement } from 'duoyun-ui/react/DyModal' import DyMore, { DuoyunMoreElement } from 'duoyun-ui/react/DyMore' import DyMoreSlot, { DuoyunMoreSlotElement } from 'duoyun-ui/react/DyMoreSlot' import DyOptions, { DuoyunOptionsElement } from 'duoyun-ui/react/DyOptions' import DyPageLoadbar, { DuoyunPageLoadbarElement } from 'duoyun-ui/react/DyPageLoadbar' import DyPagination, { DuoyunPaginationElement } from 'duoyun-ui/react/DyPagination' import DyParagraph, { DuoyunParagraphElement } from 'duoyun-ui/react/DyParagraph' import DyPicker, { DuoyunPickerElement } from 'duoyun-ui/react/DyPicker' import DyPlaceholder, { DuoyunPlaceholderElement } from 'duoyun-ui/react/DyPlaceholder' import DyPopover, { DuoyunPopoverElement } from 'duoyun-ui/react/DyPopover' import DyPopoverGhost, { DuoyunPopoverGhostElement } from 'duoyun-ui/react/DyPopoverGhost' import DyProgress, { DuoyunProgressElement } from 'duoyun-ui/react/DyProgress' import DyRadio, { DuoyunRadioElement } from 'duoyun-ui/react/DyRadio' import DyRadioGroup, { DuoyunRadioGroupElement } from 'duoyun-ui/react/DyRadioGroup' import DyRate, { DuoyunRateElement } from 'duoyun-ui/react/DyRate' import DyReflect, { DuoyunReflectElement } from 'duoyun-ui/react/DyReflect' import DyResult, { DuoyunResultElement } from 'duoyun-ui/react/DyResult' import DyRoute, { DuoyunRouteElement } from 'duoyun-ui/react/DyRoute' import DyScatterChart, { DuoyunScatterChartElement } from 'duoyun-ui/react/DyScatterChart' import DySelect, { DuoyunSelectElement } from 'duoyun-ui/react/DySelect' import DySelectionBox, { DuoyunSelectionBoxElement } from 'duoyun-ui/react/DySelectionBox' import DySelectionBoxMask, { DuoyunSelectionBoxMaskElement } from 'duoyun-ui/react/DySelectionBoxMask' import DyShortcutRecord, { DuoyunShortcutRecordElement } from 'duoyun-ui/react/DyShortcutRecord' import DySideNavigation, { DuoyunSideNavigationElement } from 'duoyun-ui/react/DySideNavigation' import DySlider, { DuoyunSliderElement } from 'duoyun-ui/react/DySlider' import DySpace, { DuoyunSpaceElement } from 'duoyun-ui/react/DySpace' import DyStatistic, { DuoyunStatisticElement } from 'duoyun-ui/react/DyStatistic' import DyStatusLight, { DuoyunStatusLightElement } from 'duoyun-ui/react/DyStatusLight' import DySwitch, { DuoyunSwitchElement } from 'duoyun-ui/react/DySwitch' import DyTable, { DuoyunTableElement } from 'duoyun-ui/react/DyTable' import DyTabPanel, { DuoyunTabPanelElement } from 'duoyun-ui/react/DyTabPanel' import DyTabs, { DuoyunTabsElement } from 'duoyun-ui/react/DyTabs' import DyTag, { DuoyunTagElement } from 'duoyun-ui/react/DyTag' import DyTextMask, { DuoyunTextMaskElement } from 'duoyun-ui/react/DyTextMask' import DyTimeline, { DuoyunTimelineElement } from 'duoyun-ui/react/DyTimeline' import DyTimePanel, { DuoyunTimePanelElement } from 'duoyun-ui/react/DyTimePanel' import DyTimePicker, { DuoyunTimePickerElement } from 'duoyun-ui/react/DyTimePicker' import DyTitle, { DuoyunTitleElement } from 'duoyun-ui/react/DyTitle' import DyToast, { DuoyunToastElement } from 'duoyun-ui/react/DyToast' import DyTooltip, { DuoyunTooltipElement } from 'duoyun-ui/react/DyTooltip' import DyTree, { DuoyunTreeElement } from 'duoyun-ui/react/DyTree' import DyUnsafe, { DuoyunUnsafeElement } from 'duoyun-ui/react/DyUnsafe' import DyUse, { DuoyunUseElement } from 'duoyun-ui/react/DyUse' import DyWait, { DuoyunWaitElement } from 'duoyun-ui/react/DyWait' if (typeof window !== 'undefined') { [DuoyunActionTextElement, DuoyunActiveLinkElement, DuoyunAlertElement, DuoyunAreaChartElement, DuoyunAvatarElement, DuoyunAvatarGroupElement, DuoyunBannerElement, DuoyunBarChartElement, DuoyunBreadcrumbsElement, DuoyunButtonElement, DuoyunCalendarElement, DuoyunCardElement, DuoyunCarouselElement, DuoyunCascaderElement, DuoyunCascaderPickerElement, DuoyunChartTooltipElement, DuoyunChartZoomElement, DuoyunCheckboxElement, DuoyunCheckboxGroupElement, DuoyunCoachMarkElement, DuoyunCodeBlockElement, DuoyunCollapseElement, DuoyunCollapsePanelElement, DuoyunContextmenuElement, DuoyunColorPanelElement, DuoyunColorPickerElement, DuoyunCompartmentElement, DuoyunCopyElement, DuoyunDatePanelElement, DuoyunDatePickerElement, DuoyunDateRangePanelElement, DuoyunDateRangePickerElement, DuoyunDividerElement, DuoyunDonutChartElement, DuoyunDrawerElement, DuoyunDropAreaElement, DuoyunEmptyElement, DuoyunFilePickerElement, DuoyunFlowElement, DuoyunFlowCanvasElement, DuoyunFormElement, DuoyunFormItemElement, DuoyunFormItemInlineGroupElement, DuoyunGestureElement, DuoyunHeadingElement, DuoyunHelpTextElement, DuoyunIconsElement, DuoyunImagePreviewElement, DuoyunInputElement, DuoyunInputCaptureElement, DuoyunInputGroupElement, DuoyunKeyboardAccessElement, DuoyunLegendElement, DuoyunLightRouteElement, DuoyunLineChartElement, DuoyunLinkElement, DuoyunListElement, DuoyunListItemElement, DuoyunLoadingElement, DuoyunMapElement, DuoyunMeterElement, DuoyunModalElement, DuoyunMoreElement, DuoyunMoreSlotElement, DuoyunOptionsElement, DuoyunPageLoadbarElement, DuoyunPaginationElement, DuoyunParagraphElement, DuoyunPickerElement, DuoyunPlaceholderElement, DuoyunPopoverElement, DuoyunPopoverGhostElement, DuoyunProgressElement, DuoyunRadioElement, DuoyunRadioGroupElement, DuoyunRateElement, DuoyunReflectElement, DuoyunResultElement, DuoyunRouteElement, DuoyunScatterChartElement, DuoyunSelectElement, DuoyunSelectionBoxElement, DuoyunSelectionBoxMaskElement, DuoyunShortcutRecordElement, DuoyunSideNavigationElement, DuoyunSliderElement, DuoyunSpaceElement, DuoyunStatisticElement, DuoyunStatusLightElement, DuoyunSwitchElement, DuoyunTableElement, DuoyunTabPanelElement, DuoyunTabsElement, DuoyunTagElement, DuoyunTextMaskElement, DuoyunTimelineElement, DuoyunTimePanelElement, DuoyunTimePickerElement, DuoyunTitleElement, DuoyunToastElement, DuoyunTooltipElement, DuoyunTreeElement, DuoyunUnsafeElement, DuoyunUseElement, DuoyunWaitElement,].map((C) => { const ele = new C() console.log(`create ${ele.tagName}`, document.createElement(ele.tagName)) }) } export default function Text() { const colorRef = useRef<DyColorPickerMethods>(null) const [color, changeColor] = useState<`#${string}`>('#aaa') return <Layout layout='test'> <DyParagraph> <DySpace size='large'> <DyButton onClick={() => colorRef.current?.showPicker()}>Open Color Picker</DyButton> <DyColorPicker ref={colorRef} value={color} onchange={(e: CustomEvent) => changeColor(e.detail)}></DyColorPicker> </DySpace> </DyParagraph> <DyCard style={{ width: '300px' }} avatar="https://api.dicebear.com/5.x/bottts-neutral/svg" preview="https://picsum.photos/400/300" header={`This is Card`} detail={`CE`} actions={[{ text: "Action1", handle: console.log }, { text: "Action2", handle: console.log }, { text: "Action3", handle: console.log }, { text: "Action4", handle: console.log }, { text: "Action5", handle: console.log }]} > Fugiat do laboris ad officia in anim qui mollit nulla reprehenderit pariatur anim sunt. </DyCard> {/* <DyActionText>DyActionText</DyActionText> */} {/* <DyActiveLink>DyActiveLink</DyActiveLink> */} {/* <DyAlert /> */} {/* <DyAreaChart /> */} {/* <DyAvatar /> */} {/* <DyAvatarGroup /> */} {/* <DyBanner /> */} {/* <DyBarChart /> */} {/* <DyBreadcrumbs /> */} {/* <DyButton>DyButton</DyButton> */} {/* <DyCalendar /> */} {/* <DyCard /> */} {/* <DyCarousel /> */} {/* <DyCascader /> */} {/* <DyCascaderPicker /> */} {/* <DyChartTooltip /> */} {/* <DyChartZoom /> */} {/* <DyCheckbox /> */} {/* <DyCheckboxGroup /> */} {/* <DyCoachMark /> */} {/* <DyCodeBlock /> */} {/* <DyContextmenu /> */} {/* <DyCollapse /> */} {/* <DyCollapsePanel /> */} {/* <DyColorPanel /> */} {/* <DyColorPicker /> */} {/* <DyCompartment /> */} {/* <DyCopy /> */} {/* <DyDatePanel /> */} {/* <DyDatePicker /> */} {/* <DyDateRangePanel /> */} {/* <DyDateRangePicker /> */} {/* <DyDivider /> */} {/* <DyDonutChart /> */} {/* <DyDrawer /> */} {/* <DyDropArea /> */} {/* <DyEmpty /> */} {/* <DyFilePicker /> */} {/* <DyFlow /> */} {/* <DyFlowCanvas /> */} {/* <DyForm /> */} {/* <DyFormItem /> */} {/* <DyFormItemInlineGroup /> */} {/* <DyGesture /> */} {/* <DyHeading /> */} {/* <DyHelpText /> */} {/* <DyIcons /> */} {/* <DyImagePreview /> */} {/* <DyInput /> */} {/* <DyInputCapture /> */} {/* <DyInputGroup /> */} {/* <DyKeyboardAccess /> */} {/* <DyLegend /> */} {/* <DyLightRoute /> */} {/* <DyLineChart /> */} {/* <DyLink /> */} {/* <DyList /> */} {/* <DyListItem /> */} {/* <DyLoading /> */} {/* <DyMap /> */} {/* <DyMeter /> */} {/* <DyModal /> */} {/* <DyMore /> */} {/* <DyMoreSlot /> */} {/* <DyOptions /> */} {/* <DyPageLoadbar /> */} {/* <DyPagination /> */} {/* <DyParagraph /> */} {/* <DyPicker /> */} {/* <DyPlaceholder /> */} {/* <DyPopover /> */} {/* <DyPopoverGhost /> */} {/* <DyProgress /> */} {/* <DyRadio /> */} {/* <DyRadioGroup /> */} {/* <DyRate /> */} {/* <DyReflect /> */} {/* <DyResult /> */} {/* <DyRoute /> */} {/* <DyScatterChart /> */} {/* <DySelect /> */} {/* <DySelectionBox /> */} {/* <DySelectionBoxMask /> */} {/* <DyShortcutRecord /> */} {/* <DySideNavigation /> */} {/* <DySlider /> */} {/* <DySpace /> */} {/* <DyStatistic /> */} {/* <DyStatusLight /> */} {/* <DySwitch /> */} {/* <DyTable /> */} {/* <DyTabPanel /> */} {/* <DyTabs /> */} {/* <DyTag /> */} {/* <DyTextMask /> */} {/* <DyTimeline /> */} {/* <DyTimePanel /> */} {/* <DyTimePicker /> */} {/* <DyTitle /> */} {/* <DyToast /> */} {/* <DyTooltip /> */} {/* <DyTree /> */} {/* <DyUnsafe /> */} {/* <DyUse /> */} {/* <DyWait /> */} </Layout> }

Using React Components in <dy-route>

<dy-route> only supports rendering TemplateResult:

const routes = { about: { pattern: '/about', title: `About`, getContent(_, ele) { return html`<p-about></p-about>`; }, }, } satisfies RoutesObject;

To render React components, need to manually mount them to <dy-route>:

function renderReactNode(ele: any, node: ReactNode) { ele.react?.unmount(); ele.react = createRoot(ele); ele.react.render(node); } const routes = { about: { pattern: '/about', title: `About`, getContent(_, ele) { renderReactNode(ele, <About />); }, }, } satisfies RoutesObject;

Using React Components in Properties

Some elements support custom render content, such as the header of <dy-card>:

function Page() { return <DyCard header={html`<div>No.</div>`}></DyCard>; }

If you want to render React components, you need to first render them to an HTMLElement. This can be achieved through a custom Hook:

function useReactNode(node: ReactNode) { const ref = useRef<{ root: Root; container: HTMLElement }>(); useEffect(() => () => ref.current?.root.unmount(), []); if (ref.current) { ref.current.root.render(node); return ref.current.container; } const container = document.createElement('div'); container.style.display = 'contents'; const root = createRoot(container); ref.current = { root, container }; root.render(node); return container; } function Page() { return <DyCard header={useReactNode(<>No</>)}></DyCard>; }

Vue

DuoyunUI also exports Vue components. Usage is the same as React, with the only difference being that the path changes from react to vue. Additionally, you need to specify custom elements in the Vue configuration file:

{ compilerOptions: { isCustomElement: (tag) => tag.startsWith('dy-'); } }

In Vue, you can also write custom elements directly, but you need to distinguish between Attributes and Properties:

<script setup lang="ts"> import DySpace from 'duoyun-ui/vue/DySpace.vue' import DyButton from 'duoyun-ui/vue/DyButton.vue' import DyCard from 'duoyun-ui/vue/DyCard.vue' import DyColorPicker from 'duoyun-ui/vue/DyColorPicker.vue' import DyParagraph from 'duoyun-ui/vue/DyParagraph.vue' import type { HexColor } from 'duoyun-ui/lib/color' const colorElement = ref<InstanceType<typeof DyColorPicker>>(); const cardActions = ref([{ text: 'Action1', handle: console.log }, { text: 'Action2', handle: console.log }, { text: 'Action3', handle: console.log }, { text: 'Action4', handle: console.log }]); const cardHeader = ref('This header'); const color = ref<HexColor>('#f0f'); const clickHandle = () => { cardActions.value = cardActions.value.reverse() cardHeader.value = [...cardHeader.value].reverse().join('') } const onChange = (e: CustomEvent<HexColor>) => { color.value = e.detail } </script> <template> <DyParagraph> <DySpace> <DyButton @click="() => colorElement?.showPicker()">Open Color Picker</DyButton> <DyColorPicker ref=colorElement :value="color" alpha @change="onChange"></DyColorPicker> <dy-color-picker :value="color" alpha @change="onChange"></dy-color-picker> </DySpace> </DyParagraph> <DySpace> <DyCard @click="clickHandle" class="card" avatar="https://api.dicebear.com/5.x/bottts-neutral/svg" preview="https://picsum.photos/400/300" :header="cardHeader" :detail="`CE`" :actions="cardActions">Fugiat do laboris ad officia in anim qui mollit nulla reprehenderit pariatur anim sunt.</DyCard> <dy-card @click="clickHandle" class="card" avatar="https://api.dicebear.com/5.x/bottts-neutral/svg" preview="https://picsum.photos/400/300" .header="cardHeader" .detail="`CE`" .actions="cardActions">Fugiat do laboris ad officia in anim qui mollit nulla reprehenderit pariatur anim sunt.</dy-card> </DySpace> </template> <style scoped> .card { width: 300px; } </style>

Svelte

DuoyunUI hasn't been re-exported as Svelte components. You can use custom elements directly:

<script lang="ts"> import "duoyun-ui/svelte/button"; import "duoyun-ui/svelte/card"; import "duoyun-ui/svelte/paragraph"; import "duoyun-ui/svelte/space"; import "duoyun-ui/svelte/color-picker"; import type { DuoyunColorPickerElement } from "duoyun-ui/svelte/color-picker"; let colorElement: DuoyunColorPickerElement | undefined; let cardActions = [ { text: "Action1", handle: console.log }, { text: "Action2", handle: console.log }, { text: "Action3", handle: console.log }, { text: "Action4", handle: console.log }, ]; let cardHeader = "This header"; let color: `#${string}` = "#f0f"; const clickHandle = () => { cardActions = cardActions.reverse(); cardHeader = [...cardHeader].reverse().join(""); }; const onChange = (e: CustomEvent) => { color = e.detail; }; </script> <div> <dy-paragraph> <dy-space> <dy-button on:click={() => colorElement?.showPicker()}> Open Color Picker </dy-button> <dy-color-picker bind:this={colorElement} on:change={onChange} value={color} alpha ></dy-color-picker> </dy-space> </dy-paragraph> <dy-card on:click={clickHandle} class="card" avatar="https://api.dicebear.com/5.x/bottts-neutral/svg" preview="https://picsum.photos/400/300" header={cardHeader} detail={`CE`} actions={cardActions} > Fugiat do laboris ad officia in anim qui mollit nulla reprehenderit pariatur anim sunt. </dy-card> </div> <style> .card { width: 240px; } </style>

NOTE

When using SvelteKit, make sure svelte is installed as dependencies rather than devDependencies, otherwise types won't be imported successfully. If you encounter an "Unexpected token 'export'" error during compilation, add the following code to vite.config.ts:

{ ssr: { noExternal: ['@mantou/gem', 'duoyun-ui']; } }

SSR

DuoyunUI doesn't support SSR, or more precisely, Next/Nuxt/Svelte don't support custom element SSR. The ShadowDOM of custom elements is generated at runtime. To make it work correctly on the server side, import @mantou/gem/helper/ssr-shim at the entry point of your frontend code:

  • Next.js: pages/_app.tsx
  • Nuxt.js: app.config.ts
  • SvelteKit: src/hooks.server.ts

If you want to use DuoyunUI's routing, you can use <dy-light-route>. To avoid first-screen layout issues, add the following global style:

:not(:defined) { display: none; }