Skip to content

Commit 9f517d2

Browse files
daohoangsonclaude
andauthored
fix: merge border-radius with background-color for inline elements (#1569)
For inline elements with margin, border-radius and background-color were placed on separate Containers, causing the background to render with square corners. Let onRenderBlock handle border decoration during tree.build() so it merges with background into a single Container. Also preserve clipBehavior when buildDecoration merges into an existing Container that already has borderRadius. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 34d53c1 commit 9f517d2

3 files changed

Lines changed: 39 additions & 7 deletions

File tree

packages/core/lib/src/core_widget_factory.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,16 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory {
168168
);
169169

170170
var clipBehavior = Clip.none;
171-
if (borderRadius != null) {
171+
final baseRadius = baseDeco.borderRadius;
172+
final effectiveRadius =
173+
borderRadius ?? (baseRadius is BorderRadius ? baseRadius : null);
174+
if (effectiveRadius != null) {
172175
final borderIsUniform = decoration.border?.isUniform ?? true;
173176
if (borderIsUniform) {
174177
// TODO: add support for non-uniform border
175178
// https://github.com/flutter/flutter/commit/5054b6e
176179
// https://pub.dev/packages/non_uniform_border
177-
decoration = decoration.copyWith(borderRadius: borderRadius);
180+
decoration = decoration.copyWith(borderRadius: effectiveRadius);
178181
clipBehavior = Clip.hardEdge;
179182
}
180183
}

packages/core/lib/src/internal/ops/style_border.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@ class StyleBorder {
2121
return tree;
2222
}
2323

24-
skip(tree);
24+
// Don't skip onRenderBlock — let it handle border decoration
25+
// during tree.build() so it can be merged with background color
26+
// by buildDecoration's Container merge logic.
2527
return parent.sub()
2628
..append(
2729
WidgetBit.inline(
2830
tree,
2931
WidgetPlaceholder(
30-
builder: (context, child) {
31-
final built = _buildBorder(tree, context, child, border);
32-
return built ?? child;
33-
},
3432
debugLabel: '${tree.element.localName}--$kCssBorder',
3533
child: tree.build(),
3634
),

packages/core/test/style_border_test.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:flutter/widgets.dart';
12
import 'package:flutter_test/flutter_test.dart';
23

34
import '_.dart';
@@ -769,6 +770,36 @@ void main() {
769770
);
770771
});
771772

773+
testWidgets('#1560: border-radius with background-color and margin',
774+
(tester) async {
775+
const html = '<span style="border-radius: 1px; '
776+
'background-color: red; margin-right: 1px;">Foo</span>';
777+
final explained = await explain(tester, html);
778+
expect(
779+
explained,
780+
equals(
781+
'[HorizontalMargin:left=0,right=1,child='
782+
'[Container:color=#FFFF0000,'
783+
'radius=[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],'
784+
'child=[RichText:(:Foo)]]]',
785+
),
786+
);
787+
});
788+
789+
testWidgets('#1560: block border-radius with background-color clips',
790+
(tester) async {
791+
const html =
792+
'<section style="border-radius: 1px; background-color: red;">'
793+
'Foo</section>';
794+
await explain(tester, html);
795+
796+
final container =
797+
tester.widgetList<Container>(find.byType(Container)).firstWhere(
798+
(c) => (c.decoration as BoxDecoration?)?.borderRadius != null,
799+
);
800+
expect(container.clipBehavior, equals(Clip.hardEdge));
801+
});
802+
772803
testWidgets('ignore radius if border is not uniform', (t) async {
773804
// https://github.com/daohoangson/flutter_widget_from_html/issues/909
774805
const html = '<section style="border-bottom: 1px solid rgb(62, 62, 62); '

0 commit comments

Comments
 (0)