diff --git a/apps/example/src/router/modules/component.example.ts b/apps/example/src/router/modules/component.example.ts index ed92c8fc..3299503e 100755 --- a/apps/example/src/router/modules/component.example.ts +++ b/apps/example/src/router/modules/component.example.ts @@ -29,6 +29,14 @@ const routes: RouteRecordRaw = { title: '头像', }, }, + { + path: 'badge', + name: 'componentExampleBadge', + component: () => import('@/views/component_example/badge.vue'), + meta: { + title: '徽章', + }, + }, { path: 'button', name: 'componentExampleButton', diff --git a/apps/example/src/views/component_example/badge.vue b/apps/example/src/views/component_example/badge.vue new file mode 100644 index 00000000..7145cb16 --- /dev/null +++ b/apps/example/src/views/component_example/badge.vue @@ -0,0 +1,17 @@ + + + diff --git a/packages/components/src/basic/badge/README.md b/packages/components/src/basic/badge/README.md new file mode 100644 index 00000000..5f3491ba --- /dev/null +++ b/packages/components/src/basic/badge/README.md @@ -0,0 +1,39 @@ +# FaBadge 徽章 + +用于展示数量、状态的小徽章,支持数字、文本和点状模式,带有入场动画。 + +## 使用场景 + +- 消息通知数量提示 +- 未读消息数显示 +- 状态指示器(在线/离线) +- 新内容标记(NEW、HOT 等) +- 购物车商品数量 + +## Props + +| 属性 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `value` | `string \| number \| boolean` | - | 徽章显示内容,为空/0/false 时自动隐藏 | +| `variant` | `'default' \| 'secondary' \| 'destructive'` | `'default'` | 徽章颜色变体 | +| `class` | `HTMLAttributes['class']` | - | 容器 CSS 类 | +| `badgeClass` | `HTMLAttributes['class']` | - | 徽章本身的 CSS 类 | + +## Slots + +| 名称 | 说明 | +|------|------| +| `default` | 被包裹的内容(如图标、头像等) | + +## 注意事项 + +1. **自动隐藏**: + - 当 `value` 为 `0`、`false`、空字符串、`null` 或 `undefined` 时,徽章会自动隐藏 + - 布尔值 `true` 会显示为一个小圆点 + +2. **动画效果**:徽章显示/隐藏时有淡入淡出动画 + +3. **变体说明**: + - `default`:主色(蓝色) + - `secondary`:次要色(灰色) + - `destructive`:危险色(红色) diff --git a/packages/components/src/basic/badge/_examples/_basic.vue b/packages/components/src/basic/badge/_examples/_basic.vue new file mode 100644 index 00000000..8ede1642 --- /dev/null +++ b/packages/components/src/basic/badge/_examples/_basic.vue @@ -0,0 +1,25 @@ + + + diff --git a/packages/components/src/basic/badge/_examples/index.ts b/packages/components/src/basic/badge/_examples/index.ts new file mode 100644 index 00000000..1065244f --- /dev/null +++ b/packages/components/src/basic/badge/_examples/index.ts @@ -0,0 +1,10 @@ +import Basic from './_basic.vue' +import BasicRaw from './_basic.vue?raw' + +export default [ + { + title: '基础', + component: Basic, + componentRaw: BasicRaw, + }, +] diff --git a/packages/components/src/basic/badge/badge/Badge.vue b/packages/components/src/basic/badge/badge/Badge.vue new file mode 100644 index 00000000..0369574d --- /dev/null +++ b/packages/components/src/basic/badge/badge/Badge.vue @@ -0,0 +1,26 @@ + + + diff --git a/packages/components/src/basic/badge/badge/index.ts b/packages/components/src/basic/badge/badge/index.ts new file mode 100644 index 00000000..8f26fc38 --- /dev/null +++ b/packages/components/src/basic/badge/badge/index.ts @@ -0,0 +1,26 @@ +import type { VariantProps } from 'class-variance-authority' +import { cva } from 'class-variance-authority' + +export { default as Badge } from './Badge.vue' + +export const badgeVariants = cva( + 'inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden', + { + variants: { + variant: { + default: + 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90', + secondary: + 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90', + destructive: + 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', + outline: + 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground', + }, + }, + defaultVariants: { + variant: 'default', + }, + }, +) +export type BadgeVariants = VariantProps diff --git a/packages/components/src/basic/badge/index.vue b/packages/components/src/basic/badge/index.vue new file mode 100644 index 00000000..395e9265 --- /dev/null +++ b/packages/components/src/basic/badge/index.vue @@ -0,0 +1,75 @@ + + + diff --git a/packages/components/src/examples.ts b/packages/components/src/examples.ts index d5f449f1..642f54e7 100644 --- a/packages/components/src/examples.ts +++ b/packages/components/src/examples.ts @@ -1,5 +1,6 @@ export { default as alert } from './basic/alert/_examples' export { default as avatar } from './basic/avatar/_examples' +export { default as badge } from './basic/badge/_examples' export { default as buttonGroup } from './basic/button-group/_examples' export { default as button } from './basic/button/_examples' export { default as card } from './basic/card/_examples' diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 48baf804..c3289c38 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -1,6 +1,7 @@ // 基础版组件 export { default as FaAlert } from './basic/alert/index.vue' export { default as FaAvatar } from './basic/avatar/index.vue' +export { default as FaBadge } from './basic/badge/index.vue' export { default as FaButtonGroup } from './basic/button-group/index.vue' export { default as FaButton } from './basic/button/index.vue' export { default as FaCard } from './basic/card/index.vue'