perf: tag the center column instead of a :has() selector; stop re-stringifying the editor doc per keystroke
The bottom-push rule anchored on #root :has(> [data-slot=conversation]): a :has() match cache invalidates on every #root subtree mutation, and the streaming chat mutates that subtree constantly — every layout-push frame (the bottom drag writes --dsh-sidebar-height per frame) paid a whole-document selector re-evaluation. The shell's locator (which already holds the measured column node for the ResizeObserver) now tags it with [data-dsh-center-col]; the rule evaluates once per node. The tag retargets with the ref on boot swap / HMR node replacement and is removed on unmount; the drag lane pins exactly-one-tagged-node and its identity as the conversation slot wrapper's parent. The dead [data-pane] branch (renamed away in alpha hosts) is gone. TextEditor: the CodeMirror updateListener re-stringified the WHOLE document into React state on every keystroke (O(docLength) per key, re-rendering the shell per key). The listener now only flips the dirty flag; the preview's draft is snapshotted from the live view when entering preview (or on a content swap), and save() already reads the live document.
This commit is contained in:
+12
-12
@@ -35,14 +35,16 @@
|
||||
width var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
||||
}
|
||||
|
||||
/* The AppFrame's center column, anchored by data attributes (see above).
|
||||
Composite selector: DSH 0.1.x versions name the center grid item
|
||||
`[data-pane="conversation"]`, while rc.8-era shells put a
|
||||
`[data-slot="conversation"]` child inside it — both selectors resolve to
|
||||
the SAME element on live pages (verified), and keeping both future-proofs
|
||||
the rule against a host rename without touching shell-specific markup. */
|
||||
#root [data-dsh-frame] > [data-pane="conversation"],
|
||||
#root :has(> [data-slot="conversation"]) {
|
||||
/* The AppFrame's center column. The Sidebar shell's locator (Sidebar.tsx
|
||||
locate/measureCenter) tags the measured column node with
|
||||
[data-dsh-center-col] — one attribute write per node lifetime. The rule
|
||||
used to anchor on a structural has()-selector over the conversation slot
|
||||
wrapper, whose match cache invalidates on every #root subtree mutation
|
||||
(the streaming chat mutates it constantly), re-evaluating the selector
|
||||
against the whole document; the tag is evaluated once per node instead.
|
||||
A stretched grid item shrinks by its margins, so the conversation
|
||||
content (output + input bar) lifts without touching the sidebars. */
|
||||
#root [data-dsh-center-col] {
|
||||
margin-bottom: var(--dsh-sidebar-height, 0px);
|
||||
/* Grid/flex items default to min-height:auto. A long unbreakable token
|
||||
(OAuth URL) then grows this column past the viewport and clips the
|
||||
@@ -68,8 +70,7 @@ body[data-dsh-sidebar-collapsed] [data-slot="conversation.session.header"] > hea
|
||||
}
|
||||
|
||||
body[data-dsh-sidebar-dragging] #root,
|
||||
body[data-dsh-sidebar-dragging] #root [data-dsh-frame] > [data-pane="conversation"],
|
||||
body[data-dsh-sidebar-dragging] #root :has(> [data-slot="conversation"]) {
|
||||
body[data-dsh-sidebar-dragging] #root [data-dsh-center-col] {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
@@ -94,8 +95,7 @@ body[data-dsh-sidebar-dragging] #root :has(> [data-slot="conversation"]) {
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
#root,
|
||||
#root [data-dsh-frame] > [data-pane="conversation"],
|
||||
#root :has(> [data-slot="conversation"]) {
|
||||
#root [data-dsh-center-col] {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user