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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>How do you add it to html_helpers/0 ? I am trying to make it work by adding it as:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">use MyAppWeb.Components
</code></pre>
<p>but then I get a</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">== Compilation error in file lib/my_app_web/controllers/page_html.ex ==
** (CompileError) lib/my_app_web/controllers/page_html.ex:2: module MyAppWeb.Components.CustomComponents.MyButton is not loaded and could not be found. This may be happening because the module you are trying to load directly or indirectly depends on the current module
    expanding macro: MyAppWeb.Components.__using__/1
</code></pre>
<p>Code for further reference:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">#components.ex
defmodule MyAppWeb.Components do
  defmacro __using__(_) do
    quote do
      import unquote(__MODULE__).CustomComponents.{
        MyButton 
        # ....
      }
    end
  end
end
</code></pre>
<p>And the directory looks like this:<br>
my_app_web/<br>
|-- components/<br>
|   |-- custom_components/<br>
|   |   |-- my_button.ex<br>
|   |   |-- other_component1.ex<br>
|   |-- components.ex</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="318555" data-batch-url="/posts/batch_likers">
                        1
                      </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/how-do-you-organize-your-components-with-phoenix-1-7/53901/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-318555" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="318555"
                     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 #21"></div>
  </section>
</div>
    <div class="postbit" id="318569" data-post-id="318569">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>We would need to see the code in <code>my_button.ex</code> to know for sure but it looks like you just don’t have the <code>MyButon</code> module properly defined.  It must be:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule  MyAppWeb.Components.CustomComponents.MyButton do
  # ...
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="318569" data-batch-url="/posts/batch_likers">
                        1
                      </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/how-do-you-organize-your-components-with-phoenix-1-7/53901/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-318569" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="318569"
                     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 #22"></div>
  </section>
</div>
    <div class="postbit" id="318611" data-post-id="318611">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Saw this thread pop up and thought I’d share how I’ve ended up doing this.</p>
<p>I mostly work with umbrella applications, where we usually have a separate application which handles assets and components. Depending on the project, it’s been called either <code>DesignSystem</code>, <code>WebAssets</code>, <code>CommonWeb</code> or similar. In the most recent one it’s called <code>DesignSystem</code> so I’ll go with that one for the examples. All the components are in separate files and the folder structure is something along the lines of:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">apps/
|-- design_system/
||-- assets/
|||-- css/
|||-- js/
||-- lib/
|||-- design_system/
||||-- components/
|||||-- form/
||||||-- error.ex
||||||-- input.ex
|||||-- button.ex
|||||-- table.ex
|||-- design_system.ex
...
</code></pre>
<p>Component’s module naming follows the folder structure.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule DesignSystem.Components.Button do
  def button(assigns) do
    ...
  end
end
</code></pre>
<p>In <code>design_system.ex</code> I have a <code>defdelegate</code> for every component, which allows me to call them without specifying the full module name.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule DesignSystem do
  defdelegate button(), to: __MODULE__.Button
  defdelegate input(), to: __MODULE__.Form.Input
  ...
end
</code></pre>
<p>Verbose code is more to my liking, and it also allows easy code completion, so I don’t mind my <code>.heex</code> files looking like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;DesignSystem.box&gt;
  &lt;DesignSystem.button&gt;
    Click me!
  &lt;/DesignSystem.button&gt;
&lt;/DesignSystem.box&gt;
</code></pre>
<p>To deal with typing out the <code>DesignSystem</code> part every time, I would either import or alias the module:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule ExampleWeb do
  def live_view() do
    quote do
      use Phoenix.LiveView,
        layout: {ExampleWeb.Layouts, :live}

      # Either this
      import DesignSystem

      # Or this
      alias DesignSystem, as: DS

      unquote(html_helpers())
    end
  end

end
</code></pre>
<p>The reason I don’t do this is because in my view it’s easier for beginners to clearly see where the function is defined at. Also this one time I made a component called <code>Form</code> and I wanted to call it with <code>&lt;.form&gt;</code> but it’s already defined in <code>Phoenix.Component</code>, and I didn’t want to call it <code>.simple_form</code> or similar. So yeah, a ridiculous reason but I am a ridiculous person.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="318611" data-batch-url="/posts/batch_likers">
                        7
                      </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/how-do-you-organize-your-components-with-phoenix-1-7/53901/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-318611" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="318611"
                     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 #23"></div>
  </section>
</div>
    <div class="postbit" id="353445" data-post-id="353445">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi. Would like to ask, do you have any public repository where this approach is implemented?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="353445" 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/how-do-you-organize-your-components-with-phoenix-1-7/53901/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-353445" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="353445"
                     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 #24"></div>
  </section>
