-
Notifications
You must be signed in to change notification settings - Fork 87
fix(genui): missing weight property to Component constructor; Prevent unbounded text field width
#588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(genui): missing weight property to Component constructor; Prevent unbounded text field width
#588
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces two important fixes. First, it correctly parses the weight property in SurfaceUpdateTool, allowing components to be laid out with flex weights. This is well-tested with new unit tests for both integer and double values. Second, it prevents TextField from causing layout errors due to unbounded width by using a LayoutBuilder to detect this scenario, logging a warning, and applying a default width. This defensive measure is also accompanied by new widget tests. The changes are well-implemented and improve the robustness of the UI generation. I have one minor suggestion regarding test file imports to improve long-term maintainability.
weight property to Component constructor; Prevent unbounded text field widthweight property to Component constructor; Prevent unbounded text field width
|
|
||
| final _schema = S.object( | ||
| description: | ||
| 'A text input field. IMPORTANT: If this is placed inside a Row, ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm I think we can't rely on this, because weight should always be optional. If I put a textField inside a row, shouldn't the row have a maximum width, and the textField be constrained to that? I know that is clearly not what's happening here, but that's what I'd hope for.
Can we do something like default the weight to 1.0 essentially, even if it isn't specified?
The overall goal here is to provide enough default behavior that the LLM can compose any element inside any other without complying with additional rules. The LLM here may be running on a server and not know the difference between flutter or lit etc, so we can't impose platform-specific constraints!
Description
This is a two-for-one change. Feel free to ask me to refactor this into two PRs.
Fixes #559. This isn't an air-tight fix, but I hope it is sufficient for now.
Changes
SurfaceUpdateToolwasn't parsing the value of theweightproperty and passing it to theComponentconstructor for any component it was constructing1. Definition ofweightproperty:genui/packages/genui/lib/src/model/a2ui_schemas.dart
Lines 227 to 230 in 061ba89
widgetBuilderof the text field catalog component was modified. It now usesLayoutBuilderto determine if whether the width is unbounded, in which case a warning will be logged and the text field will be rendered in aSizedBoxwith a width of 300 pixels. I chose this width arbitrarily.descriptionofTextFieldand thedescriptionofweightnow include a specific call out aboutTextFieldand how it needs its width bound. This creates an undesirable coupling betweenTextFieldandComponent, and it feels wrong forComponentto be aware of a downstream detail likeTextField. However, this was the only way I found to get Gemini Flash 2.5 to respect this rule with any level of consistency (Pro 2.5 seems to be more rigorous and anticipate the need to useweightwithout explicit instruction). Making these explicit callouts may also impose more token burden on Flash (and similarly lightweight) models, possibility reducing the quality of the library's output elsewhere, but we currently do not have a way to measure this.Repro
You can checkout this branch and create a basic test app with the following (LLM-generated) code:
Repro app code
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-devrel channel on Discord.
Footnotes
https://github.com/flutter/genui/blob/061ba8943160894a16ab0ffeaae99b7859e0ac49/packages/genui/lib/src/core/ui_tools.dart#L35-L37 ↩