| ... | @@ -53,6 +53,7 @@ export function ThreadDetailsCard({ | ... | @@ -53,6 +53,7 @@ export function ThreadDetailsCard({ |
| 53 | const [measurements, setMeasurements] = useState({ | 53 | const [measurements, setMeasurements] = useState({ |
| 54 | key: measurementKey, | 54 | key: measurementKey, |
| 55 | heights: { full: 0, compact: 0 }, | 55 | heights: { full: 0, compact: 0 }, |
| | 56 | fullContentHeight: 0, |
| 56 | }); | 57 | }); |
| 57 | const contentHeights = | 58 | const contentHeights = |
| 58 | measurements.key === measurementKey ? measurements.heights : { full: 0, compact: 0 }; | 59 | measurements.key === measurementKey ? measurements.heights : { full: 0, compact: 0 }; |
| ... | @@ -64,8 +65,8 @@ export function ThreadDetailsCard({ | ... | @@ -64,8 +65,8 @@ export function ThreadDetailsCard({ |
| 64 | ? preferredPlacement.x + preferredPlacement.width | 65 | ? preferredPlacement.x + preferredPlacement.width |
| 65 | : undefined; | 66 | : undefined; |
| 66 | const cardBottom = | 67 | const cardBottom = |
| 67 | preferredPlacement && contentHeights.full > 0 | 68 | preferredPlacement && measurements.key === measurementKey && measurements.fullContentHeight > 0 |
| 68 | ? preferredPlacement.y + Math.min(contentHeights.full, preferredPlacement.height) | 69 | ? preferredPlacement.y + Math.min(measurements.fullContentHeight, preferredPlacement.height) |
| 69 | : undefined; | 70 | : undefined; |
| 70 | useLayoutEffect(() => { | 71 | useLayoutEffect(() => { |
| 71 | reportDetailsCard?.( | 72 | reportDetailsCard?.( |
| ... | @@ -88,11 +89,27 @@ export function ThreadDetailsCard({ | ... | @@ -88,11 +89,27 @@ export function ThreadDetailsCard({ |
| 88 | const measure = () => { | 89 | const measure = () => { |
| 89 | const frame = element.closest<HTMLElement>("[data-thread-details-card]"); | 90 | const frame = element.closest<HTMLElement>("[data-thread-details-card]"); |
| 90 | const next = element.offsetHeight + (frame ? frame.offsetHeight - frame.clientHeight : 0); | 91 | const next = element.offsetHeight + (frame ? frame.offsetHeight - frame.clientHeight : 0); |
| | 92 | // Lineage scrolls as it expands. Counting it toward density would hide |
| | 93 | // the section and workspace controls when the user asks to see more rows. |
| | 94 | const lineage = element.querySelector<HTMLElement>("[data-thread-relationships-panel]"); |
| | 95 | const fittingHeight = next - (lineage?.offsetHeight ?? 0); |
| 91 | setMeasurements((current) => { | 96 | setMeasurements((current) => { |
| 92 | const heights = current.key === measurementKey ? current.heights : { full: 0, compact: 0 }; | 97 | const heights = current.key === measurementKey ? current.heights : { full: 0, compact: 0 }; |
| 93 | return current.key === measurementKey && heights[density] === next | 98 | const fullContentHeight = |
| | 99 | density === "full" |
| | 100 | ? next |
| | 101 | : current.key === measurementKey |
| | 102 | ? current.fullContentHeight |
| | 103 | : 0; |
| | 104 | return current.key === measurementKey && |
| | 105 | heights[density] === fittingHeight && |
| | 106 | current.fullContentHeight === fullContentHeight |
| 94 | ? current | 107 | ? current |
| 95 | : { key: measurementKey, heights: { ...heights, [density]: next } }; | 108 | : { |
| | 109 | key: measurementKey, |
| | 110 | heights: { ...heights, [density]: fittingHeight }, |
| | 111 | fullContentHeight, |
| | 112 | }; |
| 96 | }); | 113 | }); |
| 97 | }; | 114 | }; |
| 98 | measure(); | 115 | measure(); |