Spaces:
Running
Running
github-actions[bot] commited on
Commit ·
ba81ab3
1
Parent(s): 595055d
Deploy ddd58bf
Browse filescontent-visibility was quietly shaving the top off every enzyme name
Source: https://github.com/WINTER4000/turingDNA/commit/ddd58bf0a34a50b432f11284b3eac7f91a168ceb
- dee/static/app.css +27 -3
- dee/static/index.html +5 -5
- tests/test_plasmid_editor_ui.py +55 -0
dee/static/app.css
CHANGED
|
@@ -8103,16 +8103,40 @@ body[data-ui="bench"] #navTuring { display: none; }
|
|
| 8103 |
.seqed-line .seqed-bases { position: relative; display: inline-block; }
|
| 8104 |
.seqed-line .seqed-bases[style*="--w"] { width: calc(var(--w) * 1ch); }
|
| 8105 |
|
| 8106 |
-
/* Cut sites, above the strand. The tick is the truth; the label just names it.
|
| 8107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8108 |
.seqcut { position: absolute; bottom: 0; white-space: nowrap; }
|
| 8109 |
.seqcut-tick {
|
| 8110 |
display: block; width: 1px; height: 7px; margin-left: 0;
|
| 8111 |
background: var(--ink-soft);
|
| 8112 |
}
|
| 8113 |
.seqcut b {
|
| 8114 |
-
position: absolute; bottom:
|
| 8115 |
font-family: var(--font-ui); font-size: 9.5px; font-weight: 500;
|
|
|
|
| 8116 |
letter-spacing: .02em; color: var(--ink-soft); transform: translateX(-1px);
|
| 8117 |
}
|
| 8118 |
|
|
|
|
| 8103 |
.seqed-line .seqed-bases { position: relative; display: inline-block; }
|
| 8104 |
.seqed-line .seqed-bases[style*="--w"] { width: calc(var(--w) * 1ch); }
|
| 8105 |
|
| 8106 |
+
/* Cut sites, above the strand. The tick is the truth; the label just names it.
|
| 8107 |
+
The row must be TALL ENOUGH TO CONTAIN ITS OWN LABEL. `.seqed-line` carries
|
| 8108 |
+
`content-visibility: auto`, which applies paint containment — so anything a
|
| 8109 |
+
line paints outside its own box is clipped, silently. At `height: 15px` the
|
| 8110 |
+
label (16.1px tall at the default line-height, sitting at `bottom: 6px`)
|
| 8111 |
+
started 7.2px above the row's top edge and had that much shaved off the top
|
| 8112 |
+
of every enzyme name. Verified by hit-test, not by eye: a point inside the
|
| 8113 |
+
label but above the row returned the ancestor div with content-visibility
|
| 8114 |
+
on, and the <b> with it off.
|
| 8115 |
+
Two changes keep it inside: `line-height: 1` (a one-line 9.5px label has no
|
| 8116 |
+
use for a 1.7 line box) and a row tall enough for tick + label. Cheaper
|
| 8117 |
+
than exempting these rows from content-visibility, which would cost the
|
| 8118 |
+
repaint win that rule was added for. */
|
| 8119 |
+
.seqed-cut { height: 18px; position: relative; }
|
| 8120 |
+
/* The label's containing block is `.seqed-bases`, NOT the row — it has to be,
|
| 8121 |
+
because `left: Nch` is measured from the bases origin and that is what keeps
|
| 8122 |
+
a tick on its own base. In a cut row that span holds only absolutely
|
| 8123 |
+
positioned children, so it is zero-height, and as an inline-block its bottom
|
| 8124 |
+
lands on the line box's BASELINE — leaving a font-dependent descender gap
|
| 8125 |
+
(3px here) between it and the row's bottom edge. Every label rode that gap
|
| 8126 |
+
upward and out of the paint-contained row.
|
| 8127 |
+
`vertical-align: bottom` pins the anchor to the row's bottom edge instead,
|
| 8128 |
+
so the label's clearance is arithmetic rather than a property of whatever
|
| 8129 |
+
font happens to load. */
|
| 8130 |
+
.seqed-cut .seqed-bases { vertical-align: bottom; }
|
| 8131 |
.seqcut { position: absolute; bottom: 0; white-space: nowrap; }
|
| 8132 |
.seqcut-tick {
|
| 8133 |
display: block; width: 1px; height: 7px; margin-left: 0;
|
| 8134 |
background: var(--ink-soft);
|
| 8135 |
}
|
| 8136 |
.seqcut b {
|
| 8137 |
+
position: absolute; bottom: 7px; left: 0;
|
| 8138 |
font-family: var(--font-ui); font-size: 9.5px; font-weight: 500;
|
| 8139 |
+
line-height: 1;
|
| 8140 |
letter-spacing: .02em; color: var(--ink-soft); transform: translateX(-1px);
|
| 8141 |
}
|
| 8142 |
|
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=20260824-
|
| 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. -->
|
|
@@ -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=20260824-
|
| 3136 |
-
<script src="/static/lineage.js?v=20260824-
|
| 3137 |
-
<script src="/static/app.js?v=20260824-
|
| 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=20260824-
|
| 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-cuts3" />
|
| 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. -->
|
|
|
|
| 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-cuts3" defer></script>
|
| 3136 |
+
<script src="/static/lineage.js?v=20260824-cuts3" defer></script>
|
| 3137 |
+
<script src="/static/app.js?v=20260824-cuts3" 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-cuts3" 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_plasmid_editor_ui.py
CHANGED
|
@@ -491,3 +491,58 @@ def test_the_control_strip_has_one_height():
|
|
| 491 |
css = _code(_read(_APP_CSS))
|
| 492 |
assert re.search(r"\.pe-focus \.seqtool-find \{[^}]*height: var\(--pe-ctl-h\)", css, re.S), \
|
| 493 |
"the find group is off the shared control height again"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
css = _code(_read(_APP_CSS))
|
| 492 |
assert re.search(r"\.pe-focus \.seqtool-find \{[^}]*height: var\(--pe-ctl-h\)", css, re.S), \
|
| 493 |
"the find group is off the shared control height again"
|
| 494 |
+
|
| 495 |
+
|
| 496 |
+
def test_a_cut_row_is_tall_enough_to_paint_its_own_enzyme_name():
|
| 497 |
+
"""`.seqed-line` carries `content-visibility: auto`, which applies paint
|
| 498 |
+
containment — anything a line paints outside its own box is CLIPPED, with
|
| 499 |
+
no warning and no layout change to notice it by.
|
| 500 |
+
|
| 501 |
+
The enzyme label is absolutely positioned inside that line, so the row has
|
| 502 |
+
to be tall enough to hold it. It was not: a 16.1px label (9.5px text at the
|
| 503 |
+
default line-height) sitting at `bottom: 6px` needed 22.1px inside a 15px
|
| 504 |
+
row, and the top 7.2px of every name on the map was shaved off. Confirmed
|
| 505 |
+
by hit-test at the time — a point inside the label but above the row
|
| 506 |
+
returned the ancestor div with content-visibility on, and the <b> with it
|
| 507 |
+
off.
|
| 508 |
+
|
| 509 |
+
So this asserts the ARITHMETIC that keeps it inside, which is the thing
|
| 510 |
+
that actually has to hold. A future tweak to the font size, the offset or
|
| 511 |
+
the row height fails here rather than silently cropping the label again.
|
| 512 |
+
"""
|
| 513 |
+
css = _read(_APP_CSS)
|
| 514 |
+
|
| 515 |
+
row = _rule_bodies(css, r"\.seqed-cut")
|
| 516 |
+
assert row, ".seqed-cut rule is gone"
|
| 517 |
+
row_h = re.search(r"height:\s*([\d.]+)px", row[0])
|
| 518 |
+
assert row_h, ".seqed-cut lost its explicit height"
|
| 519 |
+
|
| 520 |
+
label = _rule_bodies(css, r"\.seqcut b")
|
| 521 |
+
assert label, ".seqcut b rule is gone"
|
| 522 |
+
body = label[0]
|
| 523 |
+
bottom = re.search(r"bottom:\s*([\d.]+)px", body)
|
| 524 |
+
size = re.search(r"font-size:\s*([\d.]+)px", body)
|
| 525 |
+
assert bottom and size, ".seqcut b lost its offset or its size"
|
| 526 |
+
|
| 527 |
+
# A one-line label with `line-height: 1` is exactly font-size tall. Without
|
| 528 |
+
# that declaration the used line box is ~1.7x, which is what overflowed.
|
| 529 |
+
assert re.search(r"line-height:\s*1\b", body), (
|
| 530 |
+
".seqcut b needs line-height: 1 — the default line box is ~1.7x the "
|
| 531 |
+
"font size and pushes the label out of the paint-contained row"
|
| 532 |
+
)
|
| 533 |
+
needed = float(bottom.group(1)) + float(size.group(1))
|
| 534 |
+
assert float(row_h.group(1)) >= needed, (
|
| 535 |
+
f".seqed-cut is {row_h.group(1)}px but the label needs {needed}px "
|
| 536 |
+
f"(bottom {bottom.group(1)}px + {size.group(1)}px of text). The top of "
|
| 537 |
+
f"every enzyme name will be clipped by content-visibility."
|
| 538 |
+
)
|
| 539 |
+
|
| 540 |
+
# The label's containing block is `.seqed-bases`, which is a zero-height
|
| 541 |
+
# inline-block in a cut row. Left on the baseline it sits a font-dependent
|
| 542 |
+
# descender gap above the row's bottom edge, and the arithmetic above stops
|
| 543 |
+
# being true. Pinning it to the bottom is what makes the sum reliable.
|
| 544 |
+
anchor = _rule_bodies(css, r"\.seqed-cut \.seqed-bases")
|
| 545 |
+
assert anchor and "vertical-align: bottom" in anchor[0], (
|
| 546 |
+
".seqed-cut .seqed-bases must be vertical-align: bottom, or the label "
|
| 547 |
+
"floats up by however much descender space the font happens to have"
|
| 548 |
+
)
|