<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ali Hamdi Ali Fadel</title>
    <description>The latest articles on DEV Community by Ali Hamdi Ali Fadel (@aliosm).</description>
    <link>https://dev.to/aliosm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2102926%2Ff69d0fd8-4c80-4bdc-b4af-e6d6ab40ee2c.jpeg</url>
      <title>DEV Community: Ali Hamdi Ali Fadel</title>
      <link>https://dev.to/aliosm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aliosm"/>
    <language>en</language>
    <item>
      <title>Enforcing Phlex Adoption in Rails: A GitHub Action to Prevent New ERB Files</title>
      <dc:creator>Ali Hamdi Ali Fadel</dc:creator>
      <pubDate>Mon, 23 Sep 2024 21:15:44 +0000</pubDate>
      <link>https://dev.to/aliosm/enforcing-phlex-adoption-in-rails-a-github-action-to-prevent-new-erb-files-28j2</link>
      <guid>https://dev.to/aliosm/enforcing-phlex-adoption-in-rails-a-github-action-to-prevent-new-erb-files-28j2</guid>
      <description>&lt;p&gt;In the world of Ruby on Rails development, choosing a templating language is a significant decision that impacts the maintainability and performance of your application. Traditionally, ERB (Embedded Ruby) has been the go-to for many developers. However, with the rise of more efficient alternatives like &lt;a href="http://phlex.fun" rel="noopener noreferrer"&gt;&lt;strong&gt;Phlex&lt;/strong&gt;&lt;/a&gt;, which offers better performance and a more elegant, Ruby-like syntax, developers are increasingly moving away from ERB (At least me and my friends 😁).&lt;/p&gt;

&lt;p&gt;After fully/partially migrating to Phlex in your Rails project, the last thing you want is to regress by inadvertently adding new ERB files. This article will walk you through a GitHub Action designed to enforce the exclusive use of Phlex in your Rails project by preventing the addition of new ERB files in pull requests (And direct pushes, if you do this…).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is This Important?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintain Consistency:&lt;/strong&gt; Allowing a mix of ERB and Phlex templates can lead to confusion and inconsistency in your codebase. By enforcing a single templating language, you ensure that all team members adhere to the same conventions, making the codebase more uniform and easier to navigate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve Performance:&lt;/strong&gt; Phlex is known for its performance benefits over ERB. By preventing new ERB files, you maintain the performance gains achieved by migrating to Phlex.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce Technical Debt:&lt;/strong&gt; If your project has fully embraced Phlex, any addition of new ERB files can be seen as a step backward, introducing potential technical debt that you'll need to address later.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The GitHub Action: How It Works
&lt;/h2&gt;

