From 1518a41b7a9b0d4493c1794f531be27d83e0eecb Mon Sep 17 00:00:00 2001 From: ashiwanikumar Date: Mon, 18 May 2026 05:21:35 +0400 Subject: [PATCH 1/2] fix(dashboard): improve responsive design and dark mode contrast - Webhooks: redesign from cramped table to card-based layout that works on all screen sizes. Cards show URL, session, status, and events clearly with proper overflow handling. - Webhooks: add dark mode contrast improvements for event tags, status badges, labels, and URL text. - Webhooks: status badge uses inline-flex with fit-content to prevent full-width stretching on mobile. - MessageTester: toggle groups (recipient type, message type) wrap into individual pill buttons on mobile instead of overflowing. - Plugins: show all engine features instead of truncating at 8, format feature names with spaces for readability. --- dashboard/src/pages/MessageTester.css | 42 ++++ dashboard/src/pages/Plugins.tsx | 7 +- dashboard/src/pages/Webhooks.css | 304 +++++++++++++++++++------- dashboard/src/pages/Webhooks.tsx | 129 +++++------ 4 files changed, 334 insertions(+), 148 deletions(-) diff --git a/dashboard/src/pages/MessageTester.css b/dashboard/src/pages/MessageTester.css index 59ba001..0b31947 100644 --- a/dashboard/src/pages/MessageTester.css +++ b/dashboard/src/pages/MessageTester.css @@ -220,3 +220,45 @@ grid-template-columns: 1fr; } } + +@media (max-width: 768px) { + .message-tester { + padding: 1rem; + } + + .compose-panel, + .response-panel { + padding: 1rem; + } + + .toggle-group { + flex-wrap: wrap; + border: none; + gap: 0.5rem; + overflow: visible; + } + + .toggle-group button { + min-width: 0; + padding: 0.5rem 0.875rem; + font-size: 0.8125rem; + border: 1px solid var(--border) !important; + border-radius: 6px; + } + + .toggle-group button.active { + border-color: var(--primary) !important; + } + + .send-btn { + font-size: 0.9375rem; + padding: 0.75rem 1rem; + } + + .form-group input, + .form-group select, + .form-group textarea { + font-size: 0.875rem; + padding: 0.625rem 0.75rem; + } +} diff --git a/dashboard/src/pages/Plugins.tsx b/dashboard/src/pages/Plugins.tsx index 7febb63..a595e79 100644 --- a/dashboard/src/pages/Plugins.tsx +++ b/dashboard/src/pages/Plugins.tsx @@ -178,14 +178,11 @@ export default function Plugins() {

{t('plugins.supportedFeatures')}

- {activeEngine.features.slice(0, 8).map(feature => ( + {activeEngine.features.map(feature => ( - {feature} + {feature.replace(/-/g, ' ')} ))} - {activeEngine.features.length > 8 && ( - {t('plugins.more', { count: activeEngine.features.length - 8 })} - )}
)} diff --git a/dashboard/src/pages/Webhooks.css b/dashboard/src/pages/Webhooks.css index ebd341b..f4d180a 100644 --- a/dashboard/src/pages/Webhooks.css +++ b/dashboard/src/pages/Webhooks.css @@ -2,6 +2,7 @@ padding: 2rem; width: 100%; box-sizing: border-box; + overflow-x: hidden; } .page-header { @@ -41,53 +42,106 @@ gap: 1.5rem; } -.webhooks-table-container { +.webhooks-list-container { + width: 100%; + min-width: 0; +} + +.webhooks-card-list { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.webhook-card { background: var(--bg-white); border-radius: 12px; box-shadow: var(--shadow-sm); border: 1px solid var(--border); - width: 100%; - overflow-x: auto; + overflow: hidden; + transition: box-shadow 0.2s; } -.webhooks-table { - display: flex; - flex-direction: column; - width: 100%; - min-width: 650px; - font-size: 0.875rem; +.webhook-card:hover { + box-shadow: var(--shadow-md); } -/* Unified row styling - same class for header and data */ -.webhooks-table .table-row { - display: grid; - grid-template-columns: 1fr 150px 140px 80px 100px; - gap: 0.75rem; - padding: 0.875rem 1.25rem; +.webhook-card-header { + display: flex; align-items: center; + justify-content: space-between; + padding: 1rem 1.25rem; border-bottom: 1px solid var(--border); + background: var(--bg-light); + gap: 1rem; } -.webhooks-table .table-row:last-child { - border-bottom: none; +.webhook-url-row { + display: flex; + align-items: center; + gap: 0.625rem; + flex: 1; + min-width: 0; } -.webhooks-table .table-row.header { - background: var(--bg-light); - font-size: 0.7rem; +.webhook-url-icon { + color: var(--primary); + flex-shrink: 0; +} + +.webhook-url { + font-size: 0.8125rem; + font-weight: 500; + color: var(--text-primary); + background: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + min-width: 0; + font-family: 'JetBrains Mono', monospace; +} + +.webhook-card-actions { + display: flex; + gap: 0.375rem; + flex-shrink: 0; +} + +.webhook-card-body { + padding: 1rem 1.25rem; + overflow: hidden; +} + +.webhook-meta { + display: flex; + gap: 2rem; + margin-bottom: 0.875rem; +} + +.webhook-meta-item { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.webhook-meta-label { + font-size: 0.6875rem; font-weight: 700; - color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.05em; - border-bottom: 1px solid var(--border); + color: var(--text-secondary); } -.webhooks-table .table-row:not(.header):hover { - background: rgba(37, 211, 102, 0.05); +.webhook-meta-value { + font-size: 0.875rem; + font-weight: 500; + color: var(--text-primary); } -.webhooks-table .table-row:not(.header):nth-child(even) { - background: rgba(0, 0, 0, 0.02); +.webhook-events { + display: flex; + flex-direction: column; + gap: 0.375rem; } .empty-table-state { @@ -119,52 +173,24 @@ max-width: 300px; } -.name-cell { - font-weight: 500; - color: var(--text-primary); - white-space: nowrap; -} - -.url-cell { - display: flex; - align-items: center; - gap: 0.5rem; -} - -.url-cell code { - font-size: 0.8125rem; - color: var(--text-secondary); - background: var(--bg-light); - padding: 0.25rem 0.5rem; - border-radius: 4px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - min-width: 0; -} - -.url-cell svg { - color: var(--text-muted); - flex-shrink: 0; -} - .events-cell { display: flex; flex-wrap: wrap; - gap: 0.25rem; + gap: 0.375rem; } .event-tag { - font-size: 0.6875rem; - padding: 0.25rem 0.5rem; - background: rgba(37, 211, 102, 0.1); + font-size: 0.75rem; + padding: 0.25rem 0.625rem; + background: rgba(37, 211, 102, 0.15); color: var(--primary); - border-radius: 4px; - font-weight: 500; + border-radius: 6px; + font-weight: 600; white-space: nowrap; - border: none; + border: 1px solid rgba(37, 211, 102, 0.25); cursor: default; + font-family: 'JetBrains Mono', monospace; + letter-spacing: -0.01em; } /* Modal event tags - clickable (webhooks only) */ @@ -191,36 +217,36 @@ } .status-badge { - display: inline-block; + display: inline-flex; + align-items: center; + gap: 0.375rem; padding: 0.25rem 0.75rem; border-radius: 9999px; font-size: 0.75rem; - font-weight: 500; + font-weight: 600; white-space: nowrap; + width: fit-content; +} + +.status-badge::before { + content: ''; + width: 6px; + height: 6px; + border-radius: 50%; + background: currentColor; + flex-shrink: 0; } .status-badge.active { - background: rgba(37, 211, 102, 0.1); + background: rgba(37, 211, 102, 0.15); color: var(--primary); } .status-badge.inactive { - background: #f3f4f6; + background: var(--bg-light); color: var(--text-muted); } -.last-triggered { - color: var(--text-secondary); - font-size: 0.875rem; - white-space: nowrap; -} - -.actions-cell { - display: flex; - gap: 0.25rem; - justify-content: flex-end; -} - .icon-btn { padding: 0.5rem; background: transparent; @@ -253,8 +279,12 @@ } .events-reference h3 { - /* Inherits from H3 */ - margin-bottom: 1rem; + font-size: 1rem; + font-weight: 700; + color: var(--text-primary); + margin: 0 0 1rem 0; + text-transform: none; + letter-spacing: normal; } .events-list { @@ -279,8 +309,59 @@ } .event-item span { - font-size: 0.75rem; + font-size: 0.8125rem; color: var(--text-secondary); + line-height: 1.4; +} + +/* Dark mode - explicit theme */ +[data-theme='dark'] .event-tag { + color: #4ade80; + background: rgba(37, 211, 102, 0.2); + border-color: rgba(37, 211, 102, 0.35); +} + +[data-theme='dark'] .status-badge.active { + color: #4ade80; + background: rgba(37, 211, 102, 0.2); +} + +[data-theme='dark'] .webhook-url { + color: #e2e8f0; +} + +[data-theme='dark'] .webhook-meta-label { + color: #94a3b8; +} + +[data-theme='dark'] .webhook-meta-value { + color: #e2e8f0; +} + +/* Dark mode - system preference */ +@media (prefers-color-scheme: dark) { + :root:not([data-theme='light']) .event-tag { + color: #4ade80; + background: rgba(37, 211, 102, 0.2); + border-color: rgba(37, 211, 102, 0.35); + } + + :root:not([data-theme='light']) .status-badge.active { + color: #4ade80; + background: rgba(37, 211, 102, 0.2); + } + + :root:not([data-theme='light']) .webhook-url { + color: #e2e8f0; + } + + :root:not([data-theme='light']) .webhook-meta-label { + color: #94a3b8; + } + + :root:not([data-theme='light']) .webhook-meta-value { + color: #e2e8f0; + } } /* Responsive */ @@ -294,6 +375,65 @@ } } +@media (max-width: 768px) { + .webhooks-page { + padding: 1rem; + } + + .webhooks-content { + grid-template-columns: 1fr; + } + + .webhook-card { + overflow: hidden; + } + + .webhook-card-header { + flex-direction: column; + align-items: flex-start; + gap: 0.75rem; + padding: 0.875rem 1rem; + } + + .webhook-url-row { + width: 100%; + min-width: 0; + } + + .webhook-url { + font-size: 0.75rem; + } + + .webhook-card-actions { + width: 100%; + justify-content: flex-end; + } + + .webhook-card-body { + padding: 0.875rem 1rem; + } + + .webhook-meta { + flex-direction: column; + gap: 0.75rem; + } + + .webhook-meta-value { + font-size: 0.8125rem; + word-break: break-all; + } + + .events-cell { + flex-wrap: wrap; + gap: 0.375rem; + } + + .event-tag { + font-size: 0.6875rem; + padding: 0.2rem 0.5rem; + } +} + /* Toast Notification */ .toast { position: fixed; diff --git a/dashboard/src/pages/Webhooks.tsx b/dashboard/src/pages/Webhooks.tsx index ce0c647..877c76d 100644 --- a/dashboard/src/pages/Webhooks.tsx +++ b/dashboard/src/pages/Webhooks.tsx @@ -360,71 +360,78 @@ export function Webhooks() { )}
-
-
-
- {t('webhooks.columns.url')} - {t('webhooks.columns.events')} - {t('webhooks.columns.session')} - {t('webhooks.columns.status')} - {t('webhooks.columns.actions')} +
+ {webhooks.length === 0 ? ( +
+ +

{t('webhooks.empty.title')}

+

{t('webhooks.empty.description')}

- {webhooks.length === 0 ? ( -
- -

{t('webhooks.empty.title')}

-

{t('webhooks.empty.description')}

-
- ) : ( - webhooks.map(webhook => ( -
- - {webhook.url} - - - - {webhook.events.map((event: string) => ( - - {event} - - ))} - - - {sessions.find(s => s.id === webhook.sessionId)?.name || webhook.sessionId.substring(0, 8)} - - - - {webhook.active ? t('common.active') : t('common.inactive')} - - - - - {canWrite && ( - <> - + ) : ( +
+ {webhooks.map(webhook => { + const sessionName = sessions.find(s => s.id === webhook.sessionId)?.name || webhook.sessionId.substring(0, 12); + return ( +
+
+
+ + {webhook.url} +
+
- - )} - -
- )) - )} -
+ {canWrite && ( + <> + + + + )} +
+
+
+
+
+ {t('webhooks.columns.session')} + {sessionName} +
+
+ {t('webhooks.columns.status')} + + {webhook.active ? t('common.active') : t('common.inactive')} + +
+
+
+ {t('webhooks.columns.events')} +
+ {webhook.events.map((event: string) => ( + + {event} + + ))} +
+
+
+
+ ); + })} +
+ )}
From 4e9b8aa77aaa0c2f55dd5db99e1fa9e98287cbd8 Mon Sep 17 00:00:00 2001 From: ashiwanikumar Date: Mon, 18 May 2026 05:32:41 +0400 Subject: [PATCH 2/2] fix: add mobile responsive styles to all remaining dashboard pages Add breakpoints for Login, Dashboard, Infrastructure, Sessions, and global index.css. Tables convert to card layouts, modals become bottom-sheets on small screens, filters stack vertically. --- dashboard/src/index.css | 53 ++++++++++++++++++ dashboard/src/pages/Dashboard.css | 77 +++++++++++++++++++++++--- dashboard/src/pages/Infrastructure.css | 54 ++++++++++++++++++ dashboard/src/pages/Login.css | 40 +++++++++++++ dashboard/src/pages/Sessions.css | 51 +++++++++++++++++ 5 files changed, 267 insertions(+), 8 deletions(-) diff --git a/dashboard/src/index.css b/dashboard/src/index.css index 82bee6d..bb267c6 100644 --- a/dashboard/src/index.css +++ b/dashboard/src/index.css @@ -359,3 +359,56 @@ code { left: 1rem; } +/* Mobile Responsive - Global */ +@media (max-width: 768px) { + h1 { + font-size: 1.5rem; + } + + .modal { + width: 95%; + max-width: none; + margin: 1rem; + border-radius: 12px; + } + + .modal-header { + padding: 1.25rem 1.25rem 0.875rem; + } + + .modal-header h2 { + font-size: 1.125rem; + } + + .modal-body { + padding: 1.25rem; + } + + .modal-footer { + padding: 0.875rem 1.25rem 1.25rem; + } + + select { + padding: 0.625rem 2.25rem 0.625rem 0.875rem; + font-size: 0.875rem; + } +} + +@media (max-width: 480px) { + h1 { + font-size: 1.25rem; + } + + .modal-overlay { + align-items: flex-end; + } + + .modal { + width: 100%; + margin: 0; + border-radius: 16px 16px 0 0; + max-height: 90vh; + overflow-y: auto; + } +} + diff --git a/dashboard/src/pages/Dashboard.css b/dashboard/src/pages/Dashboard.css index 5e2e07a..dec903c 100644 --- a/dashboard/src/pages/Dashboard.css +++ b/dashboard/src/pages/Dashboard.css @@ -286,16 +286,77 @@ gap: 1rem; } - .table-header, - .table-row { - grid-template-columns: 1fr 1fr 1fr; - font-size: 0.8125rem; + .stat-value { + font-size: 1.5rem; } - .table-header span:nth-child(4), - .table-header span:nth-child(5), - .table-row > *:nth-child(4), - .table-row > *:nth-child(5) { + .sessions-section { + padding: 1rem; + } + + .section-header { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + margin-bottom: 1rem; + } + + /* Convert table to card layout on mobile */ + .sessions-table .table-header { display: none; } + + .sessions-table .table-row { + display: flex; + flex-direction: column; + gap: 0.5rem; + padding: 1rem; + border-bottom: 1px solid var(--border); + } + + .sessions-table .table-row:last-child { + border-bottom: none; + } + + .session-info-cell { + order: 1; + } + + .session-id { + font-size: 0.9375rem; + font-weight: 600; + } + + .phone { + order: 2; + } + + .status-pill { + order: 3; + } + + .last-active { + order: 4; + font-size: 0.75rem; + color: var(--text-muted); + } + + .actions { + order: 5; + justify-content: flex-start; + padding-top: 0.5rem; + border-top: 1px solid var(--border); + } +} + +@media (max-width: 480px) { + .dashboard { + padding: 0.75rem; + } + + .header-title { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } } diff --git a/dashboard/src/pages/Infrastructure.css b/dashboard/src/pages/Infrastructure.css index ea079ec..62f9cbb 100644 --- a/dashboard/src/pages/Infrastructure.css +++ b/dashboard/src/pages/Infrastructure.css @@ -567,3 +567,57 @@ justify-content: center; } } + +@media (max-width: 768px) { + .infrastructure-page { + padding: 0.75rem; + } + + .infra-card { + padding: 1rem; + } + + .form-row .form-group.small { + max-width: none; + } + + .form-group input, + .form-group select { + font-size: 0.875rem; + padding: 0.625rem 0.875rem; + } + + .migration-item { + grid-template-columns: 24px 1fr; + gap: 0.5rem; + } + + .migration-date { + grid-column: 2; + } + + .migration-actions { + flex-direction: column; + } + + .migration-actions button { + justify-content: center; + } + + .stat-values { + gap: 1rem; + } + + .stat-item .value { + font-size: 1rem; + } + + .page-footer { + justify-content: stretch; + } + + .page-footer button { + width: 100%; + justify-content: center; + } +} diff --git a/dashboard/src/pages/Login.css b/dashboard/src/pages/Login.css index 92f31e9..d428423 100644 --- a/dashboard/src/pages/Login.css +++ b/dashboard/src/pages/Login.css @@ -189,3 +189,43 @@ .login-footer a:hover { color: var(--text-secondary); } + +/* Mobile Responsive */ +@media (max-width: 480px) { + .login-container { + padding: 1rem; + } + + .login-card { + padding: 2rem 1.5rem; + border-radius: 10px; + } + + .logo-icon { + width: 80px; + height: 80px; + } + + .login-title { + font-size: 1.375rem; + } + + .login-subtitle { + font-size: 0.875rem; + margin-bottom: 1.5rem; + } + + .input-wrapper input { + padding: 0.625rem 2.5rem 0.625rem 0.875rem; + font-size: 0.9375rem; + } + + .connect-btn { + padding: 0.75rem 1.25rem; + font-size: 0.9375rem; + } + + .login-help { + font-size: 0.8125rem; + } +} diff --git a/dashboard/src/pages/Sessions.css b/dashboard/src/pages/Sessions.css index cb6a57a..c58e556 100644 --- a/dashboard/src/pages/Sessions.css +++ b/dashboard/src/pages/Sessions.css @@ -239,6 +239,57 @@ .sessions-grid { grid-template-columns: 1fr; } + + .sessions-page { + padding: 1rem; + } + + .filters-bar { + flex-direction: column; + gap: 0.75rem; + } + + .search-input { + max-width: none; + } + + .filter-group { + width: 100%; + justify-content: space-between; + } + + .filter-group select { + flex: 1; + } + + .header-content { + flex-direction: column; + align-items: stretch; + gap: 1rem; + } + + .sessions-page .btn-primary { + width: 100%; + justify-content: center; + } + + .session-card { + padding: 1rem; + } + + .card-actions { + flex-direction: column; + } + + .card-actions .btn-action { + justify-content: center; + } +} + +@media (max-width: 480px) { + .sessions-page { + padding: 0.75rem; + } } /* Modal Overlay */