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/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/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 */
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}
+
+ ))}
+
+
+
+
+ );
+ })}
+
+ )}