&lt;p&gt;The following GitHub Action configuration is designed to check for any new ERB files added in a pull request and prevent the merge if any are found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;no-new-erbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Count ERB files in the PR&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;erb_files_pr=$(find app -type f -name "*.erb" ! -name "*.turbo_stream.erb" | wc -l)&lt;/span&gt;
          &lt;span class="s"&gt;echo "ERB_FILES_PR=${erb_files_pr}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Count ERB files in the main branch&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git fetch origin main&lt;/span&gt;
          &lt;span class="s"&gt;git checkout origin/main&lt;/span&gt;
          &lt;span class="s"&gt;erb_files_main=$(find app -type f -name "*.erb" ! -name "*.turbo_stream.erb" | wc -l)&lt;/span&gt;
          &lt;span class="s"&gt;echo "ERB_FILES_MAIN=${erb_files_main}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Compare ERB file counts&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;if [ "$ERB_FILES_PR" -gt "$ERB_FILES_MAIN" ]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "Error: The number of ERB files has increased in this PR."&lt;/span&gt;
            &lt;span class="s"&gt;exit 1&lt;/span&gt;
          &lt;span class="s"&gt;else&lt;/span&gt;
            &lt;span class="s"&gt;echo "Success: The number of ERB files has not increased."&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step-by-Step Breakdown
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trigger Conditions:&lt;/strong&gt; This action triggers on two events: pull_request and push to the main branch. This ensures that the check runs on any code changes affecting the main branch or any pull request targeting it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checkout Code:&lt;/strong&gt; The action first checks out the code from the repository using the actions/checkout@v4 action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count ERB Files in the Pull Request:&lt;/strong&gt; It counts the number of ERB files in the app directory, excluding .turbo_stream.erb files, as Turbo Streams are better to live in ERBs than controllers. The result is stored in the ERB_FILES_PR environment variable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count ERB Files in the Main Branch:&lt;/strong&gt; It fetches and checks out the latest code from the main branch. It counts the ERB files in the app directory, using the same exclusion criteria. The result is stored in the ERB_FILES_MAIN environment variable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare ERB File Counts:&lt;/strong&gt; The action compares the counts of ERB files between the pull request and the main branch. If the count of ERB files in the pull request (ERB_FILES_PR) is greater than in the main branch (ERB_FILES_MAIN), the action fails with an error message. Otherwise, it outputs a success message indicating no new ERB files have been added.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Utilize This Action
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add the Action to Your Repository:&lt;/strong&gt; Copy the YAML configuration above and add it to your .github/workflows directory in your repository as ci.yml.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customize If Necessary:&lt;/strong&gt; If you have specific directories other than app where ERB files might reside, or you want to change the exclusion criteria, adjust the find command based on your needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test It:&lt;/strong&gt; Create a pull request and intentionally add an ERB file to verify that the action correctly fails. Once confirmed, remove the ERB file and test again to ensure the action passes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforce the Rule:&lt;/strong&gt; Communicate this new rule to your team to ensure everyone understands that new ERB files are no longer allowed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Migrating to a new templating language is a significant step towards modernizing your Rails application, but maintaining that change requires vigilance. This GitHub Action offers a simple, automated way to enforce your commitment to Phlex by preventing the addition of new ERB files. Implementing it not only helps you maintain consistency and performance but also keeps your codebase clean and focused on the new standard you've set.&lt;/p&gt;

&lt;p&gt;By using this action, you can confidently say that your project is Phlex-only, safeguarding your codebase from accidental reintroductions of ERB templates and ensuring that your Rails application stays lean and efficient.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>phlex</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>A RuboCop Configuration Tailored for Phlex</title>
      <dc:creator>Ali Hamdi Ali Fadel</dc:creator>
      <pubDate>Fri, 20 Sep 2024 16:17:24 +0000</pubDate>
      <link>https://dev.to/aliosm/a-rubocop-configuration-tailored-for-phlex-2in8</link>
      <guid>https://dev.to/aliosm/a-rubocop-configuration-tailored-for-phlex-2in8</guid>
      <description>&lt;p&gt;As a developer working with &lt;a href="https://rubyonrails.org" rel="noopener noreferrer"&gt;&lt;strong&gt;Ruby on Rails&lt;/strong&gt;&lt;/a&gt; and the &lt;a href="https://www.phlex.fun" rel="noopener noreferrer"&gt;&lt;strong&gt;Phlex&lt;/strong&gt;&lt;/a&gt; framework, I encountered a common pain point: writing Phlex views that are clean, readable, and efficient, while also adhering to &lt;a href="https://rubocop.org" rel="noopener noreferrer"&gt;&lt;strong&gt;RuboCop&lt;/strong&gt;&lt;/a&gt;’s default style guidelines. While RuboCop is a fantastic tool for enforcing coding standards and preventing messy codebases, it can feel a bit restrictive when applied to view code, especially when using frameworks like Phlex along with something like &lt;a href="https://tailwindcss.com" rel="noopener noreferrer"&gt;&lt;strong&gt;TailwindCSS&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Lengthy and Complex Phlex Views and Components
&lt;/h2&gt;

