DEV Community

Cover image for Create a String to Color Helper with Ruby (and Rails)
Rails Designer
Rails Designer

Posted on • Updated on • Originally published at railsdesigner.com

Create a String to Color Helper with Ruby (and Rails)

This article was originally published on Rails Designer.


In the latest version (v1) of Rails Designer I added a Chat Messages Component.

For one of the provided variants I wanted to have a different background- and text-color based on the user's name. I like this kind of “random” customizations to UI components, as it gives an otherwise monotone UI layout some sparkle. In the context of chat messages it works well too differentiate between the different messages from users.

I used a similar technique for the AvatarComponent. Here, when no profile picture is available (attached), it calculates the color for the user name's initial.

I typically calculate these colors at runtime, but I can imagine, when your app grows, to store them alongside the user in some sort of preferences model.

Rails Designer is a professionally designed UI components library for Rails. Built with ViewComponent. Designed with Tailwind CSS. Enhanced with Hotwire. Build beautiful, faster.

For the example of the chat messages I wanted to pick one of Tailwind CSS' colors. This is because the the background- and text color is set as follows:

# …

def initialize(name:)
  @name = name
  @color = string_to_color(name)
end

def chat_css = class_names("px-3 py-1 rounded", states[@color])

def states
  {
    red: "bg-red-100 text-red-800",
    blue: "bg-blue-100 text-blue-800"
    # …
  }
end
Enter fullscreen mode Exit fullscreen mode

(example simplified for demonstration purposes)

So how does the string_to_color helper look like? It's pretty straight-forward. Let's see:

# app/helpers/string_to_color.rb
module StringToColorHelper
  def string_to_color(string, colors: TAILWIND_COLORS)
    hash_value = string.downcase.each_char.sum(&:ord)
    index = hash_value % colors.length

    colors[index]
  end

  private

  TAILWIND_COLORS = %w[
    slate gray zinc neutral stone
    red orange amber yellow lime green emerald teal cyan sky blue indigo violet purple fuchsia pink rose
  ].freeze
end
Enter fullscreen mode Exit fullscreen mode

It calculates a hash value (hash_value) from the given string by converting each character to its ASCII value. So given a string of Example will output:

"Example".downcase.each_char # ['e', 'x', 'a', 'm', 'p', 'l', 'e']
Enter fullscreen mode Exit fullscreen mode

Then, based on the ASCII characters, the sum is returned.

"Example".downcase.each_char.sum(&:ord)
# `&:ord` → [101, 120, 97, 109, 112, 108, 101]
# `sum()` → 748
Enter fullscreen mode Exit fullscreen mode

This sum is then used to select an index from the colors array. Using the modulus of the hash_value (hash_value % colors.length) with the length of the colors array ensures the index is always within the bounds of the array.

By default this uses the TAILWIND_COLORS constant, thus always returning slate, gray, red, etc. But you can also pass another array with hexadecimal colors (directly) to the method. Like this: string_to_color("Example", colors: ["#3498DB", "#2ECC71", "#F1C40F"]).

V1 of Rails Designer comes with this new helper out of the box. Check out the docs for more details.

Top comments (1)

Collapse
 
railsdesigner profile image
Rails Designer

While this method is focused on colors, there's no reason you could pass something else than a colors-array. How could you see the same technique used with a different "source" than colors?