lvwerra HF Staff Claude Fable 5 commited on
Commit
d7f74c1
·
1 Parent(s): 20d3b09

Styles: mobile viewport height, keybar, single-scroll window, send button

Browse files

.app height follows --vvh (visual viewport) on mobile so the terminal
and its control bar stay above the on-screen keyboard. Adds the
control-key bar, the conversation-window single-scroll layout (body
scrolls, output and input don't), and the reply send button.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Files changed (1) hide show
  1. web/src/styles.css +24 -7
web/src/styles.css CHANGED
@@ -243,6 +243,7 @@ body {
243
 
244
  /* card content */
245
  .ov-card { padding: 11px 14px 10px; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
 
246
  .ov-id { display: flex; align-items: center; gap: 8px; cursor: pointer; min-width: 0; }
247
  .ov-id .spacer { flex: 1; }
248
  .ov-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@@ -250,8 +251,8 @@ body {
250
  .ov-go { color: var(--muted); font-size: 12px; opacity: 0; transition: opacity 0.12s ease-out; flex: none; }
251
  .ov-card:hover .ov-go, .ov-id:focus-visible .ov-go { opacity: 1; }
252
 
253
- /* full prompt, wrapped, scrolls past a few lines */
254
- .ov-prompt { font-size: 13px; font-weight: 550; color: var(--text); white-space: pre-wrap; overflow-wrap: break-word; max-height: 160px; overflow-y: auto; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
255
  /* nothing between prompt and reply → one hairline, not two */
256
  .ov-prompt + .ov-live { border-top: none; }
257
  .ov-prompt::before { content: '❯ '; font-family: var(--font-mono); color: var(--accent); font-weight: 700; }
@@ -271,8 +272,9 @@ body {
271
  .ov-answer { font-size: 13px; line-height: 1.55; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
272
  /* live progress while running: present but clearly not the final word */
273
  .ov-answer-dim { color: var(--muted); margin-bottom: 5px; -webkit-line-clamp: 2; }
274
- /* answer flows in the card no box-in-box, scrolls past a comfortable height */
275
- .markdown.ov-md { max-height: 440px; overflow-y: auto; border: none; background: none; padding: 0; font-size: 12.5px; }
 
276
  .ov-md pre { font-size: 11px; }
277
 
278
  /* braille spinner: unmistakably a process, never an input line */
@@ -315,8 +317,12 @@ body {
315
  .ovt-gn { color: var(--border-strong); }
316
  /* conversation window: the full card, centered over the grid */
317
  .ovw-backdrop { position: fixed; inset: 0; z-index: 120; display: flex; align-items: flex-start; justify-content: center; padding: 7vh 20px 20px; background: color-mix(in srgb, #000 52%, transparent); backdrop-filter: blur(3px); animation: rise-in 0.15s ease-out; }
318
- .ovw-win { width: 100%; max-width: 640px; max-height: 82vh; overflow-y: auto; background: var(--panel); border: 1px solid var(--border); border-radius: 13px; box-shadow: 0 24px 60px rgb(0 0 0 / 0.4); }
319
- .ovw-win .ov-card { padding: 14px 17px 12px; }
 
 
 
 
320
  .ov-x { background: none; border: none; color: var(--muted); font-size: 13px; cursor: pointer; padding: 0 2px 0 8px; flex: none; }
321
  .ov-x:hover { color: var(--text); }
322
 
@@ -326,6 +332,9 @@ body {
326
  .ov-live textarea { flex: 1; min-width: 0; border: none; background: none; font: inherit; font-size: 13px; line-height: 1.45; color: var(--text); outline: none; padding: 2px 0; resize: none; overflow: hidden; max-height: 140px; }
327
  .ov-live textarea::placeholder { color: var(--muted); opacity: 0.7; }
328
  .ov-hint { font-size: 10.5px; color: var(--muted); flex: none; }
 
 
 
329
  .ov-note { font-size: 11px; color: var(--danger); }
330
 
331
  /* tree */
@@ -553,6 +562,11 @@ body {
553
  .slot.focused .pane-head { background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
554
 
555
  .term-host { flex: 1; min-height: 0; padding: 10px 8px 8px 12px; background: var(--term-bg); }
 
 
 
 
 
556
  .term-host .xterm { height: 100%; }
557
  .xterm .xterm-viewport { scrollbar-width: none; }
558
  .xterm .xterm-viewport::-webkit-scrollbar { width: 0; height: 0; display: none; }
@@ -802,7 +816,10 @@ a.btn-ghost { text-decoration: none; }
802
 
803
  /* phones: two full-screen views — the sidebar list, or the selected pane */
804
  @media (max-width: 720px) {
805
- .app { height: 100dvh; }
 
 
 
806
  .app.m-home .main { display: none; }
807
  .app.m-home .sidebar { width: 100%; border-right: none; }
808
  .app.m-stage .sidebar { display: none; }
 
243
 
244
  /* card content */
245
  .ov-card { padding: 11px 14px 10px; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
246
+ .ov-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
247
  .ov-id { display: flex; align-items: center; gap: 8px; cursor: pointer; min-width: 0; }
248
  .ov-id .spacer { flex: 1; }
249
  .ov-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
 
251
  .ov-go { color: var(--muted); font-size: 12px; opacity: 0; transition: opacity 0.12s ease-out; flex: none; }
252
  .ov-card:hover .ov-go, .ov-id:focus-visible .ov-go { opacity: 1; }
253
 
254
+ /* full prompt, wrapped — the card body scrolls, so no inner scroll here */
255
+ .ov-prompt { font-size: 13px; font-weight: 550; color: var(--text); white-space: pre-wrap; overflow-wrap: break-word; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
256
  /* nothing between prompt and reply → one hairline, not two */
257
  .ov-prompt + .ov-live { border-top: none; }
258
  .ov-prompt::before { content: '❯ '; font-family: var(--font-mono); color: var(--accent); font-weight: 700; }
 
272
  .ov-answer { font-size: 13px; line-height: 1.55; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
273
  /* live progress while running: present but clearly not the final word */
274
  .ov-answer-dim { color: var(--muted); margin-bottom: 5px; -webkit-line-clamp: 2; }
275
+ /* answer flows in the card at natural height the window body is the single
276
+ scroll region, so no inner scrollbar here */
277
+ .markdown.ov-md { border: none; background: none; padding: 0; font-size: 12.5px; }
278
  .ov-md pre { font-size: 11px; }
279
 
280
  /* braille spinner: unmistakably a process, never an input line */
 
317
  .ovt-gn { color: var(--border-strong); }
318
  /* conversation window: the full card, centered over the grid */
319
  .ovw-backdrop { position: fixed; inset: 0; z-index: 120; display: flex; align-items: flex-start; justify-content: center; padding: 7vh 20px 20px; background: color-mix(in srgb, #000 52%, transparent); backdrop-filter: blur(3px); animation: rise-in 0.15s ease-out; }
320
+ /* window is a flex column: header + scrolling body + fixed input. Only the
321
+ body scrolls (one scrollbar), the reply input stays put at the bottom. */
322
+ .ovw-win { width: 100%; max-width: 640px; max-height: 85vh; display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--border); border-radius: 13px; box-shadow: 0 24px 60px rgb(0 0 0 / 0.4); overflow: hidden; }
323
+ .ovw-win .ov-card { flex: 1; min-height: 0; padding: 14px 17px 12px; }
324
+ .ovw-win .ov-body { flex: 1; min-height: 0; overflow-y: auto; }
325
+ .ovw-win .ov-live { flex: none; }
326
  .ov-x { background: none; border: none; color: var(--muted); font-size: 13px; cursor: pointer; padding: 0 2px 0 8px; flex: none; }
327
  .ov-x:hover { color: var(--text); }
328
 
 
332
  .ov-live textarea { flex: 1; min-width: 0; border: none; background: none; font: inherit; font-size: 13px; line-height: 1.45; color: var(--text); outline: none; padding: 2px 0; resize: none; overflow: hidden; max-height: 140px; }
333
  .ov-live textarea::placeholder { color: var(--muted); opacity: 0.7; }
334
  .ov-hint { font-size: 10.5px; color: var(--muted); flex: none; }
335
+ /* send button — essential on mobile (no Shift+Enter), handy on desktop */
336
+ .ov-send { flex: none; width: 26px; height: 26px; border: none; border-radius: 999px; background: var(--accent); color: var(--accent-fg); font-size: 14px; line-height: 1; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
337
+ .ov-send:disabled { opacity: 0.5; cursor: default; }
338
  .ov-note { font-size: 11px; color: var(--danger); }
339
 
340
  /* tree */
 
562
  .slot.focused .pane-head { background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
563
 
564
  .term-host { flex: 1; min-height: 0; padding: 10px 8px 8px 12px; background: var(--term-bg); }
565
+ /* mobile control-key bar: the keys a phone keyboard lacks, pinned below the
566
+ terminal so it rides just above the on-screen keyboard */
567
+ .term-keybar { flex: none; display: flex; gap: 5px; padding: 5px 6px; background: var(--panel); border-top: 1px solid var(--border); overflow-x: auto; }
568
+ .tk-btn { flex: 1 0 auto; min-width: 34px; height: 30px; border: 1px solid var(--border-strong); border-radius: var(--r-md); background: var(--panel-2); color: var(--text); font-size: 13px; line-height: 1; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; user-select: none; -webkit-user-select: none; touch-action: manipulation; }
569
+ .tk-btn:active { background: color-mix(in srgb, var(--accent) 22%, var(--panel-2)); border-color: var(--accent); }
570
  .term-host .xterm { height: 100%; }
571
  .xterm .xterm-viewport { scrollbar-width: none; }
572
  .xterm .xterm-viewport::-webkit-scrollbar { width: 0; height: 0; display: none; }
 
816
 
817
  /* phones: two full-screen views — the sidebar list, or the selected pane */
818
  @media (max-width: 720px) {
819
+ /* Height follows the VISUAL viewport (set by App from window.visualViewport):
820
+ when the on-screen keyboard opens it shrinks the app so the terminal +
821
+ control bar stay above the keyboard instead of hiding behind it. */
822
+ .app { height: var(--vvh, 100dvh); overflow: hidden; }
823
  .app.m-home .main { display: none; }
824
  .app.m-home .sidebar { width: 100%; border-right: none; }
825
  .app.m-stage .sidebar { display: none; }