github-actions[bot] commited on
Commit
490c735
Β·
1 Parent(s): 8594c9f

Deploy 89f5564

Browse files

The composer chip was stealing the whole input

Source: https://github.com/WINTER4000/turingDNA/commit/89f55640721fd670b6f18460c232eaf6c79b590c

dee/static/app.css CHANGED
@@ -7936,11 +7936,11 @@ body[data-ui="bench"] #navTuring { display: none; }
7936
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
7937
  padding: 9px 14px; border-bottom: 1px solid var(--line);
7938
  background: var(--bg-raised); flex: 0 0 auto;
7939
- /* Wrap, don't clip. The tools row is `flex: 0 0 auto` β€” it cannot shrink,
7940
- by design, because a button narrower than its label is the bug this
7941
- header already had once. So when the pane gets too narrow for one row,
7942
- the honest outcome is a second row, not a control sliced in half by
7943
- the overflow below. */
7944
  /* Nothing escapes the header. `align-items: baseline` also mis-aligned
7945
  the 11px hint against 24px buttons β€” the text sat low enough to look
7946
  like it belonged to the row below. */
@@ -8339,13 +8339,20 @@ body[data-pe-full="1"] .pe-fullbar { display: flex; }
8339
  to send, not as a notification about something that already happened. */
8340
  .cp-selchip {
8341
  display: flex; align-items: center; gap: 8px;
8342
- margin: 0 0 8px; padding: 5px 6px 5px 11px;
 
 
 
 
8343
  border: 1px solid var(--line-strong); border-radius: 75px;
8344
  background: var(--bg-raised);
8345
  font-family: var(--font-mono); font-size: 11px; color: var(--ink-soft);
8346
  max-width: 100%;
8347
  }
8348
  .cp-selchip-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
 
 
 
8349
  .cp-selchip-x {
8350
  flex: 0 0 auto; width: 20px; height: 20px; margin-left: auto;
8351
  display: grid; place-items: center;
@@ -8353,6 +8360,13 @@ body[data-pe-full="1"] .pe-fullbar { display: flex; }
8353
  color: var(--ink-faint); font-size: 14px; line-height: 1; cursor: pointer;
8354
  }
8355
  .cp-selchip-x:hover { background: var(--bg-app); color: var(--ink); }
 
 
 
 
 
 
 
8356
 
8357
  /* ═══════════════════════════════════════════════════════════════════════
8358
  THE STAGE β€” what the agent is doing, shown ON the workspace.
@@ -9123,15 +9137,35 @@ body[data-cockpit]:not([data-bench="open"]) .cockpit { top: 0; }
9123
 
9124
  /* ── composer ───────────────────────────────────────────────────────── */
9125
  .cp-compose {
9126
- flex: 0 0 auto; display: flex; align-items: flex-end; gap: 6px;
9127
- margin: 10px 12px 12px; padding: 4px 4px 4px 16px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9128
  border: 1px solid var(--line-strong); border-radius: 22px;
9129
  background: var(--bg-app);
9130
  }
9131
  .cp-compose:focus-within { border-color: var(--ink-soft); box-shadow: 0 0 0 3px var(--brand-ring); }
