AIUI, declarative is listing what you want, while imperative is listing the steps to get what you want. Naturally, I feel that extending a declaration with conditionals or looping constructs make that not-declarative anymore.
That's because, I feel, a conditional is a sequence of steps, not a declaration.
Hence I regard (perhaps incorrectly) that declarative syntax with support for conditionals is "hacky".
(The XAML way of expressing conditionals and loops does feel hacky to me since you need the code and markup to communicate with each other instead of expressing directly in code.)
Edit:
Here is a well-considered blog post from one of the Uno Platform contributors about UI-as-code vs markup if any are interested. https://platform.uno/blog/markup-vs-code-for-ui-angled-brack...
if condition then ConditionalWidget1 else ConditionalWidget2
Where this if-statement is embedded in a declared UI/widget tree. That's hardly a hack in my opinion.
There are similar ways of building a dynamic list of widgets declaratively which don't feel hacky at all. For example, look at ListView.builder[0] in Flutter. You provide an array and a template function of how each element in the array should look and then you have your dynamic list of widgets. (Of course more complicated use cases require more complicated code, but it's still not hacky and fits well with the larger sstem.)
[0] https://docs.flutter.dev/cookbook/lists/long-lists
I might be misunderstanding your definition of declarative vs imperative but I don't think this way of building UIs is hacky in any sense.