diff --git a/muxplex/frontend/app.js b/muxplex/frontend/app.js
index 5ea7e99..9f01d2f 100644
--- a/muxplex/frontend/app.js
+++ b/muxplex/frontend/app.js
@@ -520,15 +520,12 @@ function buildSidebarHTML(session, currentSession) {
// Edge bar only (left border amber, no glow): applied when actIndicator is 'dot' or 'both'
if (isBell && (actIndicator === 'dot' || actIndicator === 'both')) classes += ' sidebar-item--edge-bell';
- // Device badge — shown in meta line when multi_device_enabled
+ // Device badge — shown in header line when multi_device_enabled
let badgeHtml = '';
if (_serverSettings && _serverSettings.multi_device_enabled && session.deviceName && ds.showDeviceBadges !== false) {
badgeHtml = `${escapeHtml(session.deviceName)}`;
}
- // Timestamp for meta line
- const timeStr = formatTimestamp(session.last_activity_at || null);
-
// Last 20 lines of snapshot — trim trailing blanks from the FULL snapshot FIRST,
// then slice. Sessions with the cursor near the top have content at rows 1-2 and
// rows 3-40 blank; slice(-20) would return only blank rows, then trim-after-slice
@@ -544,12 +541,8 @@ function buildSidebarHTML(session, currentSession) {
`` +
`` +
- `` +
`` +
``
diff --git a/muxplex/frontend/style.css b/muxplex/frontend/style.css
index 746d789..dca90e7 100644
--- a/muxplex/frontend/style.css
+++ b/muxplex/frontend/style.css
@@ -617,21 +617,12 @@ body {
margin: 0;
}
-/* Sidebar meta line — device badge + separator + timestamp */
-.sidebar-item-meta {
- display: flex;
- align-items: center;
- gap: 4px;
- padding: 0 8px 4px;
- font-size: 10px;
- color: var(--text-muted);
+.sidebar-item-header .device-badge {
+ margin-left: auto;
+ margin-right: 4px;
flex-shrink: 0;
}
-.sidebar-meta-sep {
- opacity: 0.4;
-}
-
.sidebar-empty {
padding: 16px 12px;
color: var(--text-muted);
diff --git a/muxplex/frontend/tests/test_app.mjs b/muxplex/frontend/tests/test_app.mjs
index f481293..d5ca39e 100644
--- a/muxplex/frontend/tests/test_app.mjs
+++ b/muxplex/frontend/tests/test_app.mjs
@@ -3914,22 +3914,24 @@ test('buildTileHTML does NOT add session-tile--edge-bell when activityIndicator
_localStorageStore = {};
});
-test('buildSidebarHTML has sidebar-item-meta line (two-line header)', () => {
- const session = { name: 'my-session', snapshot: '', bell: { unseen_count: 0 }, last_activity_at: null };
+test('buildSidebarHTML has single-line header with name, badge, and delete button', () => {
+ app._setServerSettings({ multi_device_enabled: true });
+ const session = { name: 'my-session', deviceName: 'Laptop', remoteId: 'fed-abc', snapshot: '', bell: { unseen_count: 0 } };
const html = app.buildSidebarHTML(session, '');
- assert.ok(html.includes('sidebar-item-meta'), 'sidebar-item-meta element must exist in sidebar HTML');
+ const headerStart = html.indexOf('sidebar-item-header');
+ const headerEnd = html.indexOf('', headerStart);
+ const headerContent = html.substring(headerStart, headerEnd);
+ assert.ok(headerContent.includes('device-badge'), 'device-badge must be inside sidebar-item-header');
+ assert.ok(headerContent.includes('sidebar-delete'), 'sidebar-delete must be inside sidebar-item-header');
+ app._setServerSettings(null);
});
-test('buildSidebarHTML sidebar-item-meta contains sidebar-meta-sep dot separator', () => {
+test('buildSidebarHTML does not have sidebar-item-meta element', () => {
const session = { name: 'my-session', snapshot: '', bell: { unseen_count: 0 }, last_activity_at: null };
const html = app.buildSidebarHTML(session, '');
- assert.ok(html.includes('sidebar-meta-sep'), 'sidebar-meta-sep must be present in sidebar HTML');
-});
-
-test('buildSidebarHTML sidebar-item-meta contains sidebar-item-time', () => {
- const session = { name: 'my-session', snapshot: '', bell: { unseen_count: 0 }, last_activity_at: null };
- const html = app.buildSidebarHTML(session, '');
- assert.ok(html.includes('sidebar-item-time'), 'sidebar-item-time must be present in sidebar HTML');
+ assert.ok(!html.includes('sidebar-item-meta'), 'sidebar-item-meta must NOT exist in sidebar HTML');
+ assert.ok(!html.includes('sidebar-meta-sep'), 'sidebar-meta-sep must NOT exist in sidebar HTML');
+ assert.ok(!html.includes('sidebar-item-time'), 'sidebar-item-time must NOT exist in sidebar HTML');
});
test('buildSidebarHTML adds sidebar-item--edge-bell when activityIndicator is dot', () => {
@@ -3983,9 +3985,9 @@ test('CSS style.css .session-tile has border-left for edge bar', () => {
assert.ok(tileBody.includes('border-left'), '.session-tile must have border-left for edge bar');
});
-test('CSS style.css has .sidebar-item-meta rule', () => {
+test('CSS style.css has .sidebar-item-header .device-badge rule for badge right-alignment', () => {
const source = fs.readFileSync(new URL('../style.css', import.meta.url), 'utf8');
- assert.ok(source.includes('.sidebar-item-meta'), 'style.css must have .sidebar-item-meta rule');
+ assert.ok(source.includes('.sidebar-item-header .device-badge'), 'style.css must have .sidebar-item-header .device-badge rule for badge alignment in single-line header');
});
test('CSS style.css .tile-meta has opacity transition for crossfade (badge + timestamp together)', () => {