&lt;p&gt;Phlex takes a more Ruby-centric approach to generating HTML by using Ruby classes and methods instead of traditional template files like &lt;a href="https://github.com/ruby/erb" rel="noopener noreferrer"&gt;ERB&lt;/a&gt; or &lt;a href="https://haml.info" rel="noopener noreferrer"&gt;HAML&lt;/a&gt;. While this is great for reusability and code organization (And writing more Ruby 🤩), it can lead to long methods and classes, especially when building complex components or pages. Adding TailwindCSS into the mix further increases line lengths because of its utility-first CSS approach, where multiple classes are often stacked together.&lt;/p&gt;

&lt;p&gt;The result? RuboCop flags violations left and right for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Line length&lt;/strong&gt;: Phlex views with TailwindCSS often lead to long lines of code due to the many utility classes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method length:&lt;/strong&gt; Complex view logic can lead to long methods, especially if you’re rendering deeply nested HTML elements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Class length:&lt;/strong&gt; Phlex encourages structuring views and components as classes, which may grow large if they represent complex components or full pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cyclomatic complexity:&lt;/strong&gt; The complexity of HTML structures, conditionals, and loops can trigger RuboCop’s complexity metrics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While these checks make sense for general Ruby code, enforcing them strictly on views and components doesn’t always add value. Instead, they add friction to writing clear, concise views, especially in the context of Phlex.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Tailoring RuboCop for Phlex Views
&lt;/h2&gt;

&lt;p&gt;To reduce this friction, I decided to customize my RuboCop configuration specifically for Phlex views. My goal was to exclude certain style checks from my &lt;code&gt;app/views/**/*&lt;/code&gt; directory (I’m still using Phlex v1.x, if you already upgraded to v2.x, you will need to exclude &lt;code&gt;app/components/**/*&lt;/code&gt; in addition to &lt;code&gt;app/views/**/*&lt;/code&gt;), allowing me to write Phlex views without unnecessary interruptions. Below is the configuration I settled on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Layout/LineLength&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;

&lt;span class="na"&gt;Metrics/AbcSize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;

&lt;span class="na"&gt;Metrics/BlockLength&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;

&lt;span class="na"&gt;Metrics/ClassLength&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;

&lt;span class="na"&gt;Metrics/CyclomaticComplexity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;

&lt;span class="na"&gt;Metrics/MethodLength&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;

&lt;span class="na"&gt;Metrics/ParameterLists&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;

&lt;span class="na"&gt;Metrics/PerceivedComplexity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;

&lt;span class="na"&gt;Style/IfUnlessModifier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app/views/**/*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why Disable These Specific RuboCop Cops?
&lt;/h2&gt;

&lt;p&gt;Let’s break down why each of these exclusions makes sense for Phlex views and components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Layout/LineLength&lt;/code&gt;&lt;/strong&gt;: When using TailwindCSS, it’s common to end up with long lines due to multiple class names being stacked together. Breaking these up into smaller lines often makes the code harder to follow and ugly. By excluding this check, I avoid cluttering the view with unnecessary line breaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Metrics/AbcSize&lt;/code&gt;&lt;/strong&gt;: Phlex views often have higher abstraction levels, meaning they will naturally include a fair amount of assignments, branches, and conditionals. Disabling this check avoids constant warnings about the complexity of view logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Metrics/BlockLength&lt;/code&gt;&lt;/strong&gt;: HTML structures can get quite large, and Phlex components represent these as Ruby blocks. Disabling this check prevents RuboCop from flagging long blocks in view components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Metrics/ClassLength&lt;/code&gt;&lt;/strong&gt;: Phlex encourages building views as Ruby classes, which can become lengthy when rendering full pages or complex components. Excluding this check allows me to write robust views without breaking them into unnecessarily small pieces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Metrics/CyclomaticComplexity&lt;/code&gt;&lt;/strong&gt; &amp;amp; &lt;strong&gt;&lt;code&gt;Metrics/PerceivedComplexity&lt;/code&gt;&lt;/strong&gt;: HTML is inherently nested and conditional in nature. Phlex views often use loops and conditionals to build the right structure dynamically. Excluding these checks keeps RuboCop from flagging views for the normal complexity of HTML generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Metrics/MethodLength&lt;/code&gt;&lt;/strong&gt;: Phlex components can sometimes require long methods to structure complex views. Breaking them down into smaller methods doesn’t always improve readability, so I excluded this check to avoid being overly granular.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Metrics/ParameterLists&lt;/code&gt;&lt;/strong&gt;: When passing data into Phlex views, sometimes a larger list of parameters is necessary. Excluding this check avoids warnings when building view components that require more complex input.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Style/IfUnlessModifier (It needs a separate section 😁)
&lt;/h2&gt;

