@srcroot/ui 0.0.3 → 0.0.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/dist/index.js +286 -47
- package/package.json +1 -1
- package/registry/accordion.tsx +6 -2
- package/registry/design-tokens.css +197 -0
- package/registry/resizable.tsx +160 -97
- package/registry/themes/gray.css +86 -0
- package/registry/themes/index.css +19 -0
- package/registry/themes/neutral.css +86 -0
- package/registry/themes/slate.css +86 -0
- package/registry/themes/stone.css +86 -0
- package/registry/themes/zinc.css +86 -0
package/registry/resizable.tsx
CHANGED
|
@@ -5,11 +5,12 @@ import { cn } from "@/lib/utils"
|
|
|
5
5
|
|
|
6
6
|
// Resizable Context
|
|
7
7
|
interface ResizablePanelGroupContextValue {
|
|
8
|
+
groupId: string
|
|
8
9
|
direction: "horizontal" | "vertical"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
registerPanel: (defaultSize: number, minSize: number, maxSize: number) => number
|
|
11
|
+
getSize: (index: number) => number
|
|
12
|
+
getTotalSize: () => number
|
|
13
|
+
onResize: (handleIndex: number, delta: number) => void
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const ResizablePanelGroupContext = React.createContext<ResizablePanelGroupContextValue | null>(null)
|
|
@@ -28,38 +29,115 @@ interface ResizablePanelGroupProps extends React.HTMLAttributes<HTMLDivElement>
|
|
|
28
29
|
onLayout?: (sizes: number[]) => void
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
interface PanelConfig {
|
|
33
|
+
defaultSize: number
|
|
34
|
+
minSize: number
|
|
35
|
+
maxSize: number
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
const ResizablePanelGroup = React.forwardRef<HTMLDivElement, ResizablePanelGroupProps>(
|
|
32
39
|
({ className, direction = "horizontal", children, onLayout, ...props }, ref) => {
|
|
33
|
-
const
|
|
40
|
+
const groupId = React.useId()
|
|
41
|
+
const containerRef = React.useRef<HTMLDivElement>(null)
|
|
42
|
+
const [, forceUpdate] = React.useReducer(x => x + 1, 0)
|
|
43
|
+
|
|
44
|
+
// Store panel configs and sizes in refs for stable access
|
|
45
|
+
const panelConfigsRef = React.useRef<PanelConfig[]>([])
|
|
46
|
+
const sizesRef = React.useRef<number[]>([])
|
|
34
47
|
const panelCountRef = React.useRef(0)
|
|
35
48
|
|
|
36
|
-
// Reset panel count
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
// Reset panel count at start of each render
|
|
50
|
+
panelCountRef.current = 0
|
|
51
|
+
|
|
52
|
+
const registerPanel = React.useCallback((defaultSize: number, minSize: number, maxSize: number) => {
|
|
53
|
+
const index = panelCountRef.current++
|
|
54
|
+
|
|
55
|
+
// Only initialize if not already set
|
|
56
|
+
if (sizesRef.current[index] === undefined) {
|
|
57
|
+
sizesRef.current[index] = defaultSize
|
|
58
|
+
panelConfigsRef.current[index] = { defaultSize, minSize, maxSize }
|
|
59
|
+
}
|
|
40
60
|
|
|
41
|
-
const registerPanel = React.useCallback(() => {
|
|
42
|
-
const index = panelCountRef.current
|
|
43
|
-
panelCountRef.current += 1
|
|
44
61
|
return index
|
|
45
62
|
}, [])
|
|
46
63
|
|
|
47
|
-
const
|
|
48
|
-
return
|
|
64
|
+
const getSize = React.useCallback((index: number) => {
|
|
65
|
+
return sizesRef.current[index] ?? 50
|
|
49
66
|
}, [])
|
|
50
67
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
68
|
+
const getTotalSize = React.useCallback(() => {
|
|
69
|
+
return sizesRef.current.reduce((sum, s) => sum + s, 0)
|
|
70
|
+
}, [])
|
|
71
|
+
|
|
72
|
+
const onResize = React.useCallback((handleIndex: number, delta: number) => {
|
|
73
|
+
const container = containerRef.current
|
|
74
|
+
if (!container) return
|
|
75
|
+
|
|
76
|
+
const containerSize = direction === "horizontal"
|
|
77
|
+
? container.offsetWidth
|
|
78
|
+
: container.offsetHeight
|
|
79
|
+
|
|
80
|
+
if (containerSize === 0) return
|
|
81
|
+
|
|
82
|
+
const deltaPercent = (delta / containerSize) * 100
|
|
83
|
+
|
|
84
|
+
const leftIndex = handleIndex
|
|
85
|
+
const rightIndex = handleIndex + 1
|
|
86
|
+
const sizes = sizesRef.current
|
|
87
|
+
const configs = panelConfigsRef.current
|
|
88
|
+
|
|
89
|
+
if (leftIndex >= sizes.length || rightIndex >= sizes.length) return
|
|
90
|
+
|
|
91
|
+
const leftSize = sizes[leftIndex]
|
|
92
|
+
const rightSize = sizes[rightIndex]
|
|
93
|
+
const totalSize = leftSize + rightSize
|
|
94
|
+
|
|
95
|
+
let newLeftSize = leftSize + deltaPercent
|
|
96
|
+
let newRightSize = rightSize - deltaPercent
|
|
97
|
+
|
|
98
|
+
const leftMin = configs[leftIndex]?.minSize ?? 10
|
|
99
|
+
const leftMax = configs[leftIndex]?.maxSize ?? 90
|
|
100
|
+
const rightMin = configs[rightIndex]?.minSize ?? 10
|
|
101
|
+
const rightMax = configs[rightIndex]?.maxSize ?? 90
|
|
102
|
+
|
|
103
|
+
// Apply constraints
|
|
104
|
+
if (newLeftSize < leftMin) {
|
|
105
|
+
newLeftSize = leftMin
|
|
106
|
+
newRightSize = totalSize - leftMin
|
|
107
|
+
}
|
|
108
|
+
if (newRightSize < rightMin) {
|
|
109
|
+
newRightSize = rightMin
|
|
110
|
+
newLeftSize = totalSize - rightMin
|
|
111
|
+
}
|
|
112
|
+
if (newLeftSize > leftMax) {
|
|
113
|
+
newLeftSize = leftMax
|
|
114
|
+
newRightSize = totalSize - leftMax
|
|
55
115
|
}
|
|
56
|
-
|
|
116
|
+
if (newRightSize > rightMax) {
|
|
117
|
+
newRightSize = rightMax
|
|
118
|
+
newLeftSize = totalSize - rightMax
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
sizesRef.current[leftIndex] = newLeftSize
|
|
122
|
+
sizesRef.current[rightIndex] = newRightSize
|
|
123
|
+
|
|
124
|
+
// Force re-render to update panel sizes
|
|
125
|
+
forceUpdate()
|
|
126
|
+
|
|
127
|
+
// Notify layout changes
|
|
128
|
+
onLayout?.([...sizesRef.current])
|
|
129
|
+
}, [direction, onLayout])
|
|
57
130
|
|
|
58
131
|
return (
|
|
59
|
-
<ResizablePanelGroupContext.Provider value={{ direction,
|
|
132
|
+
<ResizablePanelGroupContext.Provider value={{ groupId, direction, registerPanel, getSize, getTotalSize, onResize }}>
|
|
60
133
|
<div
|
|
61
|
-
ref={
|
|
134
|
+
ref={(node) => {
|
|
135
|
+
containerRef.current = node
|
|
136
|
+
if (typeof ref === "function") ref(node)
|
|
137
|
+
else if (ref) ref.current = node
|
|
138
|
+
}}
|
|
62
139
|
data-panel-group
|
|
140
|
+
data-panel-group-id={groupId}
|
|
63
141
|
data-direction={direction}
|
|
64
142
|
className={cn(
|
|
65
143
|
"flex h-full w-full",
|
|
@@ -85,31 +163,30 @@ interface ResizablePanelProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
85
163
|
|
|
86
164
|
const ResizablePanel = React.forwardRef<HTMLDivElement, ResizablePanelProps>(
|
|
87
165
|
({ className, defaultSize = 50, minSize = 10, maxSize = 90, children, style, ...props }, ref) => {
|
|
88
|
-
const { direction,
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (newSizes[index] === undefined) {
|
|
96
|
-
newSizes[index] = defaultSize
|
|
97
|
-
}
|
|
98
|
-
return newSizes
|
|
99
|
-
})
|
|
100
|
-
}, [index, defaultSize, setSizes])
|
|
166
|
+
const { groupId, direction, registerPanel, getSize, getTotalSize } = useResizablePanelGroup()
|
|
167
|
+
const indexRef = React.useRef<number>(-1)
|
|
168
|
+
|
|
169
|
+
// Register panel on first render only
|
|
170
|
+
if (indexRef.current === -1) {
|
|
171
|
+
indexRef.current = registerPanel(defaultSize, minSize, maxSize)
|
|
172
|
+
}
|
|
101
173
|
|
|
102
|
-
const size =
|
|
174
|
+
const size = getSize(indexRef.current)
|
|
175
|
+
const totalSize = getTotalSize()
|
|
176
|
+
// Convert to actual percentage of total
|
|
177
|
+
// const actualPercent = totalSize > 0 ? (size / totalSize) * 100 : size
|
|
103
178
|
|
|
104
179
|
return (
|
|
105
180
|
<div
|
|
106
181
|
ref={ref}
|
|
107
182
|
data-panel
|
|
108
|
-
data-panel-
|
|
183
|
+
data-panel-group-id={groupId}
|
|
184
|
+
data-panel-index={indexRef.current}
|
|
109
185
|
className={cn("overflow-hidden", className)}
|
|
110
186
|
style={{
|
|
111
187
|
...style,
|
|
112
|
-
flex
|
|
188
|
+
// Use flex-grow with the size as the ratio for smoother resizing
|
|
189
|
+
flex: `${size} 1 0`,
|
|
113
190
|
}}
|
|
114
191
|
{...props}
|
|
115
192
|
>
|
|
@@ -127,92 +204,78 @@ interface ResizableHandleProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
127
204
|
|
|
128
205
|
const ResizableHandle = React.forwardRef<HTMLDivElement, ResizableHandleProps>(
|
|
129
206
|
({ className, withHandle = false, ...props }, ref) => {
|
|
130
|
-
const { direction,
|
|
207
|
+
const { direction, onResize } = useResizablePanelGroup()
|
|
131
208
|
const [isDragging, setIsDragging] = React.useState(false)
|
|
209
|
+
const handleIndexRef = React.useRef<number>(-1)
|
|
210
|
+
const lastPosRef = React.useRef<number>(0)
|
|
132
211
|
const handleRef = React.useRef<HTMLDivElement>(null)
|
|
133
212
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
setIsDragging(true)
|
|
137
|
-
|
|
138
|
-
const startPos = direction === "horizontal" ? e.clientX : e.clientY
|
|
213
|
+
// Determine handle index from DOM position
|
|
214
|
+
const getHandleIndex = React.useCallback(() => {
|
|
139
215
|
const handle = handleRef.current
|
|
140
|
-
if (!handle) return
|
|
216
|
+
if (!handle) return 0
|
|
217
|
+
|
|
218
|
+
const parent = handle.parentElement
|
|
219
|
+
if (!parent) return 0
|
|
141
220
|
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
221
|
+
let handleCount = 0
|
|
222
|
+
for (const child of Array.from(parent.children)) {
|
|
223
|
+
if (child === handle) break
|
|
224
|
+
if (child.hasAttribute('data-panel-resize-handle')) {
|
|
225
|
+
handleCount++
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return handleCount
|
|
229
|
+
}, [])
|
|
146
230
|
|
|
147
|
-
|
|
148
|
-
|
|
231
|
+
const handleMouseDown = React.useCallback((e: React.MouseEvent) => {
|
|
232
|
+
e.preventDefault()
|
|
233
|
+
e.stopPropagation()
|
|
234
|
+
setIsDragging(true)
|
|
149
235
|
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
const totalSize = direction === "horizontal"
|
|
154
|
-
? prevRect.width + nextRect.width
|
|
155
|
-
: prevRect.height + nextRect.height
|
|
236
|
+
const handleIndex = getHandleIndex()
|
|
237
|
+
const startPos = direction === "horizontal" ? e.clientX : e.clientY
|
|
238
|
+
lastPosRef.current = startPos
|
|
156
239
|
|
|
157
240
|
const handleMouseMove = (moveEvent: MouseEvent) => {
|
|
158
241
|
const currentPos = direction === "horizontal" ? moveEvent.clientX : moveEvent.clientY
|
|
159
|
-
const delta = currentPos -
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const nextSize = prev[nextIndex] ?? 50
|
|
166
|
-
|
|
167
|
-
// Calculate new sizes with constraints
|
|
168
|
-
let newPrevSize = prevSize + deltaPercent
|
|
169
|
-
let newNextSize = nextSize - deltaPercent
|
|
170
|
-
|
|
171
|
-
// Apply min/max constraints
|
|
172
|
-
if (newPrevSize < 10) {
|
|
173
|
-
newPrevSize = 10
|
|
174
|
-
newNextSize = prevSize + nextSize - 10
|
|
175
|
-
}
|
|
176
|
-
if (newNextSize < 10) {
|
|
177
|
-
newNextSize = 10
|
|
178
|
-
newPrevSize = prevSize + nextSize - 10
|
|
179
|
-
}
|
|
180
|
-
if (newPrevSize > 90) {
|
|
181
|
-
newPrevSize = 90
|
|
182
|
-
newNextSize = prevSize + nextSize - 90
|
|
183
|
-
}
|
|
184
|
-
if (newNextSize > 90) {
|
|
185
|
-
newNextSize = 90
|
|
186
|
-
newPrevSize = prevSize + nextSize - 90
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
newSizes[prevIndex] = newPrevSize
|
|
190
|
-
newSizes[nextIndex] = newNextSize
|
|
191
|
-
return newSizes
|
|
192
|
-
})
|
|
242
|
+
const delta = currentPos - lastPosRef.current
|
|
243
|
+
lastPosRef.current = currentPos
|
|
244
|
+
|
|
245
|
+
if (delta !== 0) {
|
|
246
|
+
onResize(handleIndex, delta)
|
|
247
|
+
}
|
|
193
248
|
}
|
|
194
249
|
|
|
195
250
|
const handleMouseUp = () => {
|
|
196
251
|
setIsDragging(false)
|
|
197
252
|
document.removeEventListener("mousemove", handleMouseMove)
|
|
198
253
|
document.removeEventListener("mouseup", handleMouseUp)
|
|
254
|
+
document.body.style.cursor = ""
|
|
255
|
+
document.body.style.userSelect = ""
|
|
199
256
|
}
|
|
200
257
|
|
|
258
|
+
document.body.style.cursor = direction === "horizontal" ? "col-resize" : "row-resize"
|
|
259
|
+
document.body.style.userSelect = "none"
|
|
201
260
|
document.addEventListener("mousemove", handleMouseMove)
|
|
202
261
|
document.addEventListener("mouseup", handleMouseUp)
|
|
203
|
-
}
|
|
262
|
+
}, [direction, onResize, getHandleIndex])
|
|
204
263
|
|
|
205
264
|
return (
|
|
206
265
|
<div
|
|
207
|
-
ref={
|
|
266
|
+
ref={(node) => {
|
|
267
|
+
handleRef.current = node
|
|
268
|
+
if (typeof ref === "function") ref(node)
|
|
269
|
+
else if (ref) ref.current = node
|
|
270
|
+
}}
|
|
208
271
|
data-panel-resize-handle
|
|
272
|
+
data-dragging={isDragging}
|
|
209
273
|
className={cn(
|
|
210
|
-
"relative flex items-center justify-center bg-border",
|
|
274
|
+
"relative flex shrink-0 items-center justify-center bg-border",
|
|
211
275
|
direction === "horizontal"
|
|
212
|
-
? "w-
|
|
213
|
-
: "h-
|
|
214
|
-
isDragging &&
|
|
215
|
-
"transition-all",
|
|
276
|
+
? "w-1 cursor-col-resize hover:bg-primary/50 active:bg-primary"
|
|
277
|
+
: "h-1 cursor-row-resize hover:bg-primary/50 active:bg-primary",
|
|
278
|
+
isDragging && "bg-primary",
|
|
216
279
|
className
|
|
217
280
|
)}
|
|
218
281
|
onMouseDown={handleMouseDown}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @srcroot/ui - Gray Theme
|
|
3
|
+
* True neutral gray (the default)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
@layer base {
|
|
7
|
+
:root {
|
|
8
|
+
--background: 0 0% 100%;
|
|
9
|
+
--foreground: 224 71.4% 4.1%;
|
|
10
|
+
|
|
11
|
+
--card: 0 0% 100%;
|
|
12
|
+
--card-foreground: 224 71.4% 4.1%;
|
|
13
|
+
|
|
14
|
+
--popover: 0 0% 100%;
|
|
15
|
+
--popover-foreground: 224 71.4% 4.1%;
|
|
16
|
+
|
|
17
|
+
--primary: 220.9 39.3% 11%;
|
|
18
|
+
--primary-foreground: 210 20% 98%;
|
|
19
|
+
|
|
20
|
+
--secondary: 220 14.3% 95.9%;
|
|
21
|
+
--secondary-foreground: 220.9 39.3% 11%;
|
|
22
|
+
|
|
23
|
+
--muted: 220 14.3% 95.9%;
|
|
24
|
+
--muted-foreground: 220 8.9% 46.1%;
|
|
25
|
+
|
|
26
|
+
--accent: 220 14.3% 95.9%;
|
|
27
|
+
--accent-foreground: 220.9 39.3% 11%;
|
|
28
|
+
|
|
29
|
+
--destructive: 0 84.2% 60.2%;
|
|
30
|
+
--destructive-foreground: 210 20% 98%;
|
|
31
|
+
|
|
32
|
+
--success: 142.1 76.2% 36.3%;
|
|
33
|
+
--success-foreground: 210 20% 98%;
|
|
34
|
+
|
|
35
|
+
--warning: 45.4 93.4% 47.5%;
|
|
36
|
+
--warning-foreground: 220.9 39.3% 11%;
|
|
37
|
+
|
|
38
|
+
--info: 201.3 96.3% 32.2%;
|
|
39
|
+
--info-foreground: 210 20% 98%;
|
|
40
|
+
|
|
41
|
+
--border: 220 13% 91%;
|
|
42
|
+
--input: 220 13% 91%;
|
|
43
|
+
--ring: 224 71.4% 4.1%;
|
|
44
|
+
|
|
45
|
+
--radius: 0.5rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.dark {
|
|
49
|
+
--background: 224 71.4% 4.1%;
|
|
50
|
+
--foreground: 210 20% 98%;
|
|
51
|
+
|
|
52
|
+
--card: 224 71.4% 4.1%;
|
|
53
|
+
--card-foreground: 210 20% 98%;
|
|
54
|
+
|
|
55
|
+
--popover: 224 71.4% 4.1%;
|
|
56
|
+
--popover-foreground: 210 20% 98%;
|
|
57
|
+
|
|
58
|
+
--primary: 210 20% 98%;
|
|
59
|
+
--primary-foreground: 220.9 39.3% 11%;
|
|
60
|
+
|
|
61
|
+
--secondary: 215 27.9% 16.9%;
|
|
62
|
+
--secondary-foreground: 210 20% 98%;
|
|
63
|
+
|
|
64
|
+
--muted: 215 27.9% 16.9%;
|
|
65
|
+
--muted-foreground: 217.9 10.6% 64.9%;
|
|
66
|
+
|
|
67
|
+
--accent: 215 27.9% 16.9%;
|
|
68
|
+
--accent-foreground: 210 20% 98%;
|
|
69
|
+
|
|
70
|
+
--destructive: 0 62.8% 30.6%;
|
|
71
|
+
--destructive-foreground: 210 20% 98%;
|
|
72
|
+
|
|
73
|
+
--success: 142.1 70.6% 45.3%;
|
|
74
|
+
--success-foreground: 220.9 39.3% 11%;
|
|
75
|
+
|
|
76
|
+
--warning: 48 96.5% 53.1%;
|
|
77
|
+
--warning-foreground: 220.9 39.3% 11%;
|
|
78
|
+
|
|
79
|
+
--info: 199.4 95.5% 53.8%;
|
|
80
|
+
--info-foreground: 220.9 39.3% 11%;
|
|
81
|
+
|
|
82
|
+
--border: 215 27.9% 16.9%;
|
|
83
|
+
--input: 215 27.9% 16.9%;
|
|
84
|
+
--ring: 216 12.2% 83.9%;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @srcroot/ui Theme Index
|
|
3
|
+
*
|
|
4
|
+
* Available themes:
|
|
5
|
+
* - neutral.css - Pure gray, no undertones
|
|
6
|
+
* - stone.css - Warm gray with brown undertones
|
|
7
|
+
* - zinc.css - Cool gray with subtle blue undertones
|
|
8
|
+
* - gray.css - True neutral gray
|
|
9
|
+
* - slate.css - Cool gray with strong blue undertones (default)
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* Copy the theme file contents into your globals.css or import it:
|
|
13
|
+
*
|
|
14
|
+
* @import '@srcroot/ui/themes/slate.css';
|
|
15
|
+
*
|
|
16
|
+
* Or with the base tokens:
|
|
17
|
+
* @import '@srcroot/ui/design-tokens.css';
|
|
18
|
+
* @import '@srcroot/ui/themes/zinc.css';
|
|
19
|
+
*/
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @srcroot/ui - Neutral Theme
|
|
3
|
+
* A balanced gray with no strong undertones
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
@layer base {
|
|
7
|
+
:root {
|
|
8
|
+
--background: 0 0% 100%;
|
|
9
|
+
--foreground: 0 0% 3.9%;
|
|
10
|
+
|
|
11
|
+
--card: 0 0% 100%;
|
|
12
|
+
--card-foreground: 0 0% 3.9%;
|
|
13
|
+
|
|
14
|
+
--popover: 0 0% 100%;
|
|
15
|
+
--popover-foreground: 0 0% 3.9%;
|
|
16
|
+
|
|
17
|
+
--primary: 0 0% 9%;
|
|
18
|
+
--primary-foreground: 0 0% 98%;
|
|
19
|
+
|
|
20
|
+
--secondary: 0 0% 96.1%;
|
|
21
|
+
--secondary-foreground: 0 0% 9%;
|
|
22
|
+
|
|
23
|
+
--muted: 0 0% 96.1%;
|
|
24
|
+
--muted-foreground: 0 0% 45.1%;
|
|
25
|
+
|
|
26
|
+
--accent: 0 0% 96.1%;
|
|
27
|
+
--accent-foreground: 0 0% 9%;
|
|
28
|
+
|
|
29
|
+
--destructive: 0 84.2% 60.2%;
|
|
30
|
+
--destructive-foreground: 0 0% 98%;
|
|
31
|
+
|
|
32
|
+
--success: 142.1 76.2% 36.3%;
|
|
33
|
+
--success-foreground: 0 0% 98%;
|
|
34
|
+
|
|
35
|
+
--warning: 45.4 93.4% 47.5%;
|
|
36
|
+
--warning-foreground: 0 0% 9%;
|
|
37
|
+
|
|
38
|
+
--info: 201.3 96.3% 32.2%;
|
|
39
|
+
--info-foreground: 0 0% 98%;
|
|
40
|
+
|
|
41
|
+
--border: 0 0% 89.8%;
|
|
42
|
+
--input: 0 0% 89.8%;
|
|
43
|
+
--ring: 0 0% 3.9%;
|
|
44
|
+
|
|
45
|
+
--radius: 0.5rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.dark {
|
|
49
|
+
--background: 0 0% 3.9%;
|
|
50
|
+
--foreground: 0 0% 98%;
|
|
51
|
+
|
|
52
|
+
--card: 0 0% 3.9%;
|
|
53
|
+
--card-foreground: 0 0% 98%;
|
|
54
|
+
|
|
55
|
+
--popover: 0 0% 3.9%;
|
|
56
|
+
--popover-foreground: 0 0% 98%;
|
|
57
|
+
|
|
58
|
+
--primary: 0 0% 98%;
|
|
59
|
+
--primary-foreground: 0 0% 9%;
|
|
60
|
+
|
|
61
|
+
--secondary: 0 0% 14.9%;
|
|
62
|
+
--secondary-foreground: 0 0% 98%;
|
|
63
|
+
|
|
64
|
+
--muted: 0 0% 14.9%;
|
|
65
|
+
--muted-foreground: 0 0% 63.9%;
|
|
66
|
+
|
|
67
|
+
--accent: 0 0% 14.9%;
|
|
68
|
+
--accent-foreground: 0 0% 98%;
|
|
69
|
+
|
|
70
|
+
--destructive: 0 62.8% 30.6%;
|
|
71
|
+
--destructive-foreground: 0 0% 98%;
|
|
72
|
+
|
|
73
|
+
--success: 142.1 70.6% 45.3%;
|
|
74
|
+
--success-foreground: 0 0% 9%;
|
|
75
|
+
|
|
76
|
+
--warning: 48 96.5% 53.1%;
|
|
77
|
+
--warning-foreground: 0 0% 9%;
|
|
78
|
+
|
|
79
|
+
--info: 199.4 95.5% 53.8%;
|
|
80
|
+
--info-foreground: 0 0% 9%;
|
|
81
|
+
|
|
82
|
+
--border: 0 0% 14.9%;
|
|
83
|
+
--input: 0 0% 14.9%;
|
|
84
|
+
--ring: 0 0% 83.1%;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @srcroot/ui - Slate Theme
|
|
3
|
+
* Cool gray with strong blue undertones (shadcn default)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
@layer base {
|
|
7
|
+
:root {
|
|
8
|
+
--background: 0 0% 100%;
|
|
9
|
+
--foreground: 222.2 84% 4.9%;
|
|
10
|
+
|
|
11
|
+
--card: 0 0% 100%;
|
|
12
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
13
|
+
|
|
14
|
+
--popover: 0 0% 100%;
|
|
15
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
16
|
+
|
|
17
|
+
--primary: 222.2 47.4% 11.2%;
|
|
18
|
+
--primary-foreground: 210 40% 98%;
|
|
19
|
+
|
|
20
|
+
--secondary: 210 40% 96.1%;
|
|
21
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
22
|
+
|
|
23
|
+
--muted: 210 40% 96.1%;
|
|
24
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
25
|
+
|
|
26
|
+
--accent: 210 40% 96.1%;
|
|
27
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
28
|
+
|
|
29
|
+
--destructive: 0 84.2% 60.2%;
|
|
30
|
+
--destructive-foreground: 210 40% 98%;
|
|
31
|
+
|
|
32
|
+
--success: 142.1 76.2% 36.3%;
|
|
33
|
+
--success-foreground: 210 40% 98%;
|
|
34
|
+
|
|
35
|
+
--warning: 45.4 93.4% 47.5%;
|
|
36
|
+
--warning-foreground: 222.2 47.4% 11.2%;
|
|
37
|
+
|
|
38
|
+
--info: 201.3 96.3% 32.2%;
|
|
39
|
+
--info-foreground: 210 40% 98%;
|
|
40
|
+
|
|
41
|
+
--border: 214.3 31.8% 91.4%;
|
|
42
|
+
--input: 214.3 31.8% 91.4%;
|
|
43
|
+
--ring: 222.2 84% 4.9%;
|
|
44
|
+
|
|
45
|
+
--radius: 0.5rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.dark {
|
|
49
|
+
--background: 222.2 84% 4.9%;
|
|
50
|
+
--foreground: 210 40% 98%;
|
|
51
|
+
|
|
52
|
+
--card: 222.2 84% 4.9%;
|
|
53
|
+
--card-foreground: 210 40% 98%;
|
|
54
|
+
|
|
55
|
+
--popover: 222.2 84% 4.9%;
|
|
56
|
+
--popover-foreground: 210 40% 98%;
|
|
57
|
+
|
|
58
|
+
--primary: 210 40% 98%;
|
|
59
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
60
|
+
|
|
61
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
62
|
+
--secondary-foreground: 210 40% 98%;
|
|
63
|
+
|
|
64
|
+
--muted: 217.2 32.6% 17.5%;
|
|
65
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
66
|
+
|
|
67
|
+
--accent: 217.2 32.6% 17.5%;
|
|
68
|
+
--accent-foreground: 210 40% 98%;
|
|
69
|
+
|
|
70
|
+
--destructive: 0 62.8% 30.6%;
|
|
71
|
+
--destructive-foreground: 210 40% 98%;
|
|
72
|
+
|
|
73
|
+
--success: 142.1 70.6% 45.3%;
|
|
74
|
+
--success-foreground: 222.2 47.4% 11.2%;
|
|
75
|
+
|
|
76
|
+
--warning: 48 96.5% 53.1%;
|
|
77
|
+
--warning-foreground: 222.2 47.4% 11.2%;
|
|
78
|
+
|
|
79
|
+
--info: 199.4 95.5% 53.8%;
|
|
80
|
+
--info-foreground: 222.2 47.4% 11.2%;
|
|
81
|
+
|
|
82
|
+
--border: 217.2 32.6% 17.5%;
|
|
83
|
+
--input: 217.2 32.6% 17.5%;
|
|
84
|
+
--ring: 212.7 26.8% 83.9%;
|
|
85
|
+
}
|
|
86
|
+
}
|