# frozen_string_literal: true module Primer # All Primer ViewComponents accept a standard set of options called system arguments, mimicking the [styled-system API](https://styled-system.com/table) used by [Primer React](https://primer.style/components/system-props). # # Under the hood, system arguments are [mapped](https://github.com/primer/view_components/blob/main/app/lib/primer/classify.rb) to Primer CSS classes, with any remaining options passed to Rails' [`content_tag`](https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag). # # ## Responsive values # # To apply different values across responsive breakpoints, pass an array with up to five values in the order `[default, small, medium, large, xlarge]`. To skip a breakpoint, pass `nil`. # # For example: # # ```erb # <%= render Primer::HeadingComponent.new(mt: [0, nil, nil, 4, 2]) do %> # Hello world # <% end %> # ``` # # Renders: # # ```html #

Hello world

# ``` # # ## HTML attributes # # System arguments include most HTML attributes. For example: # # | Name | Type | Description | # | :- | :- | :- | # | `width` | `Integer` | Width. | # | `height` | `Integer` | Height. | # | `data` | `Hash` | Data attributes: `data: { foo: :bar }` renders `data-foo='bar'`. | # | `aria` | `Hash` | Aria attributes: `aria: { label: "foo" }` renders `aria-label='foo'`. | # | `title` | `String` | The `title` attribute. | # | `style` | `String` | Inline styles. | # | `hidden` | `Boolean` | Whether to assign the `hidden` attribute. | class BaseComponent < Primer::Component TEST_SELECTOR_TAG = :test_selector # @param test_selector [String] Adds `data-test-selector='given value'` in non-Production environments for testing purposes. # # @param m [Integer] Margin. <%= one_of((-6..6).to_a) %> # @param mt [Integer] Margin top. <%= one_of((-6..6).to_a) %> # @param mr [Integer] Margin right. <%= one_of((-6..6).to_a) %> # @param mb [Integer] Margin bottom. <%= one_of((-6..6).to_a) %> # @param ml [Integer] Margin left. <%= one_of((-6..6).to_a) %> # @param mx [Integer] Horizontal margins. <%= one_of((-6..6).to_a + [:auto]) %> # @param my [Integer] Vertical margins. <%= one_of((-6..6).to_a) %> # @param p [Integer] Padding. <%= one_of((0..6).to_a) %> # @param pt [Integer] Padding left. <%= one_of((0..6).to_a) %> # @param pr [Integer] Padding right. <%= one_of((0..6).to_a) %> # @param pb [Integer] Padding bottom. <%= one_of((0..6).to_a) %> # @param pl [Integer] Padding left. <%= one_of((0..6).to_a) %> # @param px [Integer] Horizontal padding. <%= one_of((0..6).to_a) %> # @param py [Integer] Vertical padding. <%= one_of((0..6).to_a) %> # # @param position [Symbol] <%= one_of([:relative, :absolute, :fixed]) %> # # @param top [Boolean] If `false`, sets `top: 0`. # @param right [Boolean] If `false`, sets `right: 0`. # @param bottom [Boolean] If `false`, sets `bottom: 0`. # @param left [Boolean] If `false`, sets `left: 0`. # # @param display [Symbol] <%= one_of([:none, :block, :flex, :inline, :inline_block, :table, :table_cell]) %> # # @param v [Symbol] Visibility. <%= one_of([:hidden, :visible]) %> # # @param hide [Symbol] Hide the element at a specific breakpoint. <%= one_of([:sm, :md, :lg, :xl]) %> # # @param vertical_align [Symbol] <%= one_of([:baseline, :top, :middle, :bottom, :text_top, :text_bottom]) %> # # @param float [Symbol] <%= one_of([:left, :right]) %> # # @param col [Integer] Number of columns. # # @param underline [Boolean] Whether text should be underlined. # # @param color [Symbol] Text color. <%= one_of([:blue, :red, :gray_light, :gray, :gray_dark, :green, :orange, :orange_light, :purple, :pink, :white, :inherit, :text_primary, :text_secondary, :text_tertiary, :text_link, :text_success, :text_warning, :text_danger, :icon_primary, :icon_secondary, :icon_tertiary, :icon_info, :icon_success, :icon_warning, :icon_danger]) %> # @param bg [String, Symbol] Background color. Accepts either a hex value as a String or a color name as a Symbol. # # @param box_shadow [Boolean, Symbol] Box shadow. <%= one_of([true, :medium, :large, :extra_large, :none]) %> # @param border [Symbol] <%= one_of([:left, :top, :bottom, :right, :y, :x, true]) %> # @param border_color [Symbol] <%= one_of([:blue, :blue_light, :gray, :gray_dark, :green, :purple, :red, :red_light, :white, :yellow, :black_fade]) %> Note: this API is subject to change as we move to functional colors. # @param border_top [Integer] Set to `0` to remove the top border. # @param border_bottom [Integer] Set to `0` to remove the bottom border. # @param border_left [Integer] Set to `0` to remove the left border. # @param border_right [Integer] Set to `0` to remove the right border. # @param border_radius [Integer] <%= one_of([0, 1, 2, 3]) %> # # @param font_size [String, Integer] <%= one_of(["00", 0, 1, 2, 3, 4, 5, 6]) %> # @param text_align [Symbol] Text alignment. <%= one_of([:left, :right, :center]) %> # @param font_weight [Symbol] Font weight. <%= one_of([:light, :normal, :bold]) %> # # @param flex [Integer, Symbol] <%= one_of([1, :auto]) %> # @param flex_grow [Integer] To enable, set to `0`. # @param flex_shrink [Integer] To enable, set to `0`. # @param align_self [Symbol] <%= one_of([:auto, :start, :end, :center, :baseline, :stretch]) %> # @param justify_content [Symbol] <%= one_of([:flex_start, :flex_end, :center, :space_between, :space_around]) %> # @param align_items [Symbol] <%= one_of([:flex_start, :flex_end, :center, :baseline, :stretch]) %> # @param width [Symbol] <%= one_of([:fit, :fill]) %> # @param height [Symbol] <%= one_of([:fit, :fill]) %> # # @param word_break [Symbol] Whether to break words on line breaks. Can only be `:break_all`. # # @param animation [Symbol] <%= one_of([:fade_in, :fade_out, :fade_up, :fade_down, :scale_in, :pulse, :grow_x, :grow]) %> # # @param tag [Symbol] HTML tag name to be passed to `tag.send`. # @param classes [String] CSS class name value to be concatenated with generated Primer CSS classes. def initialize(tag:, classes: nil, **system_arguments) @tag = tag @result = Primer::Classify.call(**system_arguments.merge(classes: classes)) # Filter out Primer keys so they don't get assigned as HTML attributes @content_tag_args = add_test_selector(system_arguments).except(*Primer::Classify::VALID_KEYS) end def call content_tag(@tag, content, @content_tag_args.merge(@result)) end def self.status Primer::Component::STATUSES[:beta] end private def add_test_selector(args) if args.key?(TEST_SELECTOR_TAG) && !Rails.env.production? args[:data] ||= {} args[:data][TEST_SELECTOR_TAG] = args[TEST_SELECTOR_TAG] end args.except(TEST_SELECTOR_TAG) end end end