<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="156281" data-post-id="156281">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="msaraiva" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/120/1214_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  msaraiva
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Broadway Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>Call me stupid but can someone explain the value in having such an abstraction in practice?</p>
</blockquote>
<p>I think there’s no need to call you stupid. It’s a valid question. However, I believe that either you didn’t have the opportunity to read the “Getting started” guide at <a href="http://surface-demo.msaraiva.io" rel="noopener nofollow ugc">surface-demo.msaraiva.io</a> or, most likely, I did a terrible job trying to explain some of the benefits there. So, please, let me try again.</p>
<blockquote>
<p>In the Grid example it looks like you could have put the <code>&lt;table&gt;</code> inside of a template in the render function</p>
</blockquote>
<p>Of course I could, but then I’d have missed the whole point of demonstrating how to use children as data. The Grid example was extracted from the section called <strong>“Children as data”</strong> of the <strong>“Getting started”</strong> guide mentioned above. That guide is not meant to be a tutorial on how you should design your application, it’s just a guide with simple examples that demonstrates the main features. The way you use those features is up to you.</p>
<blockquote>
<p>and it would work the same</p>
</blockquote>
<p>Well, it’s an abstraction on top of EEx, so it expected to work the same. Actually, by the end of the day, anything you can do with Surface can be done with EEx, just like anything you can do with <code>React/JSX</code> can also be done with pure Javascript. It’s hard to know when to stop adding abstractions on top of existing ones. There is always a tradeoff.</p>
<blockquote>
<p>and be more similar to how templates work with EEx.</p>
</blockquote>
<p>I have no intention whatsoever to keep Surface similar to EEx. On the contrary, I don’t want any dependency between Surface’s and EEx’s syntax. Each one of them tries to solve different problems. The main issue with EEx is that it makes no distinction between plain text and HTML (or any other structured format). Everything is treated as text. When using EEx, all you end up with is a big unstructured list of lists of chunks of text, consequently, a lot of useful information that we could use in our favour to boost productivity is lost. Here are some, IMO, clear benefits of keeping that information:</p>
<h2><a name="p-156281-normalized-syntax-for-html-elements-and-components-1" class="anchor" href="#p-156281-normalized-syntax-for-html-elements-and-components-1" aria-label="Heading link" rel="nofollow"></a>Normalized syntax for HTML elements and components</h2>
<p>Let’s take a look at how HTML elements and Phoenix components are defined in EEx:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  &lt;input style="padding: 1px"&gt;
  &lt;%= live_component(@socket, Input, style: "padding: 1px") %&gt;
</code></pre>
<p>The syntax is completely different. One is declarative and clean, the other is a function call inside a weird <code>&lt;%= ... %&gt;</code>.</p>
<p>Now let’s take a look at how HTML elements and Surface components are defined:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  &lt;input style="padding: 1px"&gt;
  &lt;Input style="padding: 1px"&gt;