&lt;p&gt;In Phlex views and components, I often need to conditionally apply classes based on state or variables. The traditional &lt;code&gt;if/else&lt;/code&gt; block syntax, while clear in Ruby logic, can become cumbersome when embedding conditional logic into class attributes for HTML elements. Disabling the &lt;code&gt;Style/IfUnlessModifier&lt;/code&gt; cop allows me to write more concise conditionals directly in-line, which enhances readability and keeps the code compact.&lt;/p&gt;

&lt;p&gt;For example, with this cop disabled, I can write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'bottom-0 top-auto translate-y-0 end-1/2 start-1/2 -translate-x-1/2 rtl:translate-x-1/2 gap-2 p-4 fixed'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@floating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of the more verbose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@floating&lt;/span&gt;
  &lt;span class="s1"&gt;'bottom-0 top-auto translate-y-0 end-1/2 start-1/2 -translate-x-1/2 rtl:translate-x-1/2 gap-2 p-4 fixed'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This flexibility is especially important in Phlex views and components, where the recommended syntax for passing classes to HTML tags looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"button"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"disabled"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_disabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"Click me"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the inline conditional syntax keeps the class attribute clean and readable, even if the line becomes long. This is particularly useful when working with TailwindCSS, where class names can quickly stack up. Disabling &lt;code&gt;Style/IfUnlessModifier&lt;/code&gt; gives me the flexibility to manage these complex view structures without sacrificing code clarity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom RuboCop Settings Instead of Disabling Cops
&lt;/h2&gt;

&lt;p&gt;While disabling specific RuboCop cops was a practical solution for easing development with Phlex views, another approach worth exploring is customizing the default values for these cops. Adjusting the configuration to align with the particular needs of Phlex views and components (Maybe different defaults!) could provide a balanced solution that maintains code quality while accommodating the unique aspects of Phlex.&lt;/p&gt;

&lt;p&gt;For instance, instead of completely excluding checks like &lt;code&gt;Layout/LineLength&lt;/code&gt;, &lt;code&gt;Metrics/ClassLength&lt;/code&gt;, or &lt;code&gt;Metrics/MethodLength&lt;/code&gt;, you could modify their thresholds to better suit the complexity of view code. This way, you ensure that the RuboCop rules still offer guidance without being overly restrictive.&lt;/p&gt;

&lt;p&gt;Unfortunately, I didn’t have the time to thoroughly investigate the appropriate values for each cop to strike this balance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By tailoring RuboCop’s configuration to exclude certain checks in my &lt;code&gt;app/views/&lt;/code&gt; directory, I’ve created a smoother development experience that allows me to write Phlex views more naturally. This setup enables me to take full advantage of Phlex’s Ruby-based approach to view generation without getting bogged down by irrelevant code style warnings.&lt;/p&gt;

