feat: Design System standards - scrollbars, cards, indicators, tree patterns for ALL themes

- Updated PROMPT.md with comprehensive Design System documentation
- Added missing CSS variables to ALL themes (border-light, border-hover, text-tertiary)
- Added global component classes: scrollable, card-status, dot-status, badge-step, tree patterns
- Updated tasks.css: no global scroll, task list scrollable, fixed layout
- All patterns from sentient theme now available to all themes
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2026-01-02 13:40:24 -03:00
parent 8e9bc9c381
commit ade2050668
4 changed files with 873 additions and 6 deletions

334
PROMPT.md
View file

@ -545,6 +545,340 @@ ui/minimal/index.html # Minimal chat UI
---
---
## Design System - UI Standards
**The `tasks.css` file defines the standard patterns for ALL screens in General Bots.**
All themes MUST implement these core components consistently.
### Layout Standards
```css
/* Full-height container - no global scroll */
.app-container {
display: flex;
flex-direction: column;
height: 100vh;
max-height: 100vh;
overflow: hidden;
}
/* Two-column layout - list + detail */
.main-content {
display: grid;
grid-template-columns: 320px 1fr;
flex: 1;
overflow: hidden;
height: calc(100vh - 120px);
}
/* Scrollable list panel (LEFT) */
.list-panel {
overflow-y: scroll;
overflow-x: hidden;
height: 100%;
scrollbar-width: auto;
scrollbar-color: var(--border-light) var(--surface);
}
/* Fixed detail panel (RIGHT) - no scroll */
.detail-panel {
display: flex;
flex-direction: column;
overflow: hidden;
height: 100%;
}
```
### Scrollbar Standards
```css
/* Visible scrollbar - 10px width */
.scrollable::-webkit-scrollbar {
width: 10px;
}
.scrollable::-webkit-scrollbar-track {
background: var(--surface);
border-radius: 5px;
}
.scrollable::-webkit-scrollbar-thumb {
background: var(--border-light);
border-radius: 5px;
border: 2px solid var(--surface);
}
.scrollable::-webkit-scrollbar-thumb:hover {
background: var(--primary);
}
/* Firefox */
.scrollable {
scrollbar-width: auto;
scrollbar-color: var(--border-light) var(--surface);
}
```
### Card Standards
```css
/* Base card - used in task lists, items, etc. */
.card {
background: var(--surface-hover);
border: 2px solid var(--border);
border-radius: 16px;
padding: 16px 20px;
cursor: pointer;
transition: all 0.2s ease;
position: relative;
}
.card:hover {
border-color: var(--border-hover);
background: var(--surface);
}
.card.selected {
border-color: var(--primary);
box-shadow: 0 0 0 2px var(--primary);
}
/* Card status indicator (left bar) */
.card::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 5px;
height: 100%;
background: var(--text-secondary);
transition: background 0.2s ease;
}
.card.status-running::before { background: var(--primary); }
.card.status-complete::before { background: var(--success); }
.card.status-error::before { background: var(--error); }
.card.status-pending::before { background: var(--text-secondary); }
```
### Progress/Tree Indicators
```css
/* Dot indicator - shows status */
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
background: var(--text-secondary);
transition: all 0.3s ease;
}
.status-dot.running {
background: var(--primary);
box-shadow: 0 0 8px var(--primary-light);
animation: dot-pulse 1.5s ease-in-out infinite;
}
.status-dot.completed {
background: var(--primary);
}
.status-dot.pending {
background: var(--text-secondary);
}
@keyframes dot-pulse {
0%, 100% {
opacity: 1;
box-shadow: 0 0 10px var(--primary-light);
transform: scale(1);
}
50% {
opacity: 0.7;
box-shadow: 0 0 4px var(--primary-light);
transform: scale(0.9);
}
}
/* Step badge */
.step-badge {
padding: 4px 12px;
background: var(--primary);
color: var(--bg);
border-radius: 4px;
font-size: 11px;
font-weight: 600;
}
.step-badge.pending {
background: var(--surface);
color: var(--text-secondary);
}
```
### Tree/List with Children
```css
/* Parent-child expandable tree */
.tree-section {
border: 1px solid var(--border);
background: var(--surface);
border-radius: 8px;
margin: 8px 16px;
overflow: hidden;
}
.tree-row {
display: flex;
align-items: center;
padding: 16px 20px;
cursor: pointer;
transition: background 0.15s;
}
.tree-row:hover {
background: var(--surface-hover);
}
.tree-children {
display: none;
background: var(--bg);
}
.tree-section.expanded .tree-children {
display: block;
}
.tree-child {
border-bottom: 1px solid var(--border);
padding-left: 24px;
}
.tree-item {
display: flex;
align-items: center;
padding: 8px 20px 8px 40px;
min-height: 32px;
}
```
### Fixed Panels (Terminal, Status)
```css
/* Fixed-height panel at bottom */
.fixed-panel {
flex: 0 0 120px;
height: 120px;
min-height: 120px;
max-height: 120px;
display: flex;
flex-direction: column;
overflow: hidden;
border-top: 1px solid var(--border);
}
/* Variable-height panel with scroll */
.variable-panel {
flex: 1 1 auto;
min-height: 150px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.variable-panel-content {
flex: 1 1 auto;
min-height: 0;
overflow-y: scroll;
}
```
### Status Badges
```css
.status-badge {
font-size: 11px;
font-weight: 700;
padding: 6px 12px;
border-radius: 6px;
text-transform: uppercase;
}
.status-badge.running {
background: rgba(var(--primary-rgb), 0.15);
color: var(--primary);
}
.status-badge.completed {
background: rgba(var(--success-rgb), 0.15);
color: var(--success);
}
.status-badge.error {
background: rgba(var(--error-rgb), 0.15);
color: var(--error);
}
.status-badge.pending {
background: var(--surface);
color: var(--text-secondary);
}
```
### Theme Variables Required
Every theme MUST define these CSS variables:
```css
[data-theme="your-theme"] {
/* Backgrounds */
--bg: #0a0a0a;
--surface: #161616;
--surface-hover: #1e1e1e;
/* Borders */
--border: #2a2a2a;
--border-light: #3a3a3a;
--border-hover: #4a4a4a;
/* Text */
--text: #ffffff;
--text-secondary: #888888;
--text-tertiary: #666666;
/* Primary (accent) */
--primary: #c5f82a;
--primary-hover: #d4ff3a;
--primary-light: rgba(197, 248, 42, 0.15);
/* Status colors */
--success: #22c55e;
--warning: #f59e0b;
--error: #ef4444;
--info: #3b82f6;
}
```
### Component Checklist for New Screens
When creating a new screen, ensure it has:
- [ ] Full-height container with `overflow: hidden`
- [ ] No global page scroll
- [ ] List panel with visible scrollbar (if applicable)
- [ ] Detail panel with fixed layout
- [ ] Cards with status indicator bar
- [ ] Status dots/badges using standard classes
- [ ] Tree sections if showing parent-child relationships
- [ ] Fixed terminal/status panels at bottom
- [ ] Variable content area with internal scroll
---
## Remember
- **ZERO WARNINGS** - Every clippy warning must be fixed

