Skip to content

Rails-Designer/partials_fx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Partials Fx

Partials FX extends Rails' partials to make them quack more like components. Each partial, located in app/views/components/, is backed by a Ruby class with the same name. It also supports CSS modules, meaning you define CSS in the component class and it gets “scoped” to that component only. It is powering the self-hosted Community Software, Forge.

Installation

bundle add partials_fx

Usage

bin/rails generate component Avatar

This creates two files:

  • app/views/components/_avatar_component.html.erb;
  • app/views/components/avatar_component.rb.

They could look like this:

<span id="user-avatar" class="<%= component_class %> <%= avatar_size %>">
  <% if avatar.attached? %>
    <%= image_tag avatar.variant(avatar_variant), alt: alt_text %>
  <% else %>
    <%= tag.span name.first.upcase, class: "initial" %>
  <% end %>
</span>
# app/views/components/avatar_component.rb
class AvatarComponent < PartialsFx::Component
  attribute :user, required: true
  attribute :size, :string, default: "md", inquiry: true
  attribute :variant, :string, default: "thumb", inquiry: true

  def avatar_size
    return "avatar-profile" if variant.profile?

    class_names(
      "avatar-xs": size.xs?,
      "avatar-sm": size.sm?,
      "avatar-md": size.md?,
      "avatar-lg": size.lg?,
      "avatar-xl": size.xl?
    )
  end

  def name
    @name ||= user.decorate.name
  end

  def avatar = profile.avatar

  def alt_text = "Avatar for #{name}"

  def avatar_variant
    variant.thumb? ? :thumb : :profile
  end

  private

  def profile
    @profile ||= user.profile
  end
end

In views:

<%= render AvatarComponent.new user: Current.user %>

CSS modules

A powerful feature of Partials FX is support for “CSS modules”. Meaning that styles are locally scoped by default, preventing style conflicts across components. This allows the use of the same class names in different components without worrying about collisions, as Partials FX automatically generates unique class names, for the parent element, during compilation. CSS modules improve maintainability by creating a clear connection between components and their styles, making it easier to manage complex UI systems.

It works like this. First define a styles block in the class:

class AvatarComponent < PartialsFx::Component
  # …

  styles do
    <<~CSS
      .component {
      }
    CSS
  end

  # …
end

Then add the component_class method to the the component partial:

<span id="user-avatar" class="<%= component_class %> <%= avatar_size %>">
</span>

You can now add any CSS selector in the .component selector, which itself will compile to something like:

/* app/assets/stylesheets/components.partialsfx.css */
.c-9af2b949 {
  --avatar-font-size-fallback:
    clamp(.75rem, calc(var(--avatar-height) * .8), 2rem);
  display: inline flex;
  align-items: center;
  justify-content: center;
  height: var(--avatar-height, 1rem);
  /* … */

  .initial {
    font-size: var(--avatar-font-size, var(--avatar-font-size-fallback));
    font-weight: 600;
    color: var(--avatar-color, var(--base-60));
  }

  &.avatar-profile {}

  /* … */
}

Inside the component partial, component_class will be replaced with the unique selector .c-9af2b949. Because nested selectors are available in CSS this will work smoothly. Keeping your selectors scoped to the one component. Making your app's CSS way more maintainable.

Make sure to import the automatically-created CSS file from Partials FX into your application.css, e.g.

@layer reset, components, utilities;

/* … */
@import url("./components.partialsfx.css") layer(components);
/* … */

Contributing

This project uses Standard for formatting Ruby code. Please make sure to run be standardrb before submitting pull requests. Run tests via rails test.

License

The gem is available as open source under the terms of the MIT License.

About

Extend Rails' partials to make them quack more like components

Resources

License

Stars

Watchers

Forks