diff --git a/packages/docs/tag.md b/packages/docs/tag.md
new file mode 100644
index 0000000000000000000000000000000000000000..3eddd8bf039ffb68b32b48147048496af74c29f8
--- /dev/null
+++ b/packages/docs/tag.md
@@ -0,0 +1,27 @@
+# Tag 标签
+
+## props
+
+| name | type | 默认值 | 说明 |
+| :--------------- | :--------------------------------------------- | :------- | ------------------------------------------------------- |
+| status | 'normal' \| 'success' \| 'warning' \| 'danger' | 'normal' | 标签状态 |
+| bordered | boolean | false | 是否有边框 |
+| size | 'large' \| 'normal' \| 'small' | 'normal' | 标签形状 |
+| shape | 'normal' \| 'round' | 'normal' | 尺寸 |
+| closable | boolean | false | 是否可关闭 |
+| checkable | boolean | false | 是否可选中 |
+| checked(v-model) | boolean | false | 是否被选中(仅 checkable 为 true 生效) |
+| defaultChecked | boolean | false | 非受控状态时,默认是否选中(仅 checkable 为 true 生效) |
+
+## event
+
+| name | 参数 | 说明 |
+| :---- | :----------- | :----------- |
+| close | | 值改变时触发 |
+| check | val: boolean | 选中时触发 |
+
+## slot
+
+| name | 说明 |
+| :--- | :------- |
+| icon | 按钮图标 |
diff --git a/packages/opendesign/src/components/tag/OTag.vue b/packages/opendesign/src/components/tag/OTag.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7b5fa5585af74d40a08824c275141c8ac454c2eb
--- /dev/null
+++ b/packages/opendesign/src/components/tag/OTag.vue
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/opendesign/src/components/tag/__demo__/IndexTag.vue b/packages/opendesign/src/components/tag/__demo__/IndexTag.vue
new file mode 100644
index 0000000000000000000000000000000000000000..2862b691c56751cf635c1f0df85efd8c2ba44b1e
--- /dev/null
+++ b/packages/opendesign/src/components/tag/__demo__/IndexTag.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/opendesign/src/components/tag/__demo__/TagBasic.vue b/packages/opendesign/src/components/tag/__demo__/TagBasic.vue
new file mode 100644
index 0000000000000000000000000000000000000000..edb8590aea52e6013cee8a4fadafcbadbbd25d92
--- /dev/null
+++ b/packages/opendesign/src/components/tag/__demo__/TagBasic.vue
@@ -0,0 +1,16 @@
+
+
+
+ 基础用法
+
+ Tag1
+ Tag2
+
+
+ Icon Tag
+
+
+
diff --git a/packages/opendesign/src/components/tag/__demo__/TagBordered.vue b/packages/opendesign/src/components/tag/__demo__/TagBordered.vue
new file mode 100644
index 0000000000000000000000000000000000000000..9cfdfe4831e11c70e554bfecf2ac746151cd749f
--- /dev/null
+++ b/packages/opendesign/src/components/tag/__demo__/TagBordered.vue
@@ -0,0 +1,13 @@
+
+
+
+ 带边框标签
+
+ Tag1
+ Tag2
+ Tag3
+ Tag4
+
+
diff --git a/packages/opendesign/src/components/tag/__demo__/TagCheckable.vue b/packages/opendesign/src/components/tag/__demo__/TagCheckable.vue
new file mode 100644
index 0000000000000000000000000000000000000000..810737ca780320537e128194273a720b54846112
--- /dev/null
+++ b/packages/opendesign/src/components/tag/__demo__/TagCheckable.vue
@@ -0,0 +1,26 @@
+
+
+
+ 可选中标签
+
+ Tag1
+ Tag2
+ Tag3
+ Tag4
+ Tag5
+ Tag6
+ Tag7
+ Tag8
+
+
diff --git a/packages/opendesign/src/components/tag/__demo__/TagClosable.vue b/packages/opendesign/src/components/tag/__demo__/TagClosable.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a050bb09bd8222f3aeac1aa510b1f14d3c30b587
--- /dev/null
+++ b/packages/opendesign/src/components/tag/__demo__/TagClosable.vue
@@ -0,0 +1,17 @@
+
+
+
+ 可关闭按钮
+
+ Tag1
+ Tag2
+ Tag3
+ Tag4
+ Tag5
+
+
diff --git a/packages/opendesign/src/components/tag/__demo__/TagShape.vue b/packages/opendesign/src/components/tag/__demo__/TagShape.vue
new file mode 100644
index 0000000000000000000000000000000000000000..322d54e269f86873816d471b9de2f06ac8a8f9fb
--- /dev/null
+++ b/packages/opendesign/src/components/tag/__demo__/TagShape.vue
@@ -0,0 +1,11 @@
+
+
+
+ Shape
+
+ Normal Tag
+ Round Tag
+
+
diff --git a/packages/opendesign/src/components/tag/__demo__/TagSize.vue b/packages/opendesign/src/components/tag/__demo__/TagSize.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ea6b8552652603a3f7c828fa2bd95eaf2d2b3774
--- /dev/null
+++ b/packages/opendesign/src/components/tag/__demo__/TagSize.vue
@@ -0,0 +1,12 @@
+
+
+
+ Size
+
+ Large Tag
+ Normal Tag
+ Small Tag
+
+
diff --git a/packages/opendesign/src/components/tag/__demo__/TagStatus.vue b/packages/opendesign/src/components/tag/__demo__/TagStatus.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4c6be2435c8006b1ae5e0d8cb81e8db8cf44a179
--- /dev/null
+++ b/packages/opendesign/src/components/tag/__demo__/TagStatus.vue
@@ -0,0 +1,19 @@
+
+
+
+ Status
+
+ Normal Tag
+ Success Tag
+ Warning Tag
+ Danger Tag
+
+
+
+
diff --git a/packages/opendesign/src/components/tag/index.ts b/packages/opendesign/src/components/tag/index.ts
index c8883279e51ebb7c6ed0c0160e689f6e5b19baeb..64dae6f735186c82c54d020bd10c2a92c12825e8 100644
--- a/packages/opendesign/src/components/tag/index.ts
+++ b/packages/opendesign/src/components/tag/index.ts
@@ -2,6 +2,8 @@ import type { App } from 'vue';
import _OTag from './OTag.vue';
+export * from './types';
+
const OTag = Object.assign(_OTag, {
install(app: App) {
app.component(_OTag.name, _OTag);
diff --git a/packages/opendesign/src/components/tag/style/index.scss b/packages/opendesign/src/components/tag/style/index.scss
new file mode 100644
index 0000000000000000000000000000000000000000..18bb1c1a00f52b01a6d385158d25a15a0d4d5190
--- /dev/null
+++ b/packages/opendesign/src/components/tag/style/index.scss
@@ -0,0 +1,108 @@
+@use './var.scss';
+
+.o-tag {
+ font-size: var(--tag-text-size);
+ line-height: var(--tag-text-height);
+ height: var(--tag-height);
+ border: 1px solid var(--tag-border);
+ border-radius: var(--tag-radius);
+ padding: var(--tag-padding);
+ transition: all var(--o-duration-s) var(--o-easing-standard);
+ background-color: var(--tag-bg);
+ color: var(--tag-color);
+ white-space: nowrap;
+
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.o-tag-size-small {
+ --tag-padding: 0 7px;
+ --tag-height: var(--tag-height-s);
+ --tag-radius: var(--tag-radius-s);
+}
+
+.o-tag-size-normal {
+ --tag-padding: 4px 15px;
+ --tag-height: var(--tag-height-m);
+ --tag-radius: var(--tag-radius-m);
+}
+
+.o-tag-size-large {
+ --tag-padding: 4px 19px;
+ --tag-height: var(--tag-height-l);
+ --tag-radius: var(--tag-radius-l);
+}
+
+.o-tag-status-success {
+ --tag-color: var(--tag-color-success);
+ --tag-bg: var(--tag-bg-success);
+ --tag-border: var(--tag-border-success);
+}
+
+.o-tag-status-warning {
+ --tag-color: var(--tag-color-warning);
+ --tag-bg: var(--tag-bg-warning);
+ --tag-border: var(--tag-border-warning);
+}
+
+.o-tag-status-danger {
+ --tag-color: var(--tag-color-danger);
+ --tag-bg: var(--tag-bg-danger);
+ --tag-border: var(--tag-border-danger);
+}
+
+.o-tag-icon {
+ display: inline-flex;
+ align-items: center;
+ > svg {
+ vertical-align: top;
+ }
+
+ &.prefix {
+ margin-right: 6px;
+ }
+
+ &.suffix {
+ margin-left: 6px;
+ }
+}
+
+.o-tag-icon-close {
+ cursor: pointer;
+}
+
+.o-tag-shape-round {
+ --tag-radius: var(--tag-height-l);
+}
+
+.o-tag-bordered {
+ --tag-bg: transparent;
+ &.o-tag-status-success {
+ --tag-color: var(--tag-bg-success);
+ }
+ &.o-tag-status-warning {
+ --tag-color: var(--tag-bg-warning);
+ }
+ &.o-tag-status-danger {
+ --tag-color: var(--tag-bg-danger);
+ }
+}
+
+.o-tag-checkable {
+ cursor: pointer;
+ &:not(.o-tag-checked) {
+ --tag-bg: transparent;
+ --tag-border: transparent;
+ &.o-tag-status-success {
+ --tag-color: var(--tag-bg-success);
+ }
+ &.o-tag-status-warning {
+ --tag-color: var(--tag-bg-warning);
+ }
+ &.o-tag-status-danger {
+ --tag-color: var(--tag-bg-danger);
+ }
+ }
+}
diff --git a/packages/opendesign/src/components/tag/style/index.ts b/packages/opendesign/src/components/tag/style/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..591b2fbd72dcd5e987362d645b561bd2fac42716
--- /dev/null
+++ b/packages/opendesign/src/components/tag/style/index.ts
@@ -0,0 +1,2 @@
+import '../../style';
+import './index.scss';
diff --git a/packages/opendesign/src/components/tag/style/var.scss b/packages/opendesign/src/components/tag/style/var.scss
new file mode 100644
index 0000000000000000000000000000000000000000..3b524dea93021a17a3cf8a16f2fd3f0c237d4707
--- /dev/null
+++ b/packages/opendesign/src/components/tag/style/var.scss
@@ -0,0 +1,27 @@
+.o-tag {
+ --tag-color: var(--o-color-text2);
+ --tag-color-success: var(--o-color-text1-inverse);
+ --tag-color-warning: var(--o-color-text1-inverse);
+ --tag-color-danger: var(--o-color-text1-inverse);
+
+ --tag-bg: var(--o-color-info1);
+ --tag-bg-success: var(--o-color-success1);
+ --tag-bg-warning: var(--o-color-warning1);
+ --tag-bg-danger: var(--o-color-danger1);
+
+ --tag-border: var(--o-color-info1);
+ --tag-border-success: var(--o-color-success1);
+ --tag-border-warning: var(--o-color-warning1);
+ --tag-border-danger: var(--o-color-danger1);
+
+ --tag-text-size: var(--o-font_size-text);
+ --tag-text-height: var(--o-line_height-text);
+
+ --tag-height-s: var(--o-size-s);
+ --tag-height-m: var(--o-size-m);
+ --tag-height-l: var(--o-size-l);
+
+ --tag-radius-s: var(--o-radius-s);
+ --tag-radius-m: var(--o-radius-s);
+ --tag-radius-l: var(--o-radius-s);
+}
diff --git a/packages/opendesign/src/components/tag/types.ts b/packages/opendesign/src/components/tag/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0d963e640912659ef9ed3c3632c0a3e3ff741f84
--- /dev/null
+++ b/packages/opendesign/src/components/tag/types.ts
@@ -0,0 +1 @@
+export type TagStatusT = 'normal' | 'success' | 'warning' | 'danger';
diff --git a/packages/portal/src/router.ts b/packages/portal/src/router.ts
index 91d99718ceb5d249559e684c3e65782f6e179463..3cf315c75e3a4b05383701247d74f0d6e1dfcad7 100644
--- a/packages/portal/src/router.ts
+++ b/packages/portal/src/router.ts
@@ -117,6 +117,12 @@ export const routes = [
label: '分割线',
component: () => import('@demo/divider/__demo__/IndexDivider.vue'),
},
+ {
+ path: '/tag',
+ name: 'Tag',
+ label: '标签',
+ component: () => import('@demo/tag/__demo__/IndexTag.vue'),
+ },
];
export const router = createRouter({