diff --git a/packages/opendesign/src/components/intersection-observer/__demo__/IntersectionObserverDemo.vue b/packages/opendesign/src/components/intersection-observer/__demo__/IntersectionDemo.vue
similarity index 100%
rename from packages/opendesign/src/components/intersection-observer/__demo__/IntersectionObserverDemo.vue
rename to packages/opendesign/src/components/intersection-observer/__demo__/IntersectionDemo.vue
diff --git a/packages/opendesign/src/components/link/OLink.vue b/packages/opendesign/src/components/link/OLink.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e5e97e041f85563b64b8a70126a9cc45f57049a6
--- /dev/null
+++ b/packages/opendesign/src/components/link/OLink.vue
@@ -0,0 +1,35 @@
+
+
+
+
diff --git a/packages/opendesign/src/components/link/__demo__/IndexLink.vue b/packages/opendesign/src/components/link/__demo__/IndexLink.vue
new file mode 100644
index 0000000000000000000000000000000000000000..80022ef774914a3c3a5002743cf7a6f5d3ca6dd8
--- /dev/null
+++ b/packages/opendesign/src/components/link/__demo__/IndexLink.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/packages/opendesign/src/components/link/__demo__/LinkDemo.vue b/packages/opendesign/src/components/link/__demo__/LinkDemo.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cd607a52cea41efe309f58fb654dc962e926f2e0
--- /dev/null
+++ b/packages/opendesign/src/components/link/__demo__/LinkDemo.vue
@@ -0,0 +1,12 @@
+
+
+
+ Primary Button
+ Outline Button
+ Text Button
+ Link Button
+
+
+
diff --git a/packages/opendesign/src/components/link/index.ts b/packages/opendesign/src/components/link/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7b8e241be348e0a8293e928b48451714528b34b1
--- /dev/null
+++ b/packages/opendesign/src/components/link/index.ts
@@ -0,0 +1,12 @@
+import _OLink from './OLink.vue';
+import type { App } from 'vue';
+
+const OLink = Object.assign(_OLink, {
+ install(app: App) {
+ app.component(_OLink.name, _OLink);
+ },
+});
+
+export {
+ OLink,
+};
diff --git a/packages/opendesign/src/components/link/style/index.scss b/packages/opendesign/src/components/link/style/index.scss
new file mode 100644
index 0000000000000000000000000000000000000000..878347d405daafc08dfe19d43e11a95174eceb95
--- /dev/null
+++ b/packages/opendesign/src/components/link/style/index.scss
@@ -0,0 +1,140 @@
+@import './var.scss';
+
+.o-btn {
+ outline: none;
+ border: 1px solid transparent;
+ font-size: var(--btn-text-size);
+ line-height: var(--btn-text-height);
+ transition: all 0.2s ease-in-out;
+ white-space: nowrap;
+ cursor: pointer;
+
+ &:focus-visible {
+ outline: 4px solid var(--btn-primary_hover);
+ outline-offset: 1px;
+ }
+
+ &:disabled {
+ color: var(--btn-color_disabled);
+ cursor: not-allowed;
+ }
+}
+
+.o-btn-size-small {
+ padding: 0 7px;
+ height: var(--btn-height-s);
+ border-radius: var(--btn-radius-s);
+ &.o-btn-icon-only {
+ width: var(--btn-height-s);
+ }
+}
+
+.o-btn-size-normal {
+ padding: 4px 15px;
+ height: var(--btn-height-m);
+ border-radius: var(--btn-radius-m);
+ &.o-btn-icon-only {
+ width: var(--btn-height-m);
+ }
+}
+
+.o-btn-size-large {
+ padding: 4px 19px;
+ height: var(--btn-height-l);
+ border-radius: var(--btn-radius-l);
+
+ &.o-btn-icon-only {
+ width: var(--btn-height-l);
+ }
+}
+
+.o-btn-primary {
+ color: var(--btn-color_inverse);
+ background-color: var(--btn-primary);
+
+ &:not(:disabled) {
+ &:hover {
+ background-color: var(--btn-primary_hover);
+ }
+
+ &:active {
+ background-color: var(--btn-primary_active);
+ }
+ }
+
+ &:disabled {
+ border-color: var(--btn-bg);
+ background-color: var(--btn-bg_disabled);
+ }
+}
+
+.o-btn-outline {
+ color: var(--btn-color);
+ background-color: transparent;
+ border-color: var(--btn-bg);
+
+ &:not(:disabled) {
+ &:hover {
+ color: var(--btn-primary_hover);
+ border-color: var(--btn-primary_hover);
+ }
+
+ &:active {
+ color: var(--btn-primary_active);
+ border-color: var(--btn-primary_active);
+ }
+ }
+
+ &:disabled {
+ background-color: var(--btn-bg_disabled);
+ }
+}
+
+.o-btn-text {
+ color: var(--btn-color);
+ background-color: transparent;
+
+ &:not(:disabled) {
+ &:hover {
+ background-color: var(--btn-bg_hover);
+ }
+
+ &:active {
+ background-color: var(--btn-bg_active);
+ }
+ }
+}
+
+.o-btn-link {
+ color: var(--btn-primary);
+ background-color: transparent;
+
+ &:not(:disabled) {
+ &:hover {
+ color: var(--btn-primary_hover);
+ }
+
+ &:active {
+ color: var(--btn-primary_active);
+ }
+ }
+}
+
+.o-btn-icon-only {
+ padding: 0;
+}
+.o-btn-icon {
+ vertical-align: middle;
+ margin-right: 6px;
+
+ .o-btn-icon-only & {
+ margin-right: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+}
+
+.o-btn-shape-round {
+ border-radius: var(--btn-height-l);
+}
diff --git a/packages/opendesign/src/components/link/style/index.ts b/packages/opendesign/src/components/link/style/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..67aac616fc2524b146b7b078fd3b67c1bd3b4a6e
--- /dev/null
+++ b/packages/opendesign/src/components/link/style/index.ts
@@ -0,0 +1 @@
+import './index.scss';
diff --git a/packages/opendesign/src/components/link/style/var.scss b/packages/opendesign/src/components/link/style/var.scss
new file mode 100644
index 0000000000000000000000000000000000000000..ca8adcf1237d0736d4a01010f8aa48c1e0b3e61a
--- /dev/null
+++ b/packages/opendesign/src/components/link/style/var.scss
@@ -0,0 +1,25 @@
+.o-btn {
+ --btn-primary: var(--o-color-primary1);
+ --btn-primary_hover: var(--o-color-primary2);
+ --btn-primary_active: var(--o-color-primary3);
+
+ --btn-bg: var(--o-color-info1);
+ --btn-bg_hover: var(--o-color-info2);
+ --btn-bg_active: var(--o-color-info3);
+ --btn-bg_disabled: var(--o-color-info4);
+
+ --btn-color: var(--o-color-text2);
+ --btn-color_inverse: var(--o-color-text2_inverse);
+ --btn-color_disabled: var(--o-color-text4);
+
+ --btn-text-size: var(--o-font_size-text);
+ --btn-text-height: var(--o-line_height-text);
+
+ --btn-height-s: var(--o-size-s);
+ --btn-height-m: var(--o-size-m);
+ --btn-height-l: var(--o-size-l);
+
+ --btn-radius-s: var(--o-radius-s);
+ --btn-radius-m: var(--o-radius-s);
+ --btn-radius-l: var(--o-radius-s);
+}
diff --git a/packages/portal/src/pages/ThePopover.vue b/packages/opendesign/src/components/popover/__demo__/IndexPopover.vue
similarity index 43%
rename from packages/portal/src/pages/ThePopover.vue
rename to packages/opendesign/src/components/popover/__demo__/IndexPopover.vue
index a16f012ba332f586c32692254e1ab574bdbbba8b..f03510f939bf156b2fa45cf3f511684a206d7256 100644
--- a/packages/portal/src/pages/ThePopover.vue
+++ b/packages/opendesign/src/components/popover/__demo__/IndexPopover.vue
@@ -1,8 +1,8 @@
diff --git a/packages/portal/src/pages/ThePopup.vue b/packages/opendesign/src/components/popup/__demo__/IndexPopup.vue
similarity index 41%
rename from packages/portal/src/pages/ThePopup.vue
rename to packages/opendesign/src/components/popup/__demo__/IndexPopup.vue
index 900d72c400e5df0fd9ed58309e755829fdc097f9..29a44a152dcdc3f6c44102b1e5d757df068bc48b 100644
--- a/packages/portal/src/pages/ThePopup.vue
+++ b/packages/opendesign/src/components/popup/__demo__/IndexPopup.vue
@@ -1,9 +1,9 @@
diff --git a/packages/portal/src/pages/TheResizeObserver.vue b/packages/opendesign/src/components/resize-observer/__demo__/IndexResize.vue
similarity index 50%
rename from packages/portal/src/pages/TheResizeObserver.vue
rename to packages/opendesign/src/components/resize-observer/__demo__/IndexResize.vue
index 9c5d0acf5e254f84e551c7d1d0f1ca8416430fd5..75df837020b9ab1db2820bf0afa2345f50f250a9 100644
--- a/packages/portal/src/pages/TheResizeObserver.vue
+++ b/packages/opendesign/src/components/resize-observer/__demo__/IndexResize.vue
@@ -1,10 +1,8 @@
-
-
diff --git a/packages/opendesign/src/components/resize-observer/__demo__/ResizeObserverDemo.vue b/packages/opendesign/src/components/resize-observer/__demo__/ResizeDemo.vue
similarity index 100%
rename from packages/opendesign/src/components/resize-observer/__demo__/ResizeObserverDemo.vue
rename to packages/opendesign/src/components/resize-observer/__demo__/ResizeDemo.vue
diff --git a/packages/portal/src/pages/TheSelect.vue b/packages/opendesign/src/components/select/__demo__/IndexSelect.vue
similarity index 36%
rename from packages/portal/src/pages/TheSelect.vue
rename to packages/opendesign/src/components/select/__demo__/IndexSelect.vue
index 91b4680e38eee6301fc00da9b517a9ac97d22adb..c9b842f0d166db282b8268473df479bc2e244f75 100644
--- a/packages/portal/src/pages/TheSelect.vue
+++ b/packages/opendesign/src/components/select/__demo__/IndexSelect.vue
@@ -1,10 +1,10 @@
diff --git a/packages/portal/src/pages/TheSwitch.vue b/packages/opendesign/src/components/switch/__demo__/IndexSwitch.vue
similarity index 44%
rename from packages/portal/src/pages/TheSwitch.vue
rename to packages/opendesign/src/components/switch/__demo__/IndexSwitch.vue
index 5db6a02f7b7f34d37f162e6bcb5d5372d991ab78..4123a14580982d461dc1c55f04465f8a31f37e25 100644
--- a/packages/portal/src/pages/TheSwitch.vue
+++ b/packages/opendesign/src/components/switch/__demo__/IndexSwitch.vue
@@ -1,11 +1,11 @@
diff --git a/packages/portal/src/router.ts b/packages/portal/src/router.ts
index c7ab0998859693004f5e91e672b9b2d5e6e5fd02..dc9e0338b857aa5ed147db5f8c9a994c51da6b24 100644
--- a/packages/portal/src/router.ts
+++ b/packages/portal/src/router.ts
@@ -12,43 +12,43 @@ export const routes = [
path: '/button',
name: 'Button',
label: '按钮',
- component: () => import('./pages/TheButton.vue'),
+ component: () => import('@demo/button/__demo__/IndexBtn.vue'),
},
{
path: '/switch',
name: 'Switch',
label: '开关',
- component: () => import('./pages/TheSwitch.vue'),
+ component: () => import('@demo/switch/__demo__/IndexSwitch.vue'),
},
{
path: '/resize-observer',
name: 'ResizeObserver',
label: 'resize监听',
- component: () => import('./pages/TheResizeObserver.vue'),
+ component: () => import('@demo/resize-observer/__demo__/IndexResize.vue'),
},
{
path: '/intersection-observer',
name: 'IntersectionObserver',
label: 'Intersection监听',
- component: () => import('./pages/TheIntersectionObserver.vue'),
+ component: () => import('@demo/intersection-observer/__demo__/IndexIntersection.vue'),
},
{
path: '/popup',
name: 'Popup',
label: '弹层',
- component: () => import('./pages/ThePopup.vue'),
+ component: () => import('@demo/popup/__demo__/IndexPopup.vue'),
},
{
path: '/popover',
name: 'Popover',
label: '弹出框',
- component: () => import('./pages/ThePopover.vue'),
+ component: () => import('@demo/popover/__demo__/IndexPopover.vue'),
},
{
path: '/select',
name: 'Select',
label: '下拉框',
- component: () => import('./pages/TheSelect.vue'),
+ component: () => import('@demo/select/__demo__/IndexSelect.vue'),
},