基于 MSCPO 像素网格设计语言的 Vue 3 组件库。提供完整的 TypeScript 类型支持,所有组件遵循严格的方形边角、2px 黑边、系统字体的设计约束。
- 🟩 Vue 3.5+ — 基于最新 Vue 3 组合式 API,
<script setup>语法 - 🔷 TypeScript — 完整的类型声明(
*.types.ts),导出所有 Props / Emits 接口 - 🎨 MSCPO 设计语言 — 2px 黑色实线边框、方形边角、ore-dark / ore-green / ore-purple 主题色
- 📦 Tree-shaking — 支持按需导入,未使用的组件不会打入最终包
- ⚡ tsdown 构建 — 基于 Rolldown,同时输出 CJS + ESM + DTS
- 🛝 Playground — 基于 antdv-next 的实时组件演示环境,支持 HMR
- ✅ 测试就绪 — Vitest + jsdom / happy-dom 单元测试基础设施
# pnpm
pnpm add mscpore-vue3
# npm
npm install mscpore-vue3
# yarn
yarn add mscpore-vue3| 依赖 | 版本 | 说明 |
|---|---|---|
| vue | ≥ 3.3 | 框架依赖 |
<template>
<VContainer>
<VHeading level="h1" gradient>
Welcome to MSCPO
</VHeading>
<VGrid cols="cols-3" gap="md">
<VCard hoverable v-for="i in 3" :key="i">
<VCardImage>
<img :src="`https://picsum.photos/360/200?${i}`" alt="demo" />
</VCardImage>
<VCardBody>
<VBadge :count="5">
<VHeading level="h3">Card {{ i }}</VHeading>
</VBadge>
<p style="font-size:0.85rem;color:#666">MSCPO pixel-grid card.</p>
</VCardBody>
</VCard>
</VGrid>
<VButton variant="ore-green" @click="handleClick" style="margin-top:16px">
Get Started
</VButton>
</VContainer>
</template>
<script setup lang="ts">
import {
VBadge, VButton, VCard, VCardBody, VCardImage,
VContainer, VGrid, VHeading,
} from 'mscpore-vue3';
const handleClick = () => console.log('clicked');
</script>// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import MscporeUI from 'mscpore-vue3';
import 'mscpore-vue3/style.css';
const app = createApp(App);
app.use(MscporeUI);
app.mount('#app');全局安装后所有 V* 组件自动注册,无需单独引入。
packages/ui/src/
├── components/
│ ├── Alert/ # 提示
│ ├── Attachment/ # 附件
│ ├── Avatar/ # 头像 + 头像组
│ ├── Badge/ # 徽标
│ ├── Bubble/ # 聊天气泡
│ ├── Button/ # 按钮
│ ├── Card/ # 卡片 + CardBody + CardFooter + CardImage
│ ├── Container/ # 容器
│ ├── Dialog/ # 对话框
│ ├── Divider/ # 分割线
│ ├── Empty/ # 空状态
│ ├── ErrorBoundary/ # 错误边界
│ ├── FeatureCard/ # 特色卡片
│ ├── FloatButton/ # 浮动按钮
│ ├── Grid/ # 网格
│ ├── Heading/ # 标题
│ ├── HeroBanner/ # 主横幅
│ ├── Input/ # 输入框
│ ├── Marker/ # 会话标记
│ ├── Message/ # 消息
│ ├── MessageScroller/ # 消息滚动容器
│ ├── Progress/ # 进度条
│ ├── SearchInput/ # 搜索框
│ ├── Skeleton/ # 骨架屏
│ ├── SocialButton/ # 社交按钮
│ ├── StatCard/ # 统计卡片
│ ├── Tabs/ # 标签页
│ ├── Tag/ # 标签
│ └── Tooltip/ # 工具提示
├── styles/
│ ├── _variables.scss # MSCPO 设计令牌
│ ├── _mixins.scss # 可复用样式混入
│ └── _index.scss # 统一入口(@forward)
├── _utils/
│ └── with-install.ts # 组件 install 注册工具
└── index.ts
所有组件名称以
V为前缀(如VButton、VCard)。Props 接口以组件名 +Props命名导出。 本章节收录 29 个组件的完整 API,按功能分组。
import { VButton } from 'mscpore-vue3';Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| variant | 'ore-dark' | 'ore-green' | 'ore-purple' |
'ore-dark' |
视觉变体 |
| fullWidth | boolean |
false |
撑满容器宽度 |
| disabled | boolean |
false |
禁用状态 |
Emits
| 事件 | 载荷 | 说明 |
|---|---|---|
| click | MouseEvent |
点击事件 |
用例
<VButton variant="ore-dark">Dark</VButton>
<VButton variant="ore-green">Green CTA</VButton>
<VButton variant="ore-purple">AI Search</VButton>
<VButton variant="ore-dark" full-width>Full Width</VButton>
<VButton variant="ore-green" disabled>Disabled</VButton>import { VInput } from 'mscpore-vue3';Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| modelValue | string |
'' |
输入值(v-model) |
| size | 'sm' | 'md' | 'lg' |
'md' |
尺寸 |
| fullWidth | boolean |
false |
撑满宽度 |
| error | boolean |
false |
错误状态 |
| disabled | boolean |
false |
禁用 |
| placeholder | string |
— | 占位文本 |
Slots
| 名称 | 说明 |
|---|---|
| prefix | 前缀 |
| suffix | 后缀 |
用例
<VInput v-model="text" placeholder="Type..." />
<VInput v-model="text" error placeholder="Error" />
<VInput v-model="text">
<template #prefix>🔍</template>
<template #suffix>.com</template>
</VInput>import { VSearchInput } from 'mscpore-vue3';| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| modelValue | string |
'' |
搜索值 (v-model) |
| placeholder | string |
'搜索...' |
占位文本 |
Slots: icon – 搜索图标
<VSearchInput v-model="q" placeholder="搜索..." style="max-width:360px">
<template #icon>🔍</template>
</VSearchInput>import { VDialog } from 'mscpore-vue3';| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| open | boolean |
false |
显示/隐藏 (v-model) |
| title | string |
— | 标题 |
| closable | boolean |
true |
关闭按钮+遮罩关闭 |
| width | string | number |
440 |
宽度 |
Slots: default, footer
<VDialog v-model:open="show" title="CONFIRM">
<p>确定执行此操作?</p>
<template #footer>
<VButton variant="ore-dark" @click="show=false">取消</VButton>
<VButton variant="ore-green" @click="confirm">确认</VButton>
</template>
</VDialog>import { VTabs, VTabsList, VTab, VTabPanel } from 'mscpore-vue3';VTabs: selected (v-model), id | VTab: index | VTabPanel: index
<script setup>const tab = ref(0);</script>
<VTabs v-model:selected="tab">
<VTabsList>
<VTab :index="0">First</VTab>
<VTab :index="1">Second</VTab>
</VTabsList>
<VTabPanel :index="0">Content 1</VTabPanel>
<VTabPanel :index="1">Content 2</VTabPanel>
</VTabs>fluid bordered borderTop borderBottom (均为 boolean)
<VContainer><p>居中</p></VContainer>
<VContainer fluid><p>全宽</p></VContainer>
<VContainer bordered border-top><p>带边框</p></VContainer>level ('h1'|'h2'|'h3'|'h4', 默认 'h1'), gradient (boolean)
<VHeading level="h1" gradient>Hero</VHeading>
<VHeading level="h2">Section</VHeading>
<VHeading level="h3">Card</VHeading>variant: 'default'|'small'|'accent'|'muted'|'danger'|'outline' (默认 'default')
<VTag>Default</VTag>
<VTag variant="accent">New</VTag>
<VTag variant="danger">Error</VTag>
<VTag variant="outline">Draft</VTag>variant ('default'|'dot'|'count'), count, overflowCount, danger
<VBadge :count="5"><VButton>Messages</VButton></VBadge>
<VBadge variant="dot" danger />VCard: hoverable compact feature featureBg inputCard
子组件: VCardImage, VCardBody, VCardFooter
<VCard hoverable>
<VCardImage><img src="/img.jpg" /></VCardImage>
<VCardBody><VHeading level="h3">Title</VHeading></VCardBody>
<VCardFooter><VButton variant="ore-green">Action</VButton></VCardFooter>
</VCard>
<VCard feature feature-bg="/bg.jpg"><VCardBody>Hover reveal</VCardBody></VCard>value (string), label (string), accent (boolean)
<VStatCard value="100+" label="Projects" accent />title description bgImage bgAlt plain
<VFeatureCard title="AI" description="Powered by ML" bg-image="/ai.jpg" />
<VFeatureCard title="Free" description="Open source" plain />cols ('cols-2'|'cols-3'|'cols-4'|'auto-fit'|'aside'), gap ('none'|'sm'|'md'|'lg'), bordered
<VGrid cols="cols-3" gap="md">
<VCard v-for="i in 6" :key="i"><VCardBody>Item {{ i }}</VCardBody></VCard>
</VGrid>direction ('horizontal'|'vertical'), dashed, labelPosition
<VDivider />
<VDivider>OR</VDivider>
<VDivider direction="vertical" />VAvatar: src alt fallback size ('sm'|'md'|'lg'|'xl') status ('online'|'offline'|'away') statusColor
VAvatarGroup: 无特殊 props
<VAvatar src="/a.jpg" size="md" status="online" />
<VAvatar fallback="JD" size="lg" />
<VAvatarGroup>
<VAvatar src="/a.jpg" size="md" />
<VAvatar fallback="+3" size="md" />
</VAvatarGroup>variant ('text'|'title'|'image'|'circle'|'custom'), width, height
VSkeletonCard: 预构建的卡片骨架
<VSkeleton variant="image" />
<VSkeleton variant="title" />
<VSkeletonCard style="max-width:300px" />type ('info'|'success'|'warning'|'error'), title, closable | Emits: close
<VAlert>Info message</VAlert>
<VAlert type="success" title="OK">Done</VAlert>
<VAlert type="error" closable @close="handleClose">Error</VAlert>percent (number, 0-100), status ('normal'|'success'|'error'), showInfo
<VProgress :percent="60" />
<VProgress :percent="100" status="success" />description, icon | Slot: default (action area)
<VEmpty description="No results">
<VButton variant="ore-green">Create</VButton>
</VEmpty>label (string), placement ('top'|'bottom'|'left'|'right')
<VTooltip label="TOP"><VButton>Hover</VButton></VTooltip>variant ('sent'|'received'), align, grouped, reactions, collapsible, collapsed, header, footer, timestamp
<VBubble variant="received" timestamp="10:30">Hello!</VBubble>
<VBubble variant="sent">Hi!</VBubble>组合 Avatar + Bubble。variant avatarSrc avatarAlt avatarFallback avatarSize avatarStatus sender timestamp footer grouped
<VMessage variant="received" sender="ALICE" avatar-src="/a.jpg" timestamp="11:00">
Hello!
</VMessage>autoScroll showScrollToBottom loading loadMoreThreshold | Emits: loadMore
<VMessageScroller style="height:400px" @load-more="loadHistory">
<VMessage v-for="m in msgs" v-bind="m">{{ m.text }}</VMessage>
</VMessageScroller>variant ('status'|'system'|'divider'|'label'), color, timestamp
<VMarker variant="status">Online</VMarker>
<VMarker variant="divider" timestamp="YESTERDAY" />name size type thumbnail state ('idle'|'uploading'|'error'|'loaded') progress | Emits: remove click
<VAttachment name="report.pdf" size="2.4 MB" type="PDF" @remove="remove" />
<VAttachment name="file.zip" state="uploading" :progress="65" />backTop (boolean), position ('bottom-right'|'bottom-left') | Emits: click
<VFloatButton back-top />
<VFloatButton @click="scroll">+</VFloatButton>href small target rel
<VSocialButton href="https://github.com">GitHub</VSocialButton>title subtitle label gradient
<VHeroBanner title="BUILD BETTER" subtitle="MSCPO library for Vue 3" label="NEW" gradient>
<VButton variant="ore-green">START</VButton>
</VHeroBanner>使用 onErrorCaptured 捕获错误,显示降级 UI。无特殊 props。
<VErrorBoundary><RiskyComponent /></VErrorBoundary>pnpm dev # 启动开发环境
pnpm dev:play # 启动 Playground
pnpm build # 构建所有包
pnpm build:ui # 仅构建 UI 包
pnpm test # 运行测试
pnpm lint:all # 代码检查
pnpm clean # 清理
pnpm generate:component # 生成新组件
pnpm rename-pkg # 替换包名遵循项目 COMPONENT_GUIDE.md 约定,所有 UI 组件以 V 为前缀,避免与原生 HTML 元素冲突。
import { VButton, VCard } from 'mscpore-vue3';Tree-shaking 自动排除未使用的代码。
MSCPO 设计令牌定义在 src/styles/_variables.scss 中,编译为 :root CSS 自定义属性 (--mscpo-*)。引入 style.css 即可。
欢迎提交 Issue 和 PR。Fork → 分支 → 提交 → Push → Pull Request。