Skip to content

Commit 07a8fc1

Browse files
committed
feat: Implement settings modal layout and functionality for agent and network configurations
1 parent 7a517ca commit 07a8fc1

2 files changed

Lines changed: 296 additions & 25 deletions

File tree

src/static/css/main.css

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,3 +3295,230 @@ body.minimap-hidden #nav-sidebar {
32953295
opacity: .55;
32963296
text-decoration: line-through;
32973297
}
3298+
3299+
/* ====================================================================================
3300+
Settings Modal Layout
3301+
==================================================================================== */
3302+
.settings-modal-container {
3303+
background: var(--bg-card);
3304+
border: 1px solid var(--border-light);
3305+
border-radius: 14px;
3306+
width: 760px;
3307+
max-width: 90vw;
3308+
height: 540px;
3309+
max-height: 90vh;
3310+
box-shadow: var(--shadow);
3311+
animation: modal-in .2s ease;
3312+
display: flex;
3313+
flex-direction: column;
3314+
overflow: hidden;
3315+
}
3316+
3317+
.settings-modal-header {
3318+
height: 56px;
3319+
padding: 0 24px;
3320+
display: flex;
3321+
align-items: center;
3322+
justify-content: space-between;
3323+
border-bottom: 1px solid var(--border);
3324+
flex-shrink: 0;
3325+
background: var(--bg-panel);
3326+
}
3327+
3328+
.settings-modal-header h3 {
3329+
font-size: 15px;
3330+
font-weight: 600;
3331+
color: var(--text-1);
3332+
}
3333+
3334+
.settings-close-btn {
3335+
background: transparent;
3336+
border: none;
3337+
color: var(--text-2);
3338+
cursor: pointer;
3339+
padding: 4px;
3340+
border-radius: 6px;
3341+
display: flex;
3342+
align-items: center;
3343+
justify-content: center;
3344+
transition: background .15s, color .15s;
3345+
}
3346+
3347+
.settings-close-btn:hover {
3348+
background: var(--bg-hover);
3349+
color: var(--text-1);
3350+
}
3351+
3352+
.settings-modal-body {
3353+
flex: 1;
3354+
display: flex;
3355+
overflow: hidden;
3356+
}
3357+
3358+
.settings-sidebar {
3359+
width: 200px;
3360+
background: var(--bg-panel);
3361+
border-right: 1px solid var(--border);
3362+
padding: 16px 12px;
3363+
display: flex;
3364+
flex-direction: column;
3365+
gap: 4px;
3366+
flex-shrink: 0;
3367+
}
3368+
3369+
.settings-nav-item {
3370+
padding: 10px 14px;
3371+
border-radius: 8px;
3372+
font-size: 13px;
3373+
font-weight: 500;
3374+
color: var(--text-2);
3375+
cursor: pointer;
3376+
transition: background .15s, color .15s;
3377+
}
3378+
3379+
.settings-nav-item:hover {
3380+
background: var(--bg-hover);
3381+
color: var(--text-1);
3382+
}
3383+
3384+
.settings-nav-item.active {
3385+
background: var(--accent-glow);
3386+
color: var(--accent);
3387+
}
3388+
3389+
body[data-theme="light"] .settings-nav-item.active {
3390+
background: rgba(37, 99, 235, .1);
3391+
}
3392+
3393+
.settings-content {
3394+
flex: 1;
3395+
background: var(--bg-base);
3396+
padding: 24px 32px;
3397+
overflow-y: auto;
3398+
}
3399+
3400+
.settings-tab-pane {
3401+
display: none;
3402+
animation: fade-in .2s ease;
3403+
}
3404+
3405+
.settings-tab-pane.active {
3406+
display: block;
3407+
}
3408+
3409+
.settings-section-title {
3410+
font-size: 11px;
3411+
font-weight: 600;
3412+
color: var(--text-3);
3413+
margin-bottom: 12px;
3414+
letter-spacing: .06em;
3415+
}
3416+
3417+
.settings-card {
3418+
border-radius: 10px;
3419+
padding: 16px;
3420+
display: flex;
3421+
flex-direction: column;
3422+
gap: 16px;
3423+
margin-bottom: 24px;
3424+
}
3425+
3426+
.settings-field {
3427+
display: flex;
3428+
flex-direction: column;
3429+
gap: 6px;
3430+
}
3431+
3432+
.settings-field-row {
3433+
flex-direction: row;
3434+
align-items: center;
3435+
justify-content: space-between;
3436+
}
3437+
3438+
.settings-field label {
3439+
font-size: 13px;
3440+
color: var(--text-1);
3441+
font-weight: 500;
3442+
}
3443+
3444+
.settings-field input[type="text"],
3445+
.settings-field input[type="number"] {
3446+
width: 100%;
3447+
background: var(--bg-input);
3448+
border: 1px solid var(--border-light);
3449+
color: var(--text-1);
3450+
border-radius: 8px;
3451+
padding: 10px 12px;
3452+
font-size: 14px;
3453+
font-family: inherit;
3454+
transition: border-color .15s;
3455+
}
3456+
3457+
.settings-field input:focus {
3458+
outline: none;
3459+
border-color: var(--accent);
3460+
}
3461+
3462+
.settings-field-note {
3463+
font-size: 12px;
3464+
color: var(--text-3);
3465+
line-height: 1.4;
3466+
}
3467+
3468+
.settings-modal-footer {
3469+
height: 64px;
3470+
padding: 0 24px;
3471+
display: flex;
3472+
align-items: center;
3473+
justify-content: flex-end;
3474+
border-top: 1px solid var(--border);
3475+
background: var(--bg-panel);
3476+
flex-shrink: 0;
3477+
}
3478+
3479+
/* Custom Toggle Switch */
3480+
.toggle-switch {
3481+
position: relative;
3482+
display: inline-block;
3483+
width: 36px;
3484+
height: 20px;
3485+
}
3486+
3487+
.toggle-switch input {
3488+
opacity: 0;
3489+
width: 0;
3490+
height: 0;
3491+
}
3492+
3493+
.toggle-slider {
3494+
position: absolute;
3495+
cursor: pointer;
3496+
top: 0;
3497+
left: 0;
3498+
right: 0;
3499+
bottom: 0;
3500+
background-color: var(--border-light);
3501+
transition: .2s;
3502+
border-radius: 20px;
3503+
}
3504+
3505+
.toggle-slider:before {
3506+
position: absolute;
3507+
content: "";
3508+
height: 14px;
3509+
width: 14px;
3510+
left: 3px;
3511+
bottom: 3px;
3512+
background-color: white;
3513+
transition: .2s;
3514+
border-radius: 50%;
3515+
box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
3516+
}
3517+
3518+
.toggle-switch input:checked+.toggle-slider {
3519+
background-color: var(--accent);
3520+
}
3521+
3522+
.toggle-switch input:checked+.toggle-slider:before {
3523+
transform: translateX(16px);
3524+
}

