diff --git a/web/app.js b/web/app.js
index be5246c..42078f6 100644
--- a/web/app.js
+++ b/web/app.js
@@ -648,6 +648,30 @@
`;
}
+ function renderInlineDetail(e) {
+ const tags = (e.tags || []).map(t => `#${t}`).join('');
+ let actions = '';
+ actions += ``;
+ if (!e.card_type) {
+ actions += ``;
+ actions += ``;
+ }
+ if (e.card_type) {
+ actions += ``;
+ } else {
+ actions += ``;
+ }
+ return `
+
${escHtml(e.body || '')}
+ ${tags ? `
${tags}
` : ''}
+
${actions}
+
+
+
+
+
`;
+ }
+
function renderEntityItem(e, idx) {
const glyph = displayGlyph(e);
const gc = glyphClass(e);
@@ -668,11 +692,18 @@
}
return `
-
${glyph}
- ${label}
- ${time}
-
${tags}${cardBadge}
-
${useBadge}
+
+ ${glyph}
+ ${label}
+ ${time}
+ ${tags}${cardBadge}
+ ${useBadge}
+
+
+
+ ${renderInlineDetail(e)}
+
+
`;
}
@@ -694,21 +725,16 @@
pane.classList.add('visible');
- const mobileBar = `
-
-
-
`;
-
if (state.peekMode === 'edit') {
- pane.innerHTML = mobileBar + renderEditMode(e);
+ pane.innerHTML = renderEditMode(e);
} else if (state.view === 'stream' || !e.card_type) {
- pane.innerHTML = mobileBar + renderStreamPeek(e);
+ pane.innerHTML = renderStreamPeek(e);
} else if (state.peekMode === 'run') {
- pane.innerHTML = mobileBar + renderRunMode(e);
+ pane.innerHTML = renderRunMode(e);
} else if (state.peekMode === 'fill') {
- pane.innerHTML = mobileBar + renderFillMode(e);
+ pane.innerHTML = renderFillMode(e);
} else {
- pane.innerHTML = mobileBar + renderCardPeek(e);
+ pane.innerHTML = renderCardPeek(e);
}
bindPeekEvents(e);
@@ -1105,6 +1131,20 @@
// ========== Actions ==========
function selectEntity(idx) {
+ if (isMobileBreakpoint()) {
+ const prev = state.selectedIndex;
+ if (prev === idx) {
+ state.selectedIndex = -1;
+ } else {
+ state.selectedIndex = idx;
+ }
+ $$('.entity-item.selected').forEach(el => el.classList.remove('selected'));
+ if (state.selectedIndex >= 0) {
+ const target = $(`.entity-item[data-index="${state.selectedIndex}"]`);
+ if (target) target.classList.add('selected');
+ }
+ return;
+ }
state.selectedIndex = idx;
state.peekMode = 'preview';
state.runChecked = new Set();
@@ -1408,13 +1448,31 @@
},
togglePeekFull() {
+ if (isMobileBreakpoint()) {
+ this.expandInline();
+ return;
+ }
const pane = $('#detail-pane');
pane.classList.toggle('peek-full');
const btn = pane.querySelector('.peek-mobile-btn');
if (btn) btn.textContent = pane.classList.contains('peek-full') ? '↓' : '↑';
},
+ expandInline() {
+ const sel = $(`.entity-item.selected`);
+ if (!sel) return;
+ sel.classList.toggle('exp-full');
+ const btn = sel.querySelector('.exp-toolbar .peek-mobile-btn');
+ if (btn) btn.textContent = sel.classList.contains('exp-full') ? '↓' : '↑';
+ },
+
dismissPeek() {
+ if (isMobileBreakpoint()) {
+ const sel = $(`.entity-item.selected`);
+ if (sel) sel.classList.remove('selected', 'exp-full');
+ state.selectedIndex = -1;
+ return;
+ }
const pane = $('#detail-pane');
pane.classList.remove('visible', 'peek-full');
state.selectedIndex = -1;
@@ -1471,6 +1529,14 @@
}
if (ev.key === 'Escape') {
+ if (isMobileBreakpoint()) {
+ if (state.selectedIndex >= 0) {
+ const sel = $(`.entity-item.selected`);
+ if (sel) sel.classList.remove('selected', 'exp-full');
+ state.selectedIndex = -1;
+ return;
+ }
+ }
const pane = $('#detail-pane');
if ($('main').classList.contains('focus-peek')) {
exitFocusPeek();
diff --git a/web/style.css b/web/style.css
index fd71a34..fb7636f 100644
--- a/web/style.css
+++ b/web/style.css
@@ -375,28 +375,72 @@ main.focus-peek .resize-handle { visibility: hidden; }
}
.entity-item {
+ cursor: pointer;
+ border-left: 2px solid transparent;
+ transition: background var(--t-fast), border-left-color var(--t-fast);
+}
+
+.entity-head {
display: flex;
align-items: center;
gap: 8px;
padding: 5px 16px 5px 20px;
- cursor: pointer;
- border-left: 2px solid transparent;
min-height: 32px;
- transition: background var(--t-fast), border-left-color var(--t-fast);
}
.entity-item:hover { background: var(--surf); }
.entity-item.selected { background: var(--surf); border-left-color: var(--accent); }
+.entity-exp { display: none; }
+
+.entity-exp-clip { overflow: hidden; }
+
+.exp-inner {
+ padding: .6rem 1rem .7rem calc(20px + 14px + 8px);
+ border-top: 1px solid var(--border);
+}
+
+.exp-body {
+ font-family: var(--mono);
+ font-size: 11px;
+ color: var(--text);
+ line-height: 1.7;
+ white-space: pre-wrap;
+ word-break: break-word;
+ margin-bottom: .5rem;
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+
+.entity-item.exp-full .exp-body {
+ -webkit-line-clamp: unset;
+ overflow: visible;
+}
+
+.exp-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: .5rem; }
+
+.exp-acts { display: flex; flex-wrap: wrap; gap: 4px; }
+
+.exp-toolbar {
+ display: none;
+ justify-content: space-between;
+ margin-top: .5rem;
+ padding-top: .5rem;
+ border-top: 1px solid var(--border);
+}
+
.entity-item.is-card {
background: var(--surf);
margin: 2px 10px;
border-radius: var(--r2);
border: 1px solid var(--border);
border-left-width: 1px;
- padding: 7px 12px;
}
+.entity-item.is-card .entity-head { padding: 7px 12px; }
+
.entity-item.is-card:hover { border-color: var(--muted); }
.entity-item.is-card.selected { border-color: var(--accent); background: var(--a-bg); }
@@ -785,13 +829,6 @@ main.focus-peek .resize-handle { visibility: hidden; }
overflow: hidden;
}
-.peek-mobile-bar {
- display: none;
- justify-content: space-between;
- padding: 6px 12px;
- border-bottom: 1px solid var(--border);
-}
-
.peek-mobile-btn {
font-family: var(--mono);
font-size: 14px;
@@ -1488,8 +1525,23 @@ kbd { background: var(--raised); border: 1px solid var(--border); border-radius:
transition: transform var(--t-base);
z-index: 50;
}
- #detail-pane.visible { transform: translateY(0); }
- #detail-pane.peek-full { height: 100vh; height: 100dvh; top: 0; }
- .peek-mobile-bar { display: flex; }
+ #detail-pane { display: none !important; }
+ .entity-exp {
+ display: grid;
+ grid-template-rows: 0fr;
+ transition: grid-template-rows .2s ease;
+ }
+ .entity-item.selected .entity-exp { grid-template-rows: 1fr; }
+ .entity-item.selected .exp-toolbar { display: flex; }
+ .entity-item.exp-full {
+ position: fixed;
+ inset: 0;
+ z-index: 60;
+ background: var(--bg);
+ overflow-y: auto;
+ border-left: none;
+ }
+ .entity-item.exp-full .entity-exp { grid-template-rows: 1fr; }
+ .entity-item.exp-full .exp-inner { padding-top: 1rem; padding-bottom: 2rem; }
main.focus-peek #entity-panel { display: block; overflow: auto; min-width: 0; }
}