Create a String to Color Helper with Ruby

3D rendering of a frog looking at a colorful rainbow

In the latest (v1) version 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.

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

(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

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']

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

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.

Get UI & Product Engineering Insights for Rails Apps (and product updates!)

Published at . Have suggestions or improvements on this content? Do reach out.

UI components for Ruby on Rails apps

$ 129 one-time
payment

Get Access
  • One-time Payment

  • Access to the Entire Library

  • Built using ViewComponent

  • Designed with Tailwind CSS

  • Enhanced with Hotwire