shahryarjb
Adding Phoenix.LiveView.JS function for getting `getBoundingClientRect` params
When proposing or suggesting something please consider:
As my experience implementing getBoundingClientRect as Phoenix.LiveView.JS function and returns all the parameters of this JS function I mean (height, top, left and etc size) can be help full for complex client side component.
It keeps the ecosystem more clear and integrated. It can prevent the use of other client frameworks or js hook.
For example we have an accordion that is created with Phoenix component and Phoenix.LiveView.JS:
Show or open the accordion:
def show_accordion_content(js \\ %JS{}, id) when is_binary(id) do
js
|> JS.show(to: "##{id}")
|> JS.show(
to: "##{id}-content",
time: 500,
transition:
{
"transition-all transform ease-out duration-300",
"will-change-[opacity] opacity-0 h-0",
"will-change-auto opacity-100 h-[400px]"
}
)
end
As you see I use hard coded height h-[400px] because browsers do not accept transition for h-auto, we have all the commands to open an accordion in Phoenix liveView as you see except some information about the element. It forces me to use hook or something like AlpineJS.
It can be an option for JS.show, JS.hide and (before or after doing operation) etc.
Thank you in advance
Refs:
Most Liked
steffend
@garrison already made some very good points. We don’t plan to make complex JS commands.
There are lots of improvements planned for hooks. One of them is to actually expose sticky JS commands like this:
mounted() {
const js = this.js();
// js.show, js.hide, js.transition, etc.
js.toggleClass(this.el, ...);
}
Another big improvement will be colocated hooks that will allow defining the necessary JavaScript next to the components themselves.
garrison
I did not elaborate because the grid trick in question was linked above
Here is a StackOverflow question with more details:
Honestly you probably could find a way to do it with radio buttons and pure CSS, but I wouldn’t. What I meant was that the animation can all be done with CSS (no JS.transition needed), and then all you need is JS.toggle_class to trigger the CSS animations.
First, you wrap each item in a grid container, and then you use CSS to toggle grid-template-rows between 0fr and 1fr. You set overflow: hidden on the child (the accordion content in your case) so that it’s not visible when closed.
The CSS would look like this:
.container {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 100ms;
}
.container.open {
grid-template-rows: 1fr;
}
.content {
overflow: hidden;
}
The HEEx would look like this:
<div>
<div class="container" phx-click={@open}>
<div class="content">Foo</div>
</div>
<div class="container" phx-click={@open}>
<div class="content">Bar</div>
</div>
</div>
And then, if you want all of the other items to close when you open one, you would do this (otherwise you could just use JS.toggle_class("open")):
open =
JS.remove_class("open", to: ".container.open")
|> JS.add_class("open")
This is just a minimal demonstration of the mechanism, obviously you would also need some sort of title for each item to actually click on ![]()
garrison
The code I’ve written to get around this issue (using the liveSocket to trigger JS commands in data- attributes) is some of my least favorite in my app - it’s obviously suboptimal. I think opening up the sticky API is inevitable, and I don’t see any obvious problems (it’s the same thing we’re already doing anyway, just directly). I would imagine the work simply hasn’t been done yet - JS commands are still relatively new and improving quickly. We only just got toggle_class, which was a big improvement ![]()







