UI: dashboard refresh phase 2 - premium polish
- Dark theme: warm sepia undertone (#0D0C07 base, #1B1A16 elevated) - Light theme: warm gray tones for premium feel - Page headers: gradient separator for visual hierarchy - Health pill: clearer connected/offline styling - Stat cards: overflow handling for collapsed sidebar - Checkbox alignment: fixes for filters and form grids - Crab loader: animated processing indicator component
This commit is contained in:
parent
6dda12f59e
commit
26148786d9
@ -1,40 +1,40 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap");
|
||||
|
||||
:root {
|
||||
/* Background - Warmer dark with depth */
|
||||
--bg: #12141a;
|
||||
--bg-accent: #14161d;
|
||||
--bg-elevated: #1a1d25;
|
||||
--bg-hover: #262a35;
|
||||
--bg-muted: #262a35;
|
||||
/* Background - Warm dark with sepia undertone */
|
||||
--bg: #0D0C07;
|
||||
--bg-accent: #11100A;
|
||||
--bg-elevated: #1B1A16;
|
||||
--bg-hover: #252419;
|
||||
--bg-muted: #252419;
|
||||
|
||||
/* Card / Surface - More contrast between levels */
|
||||
--card: #181b22;
|
||||
--card-foreground: #f4f4f5;
|
||||
--card-highlight: rgba(255, 255, 255, 0.05);
|
||||
--popover: #181b22;
|
||||
--popover-foreground: #f4f4f5;
|
||||
/* Card / Surface - Clear hierarchy with warm tones */
|
||||
--card: #151410;
|
||||
--card-foreground: #f4f4f0;
|
||||
--card-highlight: rgba(255, 252, 245, 0.05);
|
||||
--popover: #151410;
|
||||
--popover-foreground: #f4f4f0;
|
||||
|
||||
/* Panel */
|
||||
--panel: #12141a;
|
||||
--panel-strong: #1a1d25;
|
||||
--panel-hover: #262a35;
|
||||
--chrome: rgba(18, 20, 26, 0.95);
|
||||
--chrome-strong: rgba(18, 20, 26, 0.98);
|
||||
--panel: #0D0C07;
|
||||
--panel-strong: #1B1A16;
|
||||
--panel-hover: #252419;
|
||||
--chrome: rgba(13, 12, 7, 0.95);
|
||||
--chrome-strong: rgba(13, 12, 7, 0.98);
|
||||
|
||||
/* Text - Slightly warmer */
|
||||
--text: #e4e4e7;
|
||||
--text-strong: #fafafa;
|
||||
--chat-text: #e4e4e7;
|
||||
--muted: #71717a;
|
||||
--muted-strong: #52525b;
|
||||
--muted-foreground: #71717a;
|
||||
/* Text - Warm white tones */
|
||||
--text: #e8e6e0;
|
||||
--text-strong: #faf9f6;
|
||||
--chat-text: #e8e6e0;
|
||||
--muted: #7a776d;
|
||||
--muted-strong: #5c5952;
|
||||
--muted-foreground: #7a776d;
|
||||
|
||||
/* Border - Subtle but defined */
|
||||
--border: #27272a;
|
||||
--border-strong: #3f3f46;
|
||||
--border-hover: #52525b;
|
||||
--input: #27272a;
|
||||
/* Border - Warm and subtle */
|
||||
--border: #2a2820;
|
||||
--border-strong: #3d3a30;
|
||||
--border-hover: #524f42;
|
||||
--input: #2a2820;
|
||||
--ring: #ff5c5c;
|
||||
|
||||
/* Accent - Punchy signature red */
|
||||
@ -47,9 +47,9 @@
|
||||
--primary: #ff5c5c;
|
||||
--primary-foreground: #ffffff;
|
||||
|
||||
/* Secondary - Teal accent for variety */
|
||||
--secondary: #1e2028;
|
||||
--secondary-foreground: #f4f4f5;
|
||||
/* Secondary - Warm elevated surface */
|
||||
--secondary: #1B1A16;
|
||||
--secondary-foreground: #f4f4f0;
|
||||
--accent-2: #14b8a6;
|
||||
--accent-2-muted: rgba(20, 184, 166, 0.7);
|
||||
--accent-2-subtle: rgba(20, 184, 166, 0.15);
|
||||
@ -74,7 +74,7 @@
|
||||
--focus-glow: 0 0 0 2px var(--bg), 0 0 0 4px var(--ring), 0 0 20px var(--accent-glow);
|
||||
|
||||
/* Grid */
|
||||
--grid-line: rgba(255, 255, 255, 0.04);
|
||||
--grid-line: rgba(255, 252, 245, 0.04);
|
||||
|
||||
/* Theme transition */
|
||||
--theme-switch-x: 50%;
|
||||
@ -111,77 +111,85 @@
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
/* Light theme - Clean with subtle warmth */
|
||||
/* Light theme - Premium with warm gray tones and clear hierarchy */
|
||||
:root[data-theme="light"] {
|
||||
--bg: #fafafa;
|
||||
--bg-accent: #f5f5f5;
|
||||
/* Warm gray backgrounds with clear hierarchy */
|
||||
--bg: #f8f8f7;
|
||||
--bg-accent: #f3f3f1;
|
||||
--bg-elevated: #ffffff;
|
||||
--bg-hover: #f0f0f0;
|
||||
--bg-muted: #f0f0f0;
|
||||
--bg-content: #f5f5f5;
|
||||
--bg-hover: #ebebea;
|
||||
--bg-muted: #eeeeed;
|
||||
--bg-content: #f3f3f1;
|
||||
|
||||
/* Cards stand out clearly against background */
|
||||
--card: #ffffff;
|
||||
--card-foreground: #18181b;
|
||||
--card-highlight: rgba(0, 0, 0, 0.03);
|
||||
--card-foreground: #1a1a1a;
|
||||
--card-highlight: rgba(255, 255, 255, 0.8);
|
||||
--popover: #ffffff;
|
||||
--popover-foreground: #18181b;
|
||||
--popover-foreground: #1a1a1a;
|
||||
|
||||
--panel: #fafafa;
|
||||
--panel-strong: #f5f5f5;
|
||||
--panel-hover: #ebebeb;
|
||||
--chrome: rgba(250, 250, 250, 0.95);
|
||||
--chrome-strong: rgba(250, 250, 250, 0.98);
|
||||
/* Panel - subtle warm tint */
|
||||
--panel: #f8f8f7;
|
||||
--panel-strong: #f3f3f1;
|
||||
--panel-hover: #e8e8e6;
|
||||
--chrome: rgba(248, 248, 247, 0.95);
|
||||
--chrome-strong: rgba(248, 248, 247, 0.98);
|
||||
|
||||
--text: #3f3f46;
|
||||
--text-strong: #18181b;
|
||||
--chat-text: #3f3f46;
|
||||
--muted: #71717a;
|
||||
--muted-strong: #52525b;
|
||||
--muted-foreground: #71717a;
|
||||
/* Text - rich contrast */
|
||||
--text: #3d3d3d;
|
||||
--text-strong: #1a1a1a;
|
||||
--chat-text: #3d3d3d;
|
||||
--muted: #6b6b6b;
|
||||
--muted-strong: #525252;
|
||||
--muted-foreground: #6b6b6b;
|
||||
|
||||
--border: #e4e4e7;
|
||||
--border-strong: #d4d4d8;
|
||||
--border-hover: #a1a1aa;
|
||||
--input: #e4e4e7;
|
||||
/* Border - subtle definition with warm undertone */
|
||||
--border: #e0e0de;
|
||||
--border-strong: #c8c8c5;
|
||||
--border-hover: #a0a09d;
|
||||
--input: #e0e0de;
|
||||
|
||||
/* Accent - confident red */
|
||||
--accent: #dc2626;
|
||||
--accent-hover: #ef4444;
|
||||
--accent-muted: #dc2626;
|
||||
--accent-subtle: rgba(220, 38, 38, 0.12);
|
||||
--accent-subtle: rgba(220, 38, 38, 0.1);
|
||||
--accent-foreground: #ffffff;
|
||||
--accent-glow: rgba(220, 38, 38, 0.15);
|
||||
--accent-glow: rgba(220, 38, 38, 0.12);
|
||||
--primary: #dc2626;
|
||||
--primary-foreground: #ffffff;
|
||||
|
||||
--secondary: #f4f4f5;
|
||||
--secondary-foreground: #3f3f46;
|
||||
/* Secondary - warm off-white */
|
||||
--secondary: #f0f0ee;
|
||||
--secondary-foreground: #3d3d3d;
|
||||
--accent-2: #0d9488;
|
||||
--accent-2-muted: rgba(13, 148, 136, 0.75);
|
||||
--accent-2-subtle: rgba(13, 148, 136, 0.12);
|
||||
--accent-2-subtle: rgba(13, 148, 136, 0.1);
|
||||
|
||||
/* Semantic colors - slightly muted for light theme */
|
||||
--ok: #16a34a;
|
||||
--ok-muted: rgba(22, 163, 74, 0.75);
|
||||
--ok-subtle: rgba(22, 163, 74, 0.1);
|
||||
--ok-subtle: rgba(22, 163, 74, 0.08);
|
||||
--destructive: #dc2626;
|
||||
--destructive-foreground: #fafafa;
|
||||
--warn: #d97706;
|
||||
--warn-muted: rgba(217, 119, 6, 0.75);
|
||||
--warn-subtle: rgba(217, 119, 6, 0.1);
|
||||
--warn-subtle: rgba(217, 119, 6, 0.08);
|
||||
--danger: #dc2626;
|
||||
--danger-muted: rgba(220, 38, 38, 0.75);
|
||||
--danger-subtle: rgba(220, 38, 38, 0.1);
|
||||
--danger-subtle: rgba(220, 38, 38, 0.08);
|
||||
--info: #2563eb;
|
||||
|
||||
--focus: rgba(220, 38, 38, 0.2);
|
||||
--focus-glow: 0 0 0 2px var(--bg), 0 0 0 4px var(--ring), 0 0 16px var(--accent-glow);
|
||||
|
||||
--grid-line: rgba(0, 0, 0, 0.05);
|
||||
--grid-line: rgba(0, 0, 0, 0.04);
|
||||
|
||||
/* Light shadows */
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);
|
||||
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04);
|
||||
--shadow-xl: 0 24px 48px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.04);
|
||||
/* Light shadows - crisper with subtle warmth */
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05), 0 1px 1px rgba(0, 0, 0, 0.03);
|
||||
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.04);
|
||||
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.08), 0 4px 8px rgba(0, 0, 0, 0.04);
|
||||
--shadow-xl: 0 24px 48px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.05);
|
||||
--shadow-glow: 0 0 24px var(--accent-glow);
|
||||
|
||||
color-scheme: light;
|
||||
|
||||
@ -49,6 +49,8 @@
|
||||
border-color var(--duration-normal) var(--ease-out),
|
||||
box-shadow var(--duration-normal) var(--ease-out);
|
||||
box-shadow: inset 0 1px 0 var(--card-highlight);
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stat:hover {
|
||||
@ -62,6 +64,9 @@
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
@ -70,6 +75,9 @@
|
||||
margin-top: 6px;
|
||||
letter-spacing: -0.03em;
|
||||
line-height: 1.1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.stat-value.ok {
|
||||
@ -201,6 +209,30 @@
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
/* Health pill - prominent status indicator */
|
||||
.pill--health {
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.pill--health.ok {
|
||||
border-color: rgba(34, 197, 94, 0.2);
|
||||
background: var(--ok-subtle);
|
||||
}
|
||||
|
||||
.pill--health.ok .mono {
|
||||
color: var(--ok);
|
||||
}
|
||||
|
||||
.pill--health.offline {
|
||||
border-color: rgba(245, 158, 11, 0.2);
|
||||
background: var(--warn-subtle);
|
||||
}
|
||||
|
||||
.pill--health.offline .mono {
|
||||
color: var(--warn);
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Theme Toggle
|
||||
=========================================== */
|
||||
@ -326,7 +358,7 @@
|
||||
|
||||
.btn:active {
|
||||
background: var(--secondary);
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.98);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@ -447,6 +479,14 @@
|
||||
.field select:focus {
|
||||
border-color: var(--ring);
|
||||
box-shadow: var(--focus-ring);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.field input:focus-visible,
|
||||
.field textarea:focus-visible,
|
||||
.field select:focus-visible {
|
||||
border-color: var(--ring);
|
||||
box-shadow: var(--focus-glow);
|
||||
}
|
||||
|
||||
.field select {
|
||||
@ -467,16 +507,49 @@
|
||||
}
|
||||
|
||||
.field.checkbox {
|
||||
grid-template-columns: auto 1fr;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.field.checkbox span {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.field.checkbox input[type="checkbox"] {
|
||||
order: 1;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0;
|
||||
accent-color: var(--accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Checkboxes in filter rows - align to bottom like other fields */
|
||||
.filters .field.checkbox {
|
||||
align-self: flex-end;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Checkboxes in form grids - align to bottom of grid cell */
|
||||
.form-grid .field.checkbox {
|
||||
align-self: end;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.config-form .field.checkbox {
|
||||
display: grid;
|
||||
grid-template-columns: 18px minmax(0, 1fr);
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.config-form .field.checkbox span {
|
||||
order: unset;
|
||||
}
|
||||
|
||||
.config-form .field.checkbox input[type="checkbox"] {
|
||||
order: unset;
|
||||
margin: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
@ -522,6 +595,39 @@
|
||||
font-family: var(--mono);
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Keyboard Shortcuts (kbd)
|
||||
=========================================== */
|
||||
|
||||
kbd {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
padding: 0 6px;
|
||||
font-family: var(--font-body);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: var(--muted);
|
||||
background: var(--secondary);
|
||||
border: 1px solid var(--border);
|
||||
border-bottom-width: 2px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 0 var(--border);
|
||||
}
|
||||
|
||||
kbd + kbd {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
:root[data-theme="light"] kbd {
|
||||
background: var(--bg);
|
||||
border-color: var(--border-strong);
|
||||
box-shadow: 0 1px 0 var(--border-strong);
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Callouts - Informative with subtle depth
|
||||
=========================================== */
|
||||
@ -554,6 +660,156 @@
|
||||
color: var(--ok);
|
||||
}
|
||||
|
||||
.callout.warn {
|
||||
border-color: rgba(245, 158, 11, 0.25);
|
||||
background: linear-gradient(135deg, rgba(245, 158, 11, 0.08) 0%, rgba(245, 158, 11, 0.04) 100%);
|
||||
color: var(--warn);
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Empty States - Clear and helpful
|
||||
=========================================== */
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
padding: 48px 24px;
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.empty-state__icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--secondary);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--muted);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.empty-state__icon svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.empty-state__title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.empty-state__description {
|
||||
font-size: 13px;
|
||||
max-width: 320px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.empty-state__action {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* Disconnected state - More prominent */
|
||||
.disconnected-state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
padding: 16px 20px;
|
||||
border-radius: var(--radius-lg);
|
||||
border: 1px dashed var(--border-strong);
|
||||
background: var(--secondary);
|
||||
animation: rise 0.35s var(--ease-out) backwards;
|
||||
}
|
||||
|
||||
.disconnected-state__icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--warn-subtle);
|
||||
color: var(--warn);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.disconnected-state__icon svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
stroke: currentColor;
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.disconnected-state__content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.disconnected-state__title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.disconnected-state__description {
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.disconnected-state__action {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Loading state placeholder */
|
||||
.loading-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.loading-placeholder__bar {
|
||||
height: 12px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--secondary) 25%,
|
||||
var(--bg-hover) 50%,
|
||||
var(--secondary) 75%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
.loading-placeholder__bar--short {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.loading-placeholder__bar--medium {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.loading-placeholder__bar--full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Compaction indicator */
|
||||
.compaction-indicator {
|
||||
font-size: 13px;
|
||||
@ -603,6 +859,23 @@
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
/* Light theme cards - subtle shadow for elevation */
|
||||
:root[data-theme="light"] .card {
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .card:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .stat {
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .stat:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Lists
|
||||
=========================================== */
|
||||
@ -1485,3 +1758,137 @@
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Crab Loader - Processing animation
|
||||
=========================================== */
|
||||
|
||||
.crab-loader {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
padding: 32px 24px;
|
||||
}
|
||||
|
||||
.crab-loader__crab {
|
||||
position: relative;
|
||||
animation: crab-walk 0.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.crab-loader__svg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.crab-loader--sm .crab-loader__svg {
|
||||
width: 32px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.crab-loader--md .crab-loader__svg {
|
||||
width: 56px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.crab-loader--lg .crab-loader__svg {
|
||||
width: 96px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.crab-loader__claw-left {
|
||||
transform-origin: 52px 78px;
|
||||
animation: claw-pinch-left 0.4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.crab-loader__claw-right {
|
||||
transform-origin: 468px 78px;
|
||||
animation: claw-pinch-right 0.4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.crab-loader__text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: var(--muted);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.crab-loader__dots {
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.crab-loader__dot {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--muted);
|
||||
animation: dot-bounce 1.2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.crab-loader__dot:nth-child(2) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.crab-loader__dot:nth-child(3) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
/* Crab walking animation - side to side sway */
|
||||
@keyframes crab-walk {
|
||||
0%, 100% {
|
||||
transform: translateX(-2px) rotate(-2deg);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(2px) rotate(2deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Left claw pinching */
|
||||
@keyframes claw-pinch-left {
|
||||
0%, 100% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Right claw pinching */
|
||||
@keyframes claw-pinch-right {
|
||||
0%, 100% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bouncing dots */
|
||||
@keyframes dot-bounce {
|
||||
0%, 80%, 100% {
|
||||
opacity: 0.4;
|
||||
transform: translateY(0);
|
||||
}
|
||||
40% {
|
||||
opacity: 1;
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.crab-loader__crab,
|
||||
.crab-loader__claw-left,
|
||||
.crab-loader__claw-right,
|
||||
.crab-loader__dot {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.crab-loader__dot {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,6 +430,17 @@
|
||||
background: var(--bg-content);
|
||||
}
|
||||
|
||||
/* Light theme nav - subtle background difference */
|
||||
:root[data-theme="light"] .nav {
|
||||
background: var(--bg);
|
||||
border-right: 1px solid var(--border);
|
||||
}
|
||||
|
||||
:root[data-theme="light"] .topbar {
|
||||
background: var(--bg);
|
||||
box-shadow: 0 1px 0 var(--border);
|
||||
}
|
||||
|
||||
.content--chat {
|
||||
overflow: hidden;
|
||||
padding-bottom: 0;
|
||||
@ -437,19 +448,20 @@
|
||||
|
||||
/* Content header */
|
||||
.content-header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 4px 8px;
|
||||
overflow: hidden;
|
||||
padding: 4px 8px 12px;
|
||||
overflow: visible;
|
||||
transform-origin: top center;
|
||||
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: 80px;
|
||||
max-height: 90px;
|
||||
}
|
||||
|
||||
.shell--chat-focus .content-header {
|
||||
@ -481,6 +493,28 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* Page header separator - subtle gradient fade */
|
||||
.content-header::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent 0%,
|
||||
var(--border) 20%,
|
||||
var(--border) 80%,
|
||||
transparent 100%
|
||||
);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.shell--chat-focus .content-header::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Chat view header adjustments */
|
||||
.content--chat .content-header {
|
||||
flex-direction: row;
|
||||
|
||||
@ -2,7 +2,7 @@ import { html } from "lit";
|
||||
import { repeat } from "lit/directives/repeat.js";
|
||||
|
||||
import type { AppViewState } from "./app-view-state";
|
||||
import { iconForTab, pathForTab, titleForTab, type Tab } from "./navigation";
|
||||
import { iconForTab, pathForTab, titleForTab, TAB_GROUPS, type Tab } from "./navigation";
|
||||
import { icons } from "./icons";
|
||||
import { loadChatHistory } from "./controllers/chat";
|
||||
import { syncUrlWithSessionKey } from "./app-settings";
|
||||
@ -28,6 +28,13 @@ export function renderTab(state: AppViewState, tab: Tab) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
// Auto-expand the group containing this tab
|
||||
const group = TAB_GROUPS.find((g) => g.tabs.includes(tab));
|
||||
if (group && state.settings.navGroupsCollapsed[group.label]) {
|
||||
const next = { ...state.settings.navGroupsCollapsed };
|
||||
next[group.label] = false;
|
||||
state.applySettings({ ...state.settings, navGroupsCollapsed: next });
|
||||
}
|
||||
state.setTab(tab);
|
||||
}}
|
||||
title=${titleForTab(tab)}
|
||||
|
||||
@ -138,7 +138,7 @@ export function renderApp(state: AppViewState) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="topbar-status">
|
||||
<div class="pill">
|
||||
<div class="pill pill--health ${state.connected ? "ok" : "offline"}">
|
||||
<span class="statusDot ${state.connected ? "ok" : ""}"></span>
|
||||
<span>Health</span>
|
||||
<span class="mono">${state.connected ? "OK" : "Offline"}</span>
|
||||
@ -149,9 +149,8 @@ export function renderApp(state: AppViewState) {
|
||||
<aside class="nav ${state.settings.navCollapsed ? "nav--collapsed" : ""}">
|
||||
${TAB_GROUPS.map((group) => {
|
||||
const isGroupCollapsed = state.settings.navGroupsCollapsed[group.label] ?? false;
|
||||
const hasActiveTab = group.tabs.some((tab) => tab === state.tab);
|
||||
return html`
|
||||
<div class="nav-group ${isGroupCollapsed && !hasActiveTab ? "nav-group--collapsed" : ""}">
|
||||
<div class="nav-group ${isGroupCollapsed ? "nav-group--collapsed" : ""}">
|
||||
<button
|
||||
class="nav-label"
|
||||
@click=${() => {
|
||||
|
||||
BIN
ui/src/ui/components/crab-loader.gif
Normal file
BIN
ui/src/ui/components/crab-loader.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 374 KiB |
257
ui/src/ui/components/crab-loader.ts
Normal file
257
ui/src/ui/components/crab-loader.ts
Normal file
@ -0,0 +1,257 @@
|
||||
import { html, TemplateResult } from "lit";
|
||||
|
||||
export type CrabLoaderSize = "sm" | "md" | "lg";
|
||||
|
||||
export type CrabLoaderProps = {
|
||||
message?: string;
|
||||
size?: CrabLoaderSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the Clawdbot crab loader animation.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { renderCrabLoader } from "./components/crab-loader";
|
||||
*
|
||||
* // Default usage
|
||||
* ${renderCrabLoader()}
|
||||
*
|
||||
* // With custom message
|
||||
* ${renderCrabLoader({ message: "Loading sessions" })}
|
||||
*
|
||||
* // Different sizes: "sm" | "md" | "lg"
|
||||
* ${renderCrabLoader({ size: "lg" })}
|
||||
* ```
|
||||
*/
|
||||
export function renderCrabLoader(props: CrabLoaderProps = {}): TemplateResult {
|
||||
const { message = "Getting my claws on it", size = "md" } = props;
|
||||
|
||||
return html`
|
||||
<div class="crab-loader crab-loader--${size}">
|
||||
<div class="crab-loader__crab">
|
||||
${renderCrabSvg()}
|
||||
</div>
|
||||
<div class="crab-loader__text">
|
||||
<span>${message}</span>
|
||||
<span class="crab-loader__dots">
|
||||
<span class="crab-loader__dot"></span>
|
||||
<span class="crab-loader__dot"></span>
|
||||
<span class="crab-loader__dot"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderCrabSvg(): TemplateResult {
|
||||
return html`
|
||||
<svg
|
||||
class="crab-loader__svg"
|
||||
viewBox="0 0 520 442"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
shape-rendering="crispEdges"
|
||||
>
|
||||
<!-- Left claw -->
|
||||
<g class="crab-loader__claw-left">
|
||||
<rect x="26" y="156" width="26" height="26" fill="#F41641" />
|
||||
<rect y="130" width="26" height="26" fill="#F41641" />
|
||||
<rect y="104" width="26" height="26" fill="#F41641" />
|
||||
<rect y="78" width="26" height="26" fill="#F41641" />
|
||||
<rect y="52" width="26" height="26" fill="#F41641" />
|
||||
<rect y="26" width="26" height="26" fill="#F41641" />
|
||||
<rect x="26" y="78" width="26" height="26" fill="#F41641" />
|
||||
<rect x="52" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" width="26" height="26" fill="#F41641" />
|
||||
<rect x="52" y="26" width="26" height="26" fill="#F41641" />
|
||||
<rect x="52" y="78" width="26" height="26" fill="#C50026" />
|
||||
<rect x="78" y="52" width="26" height="26" fill="#C50026" />
|
||||
<rect x="26" y="52" width="26" height="26" fill="#F41641" />
|
||||
<rect x="26" y="26" width="26" height="26" fill="#F41641" />
|
||||
<rect x="26" width="26" height="26" fill="#F41641" />
|
||||
</g>
|
||||
|
||||
<!-- Right claw -->
|
||||
<g class="crab-loader__claw-right">
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 520 130)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 520 104)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 520 78)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 520 52)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 520 26)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 494 78)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 468 0)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 442 0)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 468 26)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 468 78)" fill="#C50026" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 442 52)" fill="#C50026" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 494 52)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 494 26)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 494 0)" fill="#F41641" />
|
||||
</g>
|
||||
|
||||
<!-- Eyes -->
|
||||
<rect x="130" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="156" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="130" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="78" width="26" height="26" fill="#6A0014" />
|
||||
<rect x="130" y="78" width="26" height="26" fill="#FFC1CD" />
|
||||
<rect x="130" y="104" width="26" height="26" fill="#FFC1CD" />
|
||||
<rect x="156" y="104" width="26" height="26" fill="#FFC1CD" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 182)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 156)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 130)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 78)" fill="#6A0014" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 390 78)" fill="#FFC1CD" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 390 104)" fill="#FFC1CD" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 104)" fill="#FFC1CD" />
|
||||
|
||||
<!-- Body -->
|
||||
<rect x="182" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="52" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="156" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="156" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="416" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="442" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="468" y="156" width="26" height="26" fill="#F41641" />
|
||||
<rect x="364" y="182" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="182" width="26" height="26" fill="#F41641" />
|
||||
|
||||
<!-- Body rows -->
|
||||
<rect x="130" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 260)" fill="#F41641" />
|
||||
<rect x="182" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="416" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="364" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="260" width="26" height="26" fill="#F41641" />
|
||||
<rect x="130" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 234)" fill="#F41641" />
|
||||
<rect x="182" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="416" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="364" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="234" width="26" height="26" fill="#F41641" />
|
||||
<rect x="130" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 208)" fill="#F41641" />
|
||||
<rect x="182" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="416" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="364" y="208" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="208" width="26" height="26" fill="#F41641" />
|
||||
|
||||
<!-- Lower body and legs -->
|
||||
<rect x="130" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 390)" fill="#F41641" />
|
||||
<rect x="182" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="364" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="130" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 364)" fill="#F41641" />
|
||||
<rect x="182" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="416" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="364" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="130" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 338)" fill="#F41641" />
|
||||
<rect x="182" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="416" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="442" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="468" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="494" y="364" width="26" height="26" fill="#F41641" />
|
||||
<rect x="494" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="494" y="416" width="26" height="26" fill="#F41641" />
|
||||
<rect x="442" y="390" width="26" height="26" fill="#F41641" />
|
||||
<rect x="442" y="416" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 78 338)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 52 338)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 26 364)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 26 390)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 26 416)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 78 390)" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 78 416)" fill="#F41641" />
|
||||
<rect x="364" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="338" width="26" height="26" fill="#F41641" />
|
||||
<rect x="130" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 312)" fill="#F41641" />
|
||||
<rect x="182" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="416" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="364" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="312" width="26" height="26" fill="#F41641" />
|
||||
<rect x="130" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="156" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect width="26" height="26" transform="matrix(-1 0 0 1 364 286)" fill="#F41641" />
|
||||
<rect x="182" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="78" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="104" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="286" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="312" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="208" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="234" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="260" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="416" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="364" y="286" width="26" height="26" fill="#F41641" />
|
||||
<rect x="390" y="286" width="26" height="26" fill="#F41641" />
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
@ -117,13 +117,13 @@ export function renderCron(props: CronProps) {
|
||||
/>
|
||||
</label>
|
||||
<label class="field checkbox">
|
||||
<span>Enabled</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
.checked=${props.form.enabled}
|
||||
@change=${(e: Event) =>
|
||||
props.onFormChange({ enabled: (e.target as HTMLInputElement).checked })}
|
||||
/>
|
||||
<span>Enabled</span>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Schedule</span>
|
||||
|
||||
@ -257,5 +257,6 @@ export function renderOverview(props: OverviewProps) {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user