Skip to content

Commit 091b0a3

Browse files
committed
Make ButtonProperties.buttonColor nullable
buttonColor defaulted to black and black was left out of the JSON, so a renderer could not tell an unset colour from a chosen black: a black text button rendered transparent. It is now nullable and defaults to null, the button type's default colour. A missing key (designs that omitted black) reads as null; an explicit colour, black included, is written and read back. The field setter can clear it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VtH72Dg3rGsqwaEe62Sha4
1 parent 0116f50 commit 091b0a3

4 files changed

Lines changed: 65 additions & 11 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Unreleased
22

3+
- Breaking: `ButtonProperties.buttonColor` is nullable and defaults to `null`,
4+
the button type's default colour. It was black, and black was left out of
5+
the JSON, so a missing key now reads as `null` and an explicit black is
6+
written and read back as black.
37
- `TextFieldProperties.maxLines`: `null` (unlimited lines) is written as an
48
explicit `null` and reads back as `null`; a missing key still reads as 1.
59
- `VariableData.getValue()` returns an empty text variable as `''` instead of

‎lib/src/api/nodes/button_node.dart‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,12 @@ class ButtonProperties extends CustomProperties
211211
/// Type of the button.
212212
late ButtonTypeEnum buttonType;
213213

214-
/// Background color of the button.
215-
late ColorRGBA buttonColor;
214+
/// Background color of the button, or null for the button type's default
215+
/// (no fill for a text or outlined button).
216+
///
217+
/// Designs saved before this was nullable omit black, then the default:
218+
/// a missing key reads as null, an explicit color (black too) as set.
219+
ColorRGBA? buttonColor;
216220

217221
/// Elevation shadow color of the button.
218222
late ColorRGBA shadowColor;
@@ -248,7 +252,7 @@ class ButtonProperties extends CustomProperties
248252
/// Creates a [ButtonProperties] with given data.
249253
ButtonProperties({
250254
this.buttonType = ButtonTypeEnum.elevated,
251-
this.buttonColor = ColorRGBA.black,
255+
this.buttonColor,
252256
this.shadowColor = const ColorRGBA(r: 0.65, g: 0.65, b: 0.65, a: 1),
253257
this.label = '',
254258
this.elevation = 0,
@@ -321,13 +325,11 @@ class ButtonProperties extends CustomProperties
321325
// },
322326
// ButtonTypeEnum.values,
323327
// ),
324-
'buttonColor': ColorFieldAccess<ColorRGBA>(
328+
'buttonColor': ColorFieldAccess<ColorRGBA?>(
325329
'Button Color',
326330
'Color of the button.',
327331
() => buttonColor,
328-
(ColorRGBA? value) {
329-
if (value != null) buttonColor = value;
330-
},
332+
(ColorRGBA? value) => buttonColor = value,
331333
),
332334
'shadowColor': ColorFieldAccess<ColorRGBA>(
333335
'Shadow Color',

‎lib/src/api/nodes/button_node.g.dart‎

Lines changed: 2 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/button_color_test.dart‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'dart:convert';
2+
3+
import 'package:codelessly_api/codelessly_api.dart';
4+
import 'package:test/test.dart';
5+
6+
ButtonProperties roundTrip(ButtonProperties properties) =>
7+
ButtonProperties.fromJson(jsonDecode(jsonEncode(properties.toJson())));
8+
9+
void main() {
10+
group('ButtonProperties.buttonColor', () {
11+
test('is unset by default and left out of the JSON', () {
12+
final properties = ButtonProperties();
13+
expect(properties.buttonColor, isNull);
14+
expect(properties.toJson().containsKey('buttonColor'), isFalse);
15+
expect(roundTrip(properties).buttonColor, isNull);
16+
});
17+
18+
test('keeps an explicit black', () {
19+
final properties = ButtonProperties(buttonColor: ColorRGBA.black);
20+
expect(properties.toJson()['buttonColor'], ColorRGBA.black.toJson());
21+
expect(roundTrip(properties).buttonColor, ColorRGBA.black);
22+
});
23+
24+
test('reads old JSON: a missing key is unset, a written color is kept', () {
25+
final Map<String, dynamic> json = ButtonProperties(
26+
buttonType: ButtonTypeEnum.text,
27+
).toJson();
28+
expect(ButtonProperties.fromJson(json).buttonColor, isNull);
29+
for (final ColorRGBA color in [
30+
ColorRGBA.black,
31+
const ColorRGBA(r: 0.2, g: 0.4, b: 0.8, a: 1),
32+
]) {
33+
expect(
34+
ButtonProperties.fromJson({...json, 'buttonColor': color.toJson()})
35+
.buttonColor,
36+
color,
37+
);
38+
}
39+
});
40+
41+
test('can be set and cleared through its field', () {
42+
final properties = ButtonProperties();
43+
final field = properties.fields['buttonColor']!;
44+
field.setValue(ColorRGBA.black);
45+
expect(properties.buttonColor, ColorRGBA.black);
46+
field.setValue(null);
47+
expect(properties.buttonColor, isNull);
48+
});
49+
});
50+
}

0 commit comments

Comments
 (0)