@syncular/ui 0.0.4-25 → 0.0.4-32
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/console/api-keys-table.js +1 -1
- package/dist/console/api-keys-table.js.map +1 -1
- package/dist/console/danger-action-card.d.ts.map +1 -1
- package/dist/console/danger-action-card.js +1 -1
- package/dist/console/danger-action-card.js.map +1 -1
- package/dist/console/empty-state.js +1 -1
- package/dist/console/empty-state.js.map +1 -1
- package/dist/console/fleet-table.d.ts +14 -0
- package/dist/console/fleet-table.d.ts.map +1 -0
- package/dist/console/fleet-table.js +46 -0
- package/dist/console/fleet-table.js.map +1 -0
- package/dist/console/handlers-table.js +1 -1
- package/dist/console/handlers-table.js.map +1 -1
- package/dist/console/index.d.ts +1 -0
- package/dist/console/index.d.ts.map +1 -1
- package/dist/console/index.js +1 -0
- package/dist/console/index.js.map +1 -1
- package/dist/console/panel-shell.d.ts.map +1 -1
- package/dist/console/panel-shell.js +1 -1
- package/dist/console/panel-shell.js.map +1 -1
- package/dist/console/section-card.d.ts.map +1 -1
- package/dist/console/section-card.js +1 -1
- package/dist/console/section-card.js.map +1 -1
- package/dist/primitives/dialog.js +1 -1
- package/dist/primitives/dialog.js.map +1 -1
- package/dist/primitives/index.d.ts +1 -0
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +1 -0
- package/dist/primitives/index.js.map +1 -1
- package/dist/primitives/typography.d.ts +27 -0
- package/dist/primitives/typography.d.ts.map +1 -0
- package/dist/primitives/typography.js +36 -0
- package/dist/primitives/typography.js.map +1 -0
- package/dist/styles.css +2805 -0
- package/package.json +9 -6
- package/src/console/api-keys-table.tsx +1 -1
- package/src/console/danger-action-card.tsx +6 -2
- package/src/console/empty-state.tsx +1 -1
- package/src/console/fleet-table.tsx +147 -0
- package/src/console/handlers-table.tsx +1 -1
- package/src/console/index.ts +1 -0
- package/src/console/panel-shell.tsx +8 -2
- package/src/console/section-card.tsx +8 -2
- package/src/primitives/dialog.tsx +1 -1
- package/src/primitives/index.ts +1 -0
- package/src/primitives/typography.tsx +88 -0
- package/src/styles/styles.css +20 -16
- package/src/styles/tokens.css +94 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncular/ui",
|
|
3
|
-
"version": "0.0.4-
|
|
3
|
+
"version": "0.0.4-32",
|
|
4
4
|
"description": "Reusable Syncular UI components and styles",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Benjamin Kniffler",
|
|
@@ -81,7 +81,8 @@
|
|
|
81
81
|
"default": "./dist/navigation/index.js"
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
|
-
"./styles.css": "./
|
|
84
|
+
"./styles.css": "./dist/styles.css",
|
|
85
|
+
"./styles.source.css": "./src/styles/styles.css",
|
|
85
86
|
"./styles/tokens.css": "./src/styles/tokens.css",
|
|
86
87
|
"./package.json": "./package.json"
|
|
87
88
|
},
|
|
@@ -91,7 +92,8 @@
|
|
|
91
92
|
],
|
|
92
93
|
"scripts": {
|
|
93
94
|
"tsgo": "tsgo --noEmit",
|
|
94
|
-
"build": "
|
|
95
|
+
"build:css": "bunx @tailwindcss/cli -i src/styles/styles.css -o dist/styles.css",
|
|
96
|
+
"build": "tsgo && bun run build:css",
|
|
95
97
|
"release": "bunx syncular-publish"
|
|
96
98
|
},
|
|
97
99
|
"peerDependencies": {
|
|
@@ -102,13 +104,14 @@
|
|
|
102
104
|
"@base-ui/react": "^1.2.0",
|
|
103
105
|
"class-variance-authority": "^0.7.1",
|
|
104
106
|
"clsx": "^2.1.1",
|
|
105
|
-
"lucide-react": "^0.
|
|
107
|
+
"lucide-react": "^0.575.0",
|
|
106
108
|
"recharts": "^3.7.0",
|
|
107
|
-
"tailwind-merge": "^3.
|
|
108
|
-
"tailwindcss": "^4.
|
|
109
|
+
"tailwind-merge": "^3.5.0",
|
|
110
|
+
"tailwindcss": "^4.2.0"
|
|
109
111
|
},
|
|
110
112
|
"devDependencies": {
|
|
111
113
|
"@syncular/config": "0.0.0",
|
|
114
|
+
"@tailwindcss/cli": "^4.2.0",
|
|
112
115
|
"@types/react": "^19.2.14"
|
|
113
116
|
}
|
|
114
117
|
}
|
|
@@ -56,7 +56,7 @@ const ApiKeysTable = forwardRef<HTMLDivElement, ApiKeysTableProps>(
|
|
|
56
56
|
{/* Rows */}
|
|
57
57
|
{keys.map((k, i) => (
|
|
58
58
|
<div
|
|
59
|
-
key={k.name}
|
|
59
|
+
key={`${k.name}:${k.prefix}:${i}`}
|
|
60
60
|
className={cn(
|
|
61
61
|
'font-mono text-[11px] leading-7 px-4 flex items-center gap-4 hover:bg-white/[0.015] transition-colors cursor-default',
|
|
62
62
|
i < keys.length - 1 && 'border-b border-[#141414]'
|
|
@@ -24,9 +24,13 @@ export function DangerActionCard({
|
|
|
24
24
|
return (
|
|
25
25
|
<Card className={cn('border-offline/20', className)}>
|
|
26
26
|
<CardContent className="flex flex-col gap-3">
|
|
27
|
-
<h3 className="
|
|
27
|
+
<h3 className="font-mono text-[10px] text-offline uppercase tracking-widest">
|
|
28
|
+
{title}
|
|
29
|
+
</h3>
|
|
28
30
|
{description ? (
|
|
29
|
-
<p className="text-
|
|
31
|
+
<p className="font-mono text-[10px] text-neutral-500">
|
|
32
|
+
{description}
|
|
33
|
+
</p>
|
|
30
34
|
) : null}
|
|
31
35
|
{stats ? <div>{stats}</div> : null}
|
|
32
36
|
{onAction ? (
|
|
@@ -24,7 +24,7 @@ export function EmptyState({
|
|
|
24
24
|
)}
|
|
25
25
|
>
|
|
26
26
|
{icon ? <div className="text-neutral-500">{icon}</div> : null}
|
|
27
|
-
<p className="text-
|
|
27
|
+
<p className="font-mono text-[10px] text-neutral-500">{message}</p>
|
|
28
28
|
{action ? <div>{action}</div> : null}
|
|
29
29
|
</div>
|
|
30
30
|
);
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { type ComponentPropsWithoutRef, forwardRef } from 'react';
|
|
4
|
+
import { cn } from '../lib/cn';
|
|
5
|
+
import type { SyncClientNode } from '../lib/types';
|
|
6
|
+
import { Badge } from '../primitives/badge';
|
|
7
|
+
import {
|
|
8
|
+
Table,
|
|
9
|
+
TableBody,
|
|
10
|
+
TableCell,
|
|
11
|
+
TableHead,
|
|
12
|
+
TableHeader,
|
|
13
|
+
TableRow,
|
|
14
|
+
} from '../primitives/table';
|
|
15
|
+
|
|
16
|
+
export type FleetTableProps = ComponentPropsWithoutRef<'div'> & {
|
|
17
|
+
clients: SyncClientNode[];
|
|
18
|
+
headSeq: number;
|
|
19
|
+
onEvict?: (clientId: string) => void;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function getLagColor(lag: number) {
|
|
23
|
+
if (lag === 0) return '#22c55e';
|
|
24
|
+
if (lag < 10) return '#f59e0b';
|
|
25
|
+
if (lag < 50) return '#f97316';
|
|
26
|
+
return '#ef4444';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const statusBadgeVariant = {
|
|
30
|
+
online: 'healthy',
|
|
31
|
+
syncing: 'syncing',
|
|
32
|
+
offline: 'offline',
|
|
33
|
+
} as const;
|
|
34
|
+
|
|
35
|
+
const FleetTable = forwardRef<HTMLDivElement, FleetTableProps>(
|
|
36
|
+
({ className, clients, headSeq, onEvict, ...props }, ref) => {
|
|
37
|
+
return (
|
|
38
|
+
<div ref={ref} className={cn('w-full', className)} {...props}>
|
|
39
|
+
<Table>
|
|
40
|
+
<TableHeader>
|
|
41
|
+
<TableRow>
|
|
42
|
+
<TableHead>Client</TableHead>
|
|
43
|
+
<TableHead>Status</TableHead>
|
|
44
|
+
<TableHead>Type</TableHead>
|
|
45
|
+
<TableHead>Cursor</TableHead>
|
|
46
|
+
<TableHead>Lag</TableHead>
|
|
47
|
+
<TableHead>Dialect</TableHead>
|
|
48
|
+
<TableHead>Mode</TableHead>
|
|
49
|
+
{onEvict && <TableHead>Actions</TableHead>}
|
|
50
|
+
</TableRow>
|
|
51
|
+
</TableHeader>
|
|
52
|
+
<TableBody>
|
|
53
|
+
{clients.map((client) => {
|
|
54
|
+
const lag = Math.max(0, headSeq - client.cursor);
|
|
55
|
+
const pct =
|
|
56
|
+
headSeq > 0
|
|
57
|
+
? Math.min(100, (client.cursor / headSeq) * 100)
|
|
58
|
+
: 100;
|
|
59
|
+
const lagColor = getLagColor(lag);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<TableRow key={client.id}>
|
|
63
|
+
<TableCell>
|
|
64
|
+
<div className="flex items-center gap-2">
|
|
65
|
+
<span
|
|
66
|
+
className="w-1.5 h-1.5 rounded-full flex-shrink-0"
|
|
67
|
+
style={{
|
|
68
|
+
background: lagColor,
|
|
69
|
+
boxShadow: `0 0 4px ${lagColor}`,
|
|
70
|
+
}}
|
|
71
|
+
/>
|
|
72
|
+
<span
|
|
73
|
+
className="font-mono text-[11px] text-white truncate"
|
|
74
|
+
title={client.id}
|
|
75
|
+
>
|
|
76
|
+
{client.id.length > 18
|
|
77
|
+
? `${client.id.substring(0, 18)}\u2026`
|
|
78
|
+
: client.id}
|
|
79
|
+
</span>
|
|
80
|
+
</div>
|
|
81
|
+
</TableCell>
|
|
82
|
+
<TableCell>
|
|
83
|
+
<Badge variant={statusBadgeVariant[client.status]}>
|
|
84
|
+
{client.status}
|
|
85
|
+
</Badge>
|
|
86
|
+
</TableCell>
|
|
87
|
+
<TableCell>
|
|
88
|
+
<span className="font-mono text-[10px] text-neutral-400">
|
|
89
|
+
{client.type}
|
|
90
|
+
</span>
|
|
91
|
+
</TableCell>
|
|
92
|
+
<TableCell>
|
|
93
|
+
<span className="font-mono text-[11px] text-white font-medium">
|
|
94
|
+
#{client.cursor.toLocaleString()}
|
|
95
|
+
</span>
|
|
96
|
+
</TableCell>
|
|
97
|
+
<TableCell>
|
|
98
|
+
<div className="flex items-center gap-2">
|
|
99
|
+
<div className="w-[60px] h-[3px] rounded-full bg-surface overflow-hidden">
|
|
100
|
+
<div
|
|
101
|
+
className="h-full rounded-full transition-all"
|
|
102
|
+
style={{ width: `${pct}%`, background: lagColor }}
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
<span
|
|
106
|
+
className="font-mono text-[10px] font-medium"
|
|
107
|
+
style={{ color: lagColor }}
|
|
108
|
+
>
|
|
109
|
+
{lag === 0 ? '0' : `${lag}`}
|
|
110
|
+
</span>
|
|
111
|
+
</div>
|
|
112
|
+
</TableCell>
|
|
113
|
+
<TableCell>
|
|
114
|
+
<span className="font-mono text-[10px] text-neutral-400">
|
|
115
|
+
{client.dialect}
|
|
116
|
+
</span>
|
|
117
|
+
</TableCell>
|
|
118
|
+
<TableCell>
|
|
119
|
+
<Badge
|
|
120
|
+
variant={client.mode === 'realtime' ? 'flow' : 'ghost'}
|
|
121
|
+
>
|
|
122
|
+
{client.mode}
|
|
123
|
+
</Badge>
|
|
124
|
+
</TableCell>
|
|
125
|
+
{onEvict && (
|
|
126
|
+
<TableCell>
|
|
127
|
+
<button
|
|
128
|
+
type="button"
|
|
129
|
+
onClick={() => onEvict(client.id)}
|
|
130
|
+
className="inline-flex items-center gap-1 rounded-md font-mono text-[9px] px-2 py-1 border border-transparent text-neutral-600 hover:border-offline/50 hover:text-offline hover:bg-offline/[0.06] cursor-pointer transition-all opacity-0 group-hover:opacity-100"
|
|
131
|
+
>
|
|
132
|
+
evict
|
|
133
|
+
</button>
|
|
134
|
+
</TableCell>
|
|
135
|
+
)}
|
|
136
|
+
</TableRow>
|
|
137
|
+
);
|
|
138
|
+
})}
|
|
139
|
+
</TableBody>
|
|
140
|
+
</Table>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
FleetTable.displayName = 'FleetTable';
|
|
146
|
+
|
|
147
|
+
export { FleetTable };
|
|
@@ -46,7 +46,7 @@ const HandlersTable = forwardRef<HTMLDivElement, HandlersTableProps>(
|
|
|
46
46
|
{/* Rows */}
|
|
47
47
|
{handlers.map((h, i) => (
|
|
48
48
|
<div
|
|
49
|
-
key={h.table}
|
|
49
|
+
key={`${h.table}:${i}`}
|
|
50
50
|
className={cn(
|
|
51
51
|
'font-mono text-[11px] leading-7 px-4 flex items-center gap-4 hover:bg-white/[0.015] transition-colors cursor-default',
|
|
52
52
|
i < handlers.length - 1 && 'border-b border-[#141414]'
|
package/src/console/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from './danger-action-card';
|
|
|
9
9
|
export * from './empty-state';
|
|
10
10
|
export * from './filter-bar';
|
|
11
11
|
export * from './fleet-card';
|
|
12
|
+
export * from './fleet-table';
|
|
12
13
|
export * from './handlers-table';
|
|
13
14
|
export * from './kpi-card';
|
|
14
15
|
export * from './kpi-strip';
|
|
@@ -26,9 +26,15 @@ export function PanelShell({
|
|
|
26
26
|
{title || actions ? (
|
|
27
27
|
<div className="flex items-start justify-between px-4 pt-4">
|
|
28
28
|
<div>
|
|
29
|
-
{title ?
|
|
29
|
+
{title ? (
|
|
30
|
+
<h3 className="font-mono text-[10px] text-neutral-500 uppercase tracking-widest">
|
|
31
|
+
{title}
|
|
32
|
+
</h3>
|
|
33
|
+
) : null}
|
|
30
34
|
{description ? (
|
|
31
|
-
<p className="mt-1 text-
|
|
35
|
+
<p className="mt-1 font-mono text-[10px] text-neutral-500">
|
|
36
|
+
{description}
|
|
37
|
+
</p>
|
|
32
38
|
) : null}
|
|
33
39
|
</div>
|
|
34
40
|
{actions ? (
|
|
@@ -25,9 +25,15 @@ export function SectionCard({
|
|
|
25
25
|
{title || actions ? (
|
|
26
26
|
<div className="flex items-start justify-between px-4 pt-4">
|
|
27
27
|
<div>
|
|
28
|
-
{title ?
|
|
28
|
+
{title ? (
|
|
29
|
+
<h3 className="font-mono text-[10px] text-neutral-500 uppercase tracking-widest">
|
|
30
|
+
{title}
|
|
31
|
+
</h3>
|
|
32
|
+
) : null}
|
|
29
33
|
{description ? (
|
|
30
|
-
<p className="mt-1 text-
|
|
34
|
+
<p className="mt-1 font-mono text-[10px] text-neutral-500">
|
|
35
|
+
{description}
|
|
36
|
+
</p>
|
|
31
37
|
) : null}
|
|
32
38
|
</div>
|
|
33
39
|
{actions ? (
|
|
@@ -94,7 +94,7 @@ const DialogDescription = forwardRef<
|
|
|
94
94
|
>(({ className, ...props }, ref) => (
|
|
95
95
|
<BaseDialog.Description
|
|
96
96
|
ref={ref}
|
|
97
|
-
className={cn('text-
|
|
97
|
+
className={cn('font-mono text-[10px] text-neutral-500', className)}
|
|
98
98
|
{...props}
|
|
99
99
|
/>
|
|
100
100
|
));
|
package/src/primitives/index.ts
CHANGED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { type ComponentPropsWithoutRef, forwardRef } from 'react';
|
|
4
|
+
import { cn } from '../lib/cn';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Dialog/panel body text — primary weight.
|
|
8
|
+
* `font-mono text-[11px] text-neutral-300`
|
|
9
|
+
*/
|
|
10
|
+
const Text = forwardRef<HTMLParagraphElement, ComponentPropsWithoutRef<'p'>>(
|
|
11
|
+
({ className, ...props }, ref) => (
|
|
12
|
+
<p
|
|
13
|
+
ref={ref}
|
|
14
|
+
className={cn('font-mono text-[11px] text-neutral-300', className)}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
)
|
|
18
|
+
);
|
|
19
|
+
Text.displayName = 'Text';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Secondary / meta text — smaller, muted.
|
|
23
|
+
* `font-mono text-[10px] text-neutral-500`
|
|
24
|
+
*/
|
|
25
|
+
const TextMuted = forwardRef<
|
|
26
|
+
HTMLParagraphElement,
|
|
27
|
+
ComponentPropsWithoutRef<'p'>
|
|
28
|
+
>(({ className, ...props }, ref) => (
|
|
29
|
+
<p
|
|
30
|
+
ref={ref}
|
|
31
|
+
className={cn('font-mono text-[10px] text-neutral-500', className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
));
|
|
35
|
+
TextMuted.displayName = 'TextMuted';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Inline code / monospace value.
|
|
39
|
+
* `font-mono text-[11px] text-white`
|
|
40
|
+
*/
|
|
41
|
+
const TextCode = forwardRef<HTMLElement, ComponentPropsWithoutRef<'code'>>(
|
|
42
|
+
({ className, ...props }, ref) => (
|
|
43
|
+
<code
|
|
44
|
+
ref={ref}
|
|
45
|
+
className={cn('font-mono text-[11px] text-white', className)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
TextCode.displayName = 'TextCode';
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Uppercase monospace label — section headers, code block labels.
|
|
54
|
+
* `font-mono text-[9px] uppercase tracking-wider text-neutral-500`
|
|
55
|
+
*/
|
|
56
|
+
const TextLabel = forwardRef<HTMLSpanElement, ComponentPropsWithoutRef<'span'>>(
|
|
57
|
+
({ className, ...props }, ref) => (
|
|
58
|
+
<span
|
|
59
|
+
ref={ref}
|
|
60
|
+
className={cn(
|
|
61
|
+
'font-mono text-[9px] uppercase tracking-wider text-neutral-500',
|
|
62
|
+
className
|
|
63
|
+
)}
|
|
64
|
+
{...props}
|
|
65
|
+
/>
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
TextLabel.displayName = 'TextLabel';
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Pre-formatted code block.
|
|
72
|
+
* `font-mono text-[11px] text-neutral-300 p-3 rounded border border-border bg-panel-alt overflow-x-auto`
|
|
73
|
+
*/
|
|
74
|
+
const CodeBlock = forwardRef<HTMLPreElement, ComponentPropsWithoutRef<'pre'>>(
|
|
75
|
+
({ className, ...props }, ref) => (
|
|
76
|
+
<pre
|
|
77
|
+
ref={ref}
|
|
78
|
+
className={cn(
|
|
79
|
+
'font-mono text-[11px] text-neutral-300 p-3 rounded border border-border bg-panel-alt overflow-x-auto',
|
|
80
|
+
className
|
|
81
|
+
)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
CodeBlock.displayName = 'CodeBlock';
|
|
87
|
+
|
|
88
|
+
export { Text, TextMuted, TextCode, TextLabel, CodeBlock };
|
package/src/styles/styles.css
CHANGED
|
@@ -1,29 +1,33 @@
|
|
|
1
|
-
@import 'tailwindcss';
|
|
1
|
+
@import 'tailwindcss' source(none);
|
|
2
2
|
@import './tokens.css';
|
|
3
3
|
|
|
4
|
+
/* Explicitly scan UI component source files for Tailwind class usage */
|
|
5
|
+
@source "..";
|
|
6
|
+
|
|
4
7
|
/* ── Base ── */
|
|
5
|
-
|
|
6
|
-
background: var(--color-background);
|
|
7
|
-
color: var(--color-foreground);
|
|
8
|
-
font-family: var(--font-display), ui-sans-serif, system-ui,
|
|
8
|
+
:where(.syncular-console-root, .syncular-ui-root) {
|
|
9
|
+
background: var(--syncular-color-background);
|
|
10
|
+
color: var(--syncular-color-foreground);
|
|
11
|
+
font-family: var(--syncular-font-display), ui-sans-serif, system-ui,
|
|
12
|
+
sans-serif;
|
|
9
13
|
margin: 0;
|
|
10
14
|
-webkit-font-smoothing: antialiased;
|
|
11
15
|
-moz-osx-font-smoothing: grayscale;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
|
-
.font-mono {
|
|
15
|
-
font-family: var(--font-mono), ui-monospace, monospace;
|
|
18
|
+
:where(.syncular-console-root, .syncular-ui-root) .font-mono {
|
|
19
|
+
font-family: var(--syncular-font-mono), ui-monospace, monospace;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
/* ── Scrollbar ── */
|
|
19
|
-
::-webkit-scrollbar {
|
|
23
|
+
:where(.syncular-console-root, .syncular-ui-root) ::-webkit-scrollbar {
|
|
20
24
|
width: 3px;
|
|
21
25
|
height: 3px;
|
|
22
26
|
}
|
|
23
|
-
::-webkit-scrollbar-track {
|
|
27
|
+
:where(.syncular-console-root, .syncular-ui-root) ::-webkit-scrollbar-track {
|
|
24
28
|
background: transparent;
|
|
25
29
|
}
|
|
26
|
-
::-webkit-scrollbar-thumb {
|
|
30
|
+
:where(.syncular-console-root, .syncular-ui-root) ::-webkit-scrollbar-thumb {
|
|
27
31
|
background: #333;
|
|
28
32
|
border-radius: 2px;
|
|
29
33
|
}
|
|
@@ -112,16 +116,16 @@ body {
|
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
118
|
|
|
115
|
-
.line-active {
|
|
119
|
+
:where(.syncular-console-root, .syncular-ui-root) .line-active {
|
|
116
120
|
stroke-dasharray: 4 2;
|
|
117
121
|
animation: dashFlow 1s linear infinite;
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
.stream-entry {
|
|
124
|
+
:where(.syncular-console-root, .syncular-ui-root) .stream-entry {
|
|
121
125
|
animation: streamSlide 0.35s ease-out;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
|
-
.dot-pulse {
|
|
128
|
+
:where(.syncular-console-root, .syncular-ui-root) .dot-pulse {
|
|
125
129
|
animation: dotPulse 1.4s ease-in-out infinite;
|
|
126
130
|
}
|
|
127
131
|
|
|
@@ -137,7 +141,7 @@ body {
|
|
|
137
141
|
}
|
|
138
142
|
}
|
|
139
143
|
|
|
140
|
-
.flow-arrow {
|
|
144
|
+
:where(.syncular-console-root, .syncular-ui-root) .flow-arrow {
|
|
141
145
|
animation: flowPulse 2s ease-in-out infinite;
|
|
142
146
|
}
|
|
143
147
|
|
|
@@ -152,7 +156,7 @@ body {
|
|
|
152
156
|
}
|
|
153
157
|
}
|
|
154
158
|
|
|
155
|
-
.dot-grid {
|
|
159
|
+
:where(.syncular-console-root, .syncular-ui-root) .dot-grid {
|
|
156
160
|
background-image: radial-gradient(
|
|
157
161
|
circle at 1px 1px,
|
|
158
162
|
#1a1a1a 1px,
|
|
@@ -161,7 +165,7 @@ body {
|
|
|
161
165
|
background-size: 24px 24px;
|
|
162
166
|
}
|
|
163
167
|
|
|
164
|
-
.scan-line {
|
|
168
|
+
:where(.syncular-console-root, .syncular-ui-root) .scan-line {
|
|
165
169
|
position: absolute;
|
|
166
170
|
left: 0;
|
|
167
171
|
right: 0;
|
package/src/styles/tokens.css
CHANGED
|
@@ -1,47 +1,110 @@
|
|
|
1
|
-
@theme {
|
|
1
|
+
@theme inline {
|
|
2
|
+
--color-background: var(--syncular-color-background);
|
|
3
|
+
--color-surface: var(--syncular-color-surface);
|
|
4
|
+
--color-panel: var(--syncular-color-panel);
|
|
5
|
+
--color-panel-alt: var(--syncular-color-panel-alt);
|
|
6
|
+
--color-border: var(--syncular-color-border);
|
|
7
|
+
--color-border-bright: var(--syncular-color-border-bright);
|
|
8
|
+
|
|
9
|
+
--color-healthy: var(--syncular-color-healthy);
|
|
10
|
+
--color-syncing: var(--syncular-color-syncing);
|
|
11
|
+
--color-offline: var(--syncular-color-offline);
|
|
12
|
+
|
|
13
|
+
--color-flow: var(--syncular-color-flow);
|
|
14
|
+
--color-relay: var(--syncular-color-relay);
|
|
15
|
+
--color-encrypt: var(--syncular-color-encrypt);
|
|
16
|
+
|
|
17
|
+
--color-foreground: var(--syncular-color-foreground);
|
|
18
|
+
--color-foreground-muted: var(--syncular-color-foreground-muted);
|
|
19
|
+
|
|
20
|
+
--color-primary: var(--syncular-color-primary);
|
|
21
|
+
--color-destructive: var(--syncular-color-destructive);
|
|
22
|
+
--color-secondary: var(--syncular-color-secondary);
|
|
23
|
+
|
|
24
|
+
--font-display: var(--syncular-font-display);
|
|
25
|
+
--font-mono: var(--syncular-font-mono);
|
|
26
|
+
|
|
27
|
+
--radius-sm: var(--syncular-radius-sm);
|
|
28
|
+
--radius-md: var(--syncular-radius-md);
|
|
29
|
+
--radius-lg: var(--syncular-radius-lg);
|
|
30
|
+
--radius-xl: var(--syncular-radius-xl);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:where(.syncular-console-root, .syncular-ui-root) {
|
|
2
34
|
/* ── Surface ── */
|
|
3
|
-
--color-background: #0c0c0c;
|
|
4
|
-
--color-surface: #0c0c0c;
|
|
5
|
-
--color-panel: #111111;
|
|
6
|
-
--color-panel-alt: #0e0e0e;
|
|
7
|
-
--color-border: #1e1e1e;
|
|
8
|
-
--color-border-bright: #2a2a2a;
|
|
35
|
+
--syncular-color-background: #0c0c0c;
|
|
36
|
+
--syncular-color-surface: #0c0c0c;
|
|
37
|
+
--syncular-color-panel: #111111;
|
|
38
|
+
--syncular-color-panel-alt: #0e0e0e;
|
|
39
|
+
--syncular-color-border: #1e1e1e;
|
|
40
|
+
--syncular-color-border-bright: #2a2a2a;
|
|
9
41
|
|
|
10
42
|
/* ── Status ── */
|
|
11
|
-
--color-healthy: #22c55e;
|
|
12
|
-
--color-syncing: #f59e0b;
|
|
13
|
-
--color-offline: #ef4444;
|
|
43
|
+
--syncular-color-healthy: #22c55e;
|
|
44
|
+
--syncular-color-syncing: #f59e0b;
|
|
45
|
+
--syncular-color-offline: #ef4444;
|
|
14
46
|
|
|
15
47
|
/* ── Flow ── */
|
|
16
|
-
--color-flow: #3b82f6;
|
|
17
|
-
--color-relay: #8b5cf6;
|
|
18
|
-
--color-encrypt: #f472b6;
|
|
48
|
+
--syncular-color-flow: #3b82f6;
|
|
49
|
+
--syncular-color-relay: #8b5cf6;
|
|
50
|
+
--syncular-color-encrypt: #f472b6;
|
|
19
51
|
|
|
20
52
|
/* ── Text ── */
|
|
21
|
-
--color-foreground: #e5e5e5;
|
|
22
|
-
--color-foreground-muted: #737373;
|
|
53
|
+
--syncular-color-foreground: #e5e5e5;
|
|
54
|
+
--syncular-color-foreground-muted: #737373;
|
|
23
55
|
|
|
24
56
|
/* ── Semantic ── */
|
|
25
|
-
--color-primary: #22c55e;
|
|
26
|
-
--color-destructive: #ef4444;
|
|
27
|
-
--color-secondary: #1e1e1e;
|
|
57
|
+
--syncular-color-primary: #22c55e;
|
|
58
|
+
--syncular-color-destructive: #ef4444;
|
|
59
|
+
--syncular-color-secondary: #1e1e1e;
|
|
28
60
|
|
|
29
61
|
/* ── Fonts ── */
|
|
30
|
-
--font-display: 'Inter Tight', system-ui, sans-serif;
|
|
31
|
-
--font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo,
|
|
32
|
-
Consolas, 'Liberation Mono', 'Courier New', monospace;
|
|
62
|
+
--syncular-font-display: 'Inter Tight', system-ui, sans-serif;
|
|
63
|
+
--syncular-font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo,
|
|
64
|
+
Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
|
|
33
65
|
|
|
34
66
|
/* ── Radii ── */
|
|
35
|
-
--radius-sm: 4px;
|
|
36
|
-
--radius-md: 6px;
|
|
37
|
-
--radius-lg: 8px;
|
|
38
|
-
--radius-xl: 10px;
|
|
67
|
+
--syncular-radius-sm: 4px;
|
|
68
|
+
--syncular-radius-md: 6px;
|
|
69
|
+
--syncular-radius-lg: 8px;
|
|
70
|
+
--syncular-radius-xl: 10px;
|
|
39
71
|
|
|
40
72
|
/* ── Glows ── */
|
|
41
|
-
--
|
|
42
|
-
--
|
|
43
|
-
--
|
|
44
|
-
--
|
|
45
|
-
--
|
|
46
|
-
--
|
|
73
|
+
--syncular-glow-healthy: 0 0 6px #22c55e;
|
|
74
|
+
--syncular-glow-syncing: 0 0 6px #f59e0b;
|
|
75
|
+
--syncular-glow-offline: 0 0 6px #ef4444;
|
|
76
|
+
--syncular-glow-flow: 0 0 6px #3b82f6;
|
|
77
|
+
--syncular-glow-relay: 0 0 6px #8b5cf6;
|
|
78
|
+
--syncular-glow-encrypt: 0 0 6px #f472b6;
|
|
79
|
+
|
|
80
|
+
/* Backward token aliases used by chart primitives */
|
|
81
|
+
--color-background: var(--syncular-color-background);
|
|
82
|
+
--color-surface: var(--syncular-color-surface);
|
|
83
|
+
--color-panel: var(--syncular-color-panel);
|
|
84
|
+
--color-panel-alt: var(--syncular-color-panel-alt);
|
|
85
|
+
--color-border: var(--syncular-color-border);
|
|
86
|
+
--color-border-bright: var(--syncular-color-border-bright);
|
|
87
|
+
--color-healthy: var(--syncular-color-healthy);
|
|
88
|
+
--color-syncing: var(--syncular-color-syncing);
|
|
89
|
+
--color-offline: var(--syncular-color-offline);
|
|
90
|
+
--color-flow: var(--syncular-color-flow);
|
|
91
|
+
--color-relay: var(--syncular-color-relay);
|
|
92
|
+
--color-encrypt: var(--syncular-color-encrypt);
|
|
93
|
+
--color-foreground: var(--syncular-color-foreground);
|
|
94
|
+
--color-foreground-muted: var(--syncular-color-foreground-muted);
|
|
95
|
+
--color-primary: var(--syncular-color-primary);
|
|
96
|
+
--color-destructive: var(--syncular-color-destructive);
|
|
97
|
+
--color-secondary: var(--syncular-color-secondary);
|
|
98
|
+
--font-display: var(--syncular-font-display);
|
|
99
|
+
--font-mono: var(--syncular-font-mono);
|
|
100
|
+
--radius-sm: var(--syncular-radius-sm);
|
|
101
|
+
--radius-md: var(--syncular-radius-md);
|
|
102
|
+
--radius-lg: var(--syncular-radius-lg);
|
|
103
|
+
--radius-xl: var(--syncular-radius-xl);
|
|
104
|
+
--sync-glow-healthy: var(--syncular-glow-healthy);
|
|
105
|
+
--sync-glow-syncing: var(--syncular-glow-syncing);
|
|
106
|
+
--sync-glow-offline: var(--syncular-glow-offline);
|
|
107
|
+
--sync-glow-flow: var(--syncular-glow-flow);
|
|
108
|
+
--sync-glow-relay: var(--syncular-glow-relay);
|
|
109
|
+
--sync-glow-encrypt: var(--syncular-glow-encrypt);
|
|
47
110
|
}
|