&lt;p&gt;The key takeaway is that enforcing consistent code style across your entire application is important, but flexibility in your linting tools can also be valuable — especially when dealing with areas like view generation, where different rules may apply.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>phlex</category>
      <category>rubocop</category>
    </item>
    <item>
      <title>Icons gem for Phlex</title>
      <dc:creator>Ali Hamdi Ali Fadel</dc:creator>
      <pubDate>Fri, 20 Sep 2024 15:54:18 +0000</pubDate>
      <link>https://dev.to/aliosm/icons-gem-for-phlex-3bok</link>
      <guid>https://dev.to/aliosm/icons-gem-for-phlex-3bok</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When it comes to building sleek, interactive UIs, having access to a robust set of icons is essential. Over the last few weeks, I've been migrating one of my projects from ERBs to &lt;a href="https://www.phlex.fun" rel="noopener noreferrer"&gt;&lt;strong&gt;Phlex&lt;/strong&gt;&lt;/a&gt;. During this process, I found myself frequently reaching for SVG icons from popular libraries like &lt;a href="https://heroicons.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Heroicons&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://icons.getbootstrap.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Bootstrap icons&lt;/strong&gt;&lt;/a&gt;, and &lt;a href="https://flagicons.lipis.dev" rel="noopener noreferrer"&gt;&lt;strong&gt;Flag icons&lt;/strong&gt;&lt;/a&gt;. After some frustration with manual integration into a Shared::Icon Phlex component, I had an idea - why not create a gem to simplify this process?&lt;/p&gt;

&lt;p&gt;Thus, &lt;a href="https://github.com/AliOsm/phlex-icons" rel="noopener noreferrer"&gt;&lt;strong&gt;Phlex::Icons&lt;/strong&gt;&lt;/a&gt; was born. This gem provides Phlex components for a variety of popular icon packs, all in one place. By leveraging the &lt;a href="https://github.com/marcoroth/phlexing" rel="noopener noreferrer"&gt;&lt;strong&gt;phlexing gem&lt;/strong&gt;&lt;/a&gt;, Phlex::Icons automates the generation of over 12,000 icon components across seven different sources. Whether you're looking for a Bootstrap house icon, a Flag for a country, or a Heroicon for pagination, Phlex::Icons makes it easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built Phlex::Icons
&lt;/h2&gt;

&lt;p&gt;Initially, I stumbled upon &lt;a href="https://github.com/nejdetkadir/phlex-heroicons" rel="noopener noreferrer"&gt;&lt;strong&gt;phlex-heroicons&lt;/strong&gt;&lt;/a&gt;, which provided Phlex components for Heroicons. This was a great start, but I needed icons from other sources as well. After searching for a solution and coming up short, I decided to build a more generic solution. Phlex::Icons now supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://icons.getbootstrap.com" rel="noopener noreferrer"&gt;Bootstrap Icons&lt;/a&gt; (2,000+)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://flagicons.lipis.dev" rel="noopener noreferrer"&gt;Flag Icons&lt;/a&gt; (250+)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://heroicons.com" rel="noopener noreferrer"&gt;Heroicons&lt;/a&gt; (300+)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://lucide.dev/icons" rel="noopener noreferrer"&gt;Lucide Icons&lt;/a&gt; (1,500+)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://radix-ui.com/icons" rel="noopener noreferrer"&gt;RadixUI Icons&lt;/a&gt; (300+)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://remixicon.com" rel="noopener noreferrer"&gt;Remix Icons&lt;/a&gt; (2,800+)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tabler.io/icons" rel="noopener noreferrer"&gt;Tabler Icons&lt;/a&gt; (4,800+)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Phlex::Icons, you can seamlessly integrate these icons into your Phlex projects, dramatically cutting down the time spent on setting up and managing SVG icons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features of Phlex::Icons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Centralized Icon Access:&lt;/strong&gt; Phlex::Icons brings together multiple icon packs, offering developers more than 12,000 icons, eliminating the need for individual icon pack integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Updates:&lt;/strong&gt; A GitHub Actions workflow ensures icon packs are updated weekly. This means any new icons introduced by the source libraries are automatically included in your project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible Integration:&lt;/strong&gt; Don’t want to load all 12,000 icons into your app? You can use specific gems for individual icon packs like phlex-icons-bootstrap, phlex-icons-flag, phlex-icons-hero, phlex-icons-lucide, phlex-icons-radix, phlex-icons-remix, or phlex-icons-tabler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Loading:&lt;/strong&gt; The gem supports lazy-loading icons, ensuring minimal impact on your app’s memory consumption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phlex::Kit Integration:&lt;/strong&gt; By leveraging Phlex::Kit, you can directly integrate icon packs into your UI components with minimal configuration, ensuring seamless rendering and a more streamlined workflow for Phlex projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation and Configuration
&lt;/h2&gt;

