观察类发现,顺手记录,不在任何在办单的范围内(实测于 objectstack#7016 / objectui PR #3934 的 harness 里)。
现象
packages/plugin-charts/src/ChartContainerImpl.tsx:157-165:
className={cn(
"block w-full h-[350px] …",
className
)}
// Guarantee a non-zero box for Recharts' ResponsiveContainer even when
// the consumer-supplied className overrides our h-[350px] …
// Without this min-size the chart computes width/height = -1 and
// renders invisibly.
style={{ minHeight: 280, minWidth: 0, ...props.style }}
{...props}
style 是显式属性,{...props} 在它之后展开,而 props 里就含 style(它是 React.ComponentProps["div"] 解构剩下的 rest,只摘掉了 id/className/children/config/disableSettleRemount)。JSX 里后写的同名属性覆盖先写的,所以只要调用方传了 style,整个 style 对象就被 props.style整体替换 —— minHeight: 280 与 minWidth: 0 一起消失,而 ...props.style 那次合并从来没有执行过。它是死代码。
实测证据
AdvancedChartImpl 的 containerProps(:293-300)在声明了 ChartConfig.height 时会带上 style。在一个 dashboard chart widget 上写 chartConfig.height: 420,渲染出的属性恰好是:
没有 min-height,没有 min-width —— 注释承诺的兜底不在。
为什么标 finding 而不是缺陷
今天没有用户会撞到坏图:唯一会传进来的 style 就是 height,而一个显式高度本身就提供了那个兜底想保证的盒子(反过来说,当前这个覆盖顺序还恰好让 height: 100 这类小于 280 的显式高度真的生效了,若按注释的原意合并,min-height: 280 反而会盖掉作者写的高度 —— 所以"直接改成先展开 props"也不是无脑正确,得想清楚 min-size 与显式 height 的优先级)。
值得记下来的是两点:
- 那次
...props.style 合并看起来在工作、实际从未运行,读代码的人会以为有兜底; - 以后任何一个容器级 style prop(宽度、margin、aspect-ratio……)只要走同一条
containerProps 路径,就会静默把 min-size 兜底一起带走 —— 而那个兜底是当年为"dashboard widget 把 chart 塞进 flex/grid、chart 量到 -1 渲染不出来"专门加的。
可能的修法(留给 triage 定)
- 把
{...props} 挪到 style之前,让合并真的生效;同时决定显式 height 小于 minHeight 时谁赢(倾向作者的 height 赢 —— 那时 minHeight 应当只在没有显式高度时兜底)。 - 或者把
style 从 rest 里解构出来单独合并,让"谁覆盖谁"在代码里显式写出来,而不是靠 JSX 属性顺序这种一眼看不出来的机制。
无论哪条,都值得配一条钉:传入 style 的容器仍保有 min-size 兜底(或明确记录不保有)。
发现于:objectstack#7016(dashboard chartConfig 呈现键转发)的 DOM 实测。⛔ 未在那个 PR 里顺手改 —— 不在其范围内。
观察类发现,顺手记录,不在任何在办单的范围内(实测于 objectstack#7016 / objectui PR #3934 的 harness 里)。
现象
packages/plugin-charts/src/ChartContainerImpl.tsx:157-165:style是显式属性,{...props}在它之后展开,而props里就含style(它是React.ComponentProps["div"]解构剩下的 rest,只摘掉了id/className/children/config/disableSettleRemount)。JSX 里后写的同名属性覆盖先写的,所以只要调用方传了style,整个style对象就被props.style整体替换 ——minHeight: 280与minWidth: 0一起消失,而...props.style那次合并从来没有执行过。它是死代码。实测证据
AdvancedChartImpl的containerProps(:293-300)在声明了ChartConfig.height时会带上style。在一个 dashboard chart widget 上写chartConfig.height: 420,渲染出的属性恰好是:没有
min-height,没有min-width—— 注释承诺的兜底不在。为什么标 finding 而不是缺陷
今天没有用户会撞到坏图:唯一会传进来的
style就是height,而一个显式高度本身就提供了那个兜底想保证的盒子(反过来说,当前这个覆盖顺序还恰好让height: 100这类小于 280 的显式高度真的生效了,若按注释的原意合并,min-height: 280反而会盖掉作者写的高度 —— 所以"直接改成先展开 props"也不是无脑正确,得想清楚 min-size 与显式 height 的优先级)。值得记下来的是两点:
...props.style合并看起来在工作、实际从未运行,读代码的人会以为有兜底;containerProps路径,就会静默把 min-size 兜底一起带走 —— 而那个兜底是当年为"dashboard widget 把 chart 塞进 flex/grid、chart 量到 -1 渲染不出来"专门加的。可能的修法(留给 triage 定)
{...props}挪到style之前,让合并真的生效;同时决定显式height小于minHeight时谁赢(倾向作者的 height 赢 —— 那时minHeight应当只在没有显式高度时兜底)。style从 rest 里解构出来单独合并,让"谁覆盖谁"在代码里显式写出来,而不是靠 JSX 属性顺序这种一眼看不出来的机制。无论哪条,都值得配一条钉:传入
style的容器仍保有 min-size 兜底(或明确记录不保有)。发现于:objectstack#7016(dashboard
chartConfig呈现键转发)的 DOM 实测。⛔ 未在那个 PR 里顺手改 —— 不在其范围内。