@botiverse/raft-ui 0.95.2 → 0.95.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [0.95.3](https://github.com/botiverse/raft-design/compare/v0.95.2...v0.95.3) (2026-11-12)
2
+
3
+ ### Fixed
4
+
5
+ - **A label/value list that switches layout on a resize no longer raises a ResizeObserver loop error** ([DescriptionList › Labels go above only when a value doesn't fit](https://raft-design.botiverse.build/components/description-list/#labels-go-above-only-when-a-value-doesnt-fit)). A horizontal `DescriptionList` and `MessageActionCard`'s properties decide whether their labels go above their values (`useLabelValueFit`) in the next animation frame after a resize, instead of inside the ResizeObserver's callback; several resizes before that frame share one decision. The first frame, a label or value changing and a web font arriving are still decided before the paint.
6
+ - Why: the hook observes the list and every value's children; when a value's notification flipped `data-stacked`, the list's height changed while the observer was still delivering, and the browser fired "ResizeObserver loop completed with undelivered notifications" as a window error. Hosts that surface window errors, such as the Artifact viewer, showed it as a failure (a horizontal DescriptionList in an Artifact page at 1781px).
7
+ - Affects: a resize that crosses the boundary stacks or unstacks the labels one frame later; nothing else changes.
8
+ - Docs: https://raft-design.botiverse.build/components/description-list/#labels-go-above-only-when-a-value-doesnt-fit
9
+
1
10
  ## [0.95.2](https://github.com/botiverse/raft-design/compare/v0.95.1...v0.95.2) (2026-11-12)
2
11
 
3
12
  ### Added
@@ -90,11 +90,17 @@ function labelsGoAbove(list, parts) {
90
90
  /**
91
91
  * Sets `data-stacked` on a two-column label/value list while its labels have
92
92
  * to go above their values (`labelsGoAbove`), and takes it off when they fit
93
- * beside them again: the list's CSS does the rest. The decision is taken
94
- * synchronously, in the layout effect and the observers' callbacks, so the
95
- * first frame and every resize paint the right layout; again when the list
96
- * or a value resizes, a label or value changes, or a web font arrives
97
- * (design/patterns/responsive.md#when-a-row-runs-out-of-room).
93
+ * beside them again: the list's CSS does the rest. The first frame is
94
+ * decided synchronously, in the layout effect, and so is a label or value
95
+ * changing (the MutationObserver) or a web font arriving: those paint the
96
+ * right layout at once. A resize of the list or a value is decided in the
97
+ * next animation frame, so a resize that crosses the boundary takes effect
98
+ * one frame later: deciding inside the ResizeObserver's callback changed
99
+ * the list's height while the observer was still delivering its children's
100
+ * sizes, and the browser reported "ResizeObserver loop completed with
101
+ * undelivered notifications" as a window error
102
+ * (design/patterns/responsive.md#when-a-row-runs-out-of-room,
103
+ * #the-first-frame-is-the-settled-one).
98
104
  */
99
105
  function useLabelValueFit(list, enabled, parts) {
100
106
  const { label, value } = parts;
@@ -108,7 +114,14 @@ function useLabelValueFit(list, enabled, parts) {
108
114
  const stacked = labelsGoAbove(list, selectors);
109
115
  if (stacked !== list.hasAttribute("data-stacked")) list.toggleAttribute("data-stacked", stacked);
110
116
  };
111
- const resize = new ResizeObserver(fit);
117
+ let frame = 0;
118
+ const resize = new ResizeObserver(() => {
119
+ cancelAnimationFrame(frame);
120
+ frame = requestAnimationFrame(() => {
121
+ frame = 0;
122
+ fit();
123
+ });
124
+ });
112
125
  const observeAll = () => {
113
126
  resize.disconnect();
114
127
  resize.observe(list);
@@ -128,6 +141,7 @@ function useLabelValueFit(list, enabled, parts) {
128
141
  fonts?.addEventListener("loadingdone", fit);
129
142
  fit();
130
143
  return () => {
144
+ cancelAnimationFrame(frame);
131
145
  resize.disconnect();
132
146
  mutation.disconnect();
133
147
  fonts?.removeEventListener("loadingdone", fit);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/raft-ui",
3
- "version": "0.95.2",
3
+ "version": "0.95.3",
4
4
  "description": "React components and CSS foundations for the Raft Design System.",
5
5
  "keywords": [
6
6
  "agent-skills",