Well, yeah, obviously, somebody has to retain some state at some point. The nice thing about a good IMGUI is that it's easy to integrate with your own state-maintenance logic. It's all about separation of concerns.
In practice, every time I've built an IMGUI, it's always turned into some kind of hybrid immediate/retained-mode approach. There's nothing desirable about forcing the business logic to remember the state of a button on the screen, after all. It comes down to how easy it is to build and maintain the mixed-paradigm model that everybody inevitably ends up with anyway.
In the case of the last framework I put together, individual buttons can be treated as true immediate-mode controls, where hit-testing, labeling, and other interaction with the program takes place at render time, while button groups retain the necessary state to lay themselves out, handle mutual exclusion, and so forth. Nothing keeps the app from maintaining its own list of buttons and calling it a group or whatever, but if I don't need to do that myself I can let the GUI do it.
In practice, every time I've built an IMGUI, it's always turned into some kind of hybrid immediate/retained-mode approach. There's nothing desirable about forcing the business logic to remember the state of a button on the screen, after all. It comes down to how easy it is to build and maintain the mixed-paradigm model that everybody inevitably ends up with anyway.
In the case of the last framework I put together, individual buttons can be treated as true immediate-mode controls, where hit-testing, labeling, and other interaction with the program takes place at render time, while button groups retain the necessary state to lay themselves out, handle mutual exclusion, and so forth. Nothing keeps the app from maintaining its own list of buttons and calling it a group or whatever, but if I don't need to do that myself I can let the GUI do it.