@xlui/xux-ui 0.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 +55 -0
- package/dist/index.css +1 -0
- package/dist/index.js +128 -0
- package/dist/index.mjs +4819 -0
- package/package.json +57 -0
- package/src/components/Accordion/index.vue +355 -0
- package/src/components/Button/index.vue +440 -0
- package/src/components/Card/index.vue +386 -0
- package/src/components/Checkboxes/index.vue +416 -0
- package/src/components/CountrySelect/data/countries.json +2084 -0
- package/src/components/CountrySelect/index.vue +319 -0
- package/src/components/Input/index.vue +293 -0
- package/src/components/Modal/index.vue +360 -0
- package/src/components/Select/index.vue +411 -0
- package/src/components/Skeleton/index.vue +110 -0
- package/src/components/ThumbnailContainer/index.vue +451 -0
- package/src/composables/Msg.ts +349 -0
- package/src/index.ts +28 -0
- package/src/styles/theme.css +120 -0
@@ -0,0 +1,349 @@
|
|
1
|
+
/**
|
2
|
+
* Msg 消息提示组件
|
3
|
+
* @displayName XMsg
|
4
|
+
*/
|
5
|
+
|
6
|
+
interface ConfirmOptions {
|
7
|
+
title: string
|
8
|
+
content: string
|
9
|
+
confirmText?: string
|
10
|
+
cancelText?: string
|
11
|
+
onConfirm?: () => void
|
12
|
+
onCancel?: () => void
|
13
|
+
type?: 'success' | 'error' | 'warning' | 'info'
|
14
|
+
duration?: number
|
15
|
+
}
|
16
|
+
|
17
|
+
interface MessageOptions {
|
18
|
+
title: string
|
19
|
+
content?: string
|
20
|
+
type?: 'success' | 'error' | 'warning' | 'info'
|
21
|
+
duration?: number
|
22
|
+
}
|
23
|
+
|
24
|
+
export const xlMsg = () => {
|
25
|
+
// 创建消息容器
|
26
|
+
const createMessageContainer = () => {
|
27
|
+
let container = document.getElementById('xl-message-container')
|
28
|
+
if (!container) {
|
29
|
+
container = document.createElement('div')
|
30
|
+
container.id = 'xl-message-container'
|
31
|
+
container.style.cssText = `
|
32
|
+
position: fixed;
|
33
|
+
top: 20px;
|
34
|
+
right: 20px;
|
35
|
+
z-index: 9999;
|
36
|
+
display: flex;
|
37
|
+
flex-direction: column;
|
38
|
+
gap: 10px;
|
39
|
+
`
|
40
|
+
document.body.appendChild(container)
|
41
|
+
}
|
42
|
+
return container
|
43
|
+
}
|
44
|
+
|
45
|
+
// 获取类型对应的样式和图标
|
46
|
+
const getTypeStyles = (type: string) => {
|
47
|
+
const styles = {
|
48
|
+
success: {
|
49
|
+
bgColor: '#f0fdf4',
|
50
|
+
borderColor: '#86efac',
|
51
|
+
textColor: '#166534',
|
52
|
+
iconColor: '#22c55e',
|
53
|
+
iconSvg: `<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>`
|
54
|
+
},
|
55
|
+
error: {
|
56
|
+
bgColor: '#fef2f2',
|
57
|
+
borderColor: '#fca5a5',
|
58
|
+
textColor: '#991b1b',
|
59
|
+
iconColor: '#ef4444',
|
60
|
+
iconSvg: `<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>`
|
61
|
+
},
|
62
|
+
warning: {
|
63
|
+
bgColor: '#fefce8',
|
64
|
+
borderColor: '#fde047',
|
65
|
+
textColor: '#854d0e',
|
66
|
+
iconColor: '#eab308',
|
67
|
+
iconSvg: `<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>`
|
68
|
+
},
|
69
|
+
info: {
|
70
|
+
bgColor: '#f8fafc',
|
71
|
+
borderColor: '#cbd5e1',
|
72
|
+
textColor: '#1e293b',
|
73
|
+
iconColor: '#64748b',
|
74
|
+
iconSvg: `<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>`
|
75
|
+
}
|
76
|
+
}
|
77
|
+
return styles[type as keyof typeof styles] || styles.info
|
78
|
+
}
|
79
|
+
|
80
|
+
// 显示消息
|
81
|
+
const show = (options: MessageOptions) => {
|
82
|
+
const container = createMessageContainer()
|
83
|
+
const type = options.type || 'info'
|
84
|
+
const duration = options.duration !== undefined ? options.duration : 3000
|
85
|
+
const styles = getTypeStyles(type)
|
86
|
+
|
87
|
+
const messageId = `xl-msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
88
|
+
|
89
|
+
const message = document.createElement('div')
|
90
|
+
message.id = messageId
|
91
|
+
message.style.cssText = `
|
92
|
+
background-color: ${styles.bgColor};
|
93
|
+
border: 1px solid ${styles.borderColor};
|
94
|
+
color: ${styles.textColor};
|
95
|
+
border-radius: 12px;
|
96
|
+
padding: 16px;
|
97
|
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
98
|
+
max-width: 384px;
|
99
|
+
transform: translateX(100%);
|
100
|
+
opacity: 0;
|
101
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
102
|
+
pointer-events: auto;
|
103
|
+
`
|
104
|
+
|
105
|
+
message.innerHTML = `
|
106
|
+
<div style="display: flex; align-items: flex-start; gap: 12px;">
|
107
|
+
<div style="flex-shrink: 0; color: ${styles.iconColor}; margin-top: 2px;">
|
108
|
+
${styles.iconSvg}
|
109
|
+
</div>
|
110
|
+
<div style="flex: 1; min-width: 0;">
|
111
|
+
<div style="font-size: 14px; font-weight: 500; line-height: 1.5; color: ${styles.textColor};">
|
112
|
+
${options.title}
|
113
|
+
</div>
|
114
|
+
${options.content ? `<div style="margin-top: 4px; font-size: 13px; line-height: 1.5; color: ${styles.textColor}; opacity: 0.8;">${options.content}</div>` : ''}
|
115
|
+
</div>
|
116
|
+
<button
|
117
|
+
style="flex-shrink: 0; background: none; border: none; padding: 4px; cursor: pointer; color: ${styles.textColor}; opacity: 0.5; border-radius: 4px; transition: all 0.15s; display: flex; align-items: center; justify-content: center;"
|
118
|
+
onmouseover="this.style.opacity='1'; this.style.backgroundColor='rgba(0,0,0,0.05)';"
|
119
|
+
onmouseout="this.style.opacity='0.5'; this.style.backgroundColor='transparent';"
|
120
|
+
onclick="document.getElementById('${messageId}')?.remove()"
|
121
|
+
>
|
122
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
123
|
+
<path d="M18 6L6 18M6 6l12 12"/>
|
124
|
+
</svg>
|
125
|
+
</button>
|
126
|
+
</div>
|
127
|
+
`
|
128
|
+
|
129
|
+
container.appendChild(message)
|
130
|
+
|
131
|
+
// 动画进入
|
132
|
+
requestAnimationFrame(() => {
|
133
|
+
requestAnimationFrame(() => {
|
134
|
+
message.style.transform = 'translateX(0)'
|
135
|
+
message.style.opacity = '1'
|
136
|
+
})
|
137
|
+
})
|
138
|
+
|
139
|
+
// 自动移除
|
140
|
+
if (duration > 0) {
|
141
|
+
setTimeout(() => {
|
142
|
+
removeMessage(messageId)
|
143
|
+
}, duration)
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
// 移除消息
|
148
|
+
const removeMessage = (messageId: string) => {
|
149
|
+
const message = document.getElementById(messageId)
|
150
|
+
if (message) {
|
151
|
+
message.style.transform = 'translateX(100%)'
|
152
|
+
message.style.opacity = '0'
|
153
|
+
setTimeout(() => {
|
154
|
+
if (message.parentNode) {
|
155
|
+
message.parentNode.removeChild(message)
|
156
|
+
}
|
157
|
+
}, 300)
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
// 确认对话框
|
162
|
+
const confirm = (options: ConfirmOptions) => {
|
163
|
+
const type = options.type || 'info'
|
164
|
+
const styles = getTypeStyles(type)
|
165
|
+
|
166
|
+
const modalId = `xl-confirm-${Date.now()}`
|
167
|
+
const modal = document.createElement('div')
|
168
|
+
modal.id = modalId
|
169
|
+
modal.style.cssText = `
|
170
|
+
position: fixed;
|
171
|
+
inset: 0;
|
172
|
+
z-index: 9999;
|
173
|
+
display: flex;
|
174
|
+
align-items: center;
|
175
|
+
justify-content: center;
|
176
|
+
background-color: rgba(0, 0, 0, 0.5);
|
177
|
+
opacity: 0;
|
178
|
+
transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
179
|
+
backdrop-filter: blur(4px);
|
180
|
+
`
|
181
|
+
|
182
|
+
const dialogHtml = `
|
183
|
+
<div class="xl-confirm-dialog" style="
|
184
|
+
background-color: white;
|
185
|
+
border-radius: 12px;
|
186
|
+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
187
|
+
max-width: 448px;
|
188
|
+
width: 100%;
|
189
|
+
margin: 16px;
|
190
|
+
transform: scale(0.95);
|
191
|
+
opacity: 0;
|
192
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
193
|
+
">
|
194
|
+
<div style="padding: 24px;">
|
195
|
+
<div style="display: flex; align-items: flex-start; gap: 16px; margin-bottom: 20px;">
|
196
|
+
<div style="flex-shrink: 0; color: ${styles.iconColor}; margin-top: 2px;">
|
197
|
+
${styles.iconSvg}
|
198
|
+
</div>
|
199
|
+
<div style="flex: 1;">
|
200
|
+
<h3 style="font-size: 18px; font-weight: 600; color: #1a1a1a; line-height: 1.5; margin: 0;">
|
201
|
+
${options.title}
|
202
|
+
</h3>
|
203
|
+
</div>
|
204
|
+
</div>
|
205
|
+
<div style="font-size: 14px; color: #64748b; line-height: 1.6; margin-bottom: 24px; padding-left: 36px;">
|
206
|
+
${options.content}
|
207
|
+
</div>
|
208
|
+
<div style="display: flex; justify-content: flex-end; gap: 12px;">
|
209
|
+
<button class="xl-confirm-cancel" style="
|
210
|
+
padding: 8px 16px;
|
211
|
+
font-size: 14px;
|
212
|
+
font-weight: 500;
|
213
|
+
height: 36px;
|
214
|
+
color: #1a1a1a;
|
215
|
+
background-color: white;
|
216
|
+
border: 1px solid #cacaca;
|
217
|
+
border-radius: 6px;
|
218
|
+
cursor: pointer;
|
219
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
220
|
+
box-shadow: 0 1px 2px rgba(26, 26, 26, 0.05);
|
221
|
+
position: relative;
|
222
|
+
overflow: hidden;
|
223
|
+
transform: translateY(0);
|
224
|
+
"
|
225
|
+
onmouseover="this.style.borderColor='#1a1a1a'; this.style.color='#1a1a1a'; this.style.boxShadow='0 4px 12px rgba(26, 26, 26, 0.3)'; this.style.transform='translateY(-2px)';"
|
226
|
+
onmouseout="this.style.backgroundColor='white'; this.style.borderColor='#cacaca'; this.style.color='#1a1a1a'; this.style.boxShadow='0 1px 2px rgba(26, 26, 26, 0.05)'; this.style.transform='translateY(0)';"
|
227
|
+
onmousedown="this.style.transform='translateY(1px)'; this.style.boxShadow='0 2px 4px rgba(0, 0, 0, 0.1)';"
|
228
|
+
onmouseup="this.style.transform='translateY(-2px)';">
|
229
|
+
${options.cancelText || '取消'}
|
230
|
+
</button>
|
231
|
+
<button class="xl-confirm-ok" style="
|
232
|
+
padding: 8px 16px;
|
233
|
+
font-size: 14px;
|
234
|
+
font-weight: 500;
|
235
|
+
height: 36px;
|
236
|
+
color: white;
|
237
|
+
background: linear-gradient(135deg, #1a1a1a 0%, #3a3a3a 100%);
|
238
|
+
border: 1px solid #1a1a1a;
|
239
|
+
border-radius: 6px;
|
240
|
+
cursor: pointer;
|
241
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
242
|
+
box-shadow: 0 4px 12px rgba(26, 26, 26, 0.3);
|
243
|
+
position: relative;
|
244
|
+
overflow: hidden;
|
245
|
+
transform: translateY(0);
|
246
|
+
"
|
247
|
+
onmouseover="this.style.background='linear-gradient(135deg, #3a3a3a 0%, #4a4a4a 100%)'; this.style.boxShadow='0 8px 24px rgba(26, 26, 26, 0.4)'; this.style.transform='translateY(-2px)';"
|
248
|
+
onmouseout="this.style.background='linear-gradient(135deg, #1a1a1a 0%, #3a3a3a 100%)'; this.style.boxShadow='0 4px 12px rgba(26, 26, 26, 0.3)'; this.style.transform='translateY(0)';"
|
249
|
+
onmousedown="this.style.transform='translateY(1px)'; this.style.boxShadow='0 2px 4px rgba(0, 0, 0, 0.1)';"
|
250
|
+
onmouseup="this.style.transform='translateY(-2px)';">
|
251
|
+
${options.confirmText || '确认'}
|
252
|
+
</button>
|
253
|
+
</div>
|
254
|
+
</div>
|
255
|
+
</div>
|
256
|
+
`
|
257
|
+
|
258
|
+
modal.innerHTML = dialogHtml
|
259
|
+
|
260
|
+
document.body.appendChild(modal)
|
261
|
+
|
262
|
+
// 动画进入
|
263
|
+
requestAnimationFrame(() => {
|
264
|
+
modal.style.opacity = '1'
|
265
|
+
const dialog = modal.querySelector('.xl-confirm-dialog') as HTMLElement
|
266
|
+
if (dialog) {
|
267
|
+
requestAnimationFrame(() => {
|
268
|
+
dialog.style.transform = 'scale(1)'
|
269
|
+
dialog.style.opacity = '1'
|
270
|
+
})
|
271
|
+
}
|
272
|
+
})
|
273
|
+
|
274
|
+
// 绑定事件
|
275
|
+
const confirmBtn = modal.querySelector('.xl-confirm-ok')
|
276
|
+
const cancelBtn = modal.querySelector('.xl-confirm-cancel')
|
277
|
+
|
278
|
+
const closeModal = () => {
|
279
|
+
const dialog = modal.querySelector('.xl-confirm-dialog') as HTMLElement
|
280
|
+
if (dialog) {
|
281
|
+
dialog.style.transform = 'scale(0.95)'
|
282
|
+
dialog.style.opacity = '0'
|
283
|
+
}
|
284
|
+
modal.style.opacity = '0'
|
285
|
+
setTimeout(() => {
|
286
|
+
if (modal.parentNode) {
|
287
|
+
modal.parentNode.removeChild(modal)
|
288
|
+
}
|
289
|
+
}, 300)
|
290
|
+
}
|
291
|
+
|
292
|
+
confirmBtn?.addEventListener('click', () => {
|
293
|
+
options.onConfirm?.()
|
294
|
+
closeModal()
|
295
|
+
})
|
296
|
+
|
297
|
+
cancelBtn?.addEventListener('click', () => {
|
298
|
+
options.onCancel?.()
|
299
|
+
closeModal()
|
300
|
+
})
|
301
|
+
|
302
|
+
// 点击背景关闭
|
303
|
+
modal.addEventListener('click', (e) => {
|
304
|
+
if (e.target === modal) {
|
305
|
+
options.onCancel?.()
|
306
|
+
closeModal()
|
307
|
+
}
|
308
|
+
})
|
309
|
+
|
310
|
+
// ESC 键关闭
|
311
|
+
const handleEsc = (e: KeyboardEvent) => {
|
312
|
+
if (e.key === 'Escape') {
|
313
|
+
options.onCancel?.()
|
314
|
+
closeModal()
|
315
|
+
document.removeEventListener('keydown', handleEsc)
|
316
|
+
}
|
317
|
+
}
|
318
|
+
document.addEventListener('keydown', handleEsc)
|
319
|
+
}
|
320
|
+
|
321
|
+
// 快捷方法
|
322
|
+
const success = (title: string, content?: string, duration?: number) => {
|
323
|
+
show({ title, content, type: 'success', duration })
|
324
|
+
}
|
325
|
+
|
326
|
+
const error = (title: string, content?: string, duration?: number) => {
|
327
|
+
show({ title, content, type: 'error', duration })
|
328
|
+
}
|
329
|
+
|
330
|
+
const warning = (title: string, content?: string, duration?: number) => {
|
331
|
+
show({ title, content, type: 'warning', duration })
|
332
|
+
}
|
333
|
+
|
334
|
+
const info = (title: string, content?: string, duration?: number) => {
|
335
|
+
show({ title, content, type: 'info', duration })
|
336
|
+
}
|
337
|
+
|
338
|
+
return {
|
339
|
+
show,
|
340
|
+
confirm,
|
341
|
+
success,
|
342
|
+
error,
|
343
|
+
warning,
|
344
|
+
info,
|
345
|
+
remove: removeMessage
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
export default xlMsg
|
package/src/index.ts
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
// 导入主题样式
|
2
|
+
import './styles/theme.css'
|
3
|
+
|
4
|
+
// 导出组件
|
5
|
+
export { default as XButton } from './components/Button/index.vue'
|
6
|
+
export { default as XCard } from './components/Card/index.vue'
|
7
|
+
export { default as XCountrySelect } from './components/CountrySelect/index.vue'
|
8
|
+
export { default as XSelect } from './components/Select/index.vue'
|
9
|
+
export { default as XInput } from './components/Input/index.vue'
|
10
|
+
export { default as XCheckboxes } from './components/Checkboxes/index.vue'
|
11
|
+
export { default as XAccordion } from './components/Accordion/index.vue'
|
12
|
+
export { default as XThumbnailContainer } from './components/ThumbnailContainer/index.vue'
|
13
|
+
export { default as XSkeleton } from './components/Skeleton/index.vue'
|
14
|
+
export { default as XModal } from './components/Modal/index.vue'
|
15
|
+
|
16
|
+
// 导出 Composables
|
17
|
+
export { xlMsg, default as useMsg } from './composables/Msg'
|
18
|
+
|
19
|
+
// 导出类型定义
|
20
|
+
export type { Country, CountrySelectProps } from './components/CountrySelect/index.vue'
|
21
|
+
export type { SelectOption, SelectProps } from './components/Select/index.vue'
|
22
|
+
export type { InputProps } from './components/Input/index.vue'
|
23
|
+
export type { CheckboxOption, CheckboxesProps } from './components/Checkboxes/index.vue'
|
24
|
+
export type { AccordionItem, AccordionProps } from './components/Accordion/index.vue'
|
25
|
+
export type { ThumbnailContainerProps } from './components/ThumbnailContainer/index.vue'
|
26
|
+
export type { SkeletonProps } from './components/Skeleton/index.vue'
|
27
|
+
export type { ModalProps } from './components/Modal/index.vue'
|
28
|
+
|
@@ -0,0 +1,120 @@
|
|
1
|
+
/**
|
2
|
+
* XUX 电商主题色系统
|
3
|
+
* 基准色: #1a1a1a
|
4
|
+
*/
|
5
|
+
|
6
|
+
:root {
|
7
|
+
/* ========== 基准色 ========== */
|
8
|
+
--x-color-base: #1a1a1a;
|
9
|
+
|
10
|
+
/* ========== 主色 - 深色系 ========== */
|
11
|
+
--x-color-primary: #1a1a1a;
|
12
|
+
--x-color-primary-light: #3a3a3a;
|
13
|
+
--x-color-primary-lighter: #4a4a4a;
|
14
|
+
--x-color-primary-dark: #0d0d0d;
|
15
|
+
--x-color-primary-darker: #000000;
|
16
|
+
|
17
|
+
/* ========== 辅助色 - 深蓝色系(链接、信息) ========== */
|
18
|
+
--x-color-secondary: #4a90e2;
|
19
|
+
--x-color-secondary-light: #6ba8ed;
|
20
|
+
--x-color-secondary-lighter: #8dc0f7;
|
21
|
+
--x-color-secondary-dark: #3a7bc8;
|
22
|
+
--x-color-secondary-darker: #2a6bb0;
|
23
|
+
|
24
|
+
/* ========== 成功色 - 翠绿色系 ========== */
|
25
|
+
--x-color-success: #10b981;
|
26
|
+
--x-color-success-light: #34d399;
|
27
|
+
--x-color-success-lighter: #6ee7b7;
|
28
|
+
--x-color-success-dark: #059669;
|
29
|
+
--x-color-success-darker: #047857;
|
30
|
+
|
31
|
+
/* ========== 警告色 - 琥珀色系 ========== */
|
32
|
+
--x-color-warning: #f59e0b;
|
33
|
+
--x-color-warning-light: #fbbf24;
|
34
|
+
--x-color-warning-lighter: #fcd34d;
|
35
|
+
--x-color-warning-dark: #d97706;
|
36
|
+
--x-color-warning-darker: #b45309;
|
37
|
+
|
38
|
+
/* ========== 危险色 - 红色系 ========== */
|
39
|
+
--x-color-danger: #ef4444;
|
40
|
+
--x-color-danger-light: #f87171;
|
41
|
+
--x-color-danger-lighter: #fca5a5;
|
42
|
+
--x-color-danger-dark: #dc2626;
|
43
|
+
--x-color-danger-darker: #b91c1c;
|
44
|
+
|
45
|
+
/* ========== 中性色 - 基于 #1a1a1a ========== */
|
46
|
+
--x-color-black: #1a1a1a;
|
47
|
+
--x-color-gray-900: #2a2a2a;
|
48
|
+
--x-color-gray-800: #3a3a3a;
|
49
|
+
--x-color-gray-700: #4a4a4a;
|
50
|
+
--x-color-gray-600: #6a6a6a;
|
51
|
+
--x-color-gray-500: #8a8a8a;
|
52
|
+
--x-color-gray-400: #aaaaaa;
|
53
|
+
--x-color-gray-300: #cacaca;
|
54
|
+
--x-color-gray-200: #e5e5e5;
|
55
|
+
--x-color-gray-100: #f5f5f5;
|
56
|
+
--x-color-white: #ffffff;
|
57
|
+
|
58
|
+
/* ========== 渐变色 ========== */
|
59
|
+
--x-gradient-primary: linear-gradient(135deg, #1a1a1a 0%, #3a3a3a 100%);
|
60
|
+
--x-gradient-primary-hover: linear-gradient(135deg, #3a3a3a 0%, #4a4a4a 100%);
|
61
|
+
--x-gradient-secondary: linear-gradient(135deg, #4a90e2 0%, #3a7bc8 100%);
|
62
|
+
--x-gradient-success: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
63
|
+
--x-gradient-warning: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
64
|
+
--x-gradient-danger: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
|
65
|
+
--x-gradient-dark: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%);
|
66
|
+
|
67
|
+
/* ========== 阴影 ========== */
|
68
|
+
--x-shadow-sm: 0 1px 2px rgba(26, 26, 26, 0.05);
|
69
|
+
--x-shadow: 0 2px 8px rgba(26, 26, 26, 0.1);
|
70
|
+
--x-shadow-md: 0 4px 12px rgba(26, 26, 26, 0.15);
|
71
|
+
--x-shadow-lg: 0 8px 24px rgba(26, 26, 26, 0.2);
|
72
|
+
--x-shadow-xl: 0 16px 48px rgba(26, 26, 26, 0.25);
|
73
|
+
|
74
|
+
/* 彩色阴影 */
|
75
|
+
--x-shadow-primary: 0 4px 12px rgba(26, 26, 26, 0.3);
|
76
|
+
--x-shadow-primary-lg: 0 8px 24px rgba(26, 26, 26, 0.4);
|
77
|
+
--x-shadow-secondary: 0 4px 12px rgba(74, 144, 226, 0.3);
|
78
|
+
--x-shadow-success: 0 4px 12px rgba(16, 185, 129, 0.3);
|
79
|
+
--x-shadow-warning: 0 4px 12px rgba(245, 158, 11, 0.3);
|
80
|
+
--x-shadow-danger: 0 4px 12px rgba(239, 68, 68, 0.3);
|
81
|
+
|
82
|
+
/* ========== 边框圆角 ========== */
|
83
|
+
--x-radius-sm: 4px;
|
84
|
+
--x-radius: 6px;
|
85
|
+
--x-radius-md: 8px;
|
86
|
+
--x-radius-lg: 12px;
|
87
|
+
--x-radius-xl: 16px;
|
88
|
+
--x-radius-full: 9999px;
|
89
|
+
|
90
|
+
/* ========== 过渡动画 ========== */
|
91
|
+
--x-transition-fast: 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
92
|
+
--x-transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
93
|
+
--x-transition-slow: 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
94
|
+
|
95
|
+
/* ========== 字体 ========== */
|
96
|
+
--x-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
97
|
+
--x-font-size-xs: 12px;
|
98
|
+
--x-font-size-sm: 14px;
|
99
|
+
--x-font-size: 16px;
|
100
|
+
--x-font-size-lg: 18px;
|
101
|
+
--x-font-size-xl: 20px;
|
102
|
+
--x-font-size-2xl: 24px;
|
103
|
+
--x-font-size-3xl: 30px;
|
104
|
+
}
|
105
|
+
|
106
|
+
/* ========== 暗色模式 ========== */
|
107
|
+
.dark {
|
108
|
+
--x-color-white: #1a1a1a;
|
109
|
+
--x-color-black: #ffffff;
|
110
|
+
--x-color-gray-100: #2a2a2a;
|
111
|
+
--x-color-gray-200: #3a3a3a;
|
112
|
+
--x-color-gray-300: #4a4a4a;
|
113
|
+
--x-color-gray-400: #6a6a6a;
|
114
|
+
--x-color-gray-500: #8a8a8a;
|
115
|
+
--x-color-gray-600: #aaaaaa;
|
116
|
+
--x-color-gray-700: #cacaca;
|
117
|
+
--x-color-gray-800: #e5e5e5;
|
118
|
+
--x-color-gray-900: #f5f5f5;
|
119
|
+
}
|
120
|
+
|