Closes#1665
## Description
When `Input::new().font_family("font")` is used, the font hasn't been
applied yet in `Input::render`, therefore the `text_wrapper` will
calculate using the wrong font. This is why it's working when the font
is added to the parent element.
The fix moves the state update to `element` prepaint, where
`window.text_style()` has the correct styles. The only downside is that
there are now one additional state update.
## Screenshot
| Before | After |
| ---------------------------- | --------------------------- |
| <img width="1125" height="246" alt="Screenshot From 2025-11-30
20-03-11"
src="https://github.com/user-attachments/assets/1fa798a7-0b9c-4386-8940-ad5f6734b8a0"
/> | <img width="1125" height="246" alt="Screenshot From 2025-11-30
20-00-23"
src="https://github.com/user-attachments/assets/e970e7bc-1bfa-4a55-a342-3381d1684526"
/> |
## How to Test
Use some wide font, like `IBM Plex Mono`. Apply it to
`Input::new(&some_state).font_family("IBM Plex Mono")` where the input
state has `soft_wrap`. Here is a diff for `textarea_story.rs`.
```diff
diff --git a/crates/story/src/textarea_story.rs b/crates/story/src/textarea_story.rs
index f2c63d44..bd5cbb31 100644
--- a/crates/story/src/textarea_story.rs
+++ b/crates/story/src/textarea_story.rs
@@ -77,9 +77,9 @@ impl TextareaStory {
let textarea_no_wrap = cx.new(|cx| {
InputState::new(window, cx)
- .multi_line(true)
.rows(6)
- .soft_wrap(false)
+ .multi_line(true)
+ .soft_wrap(true)
.default_value("This is a very long line of text to test if the horizontal scrolling function is working properly, and it should not wrap automatically but display a horizontal scrollbar.\nThe second line is also very long text, used to test the horizontal scrolling effect under multiple lines, and you can input more content to test.\nThe third line: Here you can input other long text content that requires horizontal scrolling.\n")
});
@@ -195,7 +185,7 @@ impl Render for TextareaStory {
.child(
section("Auto Grow")
.max_w_md()
- .child(Input::new(&self.textarea_auto_grow)),
+ .child(Input::new(&self.textarea_auto_grow).font_family("IBM Plex Mono")),
)
.child(
section("Auto Grow with No Wrap")
```
## Checklist
- [x] I have read the [CONTRIBUTING](../CONTRIBUTING.md) document and
followed the guidelines.
- [x] Reviewed the changes in this PR and confirmed AI generated code
(If any) is accurate.
- [x] Passed `cargo run` for story tests related to the changes.
- [ ] Tested macOS, Windows and Linux platforms performance (if the
change is platform-specific)
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>