src/static/js/components/acb-modal-shell.js

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
(function registerAcbModalShell() {
2-
const SETTINGS_FIELDS = [
2+
const NETWORK_FIELDS = [
33
{ label: "Host", id: "setting-host", type: "text" },
44
{ label: "Port", id: "setting-port", type: "number" },
5+
];
6+
7+
const AGENT_FIELDS = [
58
{
69
label: "Agent Heartbeat Timeout (s)",
710
id: "setting-heartbeat",
@@ -13,31 +16,44 @@
1316

1417
const MINIMAP_KEY = "acb-minimap-enabled";
1518

16-
function renderSettingsFields() {
17-
return SETTINGS_FIELDS.map((field) => {
19+
function renderFields(fields) {
20+
return fields.map((field) => {
1821
const noteHtml = field.note
19-
? `<div style="font-size:11px;color:var(--text-3);margin-top:-12px;margin-bottom:16px;line-height:1.4;">${field.note}</div>`
22+
? `<div class="settings-field-note">${field.note}</div>`
2023
: "";
2124
return `
22-
<label style="display:block;font-size:13px;color:var(--text-2);margin-bottom:6px;">${field.label}</label>
23-
<input id="${field.id}" type="${field.type}"
24-
style="width:100%;background:var(--bg-input);border:1px solid var(--border-light);color:var(--text-1);border-radius:10px;padding:10px 14px;font-size:14px;font-family:inherit;margin-bottom:${field.note ? "8px" : "16px"};" />
25-
${noteHtml}`;
25+
<div class="settings-field">
26+
<label>${field.label}</label>
27+
<input id="${field.id}" type="${field.type}" />
28+
${noteHtml}
29+
</div>`;
2630
}).join("\n");
2731
}
2832

2933
function renderUiPreferences() {
3034
return `
31-
<div style="border-top:1px solid var(--border-light);margin:4px 0 16px;padding-top:16px;">
32-
<div style="font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text-2);margin-bottom:12px;">UI Preferences</div>
33-
<label style="display:flex;align-items:center;gap:10px;font-size:13px;color:var(--text-1);cursor:pointer;user-select:none;">
34-
<input id="setting-minimap" type="checkbox" style="width:15px;height:15px;cursor:pointer;accent-color:var(--accent);" />
35-
<span>Message minimap (navigation sidebar)</span>
36-
</label>
37-
<div style="font-size:11px;color:var(--text-2);margin-top:4px;padding-left:25px;">Scrollable anchor list on the right — toggle without restart.</div>
38-
</div>`;
35+
<div class="settings-field settings-field-row">
36+
<label for="setting-minimap">Message minimap (Navigation sidebar)</label>
37+
<div class="toggle-switch">
38+
<input id="setting-minimap" type="checkbox" />
39+
<span class="toggle-slider"></span>
40+
</div>
41+
</div>
42+
<div class="settings-field-note" style="margin-top: 4px;">Scrollable anchor list on the right — toggle without restart.</div>
43+
`;
3944
}
4045

46+
window.switchSettingsTab = function (tabId) {
47+
document.querySelectorAll('.settings-nav-item').forEach(el => el.classList.remove('active'));
48+
document.querySelectorAll('.settings-tab-pane').forEach(el => el.classList.remove('active'));
49+
50+
const navItem = document.getElementById('nav-' + tabId);
51+
if (navItem) navItem.classList.add('active');
52+
53+
const pane = document.getElementById('pane-' + tabId);
54+
if (pane) pane.classList.add('active');
55+
};
56+
4157
class AcbModalShell extends HTMLElement {
4258
connectedCallback() {
4359
if (this.childElementCount > 0) return;
@@ -63,15 +79,43 @@
6379
6480
<div id="settings-modal-overlay" onclick="closeSettingsModal(event)"
6581
style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.7);align-items:center;justify-content:center;z-index:100;animation:fade-in .15s ease;">
66-
<div id="settings-modal"
67-
style="background:var(--bg-card);border:1px solid var(--border-light);border-radius:14px;padding:28px;width:440px;max-width:90vw;box-shadow:var(--shadow);animation:modal-in .2s ease;"
68-
onclick="event.stopPropagation()">
69-
<h3 style="font-size:16px;font-weight:600;margin-bottom:18px;color:var(--text-1)">⚙️ MCP Server Settings</h3>
70-
${renderSettingsFields()}
71-
${renderUiPreferences()}
72-
<div id="settings-message" style="font-size:12px;color:var(--green);margin-bottom:16px;display:none;"></div>
73-
<div class="modal-actions">
74-
<button class="btn-secondary" onclick="closeSettingsModal()">Cancel</button>
82+
<div id="settings-modal" class="settings-modal-container" onclick="event.stopPropagation()">
83+
<div class="settings-modal-header">
84+
<h3>Settings - AgentChatBus</h3>
85+
<button class="settings-close-btn" onclick="closeSettingsModal()">
86+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
87+
</button>
88+
</div>
89+
<div class="settings-modal-body">
90+
<div class="settings-sidebar">
91+
<div id="nav-agent" class="settings-nav-item active" onclick="switchSettingsTab('agent')">Agent</div>
92+
<div id="nav-network" class="settings-nav-item" onclick="switchSettingsTab('network')">Network</div>
93+
<div id="nav-ui" class="settings-nav-item" onclick="switchSettingsTab('ui')">UI</div>
94+
</div>
95+
<div class="settings-content">
96+
<div id="pane-agent" class="settings-tab-pane active">
97+
<div class="settings-section-title">TIMEOUTS</div>
98+
<div class="settings-card">
99+
${renderFields(AGENT_FIELDS)}
100+
</div>
101+
</div>
102+
<div id="pane-network" class="settings-tab-pane">
103+
<div class="settings-section-title">LISTENING</div>
104+
<div class="settings-card">
105+
${renderFields(NETWORK_FIELDS)}
106+
</div>
107+
</div>
108+
<div id="pane-ui" class="settings-tab-pane">
109+
<div class="settings-section-title">PREFERENCES</div>
110+
<div class="settings-card">
111+
${renderUiPreferences()}
112+
</div>
113+
</div>
114+
</div>
115+
</div>
116+
<div class="settings-modal-footer">
117+
<div id="settings-message" style="font-size:13px;color:var(--green);display:none;"></div>
118+
<div style="flex:1"></div>
75119
<button class="btn-primary" id="btn-settings-save" onclick="submitSettings()">Save (Requires Restart)</button>
76120
</div>
77121
</div>

0 commit comments

Comments
 (0)