&lt;p&gt;Getting started with Phlex::Icons is easy. To add it to your Rails project, simply execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle add phlex-icons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want more granular control and prefer adding individual icon packs, you can install specific packs like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle add phlex-icons-bootstrap
bundle add phlex-icons-hero
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also configure global options for all icon packs, such as default CSS classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'size-4'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each icon pack can be further configured individually. For example, you can configure Flag icons to default to a rectangular variant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_variant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:rectangle&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Phlex::Icons in Your Application
&lt;/h2&gt;

&lt;p&gt;Integrating Phlex::Icons into your project is straightforward. Here’s an example of how to use multiple icons in a view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PhlexIcons&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTML&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;view_template&lt;/span&gt;
    &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;Bootstrap&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;House&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Flag&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Sa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;variant: :rectangle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Hero&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;variant: :solid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Lucide&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;House&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Radix&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Remix&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HomeLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Tabler&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;variant: :filled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, if you don’t want to use Phlex::Kit, you can render the icons like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Bootstrap&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;House&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Flag&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Sa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;variant: :rectangle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Hero&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;variant: :solid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Lucide&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;House&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Radix&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Remix&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HomeLine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Tabler&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;variant: :filled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom Icons
&lt;/h2&gt;

&lt;p&gt;Phlex::Icons is designed with flexibility in mind, allowing you to add your custom icons as well. Simply create a &lt;code&gt;phlex/icons/custom&lt;/code&gt; directory inside &lt;code&gt;views/components&lt;/code&gt; and define your own icons within:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Phlex&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Icons&lt;/span&gt;
    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Custom&lt;/span&gt;
      &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyIcon&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;view_template&lt;/span&gt;
          &lt;span class="c1"&gt;# SVG code here&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can use this custom icon like any other icon provided by Phlex::Icons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="no"&gt;Phlex&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Custom&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MyIcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;classes: &lt;/span&gt;&lt;span class="s1"&gt;'size-4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, global configurations will be applied to the newly added icon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Development and Contributions
&lt;/h2&gt;

&lt;p&gt;Phlex::Icons is constantly evolving, and I’m always open to adding more icon packs and improving the gem’s functionality. If you have feedback or feature requests, feel free to open an issue or contribute to the project via GitHub. A big thanks to &lt;a href="https://github.com/nejdetkadir" rel="noopener noreferrer"&gt;nejdetkadir&lt;/a&gt; for laying the groundwork with phlex-heroicons, which served as the foundation for this gem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Phlex::Icons streamlines the process of integrating a wide range of icons into your Phlex projects. With over 12,000 icons and growing, this gem saves you the time and hassle of manually incorporating SVGs, while ensuring that your project stays up to date with the latest icon packs.&lt;/p&gt;

&lt;p&gt;Give it a try, and let me know what you think! Contributions are always welcome on &lt;a href="https://github.com/AliOsm/phlex-icons" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post was inspired by my journey of migrating to Phlex and developing a better way to handle icons. If you’re working with Phlex, PhlexUI, or simply want to make your icon integration more efficient, Phlex::Icons might just be the solution you’ve been looking for.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>phlex</category>
      <category>svg</category>
    </item>
  </channel>
</rss>
