UI: refresh design system with new color palette and icons (#1745)
- Replace orange accent (#f59f4a) with signature red (#ff4d4d) - Switch from IBM Plex/Unbounded/Work Sans to Inter/JetBrains Mono - Replace emoji icons with Lucide-style SVG icons throughout - Add comprehensive CSS design tokens (colors, borders, semantic states) - Update tool-display.json to use icon names instead of emoji - Rebuild control-ui dist bundle
This commit is contained in:
1
dist/control-ui/assets/index-08nzABV3.css
vendored
Normal file
1
dist/control-ui/assets/index-08nzABV3.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/control-ui/assets/index-BvhR9FCb.css
vendored
1
dist/control-ui/assets/index-BvhR9FCb.css
vendored
File diff suppressed because one or more lines are too long
3119
dist/control-ui/assets/index-DQcOTEYz.js
vendored
Normal file
3119
dist/control-ui/assets/index-DQcOTEYz.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/control-ui/assets/index-DQcOTEYz.js.map
vendored
Normal file
1
dist/control-ui/assets/index-DQcOTEYz.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3059
dist/control-ui/assets/index-DsXRcnEw.js
vendored
3059
dist/control-ui/assets/index-DsXRcnEw.js
vendored
File diff suppressed because one or more lines are too long
1
dist/control-ui/assets/index-DsXRcnEw.js.map
vendored
1
dist/control-ui/assets/index-DsXRcnEw.js.map
vendored
File diff suppressed because one or more lines are too long
3047
dist/control-ui/assets/index-bYQnHP3a.js
vendored
3047
dist/control-ui/assets/index-bYQnHP3a.js
vendored
File diff suppressed because one or more lines are too long
1
dist/control-ui/assets/index-bYQnHP3a.js.map
vendored
1
dist/control-ui/assets/index-bYQnHP3a.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/control-ui/index.html
vendored
4
dist/control-ui/index.html
vendored
@@ -6,8 +6,8 @@
|
||||
<title>Clawdbot Control</title>
|
||||
<meta name="color-scheme" content="dark light" />
|
||||
<link rel="icon" href="./favicon.ico" sizes="any" />
|
||||
<script type="module" crossorigin src="./assets/index-DsXRcnEw.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-BvhR9FCb.css">
|
||||
<script type="module" crossorigin src="./assets/index-DQcOTEYz.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-08nzABV3.css">
|
||||
</head>
|
||||
<body>
|
||||
<clawdbot-app></clawdbot-app>
|
||||
|
||||
@@ -1,60 +1,172 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=Unbounded:wght@400;500;600&family=Work+Sans:wght@400;500;600;700&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap");
|
||||
|
||||
:root {
|
||||
--bg: #0a0f14;
|
||||
--bg-accent: #111826;
|
||||
--bg-grad-1: #162031;
|
||||
--bg-grad-2: #1f2a22;
|
||||
--bg-overlay: rgba(255, 255, 255, 0.05);
|
||||
--bg-glow: rgba(245, 159, 74, 0.12);
|
||||
--panel: rgba(14, 20, 30, 0.88);
|
||||
--panel-strong: rgba(18, 26, 38, 0.96);
|
||||
--chrome: rgba(9, 14, 20, 0.72);
|
||||
--chrome-strong: rgba(9, 14, 20, 0.86);
|
||||
--text: rgba(244, 246, 251, 0.96);
|
||||
--chat-text: rgba(231, 237, 244, 0.92);
|
||||
--muted: rgba(156, 169, 189, 0.72);
|
||||
--border: rgba(255, 255, 255, 0.09);
|
||||
--border-strong: rgba(255, 255, 255, 0.16);
|
||||
--accent: #f59f4a;
|
||||
--accent-2: #34c7b7;
|
||||
--ok: #2bd97f;
|
||||
--warn: #f2c94c;
|
||||
--danger: #ff6b6b;
|
||||
--focus: rgba(245, 159, 74, 0.35);
|
||||
--grid-line: rgba(255, 255, 255, 0.04);
|
||||
/* Background - Deep Navy Slate */
|
||||
--bg: #0c0d12;
|
||||
--bg-accent: #0d0e14;
|
||||
--bg-elevated: #181a21;
|
||||
--bg-hover: #252830;
|
||||
--bg-muted: #252830;
|
||||
|
||||
/* Card / Surface */
|
||||
--card: #13151c;
|
||||
--card-foreground: #f8fafc;
|
||||
--card-highlight: rgba(255, 255, 255, 0.04);
|
||||
--popover: #13151c;
|
||||
--popover-foreground: #f8fafc;
|
||||
|
||||
/* Panel */
|
||||
--panel: #0c0d12;
|
||||
--panel-strong: #181a21;
|
||||
--panel-hover: #252830;
|
||||
--chrome: rgba(12, 13, 18, 0.95);
|
||||
--chrome-strong: rgba(12, 13, 18, 0.98);
|
||||
|
||||
/* Text */
|
||||
--text: #f8fafc;
|
||||
--text-strong: #ffffff;
|
||||
--chat-text: #f8fafc;
|
||||
--muted: #94a3b8;
|
||||
--muted-strong: #64748b;
|
||||
--muted-foreground: #94a3b8;
|
||||
|
||||
/* Border */
|
||||
--border: #333842;
|
||||
--border-strong: #454d5c;
|
||||
--border-hover: #5a6373;
|
||||
--input: #333842;
|
||||
--ring: #ff4d4d;
|
||||
|
||||
/* Accent - The signature red */
|
||||
--accent: #ff4d4d;
|
||||
--accent-hover: #ff6666;
|
||||
--accent-muted: #ff4d4d;
|
||||
--accent-subtle: rgba(255, 77, 77, 0.12);
|
||||
--accent-foreground: #f8fafc;
|
||||
--primary: #ff4d4d;
|
||||
--primary-foreground: #ffffff;
|
||||
|
||||
/* Secondary */
|
||||
--secondary: #252830;
|
||||
--secondary-foreground: #f8fafc;
|
||||
--accent-2: #3b82f6;
|
||||
--accent-2-muted: rgba(59, 130, 246, 0.7);
|
||||
|
||||
/* Semantic */
|
||||
--ok: #22c55e;
|
||||
--ok-muted: rgba(34, 197, 94, 0.7);
|
||||
--ok-subtle: rgba(34, 197, 94, 0.1);
|
||||
--destructive: #ef4444;
|
||||
--destructive-foreground: #fafafa;
|
||||
--warn: #eab308;
|
||||
--warn-muted: rgba(234, 179, 8, 0.7);
|
||||
--warn-subtle: rgba(234, 179, 8, 0.1);
|
||||
--danger: #ef4444;
|
||||
--danger-muted: rgba(239, 68, 68, 0.7);
|
||||
--danger-subtle: rgba(239, 68, 68, 0.1);
|
||||
--info: #3b82f6;
|
||||
|
||||
/* Focus */
|
||||
--focus: rgba(255, 77, 77, 0.2);
|
||||
--focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--ring);
|
||||
|
||||
/* Grid */
|
||||
--grid-line: rgba(255, 255, 255, 0.03);
|
||||
|
||||
/* Theme transition */
|
||||
--theme-switch-x: 50%;
|
||||
--theme-switch-y: 50%;
|
||||
--mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
"Liberation Mono", "Courier New", monospace;
|
||||
--font-body: "Work Sans", system-ui, sans-serif;
|
||||
--font-display: "Unbounded", "Times New Roman", serif;
|
||||
|
||||
/* Typography */
|
||||
--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace;
|
||||
--font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
--font-display: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
|
||||
/* Shadows - minimal */
|
||||
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
||||
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
|
||||
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
||||
|
||||
/* Radii - shadcn uses smaller radii */
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 6px;
|
||||
--radius-lg: 8px;
|
||||
--radius-xl: 12px;
|
||||
--radius-full: 9999px;
|
||||
--radius: 6px;
|
||||
|
||||
/* Transitions */
|
||||
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--duration-fast: 150ms;
|
||||
--duration-normal: 200ms;
|
||||
--duration-slow: 300ms;
|
||||
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
/* Light theme */
|
||||
:root[data-theme="light"] {
|
||||
--bg: #f5f1ea;
|
||||
--bg-accent: #ffffff;
|
||||
--bg-grad-1: #f1e6d6;
|
||||
--bg-grad-2: #e5eef4;
|
||||
--bg-overlay: rgba(28, 32, 46, 0.05);
|
||||
--bg-glow: rgba(52, 199, 183, 0.14);
|
||||
--panel: rgba(255, 255, 255, 0.9);
|
||||
--panel-strong: rgba(255, 255, 255, 0.97);
|
||||
--chrome: rgba(255, 255, 255, 0.75);
|
||||
--chrome-strong: rgba(255, 255, 255, 0.88);
|
||||
--text: rgba(27, 36, 50, 0.98);
|
||||
--chat-text: rgba(36, 48, 66, 0.9);
|
||||
--muted: rgba(80, 94, 114, 0.7);
|
||||
--border: rgba(18, 24, 40, 0.12);
|
||||
--border-strong: rgba(18, 24, 40, 0.2);
|
||||
--accent: #e28a3f;
|
||||
--accent-2: #1ba99d;
|
||||
--ok: #1aa86c;
|
||||
--warn: #b3771c;
|
||||
--danger: #d44848;
|
||||
--focus: rgba(226, 138, 63, 0.35);
|
||||
--grid-line: rgba(18, 24, 40, 0.06);
|
||||
--bg: #f8f8f7;
|
||||
--bg-accent: #f3f2f0;
|
||||
--bg-elevated: #ffffff;
|
||||
--bg-hover: #eae8e6;
|
||||
--bg-muted: #eae8e6;
|
||||
--bg-content: #f0efed;
|
||||
|
||||
--card: #ffffff;
|
||||
--card-foreground: #1c1917;
|
||||
--card-highlight: rgba(0, 0, 0, 0.04);
|
||||
--popover: #ffffff;
|
||||
--popover-foreground: #1c1917;
|
||||
|
||||
--panel: #f8f8f7;
|
||||
--panel-strong: #f0efed;
|
||||
--panel-hover: #e5e3e1;
|
||||
--chrome: rgba(248, 248, 247, 0.95);
|
||||
--chrome-strong: rgba(248, 248, 247, 0.98);
|
||||
|
||||
--text: #44403c;
|
||||
--text-strong: #292524;
|
||||
--chat-text: #44403c;
|
||||
--muted: #5c5856;
|
||||
--muted-strong: #44403c;
|
||||
--muted-foreground: #5c5856;
|
||||
|
||||
--border: #e0dedc;
|
||||
--border-strong: #d6d3d1;
|
||||
--border-hover: #a8a5a0;
|
||||
--input: #e0dedc;
|
||||
|
||||
--accent: #b91c1c;
|
||||
--accent-hover: #dc2626;
|
||||
--accent-muted: #b91c1c;
|
||||
--accent-subtle: rgba(185, 28, 28, 0.18);
|
||||
--accent-foreground: #ffffff;
|
||||
--primary: #b91c1c;
|
||||
--primary-foreground: #ffffff;
|
||||
|
||||
--secondary: #eae8e6;
|
||||
--secondary-foreground: #44403c;
|
||||
|
||||
--ok: #15803d;
|
||||
--ok-muted: rgba(21, 128, 61, 0.75);
|
||||
--ok-subtle: rgba(21, 128, 61, 0.12);
|
||||
--destructive: #b91c1c;
|
||||
--destructive-foreground: #fafafa;
|
||||
--warn: #a16207;
|
||||
--warn-muted: rgba(161, 98, 7, 0.75);
|
||||
--warn-subtle: rgba(161, 98, 7, 0.12);
|
||||
--danger: #b91c1c;
|
||||
--danger-muted: rgba(185, 28, 28, 0.75);
|
||||
--danger-subtle: rgba(185, 28, 28, 0.12);
|
||||
--info: #1d4ed8;
|
||||
|
||||
--focus: rgba(185, 28, 28, 0.25);
|
||||
|
||||
--grid-line: rgba(0, 0, 0, 0.06);
|
||||
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
@@ -69,44 +181,21 @@ body {
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font: 15px/1.5 var(--font-body);
|
||||
background:
|
||||
radial-gradient(1200px 900px at 15% -10%, var(--bg-grad-1) 0%, transparent 55%)
|
||||
fixed,
|
||||
radial-gradient(900px 700px at 80% 10%, var(--bg-grad-2) 0%, transparent 60%)
|
||||
fixed,
|
||||
linear-gradient(160deg, var(--bg) 0%, var(--bg-accent) 100%) fixed;
|
||||
font: 400 14px/1.5 var(--font-body);
|
||||
letter-spacing: -0.011em;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background:
|
||||
linear-gradient(
|
||||
140deg,
|
||||
var(--bg-overlay) 0%,
|
||||
rgba(255, 255, 255, 0) 40%
|
||||
),
|
||||
radial-gradient(620px 420px at 75% 75%, var(--bg-glow), transparent 60%);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* Grid overlay removed for cleaner look */
|
||||
|
||||
/* Theme transition */
|
||||
@keyframes theme-circle-transition {
|
||||
0% {
|
||||
clip-path: circle(
|
||||
0% at var(--theme-switch-x, 50%) var(--theme-switch-y, 50%)
|
||||
);
|
||||
clip-path: circle(0% at var(--theme-switch-x, 50%) var(--theme-switch-y, 50%));
|
||||
}
|
||||
|
||||
100% {
|
||||
clip-path: circle(
|
||||
150% at var(--theme-switch-x, 50%) var(--theme-switch-y, 50%)
|
||||
);
|
||||
clip-path: circle(150% at var(--theme-switch-x, 50%) var(--theme-switch-y, 50%));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +212,7 @@ html.theme-transition::view-transition-old(theme) {
|
||||
html.theme-transition::view-transition-new(theme) {
|
||||
mix-blend-mode: normal;
|
||||
z-index: 2;
|
||||
animation: theme-circle-transition 0.45s ease-out forwards;
|
||||
animation: theme-circle-transition 0.4s var(--ease-out) forwards;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
@@ -141,7 +230,12 @@ clawdbot-app {
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
button,
|
||||
@@ -152,10 +246,35 @@ select {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--accent-subtle);
|
||||
color: var(--text-strong);
|
||||
}
|
||||
|
||||
/* Scrollbar styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--border);
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--border-strong);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes rise {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(6px);
|
||||
transform: translateY(4px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
@@ -163,13 +282,48 @@ select {
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scale-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dashboard-enter {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Focus visible styles */
|
||||
:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: var(--focus-ring);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
gap: 12px;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16px;
|
||||
margin-left: 16px;
|
||||
margin-left: 4px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
@@ -70,23 +70,23 @@
|
||||
}
|
||||
|
||||
.chat-avatar.user {
|
||||
background: rgba(245, 159, 74, 0.2);
|
||||
color: rgba(245, 159, 74, 1);
|
||||
background: var(--accent-subtle);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.chat-avatar.assistant {
|
||||
background: rgba(52, 199, 183, 0.2);
|
||||
color: rgba(52, 199, 183, 1);
|
||||
background: var(--secondary);
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.chat-avatar.other {
|
||||
background: rgba(150, 150, 150, 0.2);
|
||||
color: rgba(150, 150, 150, 1);
|
||||
background: var(--secondary);
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.chat-avatar.tool {
|
||||
background: rgba(134, 142, 150, 0.2);
|
||||
color: rgba(134, 142, 150, 1);
|
||||
background: var(--secondary);
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
/* Image avatar support */
|
||||
@@ -100,9 +100,9 @@ img.chat-avatar {
|
||||
.chat-bubble {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
border: 1px solid var(--border);
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
border-radius: 12px;
|
||||
border: 1px solid transparent;
|
||||
background: var(--card);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 10px 14px;
|
||||
box-shadow: none;
|
||||
transition: background 150ms ease-out, border-color 150ms ease-out;
|
||||
@@ -119,9 +119,9 @@ img.chat-avatar {
|
||||
top: 6px;
|
||||
right: 8px;
|
||||
border: 1px solid var(--border);
|
||||
background: rgba(0, 0, 0, 0.22);
|
||||
background: var(--bg);
|
||||
color: var(--muted);
|
||||
border-radius: 8px;
|
||||
border-radius: var(--radius-md);
|
||||
padding: 4px 6px;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
@@ -132,9 +132,40 @@ img.chat-avatar {
|
||||
}
|
||||
|
||||
.chat-copy-btn__icon {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
text-align: center;
|
||||
display: inline-flex;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chat-copy-btn__icon svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.chat-copy-btn__icon-copy,
|
||||
.chat-copy-btn__icon-check {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transition: opacity 150ms ease;
|
||||
}
|
||||
|
||||
.chat-copy-btn__icon-check {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.chat-copy-btn[data-copied="1"] .chat-copy-btn__icon-copy {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.chat-copy-btn[data-copied="1"] .chat-copy-btn__icon-check {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chat-bubble:hover .chat-copy-btn {
|
||||
@@ -143,7 +174,7 @@ img.chat-avatar {
|
||||
}
|
||||
|
||||
.chat-copy-btn:hover {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
.chat-copy-btn[data-copying="1"] {
|
||||
@@ -154,17 +185,17 @@ img.chat-avatar {
|
||||
.chat-copy-btn[data-error="1"] {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
border-color: rgba(255, 69, 58, 0.8);
|
||||
background: rgba(255, 69, 58, 0.18);
|
||||
color: rgba(255, 69, 58, 1);
|
||||
border-color: var(--danger-subtle);
|
||||
background: var(--danger-subtle);
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.chat-copy-btn[data-copied="1"] {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
border-color: rgba(52, 199, 183, 0.8);
|
||||
background: rgba(52, 199, 183, 0.18);
|
||||
color: rgba(52, 199, 183, 1);
|
||||
border-color: var(--ok-subtle);
|
||||
background: var(--ok-subtle);
|
||||
color: var(--ok);
|
||||
}
|
||||
|
||||
.chat-copy-btn:focus-visible {
|
||||
@@ -181,18 +212,29 @@ img.chat-avatar {
|
||||
}
|
||||
}
|
||||
|
||||
/* Light mode: restore borders */
|
||||
:root[data-theme="light"] .chat-bubble {
|
||||
border-color: var(--border);
|
||||
box-shadow: inset 0 1px 0 var(--card-highlight);
|
||||
}
|
||||
|
||||
.chat-bubble:hover {
|
||||
background: rgba(0, 0, 0, 0.18);
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
/* User bubbles have different styling */
|
||||
.chat-group.user .chat-bubble {
|
||||
background: rgba(245, 159, 74, 0.15);
|
||||
border-color: rgba(245, 159, 74, 0.3);
|
||||
background: var(--accent-subtle);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .chat-group.user .chat-bubble {
|
||||
border-color: rgba(234, 88, 12, 0.2);
|
||||
background: rgba(251, 146, 60, 0.12);
|
||||
}
|
||||
|
||||
.chat-group.user .chat-bubble:hover {
|
||||
background: rgba(245, 159, 74, 0.22);
|
||||
background: rgba(255, 77, 77, 0.15);
|
||||
}
|
||||
|
||||
/* Streaming animation */
|
||||
|
||||
@@ -52,8 +52,8 @@
|
||||
flex: 1 1 0; /* Grow, shrink, and use 0 base for proper scrolling */
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 12px;
|
||||
margin: 0 -12px;
|
||||
padding: 12px 4px;
|
||||
margin: 0 -4px;
|
||||
min-height: 0; /* Allow shrinking for flex scroll behavior */
|
||||
border-radius: 12px;
|
||||
background: transparent;
|
||||
@@ -87,23 +87,39 @@
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.chat-focus-exit svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
/* Chat compose - sticky at bottom */
|
||||
.chat-compose {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
align-items: stretch;
|
||||
gap: 12px;
|
||||
margin-top: auto; /* Push to bottom of flex container */
|
||||
padding: 16px 0 4px;
|
||||
padding: 12px 4px 4px;
|
||||
background: linear-gradient(to bottom, transparent, var(--bg) 20%);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .chat-compose {
|
||||
background: linear-gradient(to bottom, transparent, var(--bg-content) 20%);
|
||||
}
|
||||
|
||||
.chat-compose__field {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
/* Hide the "Message" label - keep textarea only */
|
||||
@@ -114,10 +130,11 @@
|
||||
/* Override .field textarea min-height (180px) from components.css */
|
||||
.chat-compose .chat-compose__field textarea {
|
||||
width: 100%;
|
||||
min-height: 36px;
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
max-height: 150px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 10px;
|
||||
padding: 9px 12px;
|
||||
border-radius: 8px;
|
||||
resize: vertical;
|
||||
white-space: pre-wrap;
|
||||
font-family: var(--font-body);
|
||||
@@ -134,13 +151,18 @@
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.chat-compose .chat-compose__actions .btn {
|
||||
padding: 8px 16px;
|
||||
padding: 0 16px;
|
||||
font-size: 13px;
|
||||
min-height: 36px;
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
max-height: 40px;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Chat controls - moved to content-header area, left aligned */
|
||||
@@ -194,20 +216,27 @@
|
||||
|
||||
/* Light theme icon button overrides */
|
||||
:root[data-theme="light"] .btn--icon {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-color: rgba(16, 24, 40, 0.2);
|
||||
background: #ffffff;
|
||||
border-color: var(--border);
|
||||
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
|
||||
color: rgba(16, 24, 40, 0.7);
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .btn--icon:hover {
|
||||
background: rgba(255, 255, 255, 1);
|
||||
border-color: rgba(16, 24, 40, 0.3);
|
||||
color: rgba(16, 24, 40, 0.9);
|
||||
background: #ffffff;
|
||||
border-color: var(--border-strong);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.btn--icon svg {
|
||||
display: block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.chat-controls__session select {
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .chat-thinking {
|
||||
border-color: rgba(16, 24, 40, 0.18);
|
||||
background: rgba(16, 24, 40, 0.03);
|
||||
border-color: rgba(16, 24, 40, 0.25);
|
||||
background: rgba(16, 24, 40, 0.04);
|
||||
}
|
||||
|
||||
.chat-text {
|
||||
@@ -75,9 +75,46 @@
|
||||
}
|
||||
|
||||
.chat-text :where(blockquote) {
|
||||
border-left: 3px solid var(--border);
|
||||
border-left: 3px solid var(--border-strong);
|
||||
padding-left: 12px;
|
||||
margin-left: 0;
|
||||
color: var(--muted);
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
padding: 8px 12px;
|
||||
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
||||
}
|
||||
|
||||
.chat-text :where(blockquote blockquote) {
|
||||
margin-top: 8px;
|
||||
border-left-color: var(--border-hover);
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.chat-text :where(blockquote blockquote blockquote) {
|
||||
border-left-color: var(--muted-strong);
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .chat-text :where(blockquote) {
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .chat-text :where(blockquote blockquote) {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .chat-text :where(blockquote blockquote blockquote) {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .chat-text :where(:not(pre) > code) {
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .chat-text :where(pre) {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.chat-text :where(hr) {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
margin-top: 8px;
|
||||
background: var(--card);
|
||||
box-shadow: inset 0 1px 0 var(--card-highlight);
|
||||
transition: border-color 150ms ease-out, background 150ms ease-out;
|
||||
/* Fixed max-height to ensure cards don't expand too much */
|
||||
max-height: 120px;
|
||||
@@ -11,8 +13,8 @@
|
||||
}
|
||||
|
||||
.chat-tool-card:hover {
|
||||
border-color: var(--accent);
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
border-color: var(--border-strong);
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
/* First tool card in a group - no top margin */
|
||||
@@ -50,33 +52,63 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.chat-tool-card__icon svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
/* "View >" action link */
|
||||
.chat-tool-card__action {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--accent);
|
||||
opacity: 0.8;
|
||||
transition: opacity 150ms ease-out;
|
||||
}
|
||||
|
||||
.chat-tool-card__action svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.chat-tool-card--clickable:hover .chat-tool-card__action {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Status indicator for completed/empty results */
|
||||
.chat-tool-card__status {
|
||||
font-size: 14px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: var(--ok);
|
||||
}
|
||||
|
||||
.chat-tool-card__status svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.chat-tool-card__status-text {
|
||||
font-size: 11px;
|
||||
margin-top: 4px;
|
||||
@@ -94,18 +126,18 @@
|
||||
color: var(--muted);
|
||||
margin-top: 8px;
|
||||
padding: 8px 10px;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
border-radius: 6px;
|
||||
background: var(--secondary);
|
||||
border-radius: var(--radius-md);
|
||||
white-space: pre-wrap;
|
||||
overflow: hidden;
|
||||
max-height: 44px;
|
||||
line-height: 1.4;
|
||||
border: 1px solid rgba(255, 255, 255, 0.04);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.chat-tool-card--clickable:hover .chat-tool-card__preview {
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
border-color: rgba(255, 255, 255, 0.08);
|
||||
background: var(--bg-hover);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
|
||||
/* Short inline output */
|
||||
@@ -114,8 +146,8 @@
|
||||
color: var(--text);
|
||||
margin-top: 6px;
|
||||
padding: 6px 8px;
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
border-radius: 4px;
|
||||
background: var(--secondary);
|
||||
border-radius: var(--radius-sm);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,14 @@
|
||||
/* ===========================================
|
||||
Shell Layout
|
||||
=========================================== */
|
||||
|
||||
.shell {
|
||||
--shell-pad: 16px;
|
||||
--shell-gap: 16px;
|
||||
--shell-nav-width: 220px;
|
||||
--shell-topbar-height: 56px;
|
||||
--shell-focus-duration: 220ms;
|
||||
--shell-focus-ease: cubic-bezier(0.2, 0.85, 0.25, 1);
|
||||
--shell-focus-duration: 200ms;
|
||||
--shell-focus-ease: var(--ease-out);
|
||||
height: 100vh;
|
||||
display: grid;
|
||||
grid-template-columns: var(--shell-nav-width) minmax(0, 1fr);
|
||||
@@ -13,7 +17,7 @@
|
||||
"topbar topbar"
|
||||
"nav content";
|
||||
gap: 0;
|
||||
animation: dashboard-enter 0.6s ease-out;
|
||||
animation: dashboard-enter 0.4s var(--ease-out);
|
||||
transition: grid-template-columns var(--shell-focus-duration) var(--shell-focus-ease);
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -61,6 +65,10 @@
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Topbar
|
||||
=========================================== */
|
||||
|
||||
.topbar {
|
||||
grid-area: topbar;
|
||||
position: sticky;
|
||||
@@ -73,8 +81,7 @@
|
||||
padding: 0 20px;
|
||||
height: var(--shell-topbar-height);
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--panel);
|
||||
backdrop-filter: blur(18px);
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.topbar-left {
|
||||
@@ -84,49 +91,83 @@
|
||||
}
|
||||
|
||||
.topbar .nav-collapse-toggle {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.topbar .nav-collapse-toggle__icon {
|
||||
font-size: 22px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.topbar .nav-collapse-toggle__icon svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Brand */
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.brand-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.brand-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.brand-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: 16px;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1.1;
|
||||
color: var(--text-strong);
|
||||
}
|
||||
|
||||
.brand-sub {
|
||||
font-size: 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: var(--muted);
|
||||
letter-spacing: 0.8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.02em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* Topbar status */
|
||||
.topbar-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* Smaller pill and theme toggle in topbar */
|
||||
.topbar-status .pill {
|
||||
padding: 4px 10px;
|
||||
padding: 6px 10px;
|
||||
gap: 6px;
|
||||
font-size: 11px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
height: 32px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.topbar-status .pill .mono {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.topbar-status .statusDot {
|
||||
@@ -135,9 +176,9 @@
|
||||
}
|
||||
|
||||
.topbar-status .theme-toggle {
|
||||
--theme-item: 22px;
|
||||
--theme-gap: 4px;
|
||||
--theme-pad: 4px;
|
||||
--theme-item: 24px;
|
||||
--theme-gap: 2px;
|
||||
--theme-pad: 3px;
|
||||
}
|
||||
|
||||
.topbar-status .theme-icon {
|
||||
@@ -145,17 +186,22 @@
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Navigation Sidebar
|
||||
=========================================== */
|
||||
|
||||
.nav {
|
||||
grid-area: nav;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 16px;
|
||||
padding: 16px 12px;
|
||||
border-right: 1px solid var(--border);
|
||||
background: var(--panel);
|
||||
backdrop-filter: blur(18px);
|
||||
transition: width var(--shell-focus-duration) var(--shell-focus-ease),
|
||||
padding var(--shell-focus-duration) var(--shell-focus-ease);
|
||||
min-height: 0; /* Allow grid item to shrink and enable scrolling */
|
||||
background: var(--bg);
|
||||
transition:
|
||||
width var(--shell-focus-duration) var(--shell-focus-ease),
|
||||
padding var(--shell-focus-duration) var(--shell-focus-ease),
|
||||
opacity var(--shell-focus-duration) var(--shell-focus-ease);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.shell--chat-focus .nav {
|
||||
@@ -164,9 +210,9 @@
|
||||
border-width: 0;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Collapsed nav sidebar - completely hidden */
|
||||
.nav--collapsed {
|
||||
width: 0;
|
||||
min-width: 0;
|
||||
@@ -177,7 +223,7 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Nav collapse toggle button */
|
||||
/* Nav collapse toggle */
|
||||
.nav-collapse-toggle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
@@ -186,71 +232,88 @@
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
border-radius: var(--radius-md);
|
||||
cursor: pointer;
|
||||
transition: background 150ms ease, border-color 150ms ease;
|
||||
transition:
|
||||
background var(--duration-fast) ease,
|
||||
border-color var(--duration-fast) ease;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.nav-collapse-toggle:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
background: var(--bg-hover);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .nav-collapse-toggle:hover {
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.nav-collapse-toggle__icon {
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: var(--muted);
|
||||
transition: color var(--duration-fast) ease;
|
||||
}
|
||||
|
||||
.nav-collapse-toggle__icon svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.nav-collapse-toggle:hover .nav-collapse-toggle__icon {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
/* Nav groups */
|
||||
.nav-group {
|
||||
margin-bottom: 18px;
|
||||
margin-bottom: 20px;
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px dashed rgba(255, 255, 255, 0.08);
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.nav-group:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.nav-group__items {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.nav-group--collapsed .nav-group__items {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Nav label */
|
||||
.nav-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 4px 0;
|
||||
padding: 6px 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1.4px;
|
||||
color: var(--text);
|
||||
opacity: 0.7;
|
||||
color: var(--muted);
|
||||
margin-bottom: 4px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
border-radius: var(--radius-sm);
|
||||
transition:
|
||||
color var(--duration-fast) ease,
|
||||
background var(--duration-fast) ease;
|
||||
}
|
||||
|
||||
.nav-label:hover {
|
||||
opacity: 1;
|
||||
color: var(--text);
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
.nav-label--static {
|
||||
@@ -258,7 +321,8 @@
|
||||
}
|
||||
|
||||
.nav-label--static:hover {
|
||||
opacity: 0.7;
|
||||
color: var(--muted);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.nav-label__text {
|
||||
@@ -266,131 +330,152 @@
|
||||
}
|
||||
|
||||
.nav-label__chevron {
|
||||
font-size: 12px;
|
||||
opacity: 0.6;
|
||||
font-size: 10px;
|
||||
opacity: 0.5;
|
||||
transition: transform var(--duration-fast) ease;
|
||||
}
|
||||
|
||||
.nav-group--collapsed .nav-label__chevron {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
/* Nav items */
|
||||
.nav-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 8px;
|
||||
padding: 10px 12px 10px 14px;
|
||||
border-radius: 12px;
|
||||
gap: 10px;
|
||||
padding: 8px 10px;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid transparent;
|
||||
background: transparent;
|
||||
color: var(--muted);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
transition: border-color 160ms ease, background 160ms ease, color 160ms ease;
|
||||
transition:
|
||||
border-color var(--duration-fast) ease,
|
||||
background var(--duration-fast) ease,
|
||||
color var(--duration-fast) ease;
|
||||
}
|
||||
|
||||
.nav-item__icon {
|
||||
font-size: 16px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
opacity: 0.7;
|
||||
transition: opacity var(--duration-fast) ease;
|
||||
}
|
||||
|
||||
.nav-item__icon svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.nav-item__text {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nav-item:hover {
|
||||
color: var(--text);
|
||||
border-color: rgba(255, 255, 255, 0.12);
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
background: var(--bg-hover);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-item::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
width: 4px;
|
||||
height: 60%;
|
||||
border-radius: 0 999px 999px 0;
|
||||
transform: translateY(-50%);
|
||||
background: transparent;
|
||||
.nav-item:hover .nav-item__icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.nav-item.active {
|
||||
color: var(--text);
|
||||
border-color: rgba(245, 159, 74, 0.45);
|
||||
background: rgba(245, 159, 74, 0.12);
|
||||
color: var(--text-strong);
|
||||
background: var(--accent-subtle);
|
||||
}
|
||||
|
||||
.nav-item.active::before {
|
||||
background: var(--accent);
|
||||
box-shadow: 0 0 12px rgba(245, 159, 74, 0.4);
|
||||
.nav-item.active .nav-item__icon {
|
||||
opacity: 1;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Content Area
|
||||
=========================================== */
|
||||
|
||||
.content {
|
||||
grid-area: content;
|
||||
padding: 8px 6px 20px;
|
||||
padding: 8px 8px 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
min-height: 0;
|
||||
overflow-y: auto; /* Enable vertical scrolling for pages with long content */
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Chat handles its own scrolling (chat-thread); avoid double scrollbars. */
|
||||
:root[data-theme="light"] .content {
|
||||
background: var(--bg-content);
|
||||
}
|
||||
|
||||
.content--chat {
|
||||
overflow: hidden;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.shell--chat .content {
|
||||
/* No-op: keep chat layout consistent with other tabs */
|
||||
}
|
||||
|
||||
/* Content header */
|
||||
.content-header {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 0 6px;
|
||||
gap: 16px;
|
||||
padding: 4px 8px;
|
||||
overflow: hidden;
|
||||
transform-origin: top center;
|
||||
transition: opacity var(--shell-focus-duration) var(--shell-focus-ease),
|
||||
transition:
|
||||
opacity var(--shell-focus-duration) var(--shell-focus-ease),
|
||||
transform var(--shell-focus-duration) var(--shell-focus-ease),
|
||||
max-height var(--shell-focus-duration) var(--shell-focus-ease),
|
||||
padding var(--shell-focus-duration) var(--shell-focus-ease);
|
||||
max-height: 90px;
|
||||
max-height: 80px;
|
||||
}
|
||||
|
||||
.shell--chat-focus .content-header {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
transform: translateY(-8px);
|
||||
max-height: 0px;
|
||||
padding: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: 26px;
|
||||
letter-spacing: 0.6px;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1.2;
|
||||
color: var(--text-strong);
|
||||
}
|
||||
|
||||
.page-sub {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.4px;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.page-meta {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* Chat view: header and controls side by side */
|
||||
/* Chat view header adjustments */
|
||||
.content--chat .content-header {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
@@ -410,9 +495,13 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Grid Utilities
|
||||
=========================================== */
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.grid-cols-2 {
|
||||
@@ -425,39 +514,42 @@
|
||||
|
||||
.stat-grid {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
gap: 12px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
}
|
||||
|
||||
.note-grid {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
gap: 12px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stack {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Responsive - Tablet
|
||||
=========================================== */
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.shell {
|
||||
--shell-pad: 12px;
|
||||
--shell-gap: 12px;
|
||||
--shell-nav-col: 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
grid-template-areas:
|
||||
@@ -470,17 +562,18 @@
|
||||
position: static;
|
||||
max-height: none;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
gap: 6px;
|
||||
overflow-x: auto;
|
||||
border-right: none;
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding: 10px 14px;
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.nav-group {
|
||||
grid-auto-flow: column;
|
||||
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.grid-cols-2,
|
||||
@@ -490,13 +583,11 @@
|
||||
|
||||
.topbar {
|
||||
position: static;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px 14px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.topbar-status {
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
/* Tablet/Mobile nav fix (under 1100px) - single horizontal scroll row */
|
||||
/* ===========================================
|
||||
Mobile Layout
|
||||
=========================================== */
|
||||
|
||||
/* Tablet: Horizontal nav */
|
||||
@media (max-width: 1100px) {
|
||||
/* Flatten nav into single horizontal scroll */
|
||||
.nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
gap: 6px;
|
||||
padding: 10px 12px;
|
||||
gap: 4px;
|
||||
padding: 10px 14px;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
@@ -16,21 +19,18 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Nav groups should flow inline, not stack */
|
||||
.nav-group {
|
||||
display: contents; /* Flatten group wrapper - items flow directly into .nav */
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.nav-group__items {
|
||||
display: contents; /* Flatten items wrapper too */
|
||||
display: contents;
|
||||
}
|
||||
|
||||
/* Hide group labels on tablet/mobile */
|
||||
.nav-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Don't hide nav items even if group is "collapsed" */
|
||||
.nav-group--collapsed .nav-group__items {
|
||||
display: contents;
|
||||
}
|
||||
@@ -38,27 +38,22 @@
|
||||
.nav-item {
|
||||
padding: 8px 14px;
|
||||
font-size: 13px;
|
||||
border-radius: 10px;
|
||||
border-radius: var(--radius-md);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-item::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile-specific improvements */
|
||||
/* Mobile-specific styles */
|
||||
@media (max-width: 600px) {
|
||||
.shell {
|
||||
--shell-pad: 8px;
|
||||
--shell-gap: 8px;
|
||||
}
|
||||
|
||||
/* Compact topbar for mobile */
|
||||
/* Topbar */
|
||||
.topbar {
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
gap: 8px;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
@@ -72,8 +67,7 @@
|
||||
}
|
||||
|
||||
.brand-title {
|
||||
font-size: 15px;
|
||||
letter-spacing: 0.3px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.brand-sub {
|
||||
@@ -100,11 +94,10 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Horizontal scrollable nav for mobile */
|
||||
/* Nav */
|
||||
.nav {
|
||||
padding: 8px;
|
||||
border-radius: 12px;
|
||||
gap: 8px;
|
||||
padding: 8px 10px;
|
||||
gap: 4px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
@@ -122,18 +115,14 @@
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
padding: 7px 10px;
|
||||
padding: 6px 10px;
|
||||
font-size: 12px;
|
||||
border-radius: 8px;
|
||||
border-radius: var(--radius-md);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-item::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide page title on mobile - nav already shows where you are */
|
||||
/* Content */
|
||||
.content-header {
|
||||
display: none;
|
||||
}
|
||||
@@ -143,17 +132,17 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* Smaller cards on mobile */
|
||||
/* Cards */
|
||||
.card {
|
||||
padding: 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* Stat grid adjustments */
|
||||
/* Stats */
|
||||
.stat-grid {
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
@@ -161,24 +150,24 @@
|
||||
|
||||
.stat {
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 10px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
/* Notes grid */
|
||||
/* Notes */
|
||||
.note-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* Form fields */
|
||||
/* Forms */
|
||||
.form-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
@@ -188,14 +177,14 @@
|
||||
.field textarea,
|
||||
.field select {
|
||||
padding: 8px 10px;
|
||||
border-radius: 10px;
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Pills */
|
||||
@@ -204,7 +193,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Chat-specific mobile improvements */
|
||||
/* Chat */
|
||||
.chat-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
@@ -227,17 +216,16 @@
|
||||
|
||||
.chat-thread {
|
||||
margin-top: 8px;
|
||||
padding: 10px 8px;
|
||||
border-radius: 12px;
|
||||
padding: 12px 8px;
|
||||
}
|
||||
|
||||
.chat-msg {
|
||||
max-width: 92%;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
.chat-bubble {
|
||||
padding: 8px 10px;
|
||||
border-radius: 12px;
|
||||
padding: 8px 12px;
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
.chat-compose {
|
||||
@@ -247,14 +235,14 @@
|
||||
.chat-compose__field textarea {
|
||||
min-height: 60px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 12px;
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Log stream mobile */
|
||||
/* Log stream */
|
||||
.log-stream {
|
||||
border-radius: 10px;
|
||||
max-height: 400px;
|
||||
border-radius: var(--radius-md);
|
||||
max-height: 380px;
|
||||
}
|
||||
|
||||
.log-row {
|
||||
@@ -279,14 +267,14 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* List items */
|
||||
/* Lists */
|
||||
.list-item {
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
.list-title {
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.list-sub {
|
||||
@@ -296,19 +284,91 @@
|
||||
/* Code blocks */
|
||||
.code-block {
|
||||
padding: 8px;
|
||||
border-radius: 10px;
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* Theme toggle smaller */
|
||||
/* Theme toggle */
|
||||
.theme-toggle {
|
||||
--theme-item: 24px;
|
||||
--theme-gap: 4px;
|
||||
--theme-pad: 4px;
|
||||
--theme-gap: 2px;
|
||||
--theme-pad: 3px;
|
||||
}
|
||||
|
||||
.theme-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Small mobile */
|
||||
@media (max-width: 400px) {
|
||||
.shell {
|
||||
--shell-pad: 4px;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.brand-title {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
padding: 6px 8px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 4px 4px 12px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.stat {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.chat-bubble {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.chat-compose__field textarea {
|
||||
min-height: 52px;
|
||||
padding: 8px 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 6px 10px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.topbar-status .pill {
|
||||
padding: 3px 6px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
--theme-item: 22px;
|
||||
--theme-gap: 2px;
|
||||
--theme-pad: 2px;
|
||||
}
|
||||
|
||||
.theme-icon {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { repeat } from "lit/directives/repeat.js";
|
||||
|
||||
import type { AppViewState } from "./app-view-state";
|
||||
import { iconForTab, pathForTab, titleForTab, type Tab } from "./navigation";
|
||||
import { icons } from "./icons";
|
||||
import { loadChatHistory } from "./controllers/chat";
|
||||
import { syncUrlWithSessionKey } from "./app-settings";
|
||||
import type { SessionsListResult } from "./types";
|
||||
@@ -31,7 +32,7 @@ export function renderTab(state: AppViewState, tab: Tab) {
|
||||
}}
|
||||
title=${titleForTab(tab)}
|
||||
>
|
||||
<span class="nav-item__icon" aria-hidden="true">${iconForTab(tab)}</span>
|
||||
<span class="nav-item__icon" aria-hidden="true">${icons[iconForTab(tab)]}</span>
|
||||
<span class="nav-item__text">${titleForTab(tab)}</span>
|
||||
</a>
|
||||
`;
|
||||
@@ -108,7 +109,7 @@ export function renderChatControls(state: AppViewState) {
|
||||
? "Disabled during onboarding"
|
||||
: "Toggle assistant thinking/working output"}
|
||||
>
|
||||
🧠
|
||||
${icons.brain}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn--sm btn--icon ${focusActive ? "active" : ""}"
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
titleForTab,
|
||||
type Tab,
|
||||
} from "./navigation";
|
||||
import { icons } from "./icons";
|
||||
import type { UiSettings } from "./storage";
|
||||
import type { ThemeMode } from "./theme";
|
||||
import type { ThemeTransitionContext } from "./theme-transition";
|
||||
@@ -124,11 +125,16 @@ export function renderApp(state: AppViewState) {
|
||||
title="${state.settings.navCollapsed ? "Expand sidebar" : "Collapse sidebar"}"
|
||||
aria-label="${state.settings.navCollapsed ? "Expand sidebar" : "Collapse sidebar"}"
|
||||
>
|
||||
<span class="nav-collapse-toggle__icon">☰</span>
|
||||
<span class="nav-collapse-toggle__icon">${icons.menu}</span>
|
||||
</button>
|
||||
<div class="brand">
|
||||
<div class="brand-title">CLAWDBOT</div>
|
||||
<div class="brand-sub">Gateway Dashboard</div>
|
||||
<div class="brand-logo">
|
||||
<img src="https://mintcdn.com/clawdhub/4rYvG-uuZrMK_URE/assets/pixel-lobster.svg?fit=max&auto=format&n=4rYvG-uuZrMK_URE&q=85&s=da2032e9eac3b5d9bfe7eb96ca6a8a26" alt="Clawdbot" />
|
||||
</div>
|
||||
<div class="brand-text">
|
||||
<div class="brand-title">CLAWDBOT</div>
|
||||
<div class="brand-sub">Gateway Dashboard</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="topbar-status">
|
||||
@@ -179,7 +185,7 @@ export function renderApp(state: AppViewState) {
|
||||
rel="noreferrer"
|
||||
title="Docs (opens in new tab)"
|
||||
>
|
||||
<span class="nav-item__icon" aria-hidden="true">📚</span>
|
||||
<span class="nav-item__icon" aria-hidden="true">${icons.book}</span>
|
||||
<span class="nav-item__text">Docs</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { html, type TemplateResult } from "lit";
|
||||
import { renderEmojiIcon, setEmojiIcon } from "../icons";
|
||||
import { icons } from "../icons";
|
||||
|
||||
const COPIED_FOR_MS = 1500;
|
||||
const ERROR_FOR_MS = 2000;
|
||||
const COPY_LABEL = "Copy as markdown";
|
||||
const COPIED_LABEL = "Copied";
|
||||
const ERROR_LABEL = "Copy failed";
|
||||
const COPY_ICON = "📋";
|
||||
const COPIED_ICON = "✓";
|
||||
const ERROR_ICON = "!";
|
||||
|
||||
type CopyButtonOptions = {
|
||||
text: () => string;
|
||||
@@ -41,7 +38,7 @@ function createCopyButton(options: CopyButtonOptions): TemplateResult {
|
||||
aria-label=${idleLabel}
|
||||
@click=${async (e: Event) => {
|
||||
const btn = e.currentTarget as HTMLButtonElement | null;
|
||||
const icon = btn?.querySelector(
|
||||
const iconContainer = btn?.querySelector(
|
||||
".chat-copy-btn__icon",
|
||||
) as HTMLElement | null;
|
||||
|
||||
@@ -61,30 +58,29 @@ function createCopyButton(options: CopyButtonOptions): TemplateResult {
|
||||
if (!copied) {
|
||||
btn.dataset.error = "1";
|
||||
setButtonLabel(btn, ERROR_LABEL);
|
||||
setEmojiIcon(icon, ERROR_ICON);
|
||||
|
||||
window.setTimeout(() => {
|
||||
if (!btn.isConnected) return;
|
||||
delete btn.dataset.error;
|
||||
setButtonLabel(btn, idleLabel);
|
||||
setEmojiIcon(icon, COPY_ICON);
|
||||
}, ERROR_FOR_MS);
|
||||
return;
|
||||
}
|
||||
|
||||
btn.dataset.copied = "1";
|
||||
setButtonLabel(btn, COPIED_LABEL);
|
||||
setEmojiIcon(icon, COPIED_ICON);
|
||||
|
||||
window.setTimeout(() => {
|
||||
if (!btn.isConnected) return;
|
||||
delete btn.dataset.copied;
|
||||
setButtonLabel(btn, idleLabel);
|
||||
setEmojiIcon(icon, COPY_ICON);
|
||||
}, COPIED_FOR_MS);
|
||||
}}
|
||||
>
|
||||
${renderEmojiIcon(COPY_ICON, "chat-copy-btn__icon")}
|
||||
<span class="chat-copy-btn__icon" aria-hidden="true">
|
||||
<span class="chat-copy-btn__icon-copy">${icons.copy}</span>
|
||||
<span class="chat-copy-btn__icon-check">${icons.check}</span>
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { html, nothing } from "lit";
|
||||
|
||||
import { formatToolDetail, resolveToolDisplay } from "../tool-display";
|
||||
import { icons } from "../icons";
|
||||
import type { ToolCard } from "../types/chat-types";
|
||||
import { TOOL_INLINE_THRESHOLD } from "./constants";
|
||||
import {
|
||||
@@ -95,13 +96,13 @@ export function renderToolCardSidebar(
|
||||
>
|
||||
<div class="chat-tool-card__header">
|
||||
<div class="chat-tool-card__title">
|
||||
<span class="chat-tool-card__icon">${display.emoji}</span>
|
||||
<span class="chat-tool-card__icon">${icons[display.icon]}</span>
|
||||
<span>${display.label}</span>
|
||||
</div>
|
||||
${canClick
|
||||
? html`<span class="chat-tool-card__action">${hasText ? "View ›" : "›"}</span>`
|
||||
? html`<span class="chat-tool-card__action">${hasText ? "View" : ""} ${icons.check}</span>`
|
||||
: nothing}
|
||||
${isEmpty && !canClick ? html`<span class="chat-tool-card__status">✓</span>` : nothing}
|
||||
${isEmpty && !canClick ? html`<span class="chat-tool-card__status">${icons.check}</span>` : nothing}
|
||||
</div>
|
||||
${detail
|
||||
? html`<div class="chat-tool-card__detail">${detail}</div>`
|
||||
|
||||
@@ -1,7 +1,59 @@
|
||||
import { html, type TemplateResult } from "lit";
|
||||
|
||||
export function renderEmojiIcon(icon: string, className: string): TemplateResult {
|
||||
return html`<span class=${className} aria-hidden="true">${icon}</span>`;
|
||||
// Lucide-style SVG icons
|
||||
// All icons use currentColor for stroke
|
||||
|
||||
export const icons = {
|
||||
// Navigation icons
|
||||
messageSquare: html`<svg viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>`,
|
||||
barChart: html`<svg viewBox="0 0 24 24"><line x1="12" x2="12" y1="20" y2="10"/><line x1="18" x2="18" y1="20" y2="4"/><line x1="6" x2="6" y1="20" y2="16"/></svg>`,
|
||||
link: html`<svg viewBox="0 0 24 24"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>`,
|
||||
radio: html`<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="2"/><path d="M16.24 7.76a6 6 0 0 1 0 8.49m-8.48-.01a6 6 0 0 1 0-8.49m11.31-2.82a10 10 0 0 1 0 14.14m-14.14 0a10 10 0 0 1 0-14.14"/></svg>`,
|
||||
fileText: html`<svg viewBox="0 0 24 24"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><line x1="16" x2="8" y1="13" y2="13"/><line x1="16" x2="8" y1="17" y2="17"/><line x1="10" x2="8" y1="9" y2="9"/></svg>`,
|
||||
zap: html`<svg viewBox="0 0 24 24"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>`,
|
||||
monitor: html`<svg viewBox="0 0 24 24"><rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/></svg>`,
|
||||
settings: html`<svg viewBox="0 0 24 24"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>`,
|
||||
bug: html`<svg viewBox="0 0 24 24"><path d="m8 2 1.88 1.88"/><path d="M14.12 3.88 16 2"/><path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"/><path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"/><path d="M12 20v-9"/><path d="M6.53 9C4.6 8.8 3 7.1 3 5"/><path d="M6 13H2"/><path d="M3 21c0-2.1 1.7-3.9 3.8-4"/><path d="M20.97 5c0 2.1-1.6 3.8-3.5 4"/><path d="M22 13h-4"/><path d="M17.2 17c2.1.1 3.8 1.9 3.8 4"/></svg>`,
|
||||
scrollText: html`<svg viewBox="0 0 24 24"><path d="M8 21h12a2 2 0 0 0 2-2v-2H10v2a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v3h4"/><path d="M19 17V5a2 2 0 0 0-2-2H4"/><path d="M15 8h-5"/><path d="M15 12h-5"/></svg>`,
|
||||
folder: html`<svg viewBox="0 0 24 24"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></svg>`,
|
||||
|
||||
// UI icons
|
||||
menu: html`<svg viewBox="0 0 24 24"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>`,
|
||||
x: html`<svg viewBox="0 0 24 24"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`,
|
||||
check: html`<svg viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>`,
|
||||
copy: html`<svg viewBox="0 0 24 24"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`,
|
||||
search: html`<svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>`,
|
||||
brain: html`<svg viewBox="0 0 24 24"><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/><path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/><path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/><path d="M17.599 6.5a3 3 0 0 0 .399-1.375"/><path d="M6.003 5.125A3 3 0 0 0 6.401 6.5"/><path d="M3.477 10.896a4 4 0 0 1 .585-.396"/><path d="M19.938 10.5a4 4 0 0 1 .585.396"/><path d="M6 18a4 4 0 0 1-1.967-.516"/><path d="M19.967 17.484A4 4 0 0 1 18 18"/></svg>`,
|
||||
book: html`<svg viewBox="0 0 24 24"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/></svg>`,
|
||||
loader: html`<svg viewBox="0 0 24 24"><path d="M12 2v4"/><path d="m16.2 7.8 2.9-2.9"/><path d="M18 12h4"/><path d="m16.2 16.2 2.9 2.9"/><path d="M12 18v4"/><path d="m4.9 19.1 2.9-2.9"/><path d="M2 12h4"/><path d="m4.9 4.9 2.9 2.9"/></svg>`,
|
||||
|
||||
// Tool icons
|
||||
wrench: html`<svg viewBox="0 0 24 24"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>`,
|
||||
fileCode: html`<svg viewBox="0 0 24 24"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><path d="m10 13-2 2 2 2"/><path d="m14 17 2-2-2-2"/></svg>`,
|
||||
edit: html`<svg viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>`,
|
||||
penLine: html`<svg viewBox="0 0 24 24"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>`,
|
||||
paperclip: html`<svg viewBox="0 0 24 24"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>`,
|
||||
globe: html`<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>`,
|
||||
image: html`<svg viewBox="0 0 24 24"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>`,
|
||||
smartphone: html`<svg viewBox="0 0 24 24"><rect width="14" height="20" x="5" y="2" rx="2" ry="2"/><path d="M12 18h.01"/></svg>`,
|
||||
plug: html`<svg viewBox="0 0 24 24"><path d="M12 22v-5"/><path d="M9 8V2"/><path d="M15 8V2"/><path d="M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/></svg>`,
|
||||
circle: html`<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/></svg>`,
|
||||
puzzle: html`<svg viewBox="0 0 24 24"><path d="M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.48-.968-.925a2.501 2.501 0 1 0-3.214 3.214c.446.166.855.497.925.968a.979.979 0 0 1-.276.837l-1.61 1.61a2.404 2.404 0 0 1-1.705.707 2.402 2.402 0 0 1-1.704-.706l-1.568-1.568a1.026 1.026 0 0 0-.877-.29c-.493.074-.84.504-1.02.968a2.5 2.5 0 1 1-3.237-3.237c.464-.18.894-.527.967-1.02a1.026 1.026 0 0 0-.289-.877l-1.568-1.568A2.402 2.402 0 0 1 1.998 12c0-.617.236-1.234.706-1.704L4.23 8.77c.24-.24.581-.353.917-.303.515.076.874.54 1.02 1.02a2.5 2.5 0 1 0 3.237-3.237c-.48-.146-.944-.505-1.02-1.02a.98.98 0 0 1 .303-.917l1.526-1.526A2.402 2.402 0 0 1 11.998 2c.617 0 1.234.236 1.704.706l1.568 1.568c.23.23.556.338.877.29.493-.074.84-.504 1.02-.968a2.5 2.5 0 1 1 3.236 3.236c-.464.18-.894.527-.967 1.02Z"/></svg>`,
|
||||
} as const;
|
||||
|
||||
export type IconName = keyof typeof icons;
|
||||
|
||||
export function icon(name: IconName): TemplateResult {
|
||||
return icons[name];
|
||||
}
|
||||
|
||||
export function renderIcon(name: IconName, className = "nav-item__icon"): TemplateResult {
|
||||
return html`<span class=${className} aria-hidden="true">${icons[name]}</span>`;
|
||||
}
|
||||
|
||||
// Legacy function for compatibility
|
||||
export function renderEmojiIcon(iconContent: string | TemplateResult, className: string): TemplateResult {
|
||||
return html`<span class=${className} aria-hidden="true">${iconContent}</span>`;
|
||||
}
|
||||
|
||||
export function setEmojiIcon(target: HTMLElement | null, icon: string): void {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { IconName } from "./icons.js";
|
||||
|
||||
export const TAB_GROUPS = [
|
||||
{ label: "Chat", tabs: ["chat"] },
|
||||
{
|
||||
@@ -98,32 +100,32 @@ export function inferBasePathFromPathname(pathname: string): string {
|
||||
return `/${segments.join("/")}`;
|
||||
}
|
||||
|
||||
export function iconForTab(tab: Tab): string {
|
||||
export function iconForTab(tab: Tab): IconName {
|
||||
switch (tab) {
|
||||
case "chat":
|
||||
return "💬";
|
||||
return "messageSquare";
|
||||
case "overview":
|
||||
return "📊";
|
||||
return "barChart";
|
||||
case "channels":
|
||||
return "🔗";
|
||||
return "link";
|
||||
case "instances":
|
||||
return "📡";
|
||||
return "radio";
|
||||
case "sessions":
|
||||
return "📄";
|
||||
return "fileText";
|
||||
case "cron":
|
||||
return "⏰";
|
||||
return "loader";
|
||||
case "skills":
|
||||
return "⚡️";
|
||||
return "zap";
|
||||
case "nodes":
|
||||
return "🖥️";
|
||||
return "monitor";
|
||||
case "config":
|
||||
return "⚙️";
|
||||
return "settings";
|
||||
case "debug":
|
||||
return "🐞";
|
||||
return "bug";
|
||||
case "logs":
|
||||
return "🧾";
|
||||
return "scrollText";
|
||||
default:
|
||||
return "📁";
|
||||
return "folder";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"fallback": {
|
||||
"emoji": "🧩",
|
||||
"icon": "puzzle",
|
||||
"detailKeys": [
|
||||
"command",
|
||||
"path",
|
||||
@@ -26,37 +26,37 @@
|
||||
},
|
||||
"tools": {
|
||||
"bash": {
|
||||
"emoji": "🛠️",
|
||||
"icon": "wrench",
|
||||
"title": "Bash",
|
||||
"detailKeys": ["command"]
|
||||
},
|
||||
"process": {
|
||||
"emoji": "🧰",
|
||||
"icon": "wrench",
|
||||
"title": "Process",
|
||||
"detailKeys": ["sessionId"]
|
||||
},
|
||||
"read": {
|
||||
"emoji": "📖",
|
||||
"icon": "fileText",
|
||||
"title": "Read",
|
||||
"detailKeys": ["path"]
|
||||
},
|
||||
"write": {
|
||||
"emoji": "✍️",
|
||||
"icon": "edit",
|
||||
"title": "Write",
|
||||
"detailKeys": ["path"]
|
||||
},
|
||||
"edit": {
|
||||
"emoji": "📝",
|
||||
"icon": "penLine",
|
||||
"title": "Edit",
|
||||
"detailKeys": ["path"]
|
||||
},
|
||||
"attach": {
|
||||
"emoji": "📎",
|
||||
"icon": "paperclip",
|
||||
"title": "Attach",
|
||||
"detailKeys": ["path", "url", "fileName"]
|
||||
},
|
||||
"browser": {
|
||||
"emoji": "🌐",
|
||||
"icon": "globe",
|
||||
"title": "Browser",
|
||||
"actions": {
|
||||
"status": { "label": "status" },
|
||||
@@ -95,7 +95,7 @@
|
||||
}
|
||||
},
|
||||
"canvas": {
|
||||
"emoji": "🖼️",
|
||||
"icon": "image",
|
||||
"title": "Canvas",
|
||||
"actions": {
|
||||
"present": { "label": "present", "detailKeys": ["target", "node", "nodeId"] },
|
||||
@@ -108,7 +108,7 @@
|
||||
}
|
||||
},
|
||||
"nodes": {
|
||||
"emoji": "📱",
|
||||
"icon": "smartphone",
|
||||
"title": "Nodes",
|
||||
"actions": {
|
||||
"status": { "label": "status" },
|
||||
@@ -127,7 +127,7 @@
|
||||
}
|
||||
},
|
||||
"cron": {
|
||||
"emoji": "⏰",
|
||||
"icon": "loader",
|
||||
"title": "Cron",
|
||||
"actions": {
|
||||
"status": { "label": "status" },
|
||||
@@ -144,7 +144,7 @@
|
||||
}
|
||||
},
|
||||
"gateway": {
|
||||
"emoji": "🔌",
|
||||
"icon": "plug",
|
||||
"title": "Gateway",
|
||||
"actions": {
|
||||
"restart": { "label": "restart", "detailKeys": ["reason", "delayMs"] },
|
||||
@@ -161,7 +161,7 @@
|
||||
}
|
||||
},
|
||||
"whatsapp_login": {
|
||||
"emoji": "🟢",
|
||||
"icon": "circle",
|
||||
"title": "WhatsApp Login",
|
||||
"actions": {
|
||||
"start": { "label": "start" },
|
||||
@@ -169,7 +169,7 @@
|
||||
}
|
||||
},
|
||||
"discord": {
|
||||
"emoji": "💬",
|
||||
"icon": "messageSquare",
|
||||
"title": "Discord",
|
||||
"actions": {
|
||||
"react": { "label": "react", "detailKeys": ["channelId", "messageId", "emoji"] },
|
||||
@@ -204,7 +204,7 @@
|
||||
}
|
||||
},
|
||||
"slack": {
|
||||
"emoji": "💬",
|
||||
"icon": "messageSquare",
|
||||
"title": "Slack",
|
||||
"actions": {
|
||||
"react": { "label": "react", "detailKeys": ["channelId", "messageId", "emoji"] },
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import rawConfig from "./tool-display.json";
|
||||
import type { IconName } from "./icons";
|
||||
|
||||
type ToolDisplayActionSpec = {
|
||||
label?: string;
|
||||
@@ -6,7 +7,7 @@ type ToolDisplayActionSpec = {
|
||||
};
|
||||
|
||||
type ToolDisplaySpec = {
|
||||
emoji?: string;
|
||||
icon?: string;
|
||||
title?: string;
|
||||
label?: string;
|
||||
detailKeys?: string[];
|
||||
@@ -21,7 +22,7 @@ type ToolDisplayConfig = {
|
||||
|
||||
export type ToolDisplay = {
|
||||
name: string;
|
||||
emoji: string;
|
||||
icon: IconName;
|
||||
title: string;
|
||||
label: string;
|
||||
verb?: string;
|
||||
@@ -29,7 +30,7 @@ export type ToolDisplay = {
|
||||
};
|
||||
|
||||
const TOOL_DISPLAY_CONFIG = rawConfig as ToolDisplayConfig;
|
||||
const FALLBACK = TOOL_DISPLAY_CONFIG.fallback ?? { emoji: "🧩" };
|
||||
const FALLBACK = TOOL_DISPLAY_CONFIG.fallback ?? { icon: "puzzle" };
|
||||
const TOOL_MAP = TOOL_DISPLAY_CONFIG.tools ?? {};
|
||||
|
||||
function normalizeToolName(name?: string): string {
|
||||
@@ -135,7 +136,7 @@ export function resolveToolDisplay(params: {
|
||||
const name = normalizeToolName(params.name);
|
||||
const key = name.toLowerCase();
|
||||
const spec = TOOL_MAP[key];
|
||||
const emoji = spec?.emoji ?? FALLBACK.emoji ?? "🧩";
|
||||
const icon = (spec?.icon ?? FALLBACK.icon ?? "puzzle") as IconName;
|
||||
const title = spec?.title ?? defaultTitle(name);
|
||||
const label = spec?.label ?? name;
|
||||
const actionRaw =
|
||||
@@ -168,7 +169,7 @@ export function resolveToolDisplay(params: {
|
||||
|
||||
return {
|
||||
name,
|
||||
emoji,
|
||||
icon,
|
||||
title,
|
||||
label,
|
||||
verb,
|
||||
@@ -186,9 +187,7 @@ export function formatToolDetail(display: ToolDisplay): string | undefined {
|
||||
|
||||
export function formatToolSummary(display: ToolDisplay): string {
|
||||
const detail = formatToolDetail(display);
|
||||
return detail
|
||||
? `${display.emoji} ${display.label}: ${detail}`
|
||||
: `${display.emoji} ${display.label}`;
|
||||
return detail ? `${display.label}: ${detail}` : display.label;
|
||||
}
|
||||
|
||||
function shortenHomeInString(input: string): string {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { repeat } from "lit/directives/repeat.js";
|
||||
import type { SessionsListResult } from "../types";
|
||||
import type { ChatQueueItem } from "../ui-types";
|
||||
import type { ChatItem, MessageGroup } from "../types/chat-types";
|
||||
import { icons } from "../icons";
|
||||
import {
|
||||
normalizeMessage,
|
||||
normalizeRoleForGrouping,
|
||||
@@ -74,7 +75,7 @@ function renderCompactionIndicator(status: CompactionIndicatorStatus | null | un
|
||||
if (status.active) {
|
||||
return html`
|
||||
<div class="callout info compaction-indicator compaction-indicator--active">
|
||||
🧹 Compacting context...
|
||||
${icons.loader} Compacting context...
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -85,7 +86,7 @@ function renderCompactionIndicator(status: CompactionIndicatorStatus | null | un
|
||||
if (elapsed < COMPACTION_TOAST_DURATION_MS) {
|
||||
return html`
|
||||
<div class="callout success compaction-indicator compaction-indicator--complete">
|
||||
🧹 Context compacted
|
||||
${icons.check} Context compacted
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -171,7 +172,7 @@ export function renderChat(props: ChatProps) {
|
||||
aria-label="Exit focus mode"
|
||||
title="Exit focus mode"
|
||||
>
|
||||
✕
|
||||
${icons.x}
|
||||
</button>
|
||||
`
|
||||
: nothing}
|
||||
@@ -223,7 +224,7 @@ export function renderChat(props: ChatProps) {
|
||||
aria-label="Remove queued message"
|
||||
@click=${() => props.onQueueRemove(item.id)}
|
||||
>
|
||||
✕
|
||||
${icons.x}
|
||||
</button>
|
||||
</div>
|
||||
`,
|
||||
@@ -265,7 +266,7 @@ export function renderChat(props: ChatProps) {
|
||||
?disabled=${!props.connected}
|
||||
@click=${props.onSend}
|
||||
>
|
||||
${isBusy ? "Queue" : "Send"}
|
||||
${isBusy ? "Queue" : "Send"}<kbd class="btn-kbd">↵</kbd>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { html, nothing } from "lit";
|
||||
import type { ConfigUiHints } from "../types";
|
||||
import { icons } from "../icons";
|
||||
import {
|
||||
hintForPath,
|
||||
humanize,
|
||||
@@ -189,7 +190,7 @@ export function renderConfigForm(props: ConfigFormProps) {
|
||||
if (filteredEntries.length === 0) {
|
||||
return html`
|
||||
<div class="config-empty">
|
||||
<div class="config-empty__icon">🔍</div>
|
||||
<div class="config-empty__icon">${icons.search}</div>
|
||||
<div class="config-empty__text">
|
||||
${searchQuery
|
||||
? `No settings match "${searchQuery}"`
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { html, nothing } from "lit";
|
||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||
|
||||
import { icons } from "../icons";
|
||||
import { toSanitizedMarkdownHtml } from "../markdown";
|
||||
|
||||
export type MarkdownSidebarProps = {
|
||||
@@ -16,7 +17,7 @@ export function renderMarkdownSidebar(props: MarkdownSidebarProps) {
|
||||
<div class="sidebar-header">
|
||||
<div class="sidebar-title">Tool Output</div>
|
||||
<button @click=${props.onClose} class="btn" title="Close sidebar">
|
||||
✕
|
||||
${icons.x}
|
||||
</button>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
|
||||
Reference in New Issue
Block a user