vue-clean-tabs 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -129
- package/dist/index.esm.js +85 -80
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +67 -67
- package/src/components/ConfigurableSimpleTabs.vue +85 -37
- package/src/index.ts +19 -18
- package/src/types.ts +181 -180
package/README.md
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
# Vue
|
|
1
|
+
# Vue Clean Tabs
|
|
2
2
|
|
|
3
3
|
🚀 一个轻量级、高度可配置的 Vue 3 简洁标签页组件,专注于简洁设计和灵活定制。
|
|
4
4
|
|
|
5
|
+
## 🆕 v1.1.0 更新
|
|
6
|
+
|
|
7
|
+
- ✨ **优化样式结构** - 简化CSS类名,提升可维护性
|
|
8
|
+
- 🎯 **改进激活指示器** - 使用CSS伪元素实现更流畅的底部线条
|
|
9
|
+
- 📱 **增强移动端适配** - 优化移动端样式和响应式体验
|
|
10
|
+
- 🚀 **性能优化** - 减少内联样式,提升渲染性能
|
|
11
|
+
|
|
5
12
|
## ✨ 特性
|
|
6
13
|
|
|
7
14
|
- 🪶 **轻量级设计** - 极简的 API 和最小的包体积
|
|
@@ -16,7 +23,7 @@
|
|
|
16
23
|
## 📦 安装
|
|
17
24
|
|
|
18
25
|
```bash
|
|
19
|
-
npm install vue-
|
|
26
|
+
npm install vue-clean-tabs
|
|
20
27
|
```
|
|
21
28
|
|
|
22
29
|
## 🚀 快速开始
|
|
@@ -33,16 +40,16 @@ npm install vue-simple-tabs
|
|
|
33
40
|
</template>
|
|
34
41
|
|
|
35
42
|
<script setup>
|
|
36
|
-
import { ConfigurableSimpleTabs } from
|
|
43
|
+
import { ConfigurableSimpleTabs } from "vue-clean-tabs";
|
|
37
44
|
|
|
38
45
|
const tabs = [
|
|
39
|
-
{ id:
|
|
40
|
-
{ id:
|
|
41
|
-
{ id:
|
|
46
|
+
{ id: "home", name: "首页" },
|
|
47
|
+
{ id: "about", name: "关于" },
|
|
48
|
+
{ id: "contact", name: "联系" },
|
|
42
49
|
];
|
|
43
50
|
|
|
44
51
|
const handleTabChange = (tabId, tab) => {
|
|
45
|
-
console.log(
|
|
52
|
+
console.log("切换到:", tab.name);
|
|
46
53
|
};
|
|
47
54
|
</script>
|
|
48
55
|
```
|
|
@@ -56,15 +63,15 @@ const handleTabChange = (tabId, tab) => {
|
|
|
56
63
|
|
|
57
64
|
<script setup>
|
|
58
65
|
const iconTabs = [
|
|
59
|
-
{
|
|
60
|
-
id:
|
|
61
|
-
name:
|
|
62
|
-
icon:
|
|
66
|
+
{
|
|
67
|
+
id: "home",
|
|
68
|
+
name: "首页",
|
|
69
|
+
icon: "<svg>...</svg>", // SVG 图标
|
|
63
70
|
},
|
|
64
|
-
{
|
|
65
|
-
id:
|
|
66
|
-
name:
|
|
67
|
-
icon:
|
|
71
|
+
{
|
|
72
|
+
id: "user",
|
|
73
|
+
name: "用户",
|
|
74
|
+
icon: "<svg>...</svg>",
|
|
68
75
|
},
|
|
69
76
|
];
|
|
70
77
|
</script>
|
|
@@ -74,18 +81,14 @@ const iconTabs = [
|
|
|
74
81
|
|
|
75
82
|
```vue
|
|
76
83
|
<template>
|
|
77
|
-
<ConfigurableSimpleTabs
|
|
78
|
-
:tabs="tabs"
|
|
79
|
-
:theme="customTheme"
|
|
80
|
-
size="large"
|
|
81
|
-
/>
|
|
84
|
+
<ConfigurableSimpleTabs :tabs="tabs" :theme="customTheme" size="large" />
|
|
82
85
|
</template>
|
|
83
86
|
|
|
84
87
|
<script setup>
|
|
85
88
|
const customTheme = {
|
|
86
|
-
activeTextColor:
|
|
87
|
-
indicatorColor:
|
|
88
|
-
backgroundColor:
|
|
89
|
+
activeTextColor: "#3b82f6",
|
|
90
|
+
indicatorColor: "#3b82f6",
|
|
91
|
+
backgroundColor: "#f8fafc",
|
|
89
92
|
};
|
|
90
93
|
</script>
|
|
91
94
|
```
|
|
@@ -102,19 +105,19 @@ const customTheme = {
|
|
|
102
105
|
|
|
103
106
|
#### 可选属性
|
|
104
107
|
|
|
105
|
-
| 属性 | 类型
|
|
106
|
-
| --------------- |
|
|
107
|
-
| `defaultActive` | `string`
|
|
108
|
-
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'`
|
|
109
|
-
| `theme` | `Partial<SimpleTabsTheme>`
|
|
110
|
-
| `style` | `Partial<StyleConfig>`
|
|
111
|
-
| `animation` | `Partial<AnimationConfig>`
|
|
112
|
-
| `responsive` | `Partial<ResponsiveConfig>`
|
|
113
|
-
| `className` | `string`
|
|
114
|
-
| `customStyle` | `Record<string, any>`
|
|
115
|
-
| `block` | `boolean`
|
|
116
|
-
| `centered` | `boolean`
|
|
117
|
-
| `scrollable` | `boolean`
|
|
108
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
109
|
+
| --------------- | -------------------------------- | -------------- | ---------------- |
|
|
110
|
+
| `defaultActive` | `string` | 第一个标签 | 默认激活的标签ID |
|
|
111
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | 组件尺寸 |
|
|
112
|
+
| `theme` | `Partial<SimpleTabsTheme>` | `defaultTheme` | 主题配置 |
|
|
113
|
+
| `style` | `Partial<StyleConfig>` | `默认样式` | 样式配置 |
|
|
114
|
+
| `animation` | `Partial<AnimationConfig>` | `默认动画` | 动画配置 |
|
|
115
|
+
| `responsive` | `Partial<ResponsiveConfig>` | `默认响应式` | 响应式配置 |
|
|
116
|
+
| `className` | `string` | `undefined` | 自定义类名 |
|
|
117
|
+
| `customStyle` | `Record<string, any>` | `undefined` | 自定义样式 |
|
|
118
|
+
| `block` | `boolean` | `false` | 块级显示 |
|
|
119
|
+
| `centered` | `boolean` | `false` | 居中对齐 |
|
|
120
|
+
| `scrollable` | `boolean` | `false` | 可滚动 |
|
|
118
121
|
|
|
119
122
|
### 类型定义
|
|
120
123
|
|
|
@@ -122,11 +125,11 @@ const customTheme = {
|
|
|
122
125
|
|
|
123
126
|
```typescript
|
|
124
127
|
interface TabItem {
|
|
125
|
-
id: string;
|
|
126
|
-
name: string;
|
|
127
|
-
disabled?: boolean;
|
|
128
|
-
route?: string;
|
|
129
|
-
icon?: string;
|
|
128
|
+
id: string; // 唯一标识符
|
|
129
|
+
name: string; // 显示名称
|
|
130
|
+
disabled?: boolean; // 是否禁用
|
|
131
|
+
route?: string; // 路由地址
|
|
132
|
+
icon?: string; // 图标 HTML (SVG)
|
|
130
133
|
}
|
|
131
134
|
```
|
|
132
135
|
|
|
@@ -134,14 +137,14 @@ interface TabItem {
|
|
|
134
137
|
|
|
135
138
|
```typescript
|
|
136
139
|
interface SimpleTabsTheme {
|
|
137
|
-
activeTextColor: string;
|
|
138
|
-
inactiveTextColor: string;
|
|
139
|
-
hoverTextColor: string;
|
|
140
|
-
backgroundColor: string;
|
|
141
|
-
indicatorColor: string;
|
|
142
|
-
fontFamily: string;
|
|
143
|
-
borderColor?: string;
|
|
144
|
-
boxShadow?: string;
|
|
140
|
+
activeTextColor: string; // 激活文字颜色
|
|
141
|
+
inactiveTextColor: string; // 非激活文字颜色
|
|
142
|
+
hoverTextColor: string; // 悬浮文字颜色
|
|
143
|
+
backgroundColor: string; // 背景色
|
|
144
|
+
indicatorColor: string; // 指示器颜色
|
|
145
|
+
fontFamily: string; // 字体系列
|
|
146
|
+
borderColor?: string; // 边框颜色
|
|
147
|
+
boxShadow?: string; // 阴影
|
|
145
148
|
}
|
|
146
149
|
```
|
|
147
150
|
|
|
@@ -149,20 +152,20 @@ interface SimpleTabsTheme {
|
|
|
149
152
|
|
|
150
153
|
```typescript
|
|
151
154
|
interface StyleConfig {
|
|
152
|
-
padding: string;
|
|
153
|
-
fontSize: string;
|
|
154
|
-
fontWeight: string;
|
|
155
|
-
indicatorHeight: string;
|
|
155
|
+
padding: string; // 内边距
|
|
156
|
+
fontSize: string; // 字体大小
|
|
157
|
+
fontWeight: string; // 字体粗细
|
|
158
|
+
indicatorHeight: string; // 指示器高度
|
|
156
159
|
indicatorStyle: IndicatorStyle; // 指示器样式
|
|
157
|
-
borderRadius?: string;
|
|
158
|
-
gap?: string;
|
|
160
|
+
borderRadius?: string; // 圆角
|
|
161
|
+
gap?: string; // 标签间距
|
|
159
162
|
}
|
|
160
163
|
```
|
|
161
164
|
|
|
162
165
|
#### 指示器样式
|
|
163
166
|
|
|
164
167
|
```typescript
|
|
165
|
-
type IndicatorStyle =
|
|
168
|
+
type IndicatorStyle = "line" | "dot" | "pill" | "underline";
|
|
166
169
|
```
|
|
167
170
|
|
|
168
171
|
- `line` - 底部线条 (默认)
|
|
@@ -172,12 +175,12 @@ type IndicatorStyle = 'line' | 'dot' | 'pill' | 'underline';
|
|
|
172
175
|
|
|
173
176
|
### 事件
|
|
174
177
|
|
|
175
|
-
| 事件名 | 参数
|
|
176
|
-
| ------------ |
|
|
177
|
-
| `tab-change` | `(tabId: string, tab: TabItem)`
|
|
178
|
-
| `tab-click` | `(tabId: string, tab: TabItem, event: Event)` | 标签页点击时触发
|
|
179
|
-
| `tab-hover` | `(tabId: string, tab: TabItem)`
|
|
180
|
-
| `tab-leave` | `(tabId: string, tab: TabItem)`
|
|
178
|
+
| 事件名 | 参数 | 描述 |
|
|
179
|
+
| ------------ | --------------------------------------------- | ---------------------- |
|
|
180
|
+
| `tab-change` | `(tabId: string, tab: TabItem)` | 标签页切换时触发 |
|
|
181
|
+
| `tab-click` | `(tabId: string, tab: TabItem, event: Event)` | 标签页点击时触发 |
|
|
182
|
+
| `tab-hover` | `(tabId: string, tab: TabItem)` | 鼠标悬浮在标签页时触发 |
|
|
183
|
+
| `tab-leave` | `(tabId: string, tab: TabItem)` | 鼠标离开标签页时触发 |
|
|
181
184
|
|
|
182
185
|
## 🎨 预设配置
|
|
183
186
|
|
|
@@ -186,22 +189,22 @@ type IndicatorStyle = 'line' | 'dot' | 'pill' | 'underline';
|
|
|
186
189
|
```typescript
|
|
187
190
|
const sizeConfigs = {
|
|
188
191
|
small: {
|
|
189
|
-
padding:
|
|
190
|
-
fontSize:
|
|
191
|
-
fontWeight:
|
|
192
|
-
indicatorHeight:
|
|
192
|
+
padding: "8px 10px",
|
|
193
|
+
fontSize: "14px",
|
|
194
|
+
fontWeight: "500",
|
|
195
|
+
indicatorHeight: "2px",
|
|
193
196
|
},
|
|
194
197
|
medium: {
|
|
195
|
-
padding:
|
|
196
|
-
fontSize:
|
|
197
|
-
fontWeight:
|
|
198
|
-
indicatorHeight:
|
|
198
|
+
padding: "14px 12px",
|
|
199
|
+
fontSize: "16px",
|
|
200
|
+
fontWeight: "600",
|
|
201
|
+
indicatorHeight: "2px",
|
|
199
202
|
},
|
|
200
203
|
large: {
|
|
201
|
-
padding:
|
|
202
|
-
fontSize:
|
|
203
|
-
fontWeight:
|
|
204
|
-
indicatorHeight:
|
|
204
|
+
padding: "16px 16px",
|
|
205
|
+
fontSize: "18px",
|
|
206
|
+
fontWeight: "700",
|
|
207
|
+
indicatorHeight: "3px",
|
|
205
208
|
},
|
|
206
209
|
};
|
|
207
210
|
```
|
|
@@ -210,12 +213,13 @@ const sizeConfigs = {
|
|
|
210
213
|
|
|
211
214
|
```typescript
|
|
212
215
|
const defaultTheme = {
|
|
213
|
-
activeTextColor:
|
|
214
|
-
inactiveTextColor:
|
|
215
|
-
hoverTextColor:
|
|
216
|
-
backgroundColor:
|
|
217
|
-
indicatorColor:
|
|
218
|
-
fontFamily:
|
|
216
|
+
activeTextColor: "rgb(20, 23, 26)",
|
|
217
|
+
inactiveTextColor: "rgb(76, 82, 89)",
|
|
218
|
+
hoverTextColor: "rgb(55, 65, 81)",
|
|
219
|
+
backgroundColor: "#ffffff",
|
|
220
|
+
indicatorColor: "rgb(20, 23, 26)",
|
|
221
|
+
fontFamily:
|
|
222
|
+
'-apple-system, BlinkMacSystemFont, "Segoe UI", "SF Pro Display", "Inter", sans-serif',
|
|
219
223
|
};
|
|
220
224
|
```
|
|
221
225
|
|
|
@@ -225,28 +229,16 @@ const defaultTheme = {
|
|
|
225
229
|
|
|
226
230
|
```vue
|
|
227
231
|
<!-- 线条指示器 -->
|
|
228
|
-
<ConfigurableSimpleTabs
|
|
229
|
-
:tabs="tabs"
|
|
230
|
-
:style="{ indicatorStyle: 'line' }"
|
|
231
|
-
/>
|
|
232
|
+
<ConfigurableSimpleTabs :tabs="tabs" :style="{ indicatorStyle: 'line' }" />
|
|
232
233
|
|
|
233
234
|
<!-- 下划线指示器 -->
|
|
234
|
-
<ConfigurableSimpleTabs
|
|
235
|
-
:tabs="tabs"
|
|
236
|
-
:style="{ indicatorStyle: 'underline' }"
|
|
237
|
-
/>
|
|
235
|
+
<ConfigurableSimpleTabs :tabs="tabs" :style="{ indicatorStyle: 'underline' }" />
|
|
238
236
|
|
|
239
237
|
<!-- 圆点指示器 -->
|
|
240
|
-
<ConfigurableSimpleTabs
|
|
241
|
-
:tabs="tabs"
|
|
242
|
-
:style="{ indicatorStyle: 'dot' }"
|
|
243
|
-
/>
|
|
238
|
+
<ConfigurableSimpleTabs :tabs="tabs" :style="{ indicatorStyle: 'dot' }" />
|
|
244
239
|
|
|
245
240
|
<!-- 药丸指示器 -->
|
|
246
|
-
<ConfigurableSimpleTabs
|
|
247
|
-
:tabs="tabs"
|
|
248
|
-
:style="{ indicatorStyle: 'pill' }"
|
|
249
|
-
/>
|
|
241
|
+
<ConfigurableSimpleTabs :tabs="tabs" :style="{ indicatorStyle: 'pill' }" />
|
|
250
242
|
```
|
|
251
243
|
|
|
252
244
|
### 深色主题
|
|
@@ -259,7 +251,7 @@ const defaultTheme = {
|
|
|
259
251
|
inactiveTextColor: '#9ca3af',
|
|
260
252
|
hoverTextColor: '#d1d5db',
|
|
261
253
|
backgroundColor: '#1f2937',
|
|
262
|
-
indicatorColor: '#3b82f6'
|
|
254
|
+
indicatorColor: '#3b82f6',
|
|
263
255
|
}"
|
|
264
256
|
/>
|
|
265
257
|
```
|
|
@@ -267,11 +259,7 @@ const defaultTheme = {
|
|
|
267
259
|
### 滚动标签页
|
|
268
260
|
|
|
269
261
|
```vue
|
|
270
|
-
<ConfigurableSimpleTabs
|
|
271
|
-
:tabs="manyTabs"
|
|
272
|
-
scrollable
|
|
273
|
-
:style="{ gap: '32px' }"
|
|
274
|
-
/>
|
|
262
|
+
<ConfigurableSimpleTabs :tabs="manyTabs" scrollable :style="{ gap: '32px' }" />
|
|
275
263
|
```
|
|
276
264
|
|
|
277
265
|
### 居中对齐
|
|
@@ -287,10 +275,7 @@ const defaultTheme = {
|
|
|
287
275
|
### 禁用动画
|
|
288
276
|
|
|
289
277
|
```vue
|
|
290
|
-
<ConfigurableSimpleTabs
|
|
291
|
-
:tabs="tabs"
|
|
292
|
-
:animation="{ enabled: false }"
|
|
293
|
-
/>
|
|
278
|
+
<ConfigurableSimpleTabs :tabs="tabs" :animation="{ enabled: false }" />
|
|
294
279
|
```
|
|
295
280
|
|
|
296
281
|
### 自定义响应式
|
|
@@ -302,8 +287,8 @@ const defaultTheme = {
|
|
|
302
287
|
mobileBreakpoint: 1024,
|
|
303
288
|
mobileStyle: {
|
|
304
289
|
padding: '12px 8px',
|
|
305
|
-
fontSize: '14px'
|
|
306
|
-
}
|
|
290
|
+
fontSize: '14px',
|
|
291
|
+
},
|
|
307
292
|
}"
|
|
308
293
|
/>
|
|
309
294
|
```
|
|
@@ -314,20 +299,17 @@ const defaultTheme = {
|
|
|
314
299
|
|
|
315
300
|
```vue
|
|
316
301
|
<template>
|
|
317
|
-
<ConfigurableSimpleTabs
|
|
318
|
-
ref="tabsRef"
|
|
319
|
-
:tabs="tabs"
|
|
320
|
-
/>
|
|
302
|
+
<ConfigurableSimpleTabs ref="tabsRef" :tabs="tabs" />
|
|
321
303
|
<button @click="switchTab">切换到联系页</button>
|
|
322
304
|
</template>
|
|
323
305
|
|
|
324
306
|
<script setup>
|
|
325
|
-
import { ref } from
|
|
307
|
+
import { ref } from "vue";
|
|
326
308
|
|
|
327
309
|
const tabsRef = ref();
|
|
328
310
|
|
|
329
311
|
const switchTab = () => {
|
|
330
|
-
tabsRef.value.setActiveTab(
|
|
312
|
+
tabsRef.value.setActiveTab("contact");
|
|
331
313
|
};
|
|
332
314
|
</script>
|
|
333
315
|
```
|
|
@@ -336,20 +318,17 @@ const switchTab = () => {
|
|
|
336
318
|
|
|
337
319
|
```vue
|
|
338
320
|
<template>
|
|
339
|
-
<ConfigurableSimpleTabs
|
|
340
|
-
:tabs="routeTabs"
|
|
341
|
-
@tab-change="handleTabChange"
|
|
342
|
-
/>
|
|
321
|
+
<ConfigurableSimpleTabs :tabs="routeTabs" @tab-change="handleTabChange" />
|
|
343
322
|
</template>
|
|
344
323
|
|
|
345
324
|
<script setup>
|
|
346
|
-
import { useRouter } from
|
|
325
|
+
import { useRouter } from "vue-router";
|
|
347
326
|
|
|
348
327
|
const router = useRouter();
|
|
349
328
|
|
|
350
329
|
const routeTabs = [
|
|
351
|
-
{ id:
|
|
352
|
-
{ id:
|
|
330
|
+
{ id: "home", name: "首页", route: "/" },
|
|
331
|
+
{ id: "about", name: "关于", route: "/about" },
|
|
353
332
|
];
|
|
354
333
|
|
|
355
334
|
const handleTabChange = (tabId, tab) => {
|
|
@@ -364,19 +343,14 @@ const handleTabChange = (tabId, tab) => {
|
|
|
364
343
|
|
|
365
344
|
```vue
|
|
366
345
|
<template>
|
|
367
|
-
<ConfigurableSimpleTabs
|
|
368
|
-
:tabs="dynamicTabs"
|
|
369
|
-
@tab-change="handleTabChange"
|
|
370
|
-
/>
|
|
346
|
+
<ConfigurableSimpleTabs :tabs="dynamicTabs" @tab-change="handleTabChange" />
|
|
371
347
|
<button @click="addTab">添加标签页</button>
|
|
372
348
|
</template>
|
|
373
349
|
|
|
374
350
|
<script setup>
|
|
375
|
-
import { ref } from
|
|
351
|
+
import { ref } from "vue";
|
|
376
352
|
|
|
377
|
-
const dynamicTabs = ref([
|
|
378
|
-
{ id: 'tab1', name: '标签1' },
|
|
379
|
-
]);
|
|
353
|
+
const dynamicTabs = ref([{ id: "tab1", name: "标签1" }]);
|
|
380
354
|
|
|
381
355
|
let tabCounter = 1;
|
|
382
356
|
|
|
@@ -448,3 +422,4 @@ MIT License
|
|
|
448
422
|
---
|
|
449
423
|
|
|
450
424
|
Made with ❤️ by SkillHarbor
|
|
425
|
+
|