simonrand / view_component_properties

Manage properties on ViewComponents (currently a proof of concept)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ViewComponentProperties

Manage, constrain and use CSS class properties on ViewComponent components.

Note: At this point in time this should be considered a proof of concept.

ViewComponentProperties allows you to:

  • apply tightly constrained CSS classes ("properties") to ViewComponents using properties defined once, but available to be applied anywhere
  • quickly create simple ViewComponents using a provided base utility component

Goals

The goal of ViewComponentProperties is to facilitate implementing a design system by providing well defined and clear constraints on the CSS that can be used to build HTML views with ViewComponents. When combined with a comprehensive CSS framework (such as Tailwind CSS), once your components and properties have been defined, it should be possible to implement the design intent of a design system in a view while writing less HTML and/or CSS. (..maybe even none at all)

While not a requirement, the current version is somewhat built assuming usage of Tailwind CSS for styling.

Compatibility

ViewComponentProperties depends on ViewComponent and therefore is intended to work with Ruby on Rails, v5.0+

Installation

The gem has not yet been published but you can install in your app using by adding this to your Gemfile:

gem 'view_component_properties', git: 'https://github.com/simonrand/view_component_properties.git'

Example usage

Ensure you have ViewComponent working in your Rails app.

First, define an ApplicationComponent which inherits from ViewComponentProperties::BaseComponent.

app/components/application_component.rb:

class ApplicationComponent < ViewComponentProperties::BaseComponent
end

Using the provided ViewComponentProperties "utility" template

app/components/example_component.rb:

class ExampleComponent < ApplicationComponent
  private

  def tag_name # optional, :div is the default
    :p
  end
end

ViewComponentProperties::BaseComponent implements an inline template which simply returns our content wrapped in the defined tag_name, so using our ExampleComponent above:

<%= render(ExampleComponent.new) do %>
  Hello, World!
<% end %>

Returns:

<p>Hello, World!</p>

Adding a margin bottom property to a component

Define our property and the allowed values in app/components/properties/margin/bottom.rb:

module Properties
  module Margin
    module Bottom
      include ViewComponentProperties::Properties::Base

      # NOTE: mb-* are Tailwind CSS margin bottom utility classes, see
      #       https://tailwindcss.com/docs/margin/#add-margin-to-a-single-side
      CLASSES = {
        2 => 'mb-2',
        4 => 'mb-4'
      }
    end
  end
end

The path and module name defines the parameter name which will set the property on a component, so in the case of our margin bottom property, the parameter name will be margin_bottom.

Add our property to our ExampleComponent by adding the parameter name the properties class method.

app/components/example_component.rb:

class ExampleComponent < ApplicationComponent
  # NOTE: You can include multiple properties here, for example `properties :margin_bottom, :margin_top`
  properties :margin_bottom
end

Now we can apply our property to the component:

<%= render(ExampleComponent.new(margin_bottom: 2)) do %>
  Hello, World!
<% end %>

Returning:

<div class="mb-2">Hello, World!</div>

Responsive properties

Responsive properties (again following Tailwind CSS conventions) are supported by passing a hash value for the property value. For example:

app/components/example_component.rb:

class ExampleComponent < ApplicationComponent
  properties :margin_bottom # as per the "Adding a margin bottom property to a component" example above
end
<%= render(ExampleComponent.new(margin_bottom: { default: 2, lg: 4 })) do %>
  Hello, World!
<% end %>

Returns:

<div class="mb-2 lg:mb-4">Hello, World!</div>

Invalid property values

By default passing invalid property values to will result in no class being returned:

app/components/example_component.rb:

class ExampleComponent < ApplicationComponent
  properties :margin_bottom # as per the "Adding a margin bottom property to a component" example above
end

Now we can apply our property to the component:

<%= render(ExampleComponent.new(margin_bottom: 1)) do %>
  Hello, World!
<% end %>

Returning:

<div>Hello, World!</div>

However, for non-production environments it would be recommended that you raise an error on invalid property values, you can do this by setting the raise_error_for_invalid_property_values configuration option to true:

ViewComponentProperties.config.raise_error_for_invalid_property_values = true

No when we provide an invalid property value:

<%= render(ExampleComponent.new(margin_bottom: 1)) do %>
  Hello, World!
<% end %>

This will raise with:

ViewComponentProperties::PropertyError

It is not recommended to raise exceptions in production environments.

TODO

  • Continue exploring this proof of concept

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/simonrand/view_component_properties. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

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

About

Manage properties on ViewComponents (currently a proof of concept)

License:MIT License


Languages

Language:Ruby 99.3%Language:Shell 0.7%