mirror of
https://github.com/fantastic-admin/basic.git
synced 2026-10-06 14:43:13 +08:00
feat(tag): 新增标签组件及示例
This commit is contained in:
@@ -294,6 +294,14 @@ const routes: RouteRecordRaw = {
|
||||
title: '开关',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'tag',
|
||||
name: 'componentExampleTag',
|
||||
component: () => import('@/views/component_example/tag.vue'),
|
||||
meta: {
|
||||
title: '标签',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'tabs',
|
||||
name: 'componentExampleTabs',
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { tag } from '@fantastic-admin/components/examples'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<FaPageHeader title="标签" description="FaTag" />
|
||||
<FaPageMain
|
||||
v-for="example in tag"
|
||||
:key="example.title"
|
||||
:code="example.componentRaw"
|
||||
:title="example.title"
|
||||
>
|
||||
<component :is="example.component" />
|
||||
</FaPageMain>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,42 @@
|
||||
# FaTag 标签
|
||||
|
||||
基础标签组件,用于标记和分类信息,支持多种样式变体和可关闭功能。
|
||||
|
||||
## 使用场景
|
||||
|
||||
- 状态标记(成功、失败、进行中)
|
||||
- 分类标签
|
||||
- 筛选条件标签
|
||||
- 展示多个属性或特征
|
||||
- 可删除的标签列表
|
||||
|
||||
## Props
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `variant` | `'default' \| 'destructive' \| 'outline' \| 'secondary'` | `'default'` | 标签样式变体 |
|
||||
| `icon` | `string` | - | 图标名称,使用 FaIcon 渲染 |
|
||||
| `closable` | `boolean` | `false` | 是否显示关闭按钮 |
|
||||
| `class` | `HTMLAttributes['class']` | - | 自定义 CSS 类 |
|
||||
|
||||
## Events
|
||||
|
||||
| 事件名 | 参数 | 说明 |
|
||||
|--------|------|------|
|
||||
| `close` | `event: MouseEvent` | 点击关闭按钮时触发 |
|
||||
|
||||
## Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|------|------|
|
||||
| `default` | 标签内容 |
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **变体选择**:
|
||||
- `default`:主色调标签,用于重要标记
|
||||
- `destructive`:危险/错误状态标签
|
||||
- `outline`:边框样式,用于次要标记
|
||||
- `secondary`:次级标签,用于一般分类
|
||||
2. **可关闭标签**:设置 `closable` 为 `true` 时,标签右侧会显示关闭按钮,点击触发 `close` 事件
|
||||
3. **关闭事件处理**:需要监听 `close` 事件来自定义关闭逻辑(如从列表中移除标签)
|
||||
@@ -0,0 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
// 组件实际使用时无需手动导入,框架会自动导入
|
||||
import FaTag from '../index.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<FaTag>
|
||||
默认标签
|
||||
</FaTag>
|
||||
<FaTag variant="destructive">
|
||||
危险标签
|
||||
</FaTag>
|
||||
<FaTag variant="outline">
|
||||
边框标签
|
||||
</FaTag>
|
||||
<FaTag variant="secondary">
|
||||
次要标签
|
||||
</FaTag>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
// 组件实际使用时无需手动导入,框架会自动导入
|
||||
import { ref } from 'vue'
|
||||
import FaTag from '../index.vue'
|
||||
|
||||
const tags = ref([
|
||||
{ id: 1, label: '标签一', variant: 'default' as const },
|
||||
{ id: 2, label: '标签二', variant: 'destructive' as const },
|
||||
{ id: 3, label: '标签三', variant: 'outline' as const },
|
||||
{ id: 4, label: '标签四', variant: 'secondary' as const },
|
||||
])
|
||||
|
||||
function handleClose(id: number) {
|
||||
tags.value = tags.value.filter(tag => tag.id !== id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<FaTag
|
||||
v-for="tag in tags"
|
||||
:key="tag.id"
|
||||
:variant="tag.variant"
|
||||
closable
|
||||
@close="handleClose(tag.id)"
|
||||
>
|
||||
{{ tag.label }}
|
||||
</FaTag>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
// 组件实际使用时无需手动导入,框架会自动导入
|
||||
import FaTag from '../index.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<FaTag icon="i-lucide:check">
|
||||
成功
|
||||
</FaTag>
|
||||
<FaTag icon="i-lucide:alert-triangle" variant="destructive">
|
||||
警告
|
||||
</FaTag>
|
||||
<FaTag icon="i-lucide:info" variant="outline">
|
||||
信息
|
||||
</FaTag>
|
||||
<FaTag icon="i-lucide:star" variant="secondary">
|
||||
收藏
|
||||
</FaTag>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,24 @@
|
||||
import Basic from './_basic.vue'
|
||||
import BasicRaw from './_basic.vue?raw'
|
||||
import Closable from './_closable.vue'
|
||||
import ClosableRaw from './_closable.vue?raw'
|
||||
import Icon from './_icon.vue'
|
||||
import IconRaw from './_icon.vue?raw'
|
||||
|
||||
export default [
|
||||
{
|
||||
title: '基础',
|
||||
component: Basic,
|
||||
componentRaw: BasicRaw,
|
||||
},
|
||||
{
|
||||
title: '图标',
|
||||
component: Icon,
|
||||
componentRaw: IconRaw,
|
||||
},
|
||||
{
|
||||
title: '可关闭',
|
||||
component: Closable,
|
||||
componentRaw: ClosableRaw,
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import type { TagVariants } from './tag'
|
||||
import { Tag } from './tag'
|
||||
|
||||
defineOptions({
|
||||
name: 'BuiltInTag',
|
||||
})
|
||||
|
||||
const props = defineProps<{
|
||||
variant?: TagVariants['variant']
|
||||
class?: HTMLAttributes['class']
|
||||
icon?: string
|
||||
closable?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
close: [event: MouseEvent]
|
||||
}>()
|
||||
|
||||
function handleClose(event: MouseEvent) {
|
||||
emit('close', event)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Tag :variant :icon :closable :class="props.class" @close="handleClose">
|
||||
<slot />
|
||||
</Tag>
|
||||
</template>
|
||||
@@ -0,0 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
import type { PrimitiveProps } from 'reka-ui'
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import type { TagVariants } from '.'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { cn } from '#utils'
|
||||
import { tagVariants } from '.'
|
||||
import FaIcon from '../../icon/index.vue'
|
||||
|
||||
interface Props extends PrimitiveProps {
|
||||
variant?: TagVariants['variant']
|
||||
icon?: string
|
||||
closable?: boolean
|
||||
class?: HTMLAttributes['class']
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
as: 'span',
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
close: [event: MouseEvent]
|
||||
}>()
|
||||
|
||||
function handleClose(event: MouseEvent) {
|
||||
emit('close', event)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Primitive
|
||||
data-slot="tag"
|
||||
:as="as"
|
||||
:as-child="asChild"
|
||||
:class="cn(tagVariants({ variant }), props.class)"
|
||||
>
|
||||
<FaIcon v-if="icon" :name="icon" class="size-3" />
|
||||
<slot />
|
||||
<button
|
||||
v-if="closable"
|
||||
type="button"
|
||||
class="me--1 outline-none rounded-full inline-flex ring-offset-background items-center justify-center focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
||||
@click="handleClose"
|
||||
>
|
||||
<FaIcon name="i-lucide:x" class="size-3" />
|
||||
</button>
|
||||
</Primitive>
|
||||
</template>
|
||||
@@ -0,0 +1,27 @@
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import { cva } from 'class-variance-authority'
|
||||
|
||||
export { default as Tag } from './Tag.vue'
|
||||
|
||||
export const tagVariants = cva(
|
||||
'inline-flex items-center gap-1 rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
'border-transparent bg-primary text-primary-foreground',
|
||||
destructive:
|
||||
'border-transparent bg-destructive text-white dark:bg-destructive/60',
|
||||
outline:
|
||||
'border bg-background text-foreground dark:bg-input/30 dark:border-input',
|
||||
secondary:
|
||||
'border-transparent bg-secondary text-secondary-foreground',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
export type TagVariants = VariantProps<typeof tagVariants>
|
||||
@@ -36,6 +36,7 @@ export { default as select } from './basic/select/_examples'
|
||||
export { default as slider } from './basic/slider/_examples'
|
||||
export { default as switch } from './basic/switch/_examples'
|
||||
export { default as tabs } from './basic/tabs/_examples'
|
||||
export { default as tag } from './basic/tag/_examples'
|
||||
export { default as textarea } from './basic/textarea/_examples'
|
||||
export { default as toast } from './basic/toast/_examples'
|
||||
export { default as tooltip } from './basic/tooltip/_examples'
|
||||
|
||||
@@ -44,6 +44,7 @@ export { default as FaSelect } from './basic/select/index.vue'
|
||||
export { default as FaSlider } from './basic/slider/index.vue'
|
||||
export { default as FaSwitch } from './basic/switch/index.vue'
|
||||
export { default as FaTabs } from './basic/tabs/index.vue'
|
||||
export { default as FaTag } from './basic/tag/index.vue'
|
||||
export { default as FaTextarea } from './basic/textarea/index.vue'
|
||||
export { useToast as useFaToast } from './basic/toast/index'
|
||||
export { default as FaToast } from './basic/toast/index.vue'
|
||||
|
||||
Reference in New Issue
Block a user