</div>
    <div class="postbit" id="353486" data-post-id="353486">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi!</p>
<p>I didn’t have one but I made a <a href="https://github.com/pasila/eggsample" rel="noopener nofollow ugc">simple example for you to look at</a>.</p>
<p>I try to avoid having <code>gettext</code> calls inside UI components and instead pass the strings from the caller’s side. This is where <code>slot</code>s come in handy. You’ll see this in how I’ve implemented the <code>Flash</code> and <code>FlashGroup</code> components, found in <code>eggsample_web/lib/eggsample_web/components/layouts/app.html.heex#3</code>. This reminds me that I should really look into <a href="https://github.com/srcrip/live_toast" rel="noopener nofollow ugc">Live Toast</a>…</p>
<p>Basically this example has <code>CoreComponents</code> pulled into a separate app, with a workaround for the existing <code>translate_error</code> function used in inputs. It relies on implementing the <code>error_translation_function</code> somewhere and configuring it for the <code>UI</code> app to use.</p>
<p>You’ll find the configuration in <code>config/config.exs#71</code> and it’s implementation in <code>eggsample/lib/eggsample/gettext.ex#4</code>. It’s used in <code>ui/lib/ui.ex#18</code>, with an example call in <code>ui/lib/ui/components/form/input.ex#64</code>.</p>
<p>Some basic examples exist in <code>eggsample_web/live/home/index.ex</code>, which is the page you’ll see when visiting the root route.</p>
<p>The solution is not perfect (this example is not exactly the same as we have in our codebase) but it has served us quite well.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="353486" data-batch-url="/posts/batch_likers">
                        1
                      </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/how-do-you-organize-your-components-with-phoenix-1-7/53901/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-353486" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="353486"
                     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 #25"></div>
  </section>
</div>
    <div class="postbit" id="353500" data-post-id="353500">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Whooah… man! I din’t even expected such generosity! Thank You for your TIME! I will explore it now. Right away i see couple of interesting things - for example, separated UI layer which is also something I am looking into.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="353500" data-batch-url="/posts/batch_likers">
                        1
                      </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/how-do-you-organize-your-components-with-phoenix-1-7/53901/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-353500" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="353500"
                     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 #26"></div>
  </section>
</div>
    <div class="postbit" id="353590" data-post-id="353590">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Looks like you have the same “issue” I were trying to solve. For example, UI is an dependency of Web. When you are developing (watching) Web, you might want to tweak some UI components and “it would be nice to see hot reload there as well”. But it doesn’t work that way. <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"> You need to restart the “phx.server”. I had worked with Bazel build system before, which basically is multi-repo system, which “feels” (from DX perspective) like a monorepo. You tweak any repo/part of your solution and Bazel takes care about diffing and compiling only those parts which are affected by the changes. Builds were like 1-2 second long for any kind of change.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="353590" 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/how-do-you-organize-your-components-with-phoenix-1-7/53901/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-353590" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="353590"
                     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 #27"></div>
  </section>
</div>
    <div class="postbit" id="353595" data-post-id="353595">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yeah you’re right. We’ve been moving away from umbrella apps since we haven’t seen the value in it for our projects. For regular non-umbrella projects, <a href="https://github.com/sasa1977/boundary" rel="noopener nofollow ugc">Boundary</a> is nice for enforcing… well, boundaries. Actually pretty much anything by Saša Jurić has worked very well for us.</p>
<p>Bazel looks nice, I’ll have to check it out, thanks!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="353595" 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/how-do-you-organize-your-components-with-phoenix-1-7/53901/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-353595" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="353595"
                     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 #28"></div>
  </section>
</div>
    <div class="postbit" id="353597" data-post-id="353597">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Oh no!.. Don’t walk that road. Bazel is HUGE rabbit hole! It is worth investing into it for larger shops and from very beginning. It is hard to jump into it for established projects as everything should be done “Bazel way”. And I’m not sure is there Elixir rules to work with it.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="353597" 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/how-do-you-organize-your-components-with-phoenix-1-7/53901/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-353597" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="353597"
                     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 #29"></div>
  </section>
</div>
    <div class="postbit" id="353600" data-post-id="353600">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Haha ok, thanks for the warning <img src="https://forum.elixirforum.com/images/emoji/apple/sweat_smile.png?v=15" title=":sweat_smile:" class="emoji" alt=":sweat_smile:" loading="lazy" width="20" height="20"></p>
<p>I work with old and new projects, both big and small, so I’ll be checking it out but with a grain of salt <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="353600" 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/how-do-you-organize-your-components-with-phoenix-1-7/53901/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-353600" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="353600"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>