Class: Gitlab::Color

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/color.rb

Defined Under Namespace

Modules: Constants

Constant Summary collapse

PATTERN =
/\A\#(?:[0-9A-Fa-f]{3}){1,2}\Z/

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value) ⇒ Color

Returns a new instance of Color.



7
8
9
# File 'lib/gitlab/color.rb', line 7

def initialize(value)
  @value = value&.strip&.freeze
end

Class Method Details

.color_for(value) ⇒ Object

Generate a hex color based on hex-encoded value



174
175
176
# File 'lib/gitlab/color.rb', line 174

def self.color_for(value)
  Color.new("##{Digest::SHA256.hexdigest(value.to_s)[0..5]}")
end

.of(color) ⇒ Object

Raises:

  • (ArgumentError)


165
166
167
168
169
170
171
# File 'lib/gitlab/color.rb', line 165

def self.of(color)
  raise ArgumentError, 'No color spec' unless color
  return color if color.is_a?(self)

  color = color.to_s.strip
  Constants::COLOR_NAME_TO_HEX[color.downcase] || new(color)
end

Instance Method Details

#as_json(_options = nil) ⇒ Object



182
183
184
# File 'lib/gitlab/color.rb', line 182

def as_json(_options = nil)
  to_s
end

#contrastObject



242
243
244
245
246
# File 'lib/gitlab/color.rb', line 242

def contrast
  return Constants::DARK if light?

  Constants::LIGHT
end

#eql(other) ⇒ Object Also known as: ==



186
187
188
189
190
# File 'lib/gitlab/color.rb', line 186

def eql(other)
  return false unless other.is_a?(self.class)

  to_s == other.to_s
end

#light?Boolean

Returns:

  • (Boolean)


217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/gitlab/color.rb', line 217

def light?
  return false unless valid?

  luminance = relative_luminance(rgb)
  light_luminance = relative_luminance([255, 255, 255])
  dark_luminance = relative_luminance([31, 30, 36])

  contrast_light = (light_luminance + 0.05) / (luminance + 0.05)
  contrast_dark = (luminance + 0.05) / (dark_luminance + 0.05)

  # Using a threshold contrast of 2.4 instead of 3
  # as this will solve weird color combinations in the mid tones
  #
  # Note that this is the negated condition from GitLab UI,
  # because the GitLab UI implementation returns the text color,
  # while this defines whether a background color is light
  !(contrast_light >= 2.4 || contrast_light > contrast_dark)
end

#luminosityObject



236
237
238
239
240
# File 'lib/gitlab/color.rb', line 236

def luminosity
  return :light if light?

  :dark
end

#relative_luminance(rgb) ⇒ Object



206
207
208
209
210
211
212
213
# File 'lib/gitlab/color.rb', line 206

def relative_luminance(rgb)
  # WCAG 2.1 formula: https://www.w3.org/TR/WCAG21/#dfn-relative-luminance
  # -
  # WCAG 3.0 will use APAC
  # Using APAC would be the ultimate goal, but was dismissed by engineering as of now
  # See https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/3418#note_1370107090
  (0.2126 * to_srgb(rgb[0])) + (0.7152 * to_srgb(rgb[1])) + (0.0722 * to_srgb(rgb[2]))
end

#to_sObject



178
179
180
# File 'lib/gitlab/color.rb', line 178

def to_s
  @value.to_s
end

#to_srgb(value) ⇒ Object



199
200
201
202
# File 'lib/gitlab/color.rb', line 199

def to_srgb(value)
  normalized = value / 255.0
  normalized <= 0.03928 ? normalized / 12.92 : ((normalized + 0.055) / 1.055)**2.4
end

#valid?Boolean

Returns:

  • (Boolean)


193
194
195
# File 'lib/gitlab/color.rb', line 193

def valid?
  PATTERN.match?(@value)
end