app/components/heading_component.rb
# typed: strict
# frozen_string_literal: true
class HeadingComponent < ViewComponent::Base
extend T::Sig
DEFAULT_SIZES = T.let({ h1: "3xl", h2: "2xl", h3: "xl", h4: "xl" }.freeze, T::Hash[Symbol, String])
DEFAULT_FONTS = T.let({ h1: "display", h2: "display", h3: "sans", h4: "sans" }.freeze, T::Hash[Symbol, String])
# Doing this very long winded way to ensure that tailwind doesn't remove styles being used here
VALID_SIZE_CLASSES = T.let(%w[text-xl text-2xl text-3xl text-4xl].freeze, T::Array[String])
VALID_WEIGHT_CLASSES = T.let(%w[font-semibold font-bold].freeze, T::Array[String])
VALID_COLOR_CLASSES = T.let(%w[text-navy text-white].freeze, T::Array[String])
VALID_FONT_CLASSES = T.let(%w[font-display font-sans].freeze, T::Array[String])
# TODO: Perhaps we should allow the size override to work by saying we want an h1 heading but with the styling of an h2?
sig { params(tag: Symbol, size: T.nilable(String), color: T.nilable(String), font: T.nilable(String), weight: T.nilable(String), extra_classes: String).void }
def initialize(tag:, size: nil, color: nil, font: nil, weight: nil, extra_classes: "")
super
default_size = DEFAULT_SIZES[tag]
raise "Unexpected tag #{tag}" if default_size.nil?
default_font = DEFAULT_FONTS[tag]
raise "Unexpected tag #{tag}" if default_font.nil?
# Set the default styling
size ||= default_size
weight ||= "bold"
color ||= "navy"
font ||= default_font
raise "Unexpected size #{size}" unless VALID_SIZE_CLASSES.include?("text-#{size}")
raise "Unexpected weight #{weight}" unless VALID_WEIGHT_CLASSES.include?("font-#{weight}")
raise "Unexpected color #{color}" unless VALID_COLOR_CLASSES.include?("text-#{color}")
raise "Unexpected font #{font}" unless VALID_FONT_CLASSES.include?("font-#{font}")
c = ["text-#{size}", "font-#{weight}", "text-#{color}", "font-#{font}"]
# TODO: Not sure whether we should be setting max width on all headings
c << "max-w-4xl" if tag == :h1
# These extra classes can't override the default styling because they're at the end
c << extra_classes
@tag = tag
@class = T.let(c, T::Array[T.nilable(String)])
end
end