Closed simonmcconnell closed 1 year ago
Did you ever find a resolution to this?
One workaround was to change the forms class to {[class="h-full flex flex-col bg-white shadow-xl"]}.
I forked Surface and changed something deep down but I can't recall where I was at with it because I haven't touched that project for a few months.
It might just work on the newer version?
Yeah, that's my short-term solution :-/ It definitely makes it a little confusing for some of our newer folks.
I was able to recreate the issue without relying on any CoreComponents code, and just render_component
which almost immediately delegates to the render
.
Phoenix.LiveViewTest.render_component(&Surface.Components.Form.Submit.render/1,
class: "test-class"
)
1) test reproduce failure .modal and Surface.Form modules bug (MyAppWeb.PropsToAttrsTest)
test/my_app_web/live/props_to_attrs_test.exs:13
** (Protocol.UndefinedError) protocol Enumerable not implemented for "test-class" of type BitString. This protocol is implemented for the following type(
s): DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Floki.HTMLTree, Function, GenEvent.Stream, HashDict, H
ashSet, IO.Stream, Jason.OrderedObject, List, Map, MapSet, Phoenix.LiveView.LiveStream, Postgrex.Stream, Range, SFTPClient.Stream, Scrivener.Page, Stream, Tim
ex.Interval
code: Phoenix.LiveViewTest.render_component(&Surface.Components.Form.Submit.render/1,
stacktrace:
(elixir 1.13.4) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.13.4) lib/enum.ex:143: Enumerable.reduce/3
(elixir 1.13.4) lib/enum.ex:4144: Enum.join/2
(surface 0.10.0) lib/surface/type_handler/css_class.ex:65: Surface.TypeHandler.CssClass.value_to_opts/2
(surface 0.10.0) lib/surface/type_handler.ex:188: Surface.TypeHandler.attr_to_opts!/3
(surface 0.10.0) lib/surface/components/form/submit.ex:26: Surface.Components.Form.Submit."render (overridable 1)"/1
(phoenix_live_view 0.18.18) lib/phoenix_live_view/test/live_view_test.ex:488: Phoenix.LiveViewTest.__render_component__/4
test/my_app_web/live/props_to_attrs_test.exs:27: (test)
Interestingly, a call to render_surface
does not cause this issue.
For people familiar with the compiler internals:
I did a bunch of digging, into the TypeHandler
, TypeHandler.Default
, TypeHandler.CssClass
, and the compiler, as well as comparing to render_component
, and I think it's something with somehow the normalize_expr
not getting called at compile-time, or getting called differently?
I am not sure how the different layers between Surface and LV work at compile-time, but it seems to be when:
A Phoenix.Component with a slot of a Surface.Component that has a prop of :css_class
, and the prop is a literal.
Something like this (not tested, just for illustration).
~F"""
<SomeOuterSurface>
<.lv_middle>
<InnerSurface class="some-class"/>
</.lv_middle>
</SomeOuterSurface>
"""
If I understand correctly, this isn't just a bug with any of the Form
or out-of-the-box components, and not specific to .focus_wrap
but with all usage of the :css_class
property on a Surface.Component
when it's a "child" of a .HEEX
component.
I am on the newest package version at this time.
Surface: v0.10.0 LiveView: v0.18.18 Elixir: v1.13.4-otp-25 Phoenix: 1.7.2
Thank you all for the detailed report. ❤️
Fixed in b2af2d07438990b58646d33bc53cf4e13a4f2131.
Describe the bug
A
Form
withclass="some string"
crashes when rendered inside a<.focus_wrap>
. It looks likevalue_to_opts(:class, value)
normally receives a list of classes regardles of whether theclass
is defined as a list or string in the template. In this case described below, it is getting a string, which upsets it.How to reproduce it
Given some page
and the SideDrawer
If I change the forms class to
{[class="h-full flex flex-col bg-white shadow-xl"]}
it works. If I remove thefocus_wrap
it works.The behavior you expected
Form's class prop works for string or list when contained within a
<.focus_wrap>
.Your Environment
Surface: v0.9.4 LiveView: v0.18.15 Elixir: v1.14.3 Phoenix: 1.6.16