@nextclaw/ui 0.2.4 → 0.2.5
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/CHANGELOG.md +6 -0
- package/dist/assets/index-BV3Gyu8h.js +225 -0
- package/dist/assets/index-iSLahgqA.css +1 -0
- package/dist/index.html +2 -2
- package/dist/logos/aihubmix.png +0 -0
- package/dist/logos/anthropic.svg +1 -0
- package/dist/logos/dashscope.png +0 -0
- package/dist/logos/deepseek.png +0 -0
- package/dist/logos/dingtalk.svg +1 -0
- package/dist/logos/discord.svg +1 -0
- package/dist/logos/email.svg +1 -0
- package/dist/logos/feishu.svg +12 -0
- package/dist/logos/gemini.svg +1 -0
- package/dist/logos/groq.svg +1 -0
- package/dist/logos/minimax.svg +1 -0
- package/dist/logos/mochat.svg +6 -0
- package/dist/logos/moonshot.png +0 -0
- package/dist/logos/openai.svg +1 -0
- package/dist/logos/openrouter.svg +1 -0
- package/dist/logos/qq.svg +1 -0
- package/dist/logos/slack.svg +1 -0
- package/dist/logos/telegram.svg +1 -0
- package/dist/logos/vllm.svg +1 -0
- package/dist/logos/whatsapp.svg +1 -0
- package/dist/logos/zhipu.svg +15 -0
- package/package.json +1 -1
- package/public/logos/aihubmix.png +0 -0
- package/public/logos/anthropic.svg +1 -0
- package/public/logos/dashscope.png +0 -0
- package/public/logos/deepseek.png +0 -0
- package/public/logos/dingtalk.svg +1 -0
- package/public/logos/discord.svg +1 -0
- package/public/logos/email.svg +1 -0
- package/public/logos/feishu.svg +12 -0
- package/public/logos/gemini.svg +1 -0
- package/public/logos/groq.svg +1 -0
- package/public/logos/minimax.svg +1 -0
- package/public/logos/mochat.svg +6 -0
- package/public/logos/moonshot.png +0 -0
- package/public/logos/openai.svg +1 -0
- package/public/logos/openrouter.svg +1 -0
- package/public/logos/qq.svg +1 -0
- package/public/logos/slack.svg +1 -0
- package/public/logos/telegram.svg +1 -0
- package/public/logos/vllm.svg +1 -0
- package/public/logos/whatsapp.svg +1 -0
- package/public/logos/zhipu.svg +15 -0
- package/src/App.tsx +0 -3
- package/src/api/config.ts +0 -19
- package/src/api/types.ts +0 -8
- package/src/components/common/LogoBadge.tsx +35 -0
- package/src/components/common/StatusBadge.tsx +4 -4
- package/src/components/config/ChannelForm.tsx +16 -18
- package/src/components/config/ChannelsList.tsx +87 -37
- package/src/components/config/ModelConfig.tsx +25 -25
- package/src/components/config/ProviderForm.tsx +9 -11
- package/src/components/config/ProvidersList.tsx +90 -38
- package/src/components/layout/Header.tsx +7 -7
- package/src/components/layout/Sidebar.tsx +10 -23
- package/src/components/ui/HighlightCard.tsx +29 -29
- package/src/components/ui/button.tsx +13 -8
- package/src/components/ui/card.tsx +8 -7
- package/src/components/ui/dialog.tsx +8 -8
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/label.tsx +1 -1
- package/src/components/ui/switch.tsx +3 -3
- package/src/components/ui/tabs-custom.tsx +6 -6
- package/src/components/ui/tabs.tsx +7 -6
- package/src/hooks/useConfig.ts +2 -29
- package/src/index.css +103 -56
- package/src/lib/i18n.ts +3 -6
- package/src/lib/logos.ts +42 -0
- package/src/stores/ui.store.ts +1 -1
- package/src/styles/design-system.css +248 -0
- package/tailwind.config.js +118 -10
- package/dist/assets/index-C4OKhpdC.css +0 -1
- package/dist/assets/index-C8nOCIVG.js +0 -240
- package/src/components/config/UiConfig.tsx +0 -189
package/src/hooks/useConfig.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
2
|
-
import { fetchConfig, fetchConfigMeta, updateModel, updateProvider, updateChannel
|
|
2
|
+
import { fetchConfig, fetchConfigMeta, updateModel, updateProvider, updateChannel } from '@/api/config';
|
|
3
3
|
import { toast } from 'sonner';
|
|
4
4
|
import { t } from '@/lib/i18n';
|
|
5
5
|
|
|
@@ -59,37 +59,10 @@ export function useUpdateChannel() {
|
|
|
59
59
|
updateChannel(channel, data as Parameters<typeof updateChannel>[1]),
|
|
60
60
|
onSuccess: () => {
|
|
61
61
|
queryClient.invalidateQueries({ queryKey: ['config'] });
|
|
62
|
-
toast.success(t('
|
|
63
|
-
},
|
|
64
|
-
onError: (error: Error) => {
|
|
65
|
-
toast.error(t('configSaveFailed') + ': ' + error.message);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function useUpdateUiConfig() {
|
|
71
|
-
const queryClient = useQueryClient();
|
|
72
|
-
|
|
73
|
-
return useMutation({
|
|
74
|
-
mutationFn: updateUiConfig,
|
|
75
|
-
onSuccess: () => {
|
|
76
|
-
queryClient.invalidateQueries({ queryKey: ['config'] });
|
|
77
|
-
toast.success(t('configSaved'));
|
|
62
|
+
toast.success(t('configSavedApplied'));
|
|
78
63
|
},
|
|
79
64
|
onError: (error: Error) => {
|
|
80
65
|
toast.error(t('configSaveFailed') + ': ' + error.message);
|
|
81
66
|
}
|
|
82
67
|
});
|
|
83
68
|
}
|
|
84
|
-
|
|
85
|
-
export function useReloadConfig() {
|
|
86
|
-
return useMutation({
|
|
87
|
-
mutationFn: reloadConfig,
|
|
88
|
-
onSuccess: () => {
|
|
89
|
-
toast.success(t('configReloaded'));
|
|
90
|
-
},
|
|
91
|
-
onError: (error: Error) => {
|
|
92
|
-
toast.error(t('configReloadFailed') + ': ' + error.message);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
package/src/index.css
CHANGED
|
@@ -1,55 +1,67 @@
|
|
|
1
|
+
/* Import Design System - must be first */
|
|
2
|
+
@import './styles/design-system.css';
|
|
3
|
+
|
|
1
4
|
@tailwind base;
|
|
2
5
|
@tailwind components;
|
|
3
6
|
@tailwind utilities;
|
|
4
7
|
|
|
5
8
|
@layer base {
|
|
6
9
|
:root {
|
|
7
|
-
/*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
--
|
|
11
|
-
|
|
10
|
+
/* ========================================
|
|
11
|
+
CORE VARIABLES (Mapped to Design System)
|
|
12
|
+
======================================== */
|
|
13
|
+
--background: 210 20% 98%;
|
|
14
|
+
--foreground: 221 39% 11%;
|
|
15
|
+
|
|
12
16
|
--card: 0 0% 100%;
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
--card-foreground: 221 39% 11%;
|
|
18
|
+
|
|
15
19
|
--popover: 0 0% 100%;
|
|
16
|
-
--popover-foreground:
|
|
17
|
-
|
|
18
|
-
/*
|
|
20
|
+
--popover-foreground: 221 39% 11%;
|
|
21
|
+
|
|
22
|
+
/* Primary: Brand Blue */
|
|
23
|
+
--primary: 217 80% 55%;
|
|
19
24
|
--primary-foreground: 0 0% 100%;
|
|
20
|
-
|
|
21
|
-
/*
|
|
22
|
-
--secondary
|
|
23
|
-
--
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
--
|
|
25
|
+
|
|
26
|
+
/* Secondary: Light Gray */
|
|
27
|
+
--secondary: 220 14% 96%;
|
|
28
|
+
--secondary-foreground: 215 28% 17%;
|
|
29
|
+
|
|
30
|
+
/* Muted */
|
|
31
|
+
--muted: 220 14% 96%;
|
|
32
|
+
--muted-foreground: 220 9% 46%;
|
|
33
|
+
|
|
34
|
+
/* Accent */
|
|
35
|
+
--accent: 217 100% 97%;
|
|
36
|
+
--accent-foreground: 217 70% 40%;
|
|
37
|
+
|
|
38
|
+
/* Destructive */
|
|
28
39
|
--destructive: 0 84% 60%;
|
|
29
40
|
--destructive-foreground: 0 0% 98%;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
--
|
|
33
|
-
--
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
--milk-
|
|
39
|
-
--milk-
|
|
40
|
-
--milk-
|
|
41
|
-
--milk-
|
|
42
|
-
--milk-
|
|
43
|
-
--milk-
|
|
44
|
-
--milk-
|
|
45
|
-
--milk-
|
|
46
|
-
--milk-
|
|
41
|
+
|
|
42
|
+
/* UI Elements */
|
|
43
|
+
--border: 220 13% 91%;
|
|
44
|
+
--input: 220 13% 91%;
|
|
45
|
+
--ring: 217 80% 55%;
|
|
46
|
+
--radius: 0.75rem;
|
|
47
|
+
|
|
48
|
+
/* Legacy compatibility */
|
|
49
|
+
--milk-50: 210 20% 98%;
|
|
50
|
+
--milk-100: 220 14% 96%;
|
|
51
|
+
--milk-200: 220 13% 91%;
|
|
52
|
+
--milk-300: 216 12% 84%;
|
|
53
|
+
--milk-400: 218 11% 65%;
|
|
54
|
+
--milk-500: 220 9% 46%;
|
|
55
|
+
--milk-600: 215 14% 34%;
|
|
56
|
+
--milk-700: 217 19% 27%;
|
|
57
|
+
--milk-800: 215 28% 17%;
|
|
58
|
+
--milk-900: 221 39% 11%;
|
|
47
59
|
}
|
|
48
60
|
}
|
|
49
61
|
|
|
50
62
|
@layer base {
|
|
51
63
|
* {
|
|
52
|
-
@apply border-border
|
|
64
|
+
@apply border-border;
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
html {
|
|
@@ -60,20 +72,21 @@
|
|
|
60
72
|
|
|
61
73
|
body {
|
|
62
74
|
@apply bg-background text-foreground;
|
|
63
|
-
font-family: -
|
|
75
|
+
font-family: var(--font-sans);
|
|
64
76
|
overflow: hidden;
|
|
65
77
|
}
|
|
66
78
|
|
|
67
|
-
/* Smooth scrolling
|
|
79
|
+
/* Smooth scrolling */
|
|
68
80
|
* {
|
|
69
81
|
scrollbar-width: thin;
|
|
70
|
-
scrollbar-color: hsl(var(--
|
|
82
|
+
scrollbar-color: hsl(var(--gray-300)) transparent;
|
|
71
83
|
}
|
|
72
84
|
}
|
|
73
85
|
|
|
74
86
|
@layer utilities {
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
/* ========================================
|
|
88
|
+
SCROLLBAR
|
|
89
|
+
======================================== */
|
|
77
90
|
.custom-scrollbar::-webkit-scrollbar {
|
|
78
91
|
width: 6px;
|
|
79
92
|
height: 6px;
|
|
@@ -84,24 +97,42 @@
|
|
|
84
97
|
}
|
|
85
98
|
|
|
86
99
|
.custom-scrollbar::-webkit-scrollbar-thumb {
|
|
87
|
-
background: hsl(var(--
|
|
100
|
+
background: hsl(var(--gray-300));
|
|
88
101
|
border-radius: 6px;
|
|
89
102
|
}
|
|
90
103
|
|
|
91
104
|
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
|
92
|
-
background: hsl(var(--
|
|
105
|
+
background: hsl(var(--gray-400));
|
|
93
106
|
}
|
|
94
107
|
|
|
95
|
-
/*
|
|
108
|
+
/* ========================================
|
|
109
|
+
GLASSMORPHISM
|
|
110
|
+
======================================== */
|
|
96
111
|
.glass {
|
|
97
|
-
|
|
112
|
+
background: rgba(255, 255, 255, 0.8);
|
|
113
|
+
backdrop-filter: blur(12px);
|
|
114
|
+
-webkit-backdrop-filter: blur(12px);
|
|
115
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
98
116
|
}
|
|
99
117
|
|
|
100
118
|
.glass-dark {
|
|
101
|
-
|
|
119
|
+
background: rgba(0, 0, 0, 0.1);
|
|
120
|
+
backdrop-filter: blur(12px);
|
|
121
|
+
-webkit-backdrop-filter: blur(12px);
|
|
122
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* ========================================
|
|
126
|
+
SHADOWS
|
|
127
|
+
======================================== */
|
|
128
|
+
.shadow-card {
|
|
129
|
+
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.05), 0 1px 2px -1px rgb(0 0 0 / 0.05);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.shadow-card-hover {
|
|
133
|
+
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.08), 0 4px 6px -4px rgb(0 0 0 / 0.05);
|
|
102
134
|
}
|
|
103
135
|
|
|
104
|
-
/* Premium Shadows */
|
|
105
136
|
.shadow-premium {
|
|
106
137
|
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.08), 0 4px 10px -4px rgba(0, 0, 0, 0.04);
|
|
107
138
|
}
|
|
@@ -109,15 +140,36 @@
|
|
|
109
140
|
.shadow-premium-hover {
|
|
110
141
|
box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.12), 0 8px 15px -6px rgba(0, 0, 0, 0.06);
|
|
111
142
|
}
|
|
143
|
+
|
|
144
|
+
/* ========================================
|
|
145
|
+
GRADIENTS
|
|
146
|
+
======================================== */
|
|
147
|
+
.bg-gradient-hero {
|
|
148
|
+
background: linear-gradient(180deg, hsl(var(--background)) 0%, hsl(var(--gray-50)) 100%);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.bg-gradient-subtle {
|
|
152
|
+
background: linear-gradient(180deg, hsl(var(--gray-50)) 0%, hsl(var(--background)) 100%);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ========================================
|
|
156
|
+
FOCUS STATES
|
|
157
|
+
======================================== */
|
|
158
|
+
.focus-ring {
|
|
159
|
+
@apply focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2;
|
|
160
|
+
--tw-ring-color: hsl(var(--ring));
|
|
161
|
+
--tw-ring-offset-color: hsl(var(--ring-offset));
|
|
162
|
+
}
|
|
112
163
|
}
|
|
113
164
|
|
|
114
|
-
/*
|
|
165
|
+
/* ========================================
|
|
166
|
+
ANIMATIONS
|
|
167
|
+
======================================== */
|
|
115
168
|
@keyframes fadeIn {
|
|
116
169
|
from {
|
|
117
170
|
opacity: 0;
|
|
118
171
|
transform: translateY(12px);
|
|
119
172
|
}
|
|
120
|
-
|
|
121
173
|
to {
|
|
122
174
|
opacity: 1;
|
|
123
175
|
transform: translateY(0);
|
|
@@ -129,7 +181,6 @@
|
|
|
129
181
|
opacity: 0;
|
|
130
182
|
transform: translateX(-12px);
|
|
131
183
|
}
|
|
132
|
-
|
|
133
184
|
to {
|
|
134
185
|
opacity: 1;
|
|
135
186
|
transform: translateX(0);
|
|
@@ -141,7 +192,6 @@
|
|
|
141
192
|
opacity: 0;
|
|
142
193
|
transform: scale(0.97);
|
|
143
194
|
}
|
|
144
|
-
|
|
145
195
|
to {
|
|
146
196
|
opacity: 1;
|
|
147
197
|
transform: scale(1);
|
|
@@ -149,12 +199,9 @@
|
|
|
149
199
|
}
|
|
150
200
|
|
|
151
201
|
@keyframes pulse-soft {
|
|
152
|
-
|
|
153
|
-
0%,
|
|
154
|
-
100% {
|
|
202
|
+
0%, 100% {
|
|
155
203
|
opacity: 1;
|
|
156
204
|
}
|
|
157
|
-
|
|
158
205
|
50% {
|
|
159
206
|
opacity: 0.8;
|
|
160
207
|
}
|
|
@@ -174,4 +221,4 @@
|
|
|
174
221
|
|
|
175
222
|
.animate-pulse-soft {
|
|
176
223
|
animation: pulse-soft 3s ease-in-out infinite;
|
|
177
|
-
}
|
|
224
|
+
}
|
package/src/lib/i18n.ts
CHANGED
|
@@ -4,7 +4,6 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
4
4
|
model: { zh: '模型', en: 'Model' },
|
|
5
5
|
providers: { zh: '提供商', en: 'Providers' },
|
|
6
6
|
channels: { zh: '渠道', en: 'Channels' },
|
|
7
|
-
uiConfig: { zh: '界面', en: 'UI' },
|
|
8
7
|
|
|
9
8
|
// Common
|
|
10
9
|
enabled: { zh: '启用', en: 'Enabled' },
|
|
@@ -41,6 +40,7 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
41
40
|
appToken: { zh: 'App Token', en: 'App Token' },
|
|
42
41
|
appId: { zh: 'App ID', en: 'App ID' },
|
|
43
42
|
appSecret: { zh: 'App Secret', en: 'App Secret' },
|
|
43
|
+
markdownSupport: { zh: 'Markdown 支持', en: 'Markdown Support' },
|
|
44
44
|
clientId: { zh: 'Client ID', en: 'Client ID' },
|
|
45
45
|
clientSecret: { zh: 'Client Secret', en: 'Client Secret' },
|
|
46
46
|
encryptKey: { zh: '加密密钥', en: 'Encrypt Key' },
|
|
@@ -93,11 +93,7 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
93
93
|
replyDelayMs: { zh: '回复延迟(ms)', en: 'Reply Delay (ms)' },
|
|
94
94
|
secret: { zh: '密钥', en: 'Secret' },
|
|
95
95
|
|
|
96
|
-
// UI
|
|
97
|
-
host: { zh: '主机', en: 'Host' },
|
|
98
|
-
port: { zh: '端口', en: 'Port' },
|
|
99
|
-
open: { zh: '自动打开', en: 'Open Automatically' },
|
|
100
|
-
reloadConfig: { zh: '重载配置', en: 'Reload Config' },
|
|
96
|
+
// UI
|
|
101
97
|
saveVerifyConnect: { zh: '保存并验证 / 连接', en: 'Save & Verify / Connect' },
|
|
102
98
|
|
|
103
99
|
// Status
|
|
@@ -108,6 +104,7 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
108
104
|
|
|
109
105
|
// Messages
|
|
110
106
|
configSaved: { zh: '配置已保存', en: 'Configuration saved' },
|
|
107
|
+
configSavedApplied: { zh: '配置已保存并已应用', en: 'Configuration saved and applied' },
|
|
111
108
|
configSaveFailed: { zh: '保存配置失败', en: 'Failed to save configuration' },
|
|
112
109
|
configReloaded: { zh: '配置已重载', en: 'Configuration reloaded' },
|
|
113
110
|
configReloadFailed: { zh: '重载配置失败', en: 'Failed to reload configuration' },
|
package/src/lib/logos.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
type LogoMap = Record<string, string>;
|
|
2
|
+
|
|
3
|
+
const PROVIDER_LOGOS: LogoMap = {
|
|
4
|
+
openrouter: "openrouter.svg",
|
|
5
|
+
aihubmix: "aihubmix.png",
|
|
6
|
+
anthropic: "anthropic.svg",
|
|
7
|
+
openai: "openai.svg",
|
|
8
|
+
gemini: "gemini.svg",
|
|
9
|
+
deepseek: "deepseek.png",
|
|
10
|
+
zhipu: "zhipu.svg",
|
|
11
|
+
dashscope: "dashscope.png",
|
|
12
|
+
moonshot: "moonshot.png",
|
|
13
|
+
minimax: "minimax.svg",
|
|
14
|
+
vllm: "vllm.svg",
|
|
15
|
+
groq: "groq.svg"
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const CHANNEL_LOGOS: LogoMap = {
|
|
19
|
+
telegram: "telegram.svg",
|
|
20
|
+
slack: "slack.svg",
|
|
21
|
+
discord: "discord.svg",
|
|
22
|
+
whatsapp: "whatsapp.svg",
|
|
23
|
+
qq: "qq.svg",
|
|
24
|
+
feishu: "feishu.svg",
|
|
25
|
+
dingtalk: "dingtalk.svg",
|
|
26
|
+
mochat: "mochat.svg",
|
|
27
|
+
email: "email.svg"
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function resolveLogo(map: LogoMap, name: string): string | null {
|
|
31
|
+
const key = name.toLowerCase();
|
|
32
|
+
const file = map[key];
|
|
33
|
+
return file ? `/logos/${file}` : null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getProviderLogo(name: string): string | null {
|
|
37
|
+
return resolveLogo(PROVIDER_LOGOS, name);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getChannelLogo(name: string): string | null {
|
|
41
|
+
return resolveLogo(CHANNEL_LOGOS, name);
|
|
42
|
+
}
|
package/src/stores/ui.store.ts
CHANGED
|
@@ -4,7 +4,7 @@ type ConnectionStatus = 'connected' | 'disconnected' | 'connecting';
|
|
|
4
4
|
|
|
5
5
|
interface UiState {
|
|
6
6
|
// Active configuration tab
|
|
7
|
-
activeTab: 'model' | 'providers' | 'channels'
|
|
7
|
+
activeTab: 'model' | 'providers' | 'channels';
|
|
8
8
|
setActiveTab: (tab: UiState['activeTab']) => void;
|
|
9
9
|
|
|
10
10
|
// Connection status
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NextClaw Design System
|
|
3
|
+
* Inspired by modern SaaS landing pages (e.g., 推理时代)
|
|
4
|
+
* Clean, professional, with blue accent
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
@layer base {
|
|
8
|
+
:root {
|
|
9
|
+
/* ========================================
|
|
10
|
+
BRAND COLORS
|
|
11
|
+
======================================== */
|
|
12
|
+
--brand-50: 217 100% 97%;
|
|
13
|
+
--brand-100: 217 100% 94%;
|
|
14
|
+
--brand-200: 217 95% 87%;
|
|
15
|
+
--brand-300: 217 90% 77%;
|
|
16
|
+
--brand-400: 217 85% 65%;
|
|
17
|
+
--brand-500: 217 80% 55%;
|
|
18
|
+
--brand-600: 217 75% 48%;
|
|
19
|
+
--brand-700: 217 70% 40%;
|
|
20
|
+
--brand-800: 217 65% 33%;
|
|
21
|
+
--brand-900: 217 60% 25%;
|
|
22
|
+
|
|
23
|
+
/* ========================================
|
|
24
|
+
NEUTRAL COLORS (Gray Scale)
|
|
25
|
+
======================================== */
|
|
26
|
+
--gray-50: 210 20% 98%;
|
|
27
|
+
--gray-100: 220 14% 96%;
|
|
28
|
+
--gray-200: 220 13% 91%;
|
|
29
|
+
--gray-300: 216 12% 84%;
|
|
30
|
+
--gray-400: 218 11% 65%;
|
|
31
|
+
--gray-500: 220 9% 46%;
|
|
32
|
+
--gray-600: 215 14% 34%;
|
|
33
|
+
--gray-700: 217 19% 27%;
|
|
34
|
+
--gray-800: 215 28% 17%;
|
|
35
|
+
--gray-900: 221 39% 11%;
|
|
36
|
+
|
|
37
|
+
/* ========================================
|
|
38
|
+
SEMANTIC COLORS
|
|
39
|
+
======================================== */
|
|
40
|
+
/* Background */
|
|
41
|
+
--background: 210 20% 98%;
|
|
42
|
+
--background-secondary: 220 14% 96%;
|
|
43
|
+
--background-tertiary: 220 13% 91%;
|
|
44
|
+
|
|
45
|
+
/* Foreground (Text) */
|
|
46
|
+
--foreground: 221 39% 11%;
|
|
47
|
+
--foreground-secondary: 215 28% 17%;
|
|
48
|
+
--foreground-tertiary: 220 9% 46%;
|
|
49
|
+
--foreground-muted: 218 11% 65%;
|
|
50
|
+
|
|
51
|
+
/* Primary (Brand Blue) */
|
|
52
|
+
--primary: 217 80% 55%;
|
|
53
|
+
--primary-hover: 217 75% 48%;
|
|
54
|
+
--primary-active: 217 70% 40%;
|
|
55
|
+
--primary-foreground: 0 0% 100%;
|
|
56
|
+
|
|
57
|
+
/* Secondary */
|
|
58
|
+
--secondary: 220 14% 96%;
|
|
59
|
+
--secondary-hover: 220 13% 91%;
|
|
60
|
+
--secondary-foreground: 215 28% 17%;
|
|
61
|
+
|
|
62
|
+
/* Accent */
|
|
63
|
+
--accent: 217 100% 97%;
|
|
64
|
+
--accent-foreground: 217 70% 40%;
|
|
65
|
+
|
|
66
|
+
/* Muted */
|
|
67
|
+
--muted: 220 14% 96%;
|
|
68
|
+
--muted-foreground: 220 9% 46%;
|
|
69
|
+
|
|
70
|
+
/* Destructive */
|
|
71
|
+
--destructive: 0 84% 60%;
|
|
72
|
+
--destructive-foreground: 0 0% 98%;
|
|
73
|
+
|
|
74
|
+
/* Success */
|
|
75
|
+
--success: 142 76% 36%;
|
|
76
|
+
--success-foreground: 0 0% 100%;
|
|
77
|
+
|
|
78
|
+
/* Warning */
|
|
79
|
+
--warning: 38 92% 50%;
|
|
80
|
+
--warning-foreground: 0 0% 100%;
|
|
81
|
+
|
|
82
|
+
/* ========================================
|
|
83
|
+
UI ELEMENTS
|
|
84
|
+
======================================== */
|
|
85
|
+
/* Card */
|
|
86
|
+
--card: 0 0% 100%;
|
|
87
|
+
--card-foreground: 221 39% 11%;
|
|
88
|
+
--card-border: 220 13% 91%;
|
|
89
|
+
|
|
90
|
+
/* Popover */
|
|
91
|
+
--popover: 0 0% 100%;
|
|
92
|
+
--popover-foreground: 221 39% 11%;
|
|
93
|
+
|
|
94
|
+
/* Border */
|
|
95
|
+
--border: 220 13% 91%;
|
|
96
|
+
--border-hover: 216 12% 84%;
|
|
97
|
+
--border-active: 217 80% 55%;
|
|
98
|
+
|
|
99
|
+
/* Input */
|
|
100
|
+
--input: 0 0% 100%;
|
|
101
|
+
--input-border: 220 13% 91%;
|
|
102
|
+
--input-focus: 217 80% 55%;
|
|
103
|
+
|
|
104
|
+
/* Ring (Focus) */
|
|
105
|
+
--ring: 217 80% 55%;
|
|
106
|
+
--ring-offset: 0 0% 100%;
|
|
107
|
+
|
|
108
|
+
/* ========================================
|
|
109
|
+
SPACING SYSTEM
|
|
110
|
+
======================================== */
|
|
111
|
+
--space-0: 0px;
|
|
112
|
+
--space-1: 4px;
|
|
113
|
+
--space-2: 8px;
|
|
114
|
+
--space-3: 12px;
|
|
115
|
+
--space-4: 16px;
|
|
116
|
+
--space-5: 20px;
|
|
117
|
+
--space-6: 24px;
|
|
118
|
+
--space-8: 32px;
|
|
119
|
+
--space-10: 40px;
|
|
120
|
+
--space-12: 48px;
|
|
121
|
+
--space-16: 64px;
|
|
122
|
+
--space-20: 80px;
|
|
123
|
+
--space-24: 96px;
|
|
124
|
+
|
|
125
|
+
/* ========================================
|
|
126
|
+
BORDER RADIUS
|
|
127
|
+
======================================== */
|
|
128
|
+
--radius-sm: 6px;
|
|
129
|
+
--radius-md: 8px;
|
|
130
|
+
--radius-lg: 12px;
|
|
131
|
+
--radius-xl: 16px;
|
|
132
|
+
--radius-2xl: 20px;
|
|
133
|
+
--radius-3xl: 24px;
|
|
134
|
+
--radius-full: 9999px;
|
|
135
|
+
|
|
136
|
+
/* ========================================
|
|
137
|
+
SHADOWS
|
|
138
|
+
======================================== */
|
|
139
|
+
--shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
140
|
+
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
141
|
+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
142
|
+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
143
|
+
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
|
144
|
+
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
|
145
|
+
|
|
146
|
+
/* Card Shadow */
|
|
147
|
+
--shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.05), 0 1px 2px -1px rgb(0 0 0 / 0.05);
|
|
148
|
+
--shadow-card-hover: 0 10px 15px -3px rgb(0 0 0 / 0.08), 0 4px 6px -4px rgb(0 0 0 / 0.05);
|
|
149
|
+
|
|
150
|
+
/* ========================================
|
|
151
|
+
TYPOGRAPHY
|
|
152
|
+
======================================== */
|
|
153
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
|
154
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
155
|
+
|
|
156
|
+
/* Font Sizes */
|
|
157
|
+
--text-xs: 12px;
|
|
158
|
+
--text-sm: 14px;
|
|
159
|
+
--text-base: 16px;
|
|
160
|
+
--text-lg: 18px;
|
|
161
|
+
--text-xl: 20px;
|
|
162
|
+
--text-2xl: 24px;
|
|
163
|
+
--text-3xl: 30px;
|
|
164
|
+
--text-4xl: 36px;
|
|
165
|
+
--text-5xl: 48px;
|
|
166
|
+
|
|
167
|
+
/* Font Weights */
|
|
168
|
+
--font-normal: 400;
|
|
169
|
+
--font-medium: 500;
|
|
170
|
+
--font-semibold: 600;
|
|
171
|
+
--font-bold: 700;
|
|
172
|
+
|
|
173
|
+
/* Line Heights */
|
|
174
|
+
--leading-tight: 1.25;
|
|
175
|
+
--leading-snug: 1.375;
|
|
176
|
+
--leading-normal: 1.5;
|
|
177
|
+
--leading-relaxed: 1.625;
|
|
178
|
+
|
|
179
|
+
/* Letter Spacing */
|
|
180
|
+
--tracking-tight: -0.025em;
|
|
181
|
+
--tracking-normal: 0;
|
|
182
|
+
--tracking-wide: 0.025em;
|
|
183
|
+
|
|
184
|
+
/* ========================================
|
|
185
|
+
TRANSITIONS
|
|
186
|
+
======================================== */
|
|
187
|
+
--transition-fast: 150ms ease;
|
|
188
|
+
--transition-base: 200ms ease;
|
|
189
|
+
--transition-slow: 300ms ease;
|
|
190
|
+
|
|
191
|
+
/* ========================================
|
|
192
|
+
Z-INDEX SCALE
|
|
193
|
+
======================================== */
|
|
194
|
+
--z-dropdown: 100;
|
|
195
|
+
--z-sticky: 200;
|
|
196
|
+
--z-fixed: 300;
|
|
197
|
+
--z-modal-backdrop: 400;
|
|
198
|
+
--z-modal: 500;
|
|
199
|
+
--z-popover: 600;
|
|
200
|
+
--z-tooltip: 700;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@layer utilities {
|
|
205
|
+
/* ========================================
|
|
206
|
+
UTILITY CLASSES
|
|
207
|
+
======================================== */
|
|
208
|
+
|
|
209
|
+
/* Brand Colors */
|
|
210
|
+
.bg-brand-50 { background-color: hsl(var(--brand-50)); }
|
|
211
|
+
.bg-brand-100 { background-color: hsl(var(--brand-100)); }
|
|
212
|
+
.bg-brand-500 { background-color: hsl(var(--brand-500)); }
|
|
213
|
+
.bg-brand-600 { background-color: hsl(var(--brand-600)); }
|
|
214
|
+
.text-brand-500 { color: hsl(var(--brand-500)); }
|
|
215
|
+
.text-brand-600 { color: hsl(var(--brand-600)); }
|
|
216
|
+
.border-brand-500 { border-color: hsl(var(--brand-500)); }
|
|
217
|
+
|
|
218
|
+
/* Gray Colors */
|
|
219
|
+
.bg-gray-50 { background-color: hsl(var(--gray-50)); }
|
|
220
|
+
.bg-gray-100 { background-color: hsl(var(--gray-100)); }
|
|
221
|
+
.bg-gray-900 { background-color: hsl(var(--gray-900)); }
|
|
222
|
+
.text-gray-500 { color: hsl(var(--gray-500)); }
|
|
223
|
+
.text-gray-600 { color: hsl(var(--gray-600)); }
|
|
224
|
+
.text-gray-900 { color: hsl(var(--gray-900)); }
|
|
225
|
+
|
|
226
|
+
/* Shadows */
|
|
227
|
+
.shadow-card { box-shadow: var(--shadow-card); }
|
|
228
|
+
.shadow-card-hover { box-shadow: var(--shadow-card-hover); }
|
|
229
|
+
|
|
230
|
+
/* Gradient Backgrounds */
|
|
231
|
+
.bg-gradient-hero {
|
|
232
|
+
background: linear-gradient(180deg, hsl(var(--background)) 0%, hsl(var(--gray-50)) 100%);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Glass Effect */
|
|
236
|
+
.glass {
|
|
237
|
+
background: rgba(255, 255, 255, 0.8);
|
|
238
|
+
backdrop-filter: blur(12px);
|
|
239
|
+
-webkit-backdrop-filter: blur(12px);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* Focus Ring */
|
|
243
|
+
.focus-ring {
|
|
244
|
+
@apply focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2;
|
|
245
|
+
--tw-ring-color: hsl(var(--ring));
|
|
246
|
+
--tw-ring-offset-color: hsl(var(--ring-offset));
|
|
247
|
+
}
|
|
248
|
+
}
|