Skip to content

Conversation

@ethan-james
Copy link
Collaborator

Fixes #3353

I added a max-width to TreeNode in order to stop it from overrunning the viewport width when the transform applied to indented thoughts exceeds the right padding. In order to do this, I needed to updated bulletWidth in LayoutTree in order to calculate the width of the bullet in the same way that it is calculated in Bullet. This might have unforeseen consequences, and I could duplicate that calculation inside TreeNode instead.

@ethan-james ethan-james self-assigned this Nov 12, 2025
@ethan-james
Copy link
Collaborator Author

ethan-james commented Nov 12, 2025

I also see that, at larger font sizes at widths exceeding the 560px breakpoint that I was targeting, we can also get some cutoff. I can try to fix that as part of this issue if you want.

Screenshot 2025-11-11 190803

@raineorshine
Copy link
Contributor

Sure! You can address the other case in this PR unless it ends up being a bigger change.

It would be great to get a puppeteer snapshot test covering this at different screen widths. Setting puppeteer's window width can be tricky sometimes, but give it a try.

@ethan-james
Copy link
Collaborator Author

Sure! You can address the other case in this PR unless it ends up being a bigger change.

It would be great to get a puppeteer snapshot test covering this at different screen widths. Setting puppeteer's window width can be tricky sometimes, but give it a try.

I added some tests, and they showing that my approach has problems with thought annotations. Putting the max-width on TreeNode doesn't work well with the padding applied to annotations. I could refactor my work to push the max-width down to StaticThought or Editable, but I think that first I should try to finish up #3352 and see if this works better without the ThoughtAnnotation placeholder.

@raineorshine
Copy link
Contributor

Okay, sounds good.

At the end we'll need to reduce this down to the fewest tests that are needed cover the behavior, since snapshot tests are expensive and we don't want to slow down the test suite unnecessarily.

@raineorshine raineorshine marked this pull request as draft November 13, 2025 19:17
@ethan-james ethan-james marked this pull request as ready for review January 5, 2026 19:53
@ethan-james
Copy link
Collaborator Author

Okay, sounds good.

At the end we'll need to reduce this down to the fewest tests that are needed cover the behavior, since snapshot tests are expensive and we don't want to slow down the test suite unnecessarily.

I figured out that the margin on editableRecipe was different from the margin being applied to ThoughtAnnotation, so I corrected that. I removed the tests for font size 23, because they weren't demonstrating anything new compared to font size 28. I also removed tests for all widths except for 560px and 575px to test the behavior on either side of the 560px breakpoint.

Comment on lines +263 to +264
// Add a negative marginRight equal to translateX to ensure the thought takes up the full width.
const marginRight = `${-indent + (isTouch ? 2 : -1)}em`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually prefer inlining this since it is only used in one place and it is easier to understand when co-located with the element that uses it. If the code becomes too verbose, it's better to split into smaller components than split the CSS away from the DOM.

{treeThoughtsPositioned.map((thought, index) => (
<TreeNode
{...thought}
style={{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An object literal will be a new reference every time, even if maxWidth hasn't changed. While TreeNode is not currently memoized, I think it's generally a good practice to preserve referential integrity of props. Therefore, I recommend using useMemo to create a stable style object that can be passed to TreeNode.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is taking place inside of treeThoughtsPositioned.map, so my options for memoizing it are to:

  1. create a new component
  2. memoize the entire treeThoughtsPositioned object

I think option 2 makes sense to me, but I figured I should check in case that introduces too much risk.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof, that's a lot of restructuring to get this memoized. Yes, I think option 2 makes the most sense.

An alternative is to pass indent as a prop and allow TreeNode to calculate and memoize maxWidth. That would be a bit of a lighter touch.

@raineorshine
Copy link
Contributor

@BayuAri Ready for testing!

@raineorshine raineorshine requested a review from BayuAri January 8, 2026 18:29
Copy link
Collaborator

@BayuAri BayuAri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed, the layout issue is no longer reproducible.
Text is not cut off before wrapped.

image

Video:

Text.is.not.cut.off.at.small.screen.before.wrapped.mov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Thought width exceeds viewport width below around 500px

3 participants