View file

@ -14,8 +14,11 @@
--surface: #1e293b;
--surface-hover: #334155;
--border: #334155;
--border-light: #475569;
--border-hover: #64748b;
--text: #f8fafc;
--text-secondary: #94a3b8;
--text-tertiary: #64748b;
--success: #22c55e;
--warning: #f59e0b;
--error: #ef4444;
@ -30,8 +33,11 @@
--surface: #1e293b;
--surface-hover: #334155;
--border: #334155;
--border-light: #475569;
--border-hover: #64748b;
--text: #f8fafc;
--text-secondary: #94a3b8;
--text-tertiary: #64748b;
}
[data-theme="light"] {
@ -39,8 +45,11 @@
--surface: #ffffff;
--surface-hover: #f1f5f9;
--border: #e2e8f0;
--border-light: #cbd5e1;
--border-hover: #94a3b8;
--text: #1e293b;
--text-secondary: #64748b;
--text-tertiary: #94a3b8;
}
[data-theme="blue"] {
@ -51,6 +60,11 @@
--surface: #1a2f47;
--surface-hover: #254063;
--border: #2d4a6f;
--border-light: #3d5a7f;
--border-hover: #4d6a8f;
--text: #f8fafc;
--text-secondary: #94a3b8;
--text-tertiary: #64748b;
}
[data-theme="purple"] {
@ -61,6 +75,11 @@
--surface: #2d1b4e;
--surface-hover: #3d2566;
--border: #4c2f7e;
--border-light: #5c3f8e;
--border-hover: #6c4f9e;
--text: #f8fafc;
--text-secondary: #c4b5fd;
--text-tertiary: #8b5cf6;
}
[data-theme="green"] {
@ -71,6 +90,11 @@
--surface: #14332a;
--surface-hover: #1e4a3d;
--border: #28604f;
--border-light: #38705f;
--border-hover: #48806f;
--text: #f8fafc;
--text-secondary: #86efac;
--text-tertiary: #4ade80;
}
[data-theme="orange"] {
@ -81,6 +105,11 @@
--surface: #2d1c0f;
--surface-hover: #442a16;
--border: #5c3a1e;
--border-light: #6c4a2e;
--border-hover: #7c5a3e;
--text: #f8fafc;
--text-secondary: #fdba74;
--text-tertiary: #fb923c;
}
[data-theme="sentient"] {
@ -91,8 +120,11 @@
--surface: #161616;
--surface-hover: #1e1e1e;
--border: #2a2a2a;
--border-light: #3a3a3a;
--border-hover: #4a4a4a;
--text: #ffffff;
--text-secondary: #888888;
--text-tertiary: #666666;
--success: #22c55e;
--warning: #f59e0b;
--error: #ef4444;
@ -108,8 +140,11 @@
--surface: #1a0a3e;
--surface-hover: #2a1a5e;
--border: #ff00ff33;
--border-light: #ff00ff55;
--border-hover: #ff00ff77;
--text: #00ffff;
--text-secondary: #ff6ec7;
--text-tertiary: #cc5aa0;
}
[data-theme="retrowave"] {
@ -120,8 +155,11 @@
--surface: #2d1b4e;
--surface-hover: #3d2b6e;
--border: #ff6b9d33;
--border-light: #ff6b9d55;
--border-hover: #ff6b9d77;
--text: #ffeaa7;
--text-secondary: #a29bfe;
--text-tertiary: #817bce;
}
[data-theme="vapordream"] {
@ -132,8 +170,11 @@
--surface: #636e72;
--surface-hover: #74b9ff;
--border: #a29bfe33;
--border-light: #a29bfe55;
--border-hover: #a29bfe77;
--text: #ffeaa7;
--text-secondary: #fd79a8;
--text-tertiary: #cd6188;
}
[data-theme="y2kglow"] {
@ -144,8 +185,11 @@
--surface: #000066;
--surface-hover: #000099;
--border: #00ff0033;
--border-light: #00ff0055;
--border-hover: #00ff0077;
--text: #ffffff;
--text-secondary: #00ffff;
--text-tertiary: #00cccc;
}
[data-theme="arcadeflash"] {
@ -156,8 +200,11 @@
--surface: #1a1a1a;
--surface-hover: #333333;
--border: #ffff0033;
--border-light: #ffff0055;
--border-hover: #ffff0077;
--text: #ff0000;
--text-secondary: #00ff00;
--text-tertiary: #00cc00;
}
[data-theme="discofever"] {
@ -168,8 +215,11 @@
--surface: #2d1a2d;
--surface-hover: #4a2a4a;
--border: #ff149333;
--border-light: #ff149355;
--border-hover: #ff149377;
--text: #ffd700;
--text-secondary: #00ced1;
--text-tertiary: #00a5a5;
}
[data-theme="grungeera"] {
@ -180,8 +230,11 @@
--surface: #2d2d1a;
--surface-hover: #3d3d2a;
--border: #8b451333;
--border-light: #8b451355;
--border-hover: #8b451377;
--text: #daa520;
--text-secondary: #808000;
--text-tertiary: #606000;
}
/* Classic Themes */
@ -193,8 +246,11 @@
--surface: #16213e;
--surface-hover: #0f3460;
--border: #d4af3733;
--border-light: #d4af3755;
--border-hover: #d4af3777;
--text: #eee8aa;
--text-secondary: #cd853f;
--text-tertiary: #a06530;
}
[data-theme="mellowgold"] {

View file

@ -1170,3 +1170,446 @@ select.form-input {
.shadow-lg {
box-shadow: 0 8px 24px hsla(var(--foreground) / 0.12);
}
/* ============================================ */
/* DESIGN SYSTEM - GLOBAL STANDARDS */
/* These patterns are used across ALL screens */
/* ============================================ */
/* ===========================================
SCROLLBAR STANDARDS
=========================================== */
/* Visible scrollbar - use on any scrollable container */
.scrollable {
overflow-y: scroll;
overflow-x: hidden;
scrollbar-width: auto;
scrollbar-color: var(--border-light, #3a3a3a) var(--surface, #1a1a1a);
}
.scrollable::-webkit-scrollbar {
width: 10px;
}
.scrollable::-webkit-scrollbar-track {
background: var(--surface, #1a1a1a);
border-radius: 5px;
}
.scrollable::-webkit-scrollbar-thumb {
background: var(--border-light, #3a3a3a);
border-radius: 5px;
border: 2px solid var(--surface, #1a1a1a);
}
.scrollable::-webkit-scrollbar-thumb:hover {
background: var(--primary, #c5f82a);
}
/* Thin scrollbar variant */
.scrollable-thin {
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: thin;
scrollbar-color: var(--border, #2a2a2a) transparent;
}
.scrollable-thin::-webkit-scrollbar {
width: 6px;
}
.scrollable-thin::-webkit-scrollbar-track {
background: transparent;
}
.scrollable-thin::-webkit-scrollbar-thumb {
background: var(--border, #2a2a2a);
border-radius: 3px;
}
.scrollable-thin::-webkit-scrollbar-thumb:hover {
background: var(--border-light, #3a3a3a);
}
/* ===========================================
LAYOUT STANDARDS
=========================================== */
/* Full-height container - no global scroll */
.app-container {
display: flex;
flex-direction: column;
height: 100vh;
max-height: 100vh;
overflow: hidden;
}
/* Two-column layout */
.layout-split {
display: grid;
grid-template-columns: 320px 1fr;
flex: 1;
overflow: hidden;
height: 100%;
}
/* Scrollable list panel (LEFT side) */
.panel-list {
display: flex;
flex-direction: column;
overflow: hidden;
border-right: 1px solid var(--border, #2a2a2a);
height: 100%;
}
.panel-list-scroll {
flex: 1;
overflow-y: scroll;
overflow-x: hidden;
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
scrollbar-width: auto;
scrollbar-color: var(--border-light, #3a3a3a) var(--surface, #1a1a1a);
}
.panel-list-scroll::-webkit-scrollbar {
width: 10px;
}
.panel-list-scroll::-webkit-scrollbar-track {
background: var(--surface, #1a1a1a);
border-radius: 5px;
}
.panel-list-scroll::-webkit-scrollbar-thumb {
background: var(--border-light, #3a3a3a);
border-radius: 5px;
border: 2px solid var(--surface, #1a1a1a);
}
.panel-list-scroll::-webkit-scrollbar-thumb:hover {
background: var(--primary, #c5f82a);
}
/* Fixed detail panel (RIGHT side) */
.panel-detail {
display: flex;
flex-direction: column;
overflow: hidden;
height: 100%;
}
/* ===========================================
CARD WITH STATUS INDICATOR
=========================================== */
.card-status {
background: var(--surface-hover, #1e1e1e);
border: 2px solid var(--border, #2a2a2a);
border-radius: 16px;
padding: 16px 20px;
cursor: pointer;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
}
/* Status indicator bar on left */
.card-status::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 5px;
height: 100%;
background: var(--text-secondary, #666);
transition: background 0.2s ease;
}
.card-status:hover {
border-color: var(--border-hover, #4a4a4a);
background: var(--surface, #161616);
}
.card-status.selected {
border-color: var(--primary, #c5f82a);
box-shadow: 0 0 0 2px var(--primary, #c5f82a);
}
/* Status colors */
.card-status.status-running::before {
background: var(--primary, #c5f82a);
}
.card-status.status-complete::before,
.card-status.status-completed::before {
background: var(--success, #22c55e);
}
.card-status.status-error::before,
.card-status.status-failed::before {
background: var(--error, #ef4444);
}
.card-status.status-pending::before {
background: var(--text-secondary, #666);
}
.card-status.status-paused::before {
background: var(--info, #3b82f6);
}
.card-status.status-awaiting::before {
background: var(--warning, #f59e0b);
}
/* ===========================================
STATUS DOT INDICATOR
=========================================== */
.dot-status {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
background: var(--text-secondary, #666);
transition: all 0.3s ease;
}
.dot-status.running {
background: var(--primary, #c5f82a);
box-shadow: 0 0 8px var(--primary-light, rgba(197, 248, 42, 0.5));
animation: dot-pulse 1.5s ease-in-out infinite;
}
.dot-status.completed {
background: var(--primary, #c5f82a);
}
.dot-status.pending {
background: var(--text-tertiary, #666);
}
.dot-status.error,
.dot-status.failed {
background: var(--error, #ef4444);
}
@keyframes dot-pulse {
0%,
100% {
opacity: 1;
box-shadow: 0 0 10px var(--primary-light, rgba(197, 248, 42, 0.8));
transform: scale(1);
}
50% {
opacity: 0.7;
box-shadow: 0 0 4px var(--primary-light, rgba(197, 248, 42, 0.4));
transform: scale(0.9);
}
}
/* ===========================================
STEP BADGE
=========================================== */
.badge-step {
padding: 4px 12px;
background: var(--primary, #c5f82a);
color: var(--bg, #0a0a0a);
border-radius: 4px;
font-size: 11px;
font-weight: 600;
white-space: nowrap;
}
.badge-step.pending {
background: var(--surface, #1a1a1a);
color: var(--text-secondary, #888);
}
.badge-step.completed {
background: var(--success, #22c55e);
color: #fff;
}
/* ===========================================
STATUS BADGE
=========================================== */
.badge-status {
font-size: 11px;
font-weight: 700;
padding: 6px 12px;
border-radius: 6px;
text-transform: uppercase;
letter-spacing: 0.02em;
}
.badge-status.running {
background: rgba(197, 248, 42, 0.15);
color: var(--primary, #c5f82a);
}
.badge-status.completed,
.badge-status.complete {
background: rgba(34, 197, 94, 0.15);
color: var(--success, #22c55e);
}
.badge-status.error,
.badge-status.failed {
background: rgba(239, 68, 68, 0.15);
color: var(--error, #ef4444);
}
.badge-status.pending {
background: var(--surface, #1a1a1a);
color: var(--text-secondary, #888);
}
.badge-status.paused {
background: rgba(59, 130, 246, 0.15);
color: var(--info, #3b82f6);
}
.badge-status.awaiting {
background: rgba(245, 158, 11, 0.15);
color: var(--warning, #f59e0b);
}
/* ===========================================
TREE / LIST WITH CHILDREN
=========================================== */
.tree-section {
border: 1px solid var(--border, #2a2a2a);
background: var(--surface, #161616);
border-radius: 8px;
margin: 8px 16px;
overflow: hidden;
}
.tree-section:last-child {
margin-bottom: 16px;
}
.tree-row {
display: flex;
align-items: center;
padding: 16px 20px;
cursor: pointer;
transition: background 0.15s;
}
.tree-row:hover {
background: var(--surface-hover, #1e1e1e);
}
.tree-name {
flex: 1;
font-size: 14px;
font-weight: 500;
color: var(--text, #fff);
}
.tree-children {
display: none;
background: var(--bg, #0a0a0a);
}
.tree-section.expanded .tree-children {
display: block;
}
.tree-child {
border-bottom: 1px solid var(--border, #2a2a2a);
padding-left: 24px;
}
.tree-child:last-child {
border-bottom: none;
}
.tree-item {
display: flex;
align-items: center;
padding: 8px 20px 8px 40px;
min-height: 32px;
}
.tree-item-name {
flex: 1;
font-size: 13px;
color: var(--text-secondary, #888);
}
.tree-item-check {
font-size: 14px;
width: 20px;
text-align: center;
}
.tree-item-check.completed {
color: var(--success, #22c55e);
}
/* ===========================================
FIXED PANELS (Terminal, Status)
=========================================== */
.panel-fixed {
flex: 0 0 120px;
height: 120px;
min-height: 120px;
max-height: 120px;
display: flex;
flex-direction: column;
overflow: hidden;
border-top: 1px solid var(--border, #2a2a2a);
}
/* Variable-height panel with internal scroll */
.panel-variable {
flex: 1 1 auto;
min-height: 150px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.panel-variable-content {
flex: 1 1 auto;
min-height: 0;
overflow-y: scroll;
scrollbar-width: auto;
scrollbar-color: var(--border-light, #3a3a3a) var(--surface, #1a1a1a);
}
.panel-variable-content::-webkit-scrollbar {
width: 12px;
}
.panel-variable-content::-webkit-scrollbar-track {
background: var(--surface, #1a1a1a);
border-radius: 6px;
}
.panel-variable-content::-webkit-scrollbar-thumb {
background: var(--border-light, #3a3a3a);
border-radius: 6px;
border: 3px solid var(--surface, #1a1a1a);
}
.panel-variable-content::-webkit-scrollbar-thumb:hover {
background: var(--primary, #c5f82a);
}
/* ===========================================
DISABLE GLOBAL SCROLL
=========================================== */
html:has(.app-container),
body:has(.app-container) {
overflow: hidden !important;
height: 100vh;
max-height: 100vh;
}

View file

@ -11,10 +11,20 @@
.tasks-app {
display: flex;
flex-direction: column;
min-height: 100%;
height: 100vh;
max-height: 100vh;
background: var(--bg, #0a0a0a);
color: var(--text, #ffffff);
font-family: var(--font-family, system-ui, -apple-system, sans-serif);
overflow: hidden;
}
/* Disable global scroll when tasks app is active */
html:has(.tasks-app),
body:has(.tasks-app) {
overflow: hidden !important;
height: 100vh;
max-height: 100vh;
}
.tasks-app *,
@ -272,10 +282,11 @@
.tasks-main {
display: grid;
grid-template-columns: 30% 70%;
grid-template-columns: 320px 1fr;
flex: 1;
overflow: hidden;
height: 100%;
height: calc(100vh - 140px);
max-height: calc(100vh - 140px);
}
/* =============================================================================
@ -288,16 +299,39 @@
overflow: hidden;
border-right: 1px solid var(--border, #2a2a2a);
height: 100%;
max-height: 100%;
}
.tasks-list-scroll {
flex: 1;
overflow-y: auto;
overflow-y: scroll;
overflow-x: hidden;
padding: 20px;
padding: 16px;
padding-right: 8px;
display: flex;
flex-direction: column;
gap: 16px;
gap: 12px;
scrollbar-width: auto;
scrollbar-color: var(--border-light, #3a3a3a) var(--surface, #1a1a1a);
}
.tasks-list-scroll::-webkit-scrollbar {
width: 10px;
}
.tasks-list-scroll::-webkit-scrollbar-track {
background: var(--surface, #1a1a1a);
border-radius: 5px;
}
.tasks-list-scroll::-webkit-scrollbar-thumb {
background: var(--border-light, #3a3a3a);
border-radius: 5px;
border: 2px solid var(--surface, #1a1a1a);
}
.tasks-list-scroll::-webkit-scrollbar-thumb:hover {
background: var(--primary, #c5f82a);
}
/* =============================================================================