Skip to content

[19.0][ADD] web_chatter_resizable - #3775

Open
lucaorioli wants to merge 1 commit into
OCA:19.0from
lucaorioli:19.0-add-web_chatter_resizable
Open

lucaorioli wants to merge 1 commit into
OCA:19.0from
lucaorioli:19.0-add-web_chatter_resizable

Conversation

@lucaorioli

@lucaorioli lucaorioli commented Oct 29, 2026 •

Copy link
Copy Markdown

New module web_chatter_resizable: the chatter shown beside a view can be resized by dragging its edge.

What it does

  • A handle on the edge of every side chatter (Chatter with isChatterAside): a thin line shows when the pointer rests on it; drag it to change the width, double-click it to restore the standard width.
  • The width never goes below $o-mail-Chatter-minWidth, or below the standard width of chatters that are narrower by design (e.g. the Enterprise bank reconciliation, whose BankRecChatter extends Chatter).
  • The width is kept per user in the browser (localStorage), one value per kind of view.
  • In form views, a button next to the pager hides or shows the side chatter, also kept in the browser.
  • Beside a side chatter, the form uses all the room left by it, also on very wide screens, so it does not jump when the chatter is resized or restored.

How

  • Patch of the mail.Chatter template and class, plus the form controller for the show/hide button: no MutationObserver, nothing changes for chatters below the view.
  • Pointer events with pointer capture (works over iframes and outside the window), RTL and dark theme supported.

How to test

  1. Install the module, open any form with a chatter on a wide screen (side chatter).
  2. Rest the pointer on the left edge of the chatter, drag it, reload: the width is kept.
  3. Double-click the edge: the standard width is back.
  4. Click the chatter button next to the pager: the chatter is hidden, click again to show it.

Hoot tests in static/tests/, run through tests/test_js.py.

Assisted-by: Claude Opus 5.5

@OCA-git-bot OCA-git-bot added series:19.0 mod:web_chatter_resizable Module web_chatter_resizable labels Oct 29, 2026
@ljmnoonan

Copy link
Copy Markdown
Member

Hello, this is quite interesting. Have you seen previous attempts at this in #2976, #3125, and #3668?

I also made an attempt in #3703 (41de571) using odoo's native ResizablePanel component.

I would love to hear your opinion and arguments for the different approaches. I preferred reusing the odoo component in order to avoid duplicating logic as much as possible, but it came with its own complications.

@lucaorioli
lucaorioli force-pushed the 19.0-add-web_chatter_resizable branch from f26ee1c to 8cfea34 Compare October 30, 2026 08:08
@lucaorioli

Copy link
Copy Markdown
Author

Hi @ljmnoonan, thanks for the pointers! I had looked at the 16.0 web_form_view_resizable attempts but missed your work in #3703.

I also considered ResizablePanel first. I ended up not using it for a few reasons:

  • Where to hook. ResizablePanel has to own the container element. For the chatter that means replacing the container built by the form compiler, which is what [19.0][IMP] web_responsive: Complete refactor and more #3703 does by patching FormCompiler. Here I only patch the mail.Chatter template and class: the handle is rendered inside .o-mail-ChatterContainer.o-aside, and the container keeps its markup and classes. Because of that it works for every side chatter, not only in forms. That includes components that extend Chatter outside forms, e.g. the Enterprise bank reconciliation, with no bridge module.
  • Behaviour of the core component. It listens to mousedown/mousemove only, with no pointer or touch support. It has no way to restore the default width. Its limit is the offsetParent width, so there is no minimum room left for the view.
  • Scope. A standalone module depending only on mail can be used with or without web_responsive, and it does not tie the feature to the larger refactor.

On top of that, the width is stored per view type (forms vs. kanban with a side chatter). There is also an optional user preference to let the form sheet use the room freed by the chatter.

The duplicated logic is small (~60 lines with pointer events, RTL and clamping). I agree reusing core components is preferable when they fit. If ResizablePanel grows pointer events and a way to wrap an existing container, I'd happily switch to it.

I also tested it together with the current web_responsive 19.0. Since it sets the side chatter to flex: 0 0 35% !important, the resized width needs !important too; it only applies once the user has dragged the handle, otherwise web_responsive's width is kept. With that, both modules' tests pass and the core mail chatter tests show no regressions.

If #3703 lands, one option would be for web_responsive to depend on this module rather than carrying its own implementation. Happy to adapt this one to fit with it.

@ljmnoonan

Copy link
Copy Markdown
Member

@lucaorioli you are right about the limitations on the behavior of ResizablePanel, especially pointer events.

I do not use enterprise, so I did not know about the side chatter without a form. I suppose the FormCompiler approach could be adapted. I have also not encountered chatter rendered next to a kanban view.

I do like the "return to default" behavior of this implementation, and in general it seems smoother. I do not believe the chatter_full_width_sheet user setting is worth it though. If a user thinks the form is too wide he can always just narrow it with the chatter. Maybe you had something else in mind?

My changes to web_responsive are unlikely to be merged anywhere, so I have been planning to break them up into separate modules and propose them in 20.0. I will plan on depending on this module for the resizable chatter functionality.

Lastly, it may be worth getting rid of $o-form-renderer-max-width and $o-form-view-sheet-max-width via

.o_form_view {
    & .o_form_renderer,  
    & .o_form_sheet_bg {
        max-width: 100%;
    }
}