9132
  .cp-compose textarea {
9133
  flex: 1; resize: none; border: 0; border-radius: 0;
9134
- padding: 8px 0; font: inherit; line-height: 1.45;
9135
  background: none; color: var(--ink); font-family: inherit;
9136
  /* The global `textarea { min-height: 160px }` above is for SEQUENCE
9137
  boxes. It also hit the chat composer, which only set max-height: 160px
@@ -9160,6 +9194,16 @@ body[data-cockpit]:not([data-bench="open"]) .cockpit { top: 0; }
9160
  color: var(--on-ink); font-size: 15px; line-height: 1;
9161
  }
9162
  .cp-send:hover { opacity: 0.86; }
 
 
 
 
 
 
 
 
 
 
9163
 
9164
  /* ── Model picker, under the composer ────────────────────────────────────
9165
  Deliberately quiet: it is a setting you touch rarely, sitting under the one
@@ -9309,7 +9353,7 @@ body[data-cockpit]:not([data-bench="open"]) .cockpit { top: 0; }
9309
  reopen, which is why the rail felt like a modal. */
9310
  body[data-cockpit="min"] .cp-transcript,
9311
  body[data-cockpit="min"] .cp-meter { display: none; }
9312
- body[data-cockpit="min"] .cp-compose { display: flex; }
9313
 
9314
  /* A desktop rule pins the rail to top:0 when it's a full-height column
9315
  beside the canvas. On a phone the rail is the BOTTOM half, so `bottom`
@@ -10155,7 +10199,7 @@ body.de-agent-run .dna-edit-actions { display: none; }
10155
  slide-over: this is a bottom sheet again. */
10156
  body[data-cockpit="min"] .cp-transcript,
10157
  body[data-cockpit="min"] .cp-meter { display: none; }
10158
- body[data-cockpit="min"] .cp-compose { display: flex; }
10159
  body[data-cockpit="min"] .cp-head {
10160
  writing-mode: horizontal-tb; height: auto;
10161
  justify-content: space-between; padding: 12px 12px 8px; gap: 10px;
 
7936
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
7937
  padding: 9px 14px; border-bottom: 1px solid var(--line);
7938
  background: var(--bg-raised); flex: 0 0 auto;
7939
+ /* Wrap, don't clip. The tools row wraps internally and the hint beside
7940
+ it yields first (see .pe-pane-hint), so a narrow pane costs a second
7941
+ row of buttons rather than a control sliced in half by the overflow
7942
+ below. Buttons themselves stay `flex: 0 0 auto` β€” one narrower than
7943
+ its own label is the bug this header already had once. */
7944
  /* Nothing escapes the header. `align-items: baseline` also mis-aligned
7945
  the 11px hint against 24px buttons β€” the text sat low enough to look
7946
  like it belonged to the row below. */
 
8339
  to send, not as a notification about something that already happened. */
8340
  .cp-selchip {
8341
  display: flex; align-items: center; gap: 8px;
8342
+ /* Spans both composer columns, so it sits ABOVE the input rather than
8343
+ beside it. `1 / -1` (not `span 2`) keeps it correct if a column is ever
8344
+ added. */
8345
+ grid-column: 1 / -1;
8346
+ margin: 0 0 6px; padding: 5px 6px 5px 11px;
8347
  border: 1px solid var(--line-strong); border-radius: 75px;
8348
  background: var(--bg-raised);
8349
  font-family: var(--font-mono); font-size: 11px; color: var(--ink-soft);
8350
  max-width: 100%;
8351
  }
8352
  .cp-selchip-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
8353
+ /* The range never shrinks: it is the part of the chip you cannot get from
8354
+ anywhere else on screen. The name above it yields instead. */
8355
+ .cp-selchip-n { flex: 0 0 auto; white-space: nowrap; color: var(--ink-faint); }
8356
  .cp-selchip-x {
8357
  flex: 0 0 auto; width: 20px; height: 20px; margin-left: auto;
8358
  display: grid; place-items: center;
 
8360
  color: var(--ink-faint); font-size: 14px; line-height: 1; cursor: pointer;
8361
  }
8362
  .cp-selchip-x:hover { background: var(--bg-app); color: var(--ink); }
8363
+ /* `[hidden]` is a UA rule (`display: none`) and loses to ANY author
8364
+ `display:` β€” including the `display: flex` above. So with nothing selected
8365
+ the chip kept its border and padding and rendered as a stray 19x12 pill
8366
+ inside the composer, permanently. Same class of bug that
8367
+ tests/test_hidden_attribute.py guards against; invisible to that test
8368
+ because this node is built in cockpit.js, not in index.html. */
8369
+ .cp-selchip[hidden] { display: none; }
8370
 
8371
  /* ═══════════════════════════════════════════════════════════════════════
8372
  THE STAGE β€” what the agent is doing, shown ON the workspace.
 
9137
 
9138
  /* ── composer ───────────────────────────────────────────────────────── */
9139
  .cp-compose {
9140
+ /* GRID, not flex. The attached-region chip is a CHILD of this form, and
9141
+ under flex it became a third item on the SAME ROW as the textarea and
9142
+ the send button. A chip carrying a construct name runs ~340px wide and
9143
+ cannot shrink; the textarea is `flex: 1 1 0%`, so it absorbed the whole
9144
+ shortfall, collapsed to 0px, and shoved the send button 39px OUTSIDE
9145
+ the rounded border. Two columns plus an auto-placed full-width chip row
9146
+ mean the chip can never take the input's width away from it again.
9147
+ Auto-placement handles both states: with the chip display:none it is
9148
+ not a grid item, so the input and send sit on row 1 and no empty row
9149
+ is reserved. */
9150
+ flex: 0 0 auto;
9151
+ display: grid;
9152
+ grid-template-columns: minmax(0, 1fr) auto;
9153
+ align-items: end;
9154
+ column-gap: 6px;
9155
+ margin: 10px 12px 12px;
9156
+ /* Symmetric. This was `4px 4px 4px 16px` β€” 16px of inset on the left and
9157
+ 4px on the right, which is what makes the bar read as lopsided. The
9158
+ text's 16px inset now comes from the textarea's own padding-left, so
9159
+ the shell can inset the chip and the send button equally on both
9160
+ sides. */
9161
+ padding: 5px;
9162
  border: 1px solid var(--line-strong); border-radius: 22px;
9163
  background: var(--bg-app);
9164
  }
9165
  .cp-compose:focus-within { border-color: var(--ink-soft); box-shadow: 0 0 0 3px var(--brand-ring); }
9166
  .cp-compose textarea {
9167
  flex: 1; resize: none; border: 0; border-radius: 0;
9168
+ padding: 8px 0 8px 11px; font: inherit; line-height: 1.45;
9169
  background: none; color: var(--ink); font-family: inherit;
9170
  /* The global `textarea { min-height: 160px }` above is for SEQUENCE
9171
  boxes. It also hit the chat composer, which only set max-height: 160px
 
9194
  color: var(--on-ink); font-size: 15px; line-height: 1;
9195
  }
9196
  .cp-send:hover { opacity: 0.86; }
9197
+ @media (min-width: 901px) {
9198
+ /* Matched to the textarea's one-line height. At 32px against a 34px input
9199
+ the bottoms aligned (align-items: end) but the tops did not, so the
9200
+ button sat 2px low in the pill β€” the other half of "asymmetric".
9201
+ This block sits AFTER `.cp-send` deliberately: same specificity, so the
9202
+ later rule is the one that wins. Written above the base rule first, it
9203
+ lost silently and the button stayed 32px. On a phone the 46px
9204
+ tap-target floor further down outranks this on purpose. */
9205
+ .cp-send { width: 34px; height: 34px; }
9206
+ }
9207
 
9208
  /* ── Model picker, under the composer ────────────────────────────────────
9209
  Deliberately quiet: it is a setting you touch rarely, sitting under the one
 
9353
  reopen, which is why the rail felt like a modal. */
9354
  body[data-cockpit="min"] .cp-transcript,
9355
  body[data-cockpit="min"] .cp-meter { display: none; }
9356
+ body[data-cockpit="min"] .cp-compose { display: grid; }
9357
 
9358
  /* A desktop rule pins the rail to top:0 when it's a full-height column
9359
  beside the canvas. On a phone the rail is the BOTTOM half, so `bottom`
 
10199
  slide-over: this is a bottom sheet again. */
10200
  body[data-cockpit="min"] .cp-transcript,
10201
  body[data-cockpit="min"] .cp-meter { display: none; }
10202
+ body[data-cockpit="min"] .cp-compose { display: grid; }
10203
  body[data-cockpit="min"] .cp-head {
10204
  writing-mode: horizontal-tb; height: auto;
10205
  justify-content: space-between; padding: 12px 12px 8px; gap: 10px;
dee/static/cockpit.js CHANGED
@@ -1905,8 +1905,13 @@
1905
  if (!el) return;
1906
  if (!_sel) { el.hidden = true; el.innerHTML = ""; return; }
1907
  el.hidden = false;
1908
- el.innerHTML = '<span class="cp-selchip-t">'
1909
- + esc(_sel.name) + " \u00b7 " + _sel.from.toLocaleString()
 
 
 
 
 
1910
  + "\u2013" + _sel.to.toLocaleString()
1911
  + " (" + _sel.length.toLocaleString() + " bp)</span>"
1912
  + '<button type="button" class="cp-selchip-x" aria-label="Don\'t send this selection">\u00d7</button>';
 
1905
  if (!el) return;
1906
  if (!_sel) { el.hidden = true; el.innerHTML = ""; return; }
1907
  el.hidden = false;
1908
+ // Name and coordinates are SEPARATE spans on purpose. As one string
1909
+ // the whole thing ellipsised from the right, so a long construct name
1910
+ // ate the coordinates β€” "pCambia2300-LUX6_-_SEB - 7,347-8,810 (1,464 b…"
1911
+ // dropped the one part you cannot reconstruct from the editor title.
1912
+ // Now the name truncates and the range always survives.
1913
+ el.innerHTML = '<span class="cp-selchip-t">' + esc(_sel.name) + '</span>'
1914
+ + '<span class="cp-selchip-n">' + _sel.from.toLocaleString()
1915
  + "\u2013" + _sel.to.toLocaleString()
1916
  + " (" + _sel.length.toLocaleString() + " bp)</span>"
1917
  + '<button type="button" class="cp-selchip-x" aria-label="Don\'t send this selection">\u00d7</button>';
dee/static/index.html CHANGED
@@ -112,7 +112,7 @@
112
  <!-- ?v= query bumps invalidate browser + iframe asset caches when app.css /
113
  app.js change. Bump these numbers whenever you ship a frontend update β€”
114
  without them, users keep getting the stale file for up to a week. -->
115
- <link rel="stylesheet" href="/static/app.css?v=20260823-grid2" />
116
  <!-- The work catalog + the draggable rail. Kept out of app.css so two new
117
  self-contained surfaces stay reviewable; every colour is an app.css
118
  token, so both themes work with nothing added. -->
@@ -2394,7 +2394,7 @@
2394
  <button class="pe-mapbtn pe-mapbtn--icon" type="button" id="peZoomIn" title="Zoom in" aria-label="Zoom in">+</button>
2395
  <button class="pe-mapbtn" type="button" id="peZoomFit" title="Fit the whole map">Fit</button>
2396
  <button class="pe-mapbtn" type="button" id="peZoomSel"
2397
- title="Zoom the map to the selected region">To sel</button>
2398
  <!-- The map draws unique cutters by
2399
  default: an enzyme that cuts once is
2400
  a cloning handle, one that cuts
@@ -3132,9 +3132,9 @@
3132
  <!-- Cloning reference data must load before app.js so the Designer
3133
  can read VECTORS / ENZYMES / CLONING_METHODS / TAGS / LINKERS. -->
3134
  <script src="/static/cloning_db.js?v=20260530-ui-polish" defer></script>
3135
- <script src="/static/context.js?v=20260823-grid2" defer></script>
3136
- <script src="/static/lineage.js?v=20260823-grid2" defer></script>
3137
- <script src="/static/app.js?v=20260823-grid2" defer></script>
3138
  <!-- The decision trace, BEFORE cockpit.js: applyEvent calls TDTrace.push
3139
  on the very first event, and both are `defer`, so document order is
3140
  load order. Loading it after would drop the opening events of a
@@ -3143,7 +3143,7 @@
3143
  <!-- THE COCKPIT β€” the persistent orchestrator rail. Loads after app.js so
3144
  TDBench/TDStructure exist when a tool result asks the workspace to
3145
  render something. This is the only conversation surface in the app. -->
3146
- <script src="/static/cockpit.js?v=20260823-grid2" defer></script>
3147
  <!-- structcard before catalog: the catalog calls TDStructCard.observe as
3148
  soon as it paints. Both are defer, so document order is load order. -->
3149
  <script src="/static/structcard.js?v=20260811-buildC" defer></script>
 
112
  <!-- ?v= query bumps invalidate browser + iframe asset caches when app.css /
113
  app.js change. Bump these numbers whenever you ship a frontend update β€”
114
  without them, users keep getting the stale file for up to a week. -->
115
+ <link rel="stylesheet" href="/static/app.css?v=20260824-composer4" />
116
  <!-- The work catalog + the draggable rail. Kept out of app.css so two new
117
  self-contained surfaces stay reviewable; every colour is an app.css
118
  token, so both themes work with nothing added. -->
 
2394
  <button class="pe-mapbtn pe-mapbtn--icon" type="button" id="peZoomIn" title="Zoom in" aria-label="Zoom in">+</button>
2395
  <button class="pe-mapbtn" type="button" id="peZoomFit" title="Fit the whole map">Fit</button>
2396
  <button class="pe-mapbtn" type="button" id="peZoomSel"
2397
+ title="Zoom the map to the selected region">Selection</button>
2398
  <!-- The map draws unique cutters by
2399
  default: an enzyme that cuts once is
2400
  a cloning handle, one that cuts
 
3132
  <!-- Cloning reference data must load before app.js so the Designer
3133
  can read VECTORS / ENZYMES / CLONING_METHODS / TAGS / LINKERS. -->
3134
  <script src="/static/cloning_db.js?v=20260530-ui-polish" defer></script>
3135
+ <script src="/static/context.js?v=20260824-composer4" defer></script>
3136
+ <script src="/static/lineage.js?v=20260824-composer4" defer></script>
3137
+ <script src="/static/app.js?v=20260824-composer4" defer></script>
3138
  <!-- The decision trace, BEFORE cockpit.js: applyEvent calls TDTrace.push
3139
  on the very first event, and both are `defer`, so document order is
3140
  load order. Loading it after would drop the opening events of a
 
3143
  <!-- THE COCKPIT β€” the persistent orchestrator rail. Loads after app.js so
3144
  TDBench/TDStructure exist when a tool result asks the workspace to
3145
  render something. This is the only conversation surface in the app. -->
3146
+ <script src="/static/cockpit.js?v=20260824-composer4" defer></script>
3147
  <!-- structcard before catalog: the catalog calls TDStructCard.observe as
3148
  soon as it paints. Both are defer, so document order is load order. -->
3149
  <script src="/static/structcard.js?v=20260811-buildC" defer></script>
tests/test_mobile_reach.py CHANGED
@@ -194,8 +194,18 @@ def test_the_small_detent_is_a_working_state_not_a_closed_one():
194
  Hiding the composer would turn it into a dead bar you can only reopen,
195
  which is what made the rail feel like a modal."""
196
  block = _all_phone_css(_read(_APP_CSS))
197
- m = re.search(r'body\[data-cockpit="min"\] \.cp-compose \{([^}]*)\}', block)
198
- assert m and "display: flex" in m.group(1), "peek must keep the composer"
 
 
 
 
 
 
 
 
 
 
199
  # and the transcript is what yields, not the head β€” the head carries the
200
  # live status, so "Designing guides…" is readable at 132px.
201
  assert 'body[data-cockpit="min"] .cp-transcript' in block
 
194
  Hiding the composer would turn it into a dead bar you can only reopen,
195
  which is what made the rail feel like a modal."""
196
  block = _all_phone_css(_read(_APP_CSS))
197
+ # The guarantee is that the composer is still DISPLAYED at peek β€” not
198
+ # which layout mode it uses. It was `display: flex` until the attached-
199
+ # region chip was given its own row and the composer became a grid;
200
+ # pinning the mechanism made a correct change look like a regression.
201
+ # An author `display: none` here is the thing that would actually break
202
+ # peek, so that is what this asserts. Every occurrence, not the first:
203
+ # two phone blocks set this and `re.search` would only ever see one.
204
+ decls = re.findall(r'body\[data-cockpit="min"\] \.cp-compose \{([^}]*)\}', block)
205
+ assert decls, "peek must keep the composer"
206
+ for d in decls:
207
+ assert "display:" in d and "display: none" not in d, (
208
+ "peek must keep the composer visible, got: " + d.strip())
209
  # and the transcript is what yields, not the head β€” the head carries the
210
  # live status, so "Designing guides…" is readable at 132px.
211
  assert 'body[data-cockpit="min"] .cp-transcript' in block