</code></pre>
<p>Now both definitions are declarative, clean and use the same syntax. That makes the reading experience much more pleasant. I can also read it much faster, not only because there’s less noise but also because I don’t have to keep switching contexts (HTML ↔ EEx) all the time. This is only possible because we know that <code>&lt;Input&gt;</code> is a component. We didn’t’ lose that information so we can generate the necessary code to initialize it.</p>
<h2><a name="p-156281-syntactic-sugar-for-attributesproperties-2" class="anchor" href="#p-156281-syntactic-sugar-for-attributesproperties-2" aria-label="Heading link" rel="nofollow"></a>Syntactic sugar for attributes/properties</h2>
<p>There’s an example of this feature in the “Getting Started” guide. I’ll just write a shorter version here to save us some time.</p>
<p>Imagine you want to create a button component that sets CSS classes based on the following<br>
rules:</p>
<ul>
<li><code>button</code> - always set</li>
<li><code>is-loading</code> - set if <code>@loading</code> is truthy</li>
</ul>
<p>so assuminng <code>@loading</code> is <code>true</code>, the following code should be generated:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;button class="button is-loading"&gt;
</code></pre>
<p>if it’s false:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;button class="button"&gt;
</code></pre>
<p>Using Surface we can achieve what we want by just:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;button class={{ "button", isLoading: @loading }}&gt;
</code></pre>
<p>Do you see how clean that code looks without any conditional or ugly string concatenation?</p>
<p>Now you can argue that we could achieve the same result with EEx by creating a function. Again, of course you can. After all, that’s exactly how it’s implemented under the hood.</p>
<p>We could also extend this very same concept to boolean attributes like <code>disabled</code> or <code>readonly</code> and create another function so we can handle those too. Something like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;button class=&lt;%= css_class(["button", isLoading: @loading]) %&gt; &lt;%= boolean_attr(:disabled, @disabled) %&gt;&gt;
</code></pre>
<p>Well, that works for sure. But I must confess that it makes my eyes bleed. Could Surface do any better? Let’s see:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;button class={{ "button", isLoading: @loading }} disabled={{ @disabled }}&gt;
</code></pre>
<p>Doesn’t it look better? I truly believe it does.</p>
<h2><a name="p-156281-static-checking-3" class="anchor" href="#p-156281-static-checking-3" aria-label="Heading link" rel="nofollow"></a>Static checking</h2>
<ul>
<li>
<p><strong>Syntax checking</strong> - Since EEx doesn’t care about the structure of your code, any invalid HTML will only raise errors at runtime. When using Surface, most checks are done at compile-time.</p>
</li>
<li>
<p><strong>Validation of properties and children</strong> - you can restrict what kind of properties and children a component accepts.</p>
</li>
<li>
<p><strong>Other examples</strong> of static checking are available at <a href="https://github.com/msaraiva/surface#static-checking" class="inline-onebox" rel="noopener nofollow ugc">GitHub - surface-ui/surface: A server-side rendering component library for Phoenix · GitHub</a></p>
</li>
</ul>
<h2><a name="p-156281-grouping-and-traversing-children-4" class="anchor" href="#p-156281-grouping-and-traversing-children-4" aria-label="Heading link" rel="nofollow"></a>Grouping and traversing children</h2>
<p>A parent component can classify its children in different logical groups and later traverse them and make decisions based on the information retrieved. They are not just dumb unstructured chunks of text. The concept of <strong>parent</strong> and <strong>child</strong> is not lost.</p>
<h2><a name="p-156281-tooling-5" class="anchor" href="#p-156281-tooling-5" aria-label="Heading link" rel="nofollow"></a>Tooling</h2>
<ul>
<li>
<p><strong>Syntax highlighting</strong> - Since EEx allows you to create incomplete/invalid HTML code, it might get tricky to make syntax highlighting work properly when mixing HTML with EEx/Elixir code. Code written in Surface, on the other hand, is structured, predictable and validated at compile-time. It took me just a couple of hours to create a VS Code extension for it.</p>
</li>
<li>
<p><strong>Auto-complete</strong> - Since information about components, properties and data (state assigns) are always available for introspection, it was trivial to add this feature to <a href="https://github.com/elixir-lsp/elixir_sense/" rel="noopener nofollow ugc">ElxirSense</a>.</p>
</li>
<li>
<p><strong>Documentation, Go-to-Definition and …</strong> a bunch of other related stuff around tooling.</p>
</li>
</ul>
<p>Example of auto-complete/suggestions of <strong>assigns</strong>:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/5/b/5b77229aeb90a15c56f77a604dfe35120a7f90a9.png" data-download-href="https://forum.elixirforum.com/uploads/default/5b77229aeb90a15c56f77a604dfe35120a7f90a9" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/5/b/5b77229aeb90a15c56f77a604dfe35120a7f90a9_2_690x366.png" alt="image" data-base62-sha1="d38H8suzGFrx5luxpabqYOI8y3D" width="690" height="366" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/5/b/5b77229aeb90a15c56f77a604dfe35120a7f90a9_2_690x366.png, https://forum.elixirforum.com/uploads/default/original/3X/5/b/5b77229aeb90a15c56f77a604dfe35120a7f90a9.png 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/5/b/5b77229aeb90a15c56f77a604dfe35120a7f90a9.png 2x" data-dominant-color="232425"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">884×470 39.1 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>Example of auto-complete/suggestions of <strong>properties</strong> and <strong>directives</strong>:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/1/5/154d84e3b5438b1f7f4dc4e4f8070a99f6eb6b37.png" data-download-href="https://forum.elixirforum.com/uploads/default/154d84e3b5438b1f7f4dc4e4f8070a99f6eb6b37" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/1/5/154d84e3b5438b1f7f4dc4e4f8070a99f6eb6b37_2_690x283.png" alt="image" data-base62-sha1="32s6RQZcVi9rABaLf3Ugx8fQZYH" width="690" height="283" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/1/5/154d84e3b5438b1f7f4dc4e4f8070a99f6eb6b37_2_690x283.png, https://forum.elixirforum.com/uploads/default/original/3X/1/5/154d84e3b5438b1f7f4dc4e4f8070a99f6eb6b37.png 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/1/5/154d84e3b5438b1f7f4dc4e4f8070a99f6eb6b37.png 2x" data-dominant-color="232527"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">824×339 23 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>I could keep going on and on, showing more benefits of the proposed abstraction and its positive impact on productivity and maintainability. I could also try to introduce some of the planned features like <strong>scoped styles</strong> or <strong>slots</strong>, but I’m afraid that, if I haven’t convinced you yet, keep trying is not going to make any difference.</p>
<p>BTW, it’s totally fine if you don’t see any value in the solution. As I mentioned before, choosing the write abstraction is hard and will depend heavily on the requirements of the project in hand. I don’t’ have any expectation that <code>Surface</code> or even <code>LiveView</code> will always be a good choice for all kinds of projects. There’s still a long way to go, lots of ideas to be validated and certainly many mistakes to be made. The one thing I believe is that keeping an open mind, trying to explore new ideas to improve existing solutions will always be beneficial to any ecosystem.</p>
<p>Cheers.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156281" data-batch-url="/posts/batch_likers">
                        35
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-156281" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156281"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="156298" data-post-id="156298">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MrDoops" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/MrDoops/120/7118_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MrDoops
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Looking forward to those component examples on the demo page. I’ve got a bunch of reusable Tailwind+Liveview components in the backlog for a couple projects.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156298" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-156298" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156298"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="156344" data-post-id="156344">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="cnck1387" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  cnck1387
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>These questions I’m about to ask are for curiosity’s sake btw. Only because what you wrote sounds kind of interesting. At least to get a better understanding of how your tool works.</p>
<aside class="quote no-group" data-username="msaraiva" data-post="12" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/48/1214_2.png" class="avatar"> msaraiva:</div>
<blockquote>
<p>I believe that either you didn’t have the opportunity to read the “Getting started” guide at <a href="http://surface-demo.msaraiva.io" rel="noopener nofollow ugc">surface-demo.msaraiva.io </a> or, most likely, I did a terrible job trying to explain some of the benefits there. So, please, let me try again.</p>
</blockquote>
</aside>
<p>I didn’t read it, I only checked what was posted in this thread. But after having read that page, the “why” aspect isn’t covered. The motivation part of the docs you linked mentioned <em>“Provide a more declarative way to express and use components in  Phoenix”</em>. But all I thought after that was “why?”.</p>
<p>This is coming at it from not ever using React in the past. I understand that React components exist, but I don’t have experience using and leveraging them in the real world. Personally I never found any front-end abstraction to be 100% re-usable (prior to React) and often just tackled front-end development with an approach of “ok, this is a new project, so I’m going to likely use Bootstrap and modify some bits and pieces for this specific project so that I have full 100% control over every element”.</p>
<aside class="quote no-group" data-username="msaraiva" data-post="12" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/48/1214_2.png" class="avatar"> msaraiva:</div>
<blockquote>
<p>it’s just a guide with simple examples that demonstrates the main features</p>
</blockquote>
</aside>
<p>For folks who never touched React, they don’t know the benefits of doing things this way.</p>
<aside class="quote no-group" data-username="msaraiva" data-post="12" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/48/1214_2.png" class="avatar"> msaraiva:</div>
<blockquote>
<p>I don’t have to keep switching contexts (HTML ↔ EEx) all the time. This is only possible because we know that <code>&lt;Input&gt;</code> is a component.</p>
</blockquote>
</aside>
<p>I see. Personally I find that distinction to be a perk. It’s letting me know “hey, this snippet of code is going to be evaluated” and then I can trace code back to what <code>live_component</code> does. Where as my first instinct with <code>&lt;Input ...&gt;</code> is that it looks like maybe a typo and should be in lowercase and should probably be refactored to move the in-line style out of the HTML style attribute.</p>
<p>Do you have any large scale projects where you can gist one of your surface templates to see how it looks beyond a 2 line example? So we can see the skimmability of it.</p>
<aside class="quote no-group" data-username="msaraiva" data-post="12" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/48/1214_2.png" class="avatar"> msaraiva:</div>
<blockquote>
<p>But I must confess that it makes my eyes bleed. Could Surface do any better?</p>
</blockquote>
</aside>
<p>Does Surface ultimately get transformed into EEx at compile time? In other words, is there zero performance implications of using it at run time?</p>
<aside class="quote no-group" data-username="msaraiva" data-post="12" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/48/1214_2.png" class="avatar"> msaraiva:</div>
<blockquote>
<p>When using Surface, most checks are done at compile-time.</p>
</blockquote>
</aside>
<p>And I’m guessing LiveComponent is dealing with EEx templates in the end? I haven’t looked into its API yet or details. But I like the idea of having compiled time syntax checks.</p>
<aside class="quote no-group" data-username="msaraiva" data-post="12" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/48/1214_2.png" class="avatar"> msaraiva:</div>
<blockquote>
<p>It took me just a couple of hours to create a VS Code extension for it.</p>
</blockquote>
</aside>
<p>Is there a Vim plugin in the works? <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="msaraiva" data-post="12" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/48/1214_2.png" class="avatar"> msaraiva:</div>
<blockquote>
<p>I don’t’ have any expectation that <code>Surface</code> or even <code>LiveView</code> will always be a good choice for all kinds of projects.</p>
</blockquote>
</aside>
<p>What types of projects would you use and not use Surface on?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156344" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-156344" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156344"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="156364" data-post-id="156364">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mazz-seven" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mazz-seven/120/17274_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mazz-seven
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Wow, this looks great. will take it for a spin! <img src="https://forum.elixirforum.com/images/emoji/apple/smiley.png?v=15" title=":smiley:" class="emoji" alt=":smiley:" loading="lazy" width="20" height="20"></p>
<p>Can I use the components in .eex file?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156364" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-156364" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156364"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="156460" data-post-id="156460">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="msaraiva" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/120/1214_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  msaraiva
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Broadway Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi Zack!</p>
<p>My plan for the “Components” section is to list different reusable components suites written using different technologies like <strong>Bootstrap</strong>, <strong>Bulma</strong>, <strong>Tailwind</strong>, etc. Each one of them as a separate project. Since I’m still working on the core API, I didn’t have time to create any full set of components yet. In case you already have a few working examples and want to convert them to Surface, please let me know, I’ll be glad to update the page to list them. Also, feel free to contact me if need any assistance while converting the components and keep in mind that since it’s this is a work-in-progress, we might still have some changes in the API until we reach the first stable version.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156460" data-batch-url="/posts/batch_likers">
                        5
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-156460" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156460"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="156469" data-post-id="156469">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="msaraiva" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/120/1214_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  msaraiva
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Broadway Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="cnck1387" data-post="14" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>I didn’t read it, I only checked what was posted in this thread. But after having read that page, the “why” aspect isn’t covered. The motivation part of the docs you linked mentioned <em>“Provide a more declarative way to express and use components in  Phoenix”</em>. But all I thought after that was “why?”.</p>
</blockquote>
</aside>
<p>Like everything else in this project, the documentation is still a work-in-progress. I’ll try to write more about “why?”. Thanks for the feedback.</p>
<aside class="quote no-group" data-username="cnck1387" data-post="14" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>I see. Personally I find that distinction to be a perk. It’s letting me know “hey, this snippet of code is going to be evaluated” and then I can trace code back to what <code>live_component</code> does. Where as my first instinct with <code>&lt;Input ...&gt;</code> is that it looks like maybe a typo</p>
</blockquote>
</aside>
<p>Ok, first. I find hard to believe you would think it was a typo since the syntax highlighter uses different colours for HTML tags and components:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/a/9/a923f0660d9dddb8389057199956cbdda1904d5d.png" data-download-href="https://forum.elixirforum.com/uploads/default/a923f0660d9dddb8389057199956cbdda1904d5d" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/a/9/a923f0660d9dddb8389057199956cbdda1904d5d_2_690x270.png" alt="image" data-base62-sha1="o8hGSr4TFOdyfntLc26oyqORQjX" width="690" height="270" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/a/9/a923f0660d9dddb8389057199956cbdda1904d5d_2_690x270.png, https://forum.elixirforum.com/uploads/default/original/3X/a/9/a923f0660d9dddb8389057199956cbdda1904d5d.png 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/a/9/a923f0660d9dddb8389057199956cbdda1904d5d.png 2x" data-dominant-color="222223"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">727×285 16.7 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>Secondly. Even you if don’t have syntax highlighting, you’ll get a nice warning telling you that there’s no Input component:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/5/4/5492e2f2f97391ffcd9cd665709b59874be9fc06.png" data-download-href="https://forum.elixirforum.com/uploads/default/5492e2f2f97391ffcd9cd665709b59874be9fc06" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/5/4/5492e2f2f97391ffcd9cd665709b59874be9fc06_2_690x363.png" alt="image" data-base62-sha1="c4aOfjs17TpHzNWQ3m7Gt5IH2ZM" width="690" height="363" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/5/4/5492e2f2f97391ffcd9cd665709b59874be9fc06_2_690x363.png, https://forum.elixirforum.com/uploads/default/original/3X/5/4/5492e2f2f97391ffcd9cd665709b59874be9fc06.png 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/5/4/5492e2f2f97391ffcd9cd665709b59874be9fc06.png 2x" data-dominant-color="232323"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">781×411 30.3 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>Cool, isn’t it?</p>
<p>Lastly and most importantly, this is just an <strong>example</strong> made to demonstrate the benefits of a unified syntax. In real life you don’t have to create components with the same name of existing tags.</p>
<aside class="quote no-group quote-modified" data-username="cnck1387" data-post="14" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>…and should probably be refactored to move the in-line style out of the HTML style attribute.</p>
</blockquote>
</aside>
<p>You certainly have a problem understanding the concept of an “example”. Forget about the inline style. Again, the point was to demonstrate the syntax, not to show you the best practices of using CSS styles. Please, focus on the subject of the discussion, not on secondary pointless aspects.</p>
<aside class="quote no-group" data-username="cnck1387" data-post="14" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>Do you have any large scale projects where you can gist one of your surface templates to see how it looks beyond a 2 line example? So we can see the skimmability of it.</p>
</blockquote>
</aside>
<p>No. The project is still an experimental unfinished work-in-progress. There’s no way anyone could possibly have a large scale project using it. Not even me.</p>
<aside class="quote no-group" data-username="cnck1387" data-post="14" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>Does Surface ultimately get transformed into EEx at compile time? In other words, is there zero performance implications of using it at run time?</p>
</blockquote>
</aside>
<p>Yes. Everything is translated at compile-time. There shouldn’t be any perfomance issue at runtime.</p>
<aside class="quote no-group" data-username="cnck1387" data-post="14" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>Is there a Vim plugin in the works? <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>For syntax highlighting, I’m not aware of anyone working on it. I have no idea how easy it would be to convert the one I created for VS Code. The code is available at <a href="https://github.com/msaraiva/vscode-surface" class="inline-onebox" rel="noopener nofollow ugc">GitHub - msaraiva/vscode-surface: A VS Code extension to add syntax highlighting support for Surface/Elixir · GitHub</a>. Feel free to give it a try if you want. Regarding other features like auto-complete and friends, if your editor uses a plugin on top of ElixirSense, you’ll get all the benefits as soon as the maintainer updates to the new version, which by the way should be out in a couple of days.</p>
<aside class="quote no-group" data-username="cnck1387" data-post="14" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>What types of projects would you use and not use Surface on?</p>
</blockquote>
</aside>
<p>Roughly, I think that any project that is suitable for LiveView would also be suitable for Surface. But as I said, the project is still experimental. It’s going to take some time to collect feedback to see if there will be any limitation.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156469" data-batch-url="/posts/batch_likers">
                        6
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-156469" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156469"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="156471" data-post-id="156471">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="msaraiva" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/120/1214_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  msaraiva
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Broadway Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="mazz-seven" data-post="15" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mazz-seven/48/17274_2.png" class="avatar"> mazz-seven:</div>
<blockquote>
<p>Can I use the components in .eex file?</p>
</blockquote>
</aside>
<p>No. EEx files will not get translated, however, you can wrap any component inside a separate function and call it normally in any EEx template. If your intention is to use Surface keeping the templates as external files, I’m working already on this feature. The plan is to allow components to load external templates with the <code>.sface</code> extension.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156471" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-156471" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156471"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="156558" data-post-id="156558">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="msaraiva" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/msaraiva/120/1214_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  msaraiva
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Broadway Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="niccolox" data-post="9" data-topic="27671">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/niccolox/48/2601_2.png" class="avatar"> niccolox:</div>
<blockquote>
<p>have you thought about using something like Liquid templates for your syntax?</p>
</blockquote>
</aside>
<p>Not really. It would be really hard to keep the exact same syntax since we need to keep compatibility with Elixir code inside interpolation, e.g. the <code>|</code> operator is already taken by Elixir. Having said that, we could try to find an alternative way for the syntax to achieve the same goal. Is there any specific feature that you think it would be just awesome to have in Surface?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156558" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-156558" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156558"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="156685" data-post-id="156685">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="joerichsen" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/joerichsen/120/3267_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  joerichsen
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just for fun, I created a demo project with some simple Surface components using Bootstrap.</p>
<p>Check out the demo: <a href="https://surface-bootstrap-demo.herokuapp.com/" rel="noopener nofollow ugc">https://surface-bootstrap-demo.herokuapp.com/</a></p>
<p>And check out the implementation of the components here: <a href="https://github.com/joerichsen/surface_bootstrap_demo/tree/master/lib/surface_demo_web/components" class="inline-onebox" rel="noopener nofollow ugc">surface_bootstrap_demo/lib/surface_demo_web/components at master · joerichsen/surface_bootstrap_demo · GitHub</a></p>
<p>It’s pretty simple for these (admittedly) simple components <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>When I get the time, I want to tackle some more complex components like for example forms and modals.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156685" data-batch-url="/posts/batch_likers">
                        14
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-156685" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156685"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="156686" data-post-id="156686">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="wolfiton" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/wolfiton/120/15884_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  wolfiton
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thanks for creating this example.</p>
<p>Your demo looks good but too improve it you can use highlight.js for your code snippets</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="156686" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/surface-a-component-based-library-for-phoenix-liveview/27671/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-156686" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="156686"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #20"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/27671/load_more?page=3">Load more posts (194 remaining)</a>
</div></template></turbo-stream>