because they limit the growth of the form renderer on ultra wide screens. This is fine when the chatter is a fixed width, but now we have the possibility to make the screen very wide and basically have the form and the chatter each take up the width of a regular size screen.

image

Before:
image

Again, thanks for your work on this. I think yours is the right approach

@lucaorioli
lucaorioli force-pushed the 19.0-add-web_chatter_resizable branch from 8cfea34 to 5178373 Compare October 30, 2026 12:17
@lucaorioli

Copy link
Copy Markdown
Author

Thanks a lot @ljmnoonan, both for the review and for planning to build on this module for 20.0!

I agree with you on the user setting and removed it. The idea behind it was to let the form sheet use the room freed by a narrower chatter. In practice it only made a difference on very wide screens: with a side chatter, Odoo 19 already lets the sheet grow up to 2560px. And as you say, the handle is already the control. If the form gets too wide, the user can widen the chatter.

So now, once the chatter has been resized, the form renderer and the sheet beside it lose their maximum width and fill all the room left by the chatter. For example, on a 3440px screen with the chatter at 300px, the sheet now grows to ~3100px instead of stopping at 2560px with an empty gap. I scoped this to forms whose chatter has been resized rather than to all form views. Until the handle is used, the layout stays exactly as in core (or as set by web_responsive), and forms without a chatter and wizards are not affected. This also made the module pure JS/CSS, with no Python models anymore.

What do you think about this scoping? Would you rather lift the limits as soon as the chatter is beside the form, even before it is resized?

@ljmnoonan

Copy link
Copy Markdown
Member

I think it should not be scoped. Having this scope creates a jump when you resize for the first time or reset.

2026-10-30.08-26-08.mp4

@lucaorioli
lucaorioli force-pushed the 19.0-add-web_chatter_resizable branch from 5178373 to 3712218 Compare October 30, 2026 13:31
@lucaorioli

Copy link
Copy Markdown
Author

Good point, thanks for the video. Done: the maximum widths of the form renderer and of the sheet are now lifted on every form with a side chatter, resized or not, so there is no jump on the first resize or on reset. Forms without a chatter, wizards and forms with the chatter below are left as in core.

@lucaorioli
lucaorioli marked this pull request as ready for review October 30, 2026 13:48
@ljmnoonan

Copy link
Copy Markdown
Member

Hello, @lucaorioli, sorry for the long delay.
I have begun reviewing, but am not quite done. I was testing a few things in https://github.com/Pyxiris/web/tree/19.0-web_chatter_resizable_review. The changes to the css and xml there are my own, the changes to the js are from AI. It was mainly concerned with losing the event when the pointer goes over an iframe or out of the window, but I haven't gotten the time to really look into it.

I also took another look at using ResizablePanel without patching form compiler. You can see a draft of that here https://github.com/Pyxiris/web/tree/19.0-web_side_chatter_resizable. The idea is that eventually upstream would adopt pointer events, probably in 21.0 and then we could get rid of the modified copy of resizable_panel.js. It is still a bit clunky though as it introduces a resizable container between the chatter container and the chatter itself, so it is impossible to let it flex grow any more. I'm a bit divided on this as we don't really need flex anymore seeing we can just resize to whatever we want, but still.

There are two points I think should be implemented here though:

The resizable handle is too similar to a scrollbar. I wasn't sure what to recommend as a replacement, but then I found that odoo is already working on this here: odoo/odoo@bbca5b2. I think it would be best to just copy this behavior.

The side chatter is not meant to get narrower than 530px. Doing so seems to cause some stuttering and it just does not look good. What do you think of setting this as a minimum, and then introducing a show/hide chatter button by the pagers just like enterprise has in documents and bank statements?

@lucaorioli
lucaorioli force-pushed the 19.0-add-web_chatter_resizable branch from 3712218 to 37b82b1 Compare November 7, 2026 08:44
@lucaorioli

Copy link
Copy Markdown
Author

Thanks @ljmnoonan, no worries about the delay, and thanks for the two branches!

Done in the last push:

  • Pointer handling: pointer capture, so the drag keeps going over iframes and outside the window; pointercancel, primary pointer only, one update per animation frame, and the stored width is clamped again when the window is resized.
  • Handle: same look as the outer handle of ResizablePanel in odoo/odoo@bbca5b2: invisible, with a thin primary line when the pointer rests on it (after a short delay) and while dragging; the grab offset is kept, so the width no longer jumps on pointerdown. One difference: it sits on the inner edge of the chatter, because the edge of the form sheet next to it holds the sheet scrollbar (there is no gap there, unlike in Discuss).
  • Minimum width: $o-mail-Chatter-minWidth (530px), or the standard width of the chatter when it is narrower by design, like the bank reconciliation, so that the first drag does not jump. I would have preferred full control over the size, but a minimum width together with a button to hide the chatter is indeed the more standard behavior.
  • Show/hide: a button next to the pager in form views hides the side chatter, remembered in the browser. With the chatter hidden, the form is laid out as without a chatter.
  • ResizablePanel: I'd keep patching Chatter for now, for the reasons you mention (extra wrapper, no flex, a modified copy of core). With the same handle look, switching later should be easy if core adopts pointer events.

It's getting more complex than my initial design: very interesting! But I needed some help, so I'm adding an Assisted-by: Claude to this PR.

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

Labels

mod:web_chatter_resizable Module web_chatter_resizable series:19.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants