# frozen_string_literal: true module Ariadne # Use `Counter` to add a count to navigational elements and buttons. # # @accessibility # Always use `Counter` with adjacent text that provides supplementary information regarding what the count is for. For instance, `Counter` # should be accompanied with text such as `issues` or `pull requests`. # class CounterComponent < Ariadne::Component DEFAULT_CLASSES = "inline-flex items-center p-1 border border-transparent rounded-full shadow-sm text-white bg-gray-600 hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500" # # @example Default # <%= render(Ariadne::CounterComponent.new(count: 25)) %> # # @example Schemes # <%= render(Ariadne::CounterComponent.new(count: 25)) %> # <%= render(Ariadne::CounterComponent.new(count: 25)) %> # # @param tag [Symbol, String] The rendered tag name # @param classes [String] <%= link_to_classes_docs %> # @param count [Integer, Float::INFINITY, nil] The number to be displayed (e.x. # of issues, pull requests) # @param limit [Integer, nil] Maximum value to display. Pass `nil` for no limit. (e.x. if `count` == 6,000 and `limit` == 5000, counter will display "5,000+") # @param hide_if_zero [Boolean] If true, a `hidden` attribute is added to the counter if `count` is zero. # @param text [String] Text to display instead of count. # @param round [Boolean] Whether to apply rounding logic to value. # @param attributes [Hash] <%= link_to_attributes_docs %> def initialize( tag: :span, count: 0, limit: 9_000, hide_if_zero: false, text: "", round: false, classes: "", attributes: {} ) @count = count @limit = limit @hide_if_zero = hide_if_zero @text = text @round = round @attributes = attributes @has_limit = !@limit.nil? @tag = check_incoming_tag(:span, tag) @attributes[:title] = title @classes = class_names( DEFAULT_CLASSES, classes ) @attributes[:hidden] = true if count == 0 && hide_if_zero end def call render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) { value } end private def title if @text.present? @text elsif @count.nil? "Not available" elsif @count == Float::INFINITY "Infinity" else count = @count.to_i str = number_with_delimiter(@has_limit ? [count, @limit].min : count) str += "+" if @has_limit && count > @limit str end end private def value if @text.present? @text elsif @count.nil? "" # CSS will hide it elsif @count == Float::INFINITY "∞" else if @round count = @has_limit ? [@count.to_i, @limit].min : @count.to_i precision = count.between?(100_000, 999_999) ? 0 : 1 units = { thousand: "k", million: "m", billion: "b" } str = number_to_human(count, precision: precision, significant: false, units: units, format: "%n%u") else @count = @count.to_i str = number_with_delimiter(@has_limit ? [@count, @limit].min : @count) end str += "+" if @has_limit && @count.to_i > @limit str end end end end