Class: Primer::Alpha::ActionList

Inherits:
Component
  • Object
show all
Defined in:
app/components/primer/alpha/action_list.rb,
app/components/primer/alpha/action_list/item.rb,
app/components/primer/alpha/action_list/divider.rb,
app/components/primer/alpha/action_list/heading.rb,
app/components/primer/alpha/action_list/form_wrapper.rb

Overview

An ActionList is a styled list of links. It acts as the base component for many other menu-type components, including ‘ActionMenu` and `SelectPanel`, as well as the navigational component `NavList`.

Each item in an action list can be augmented by specifying corresponding leading and/or trailing visuals.

Defined Under Namespace

Classes: Divider, FormWrapper, Heading, Item

Constant Summary collapse

DEFAULT_ROLE =
:list
:menu
DEFAULT_MENU_ITEM_ROLE =
:menuitem
DEFAULT_SCHEME =
:full
SCHEME_MAPPINGS =
{
  DEFAULT_SCHEME => nil,
  :inset => "ActionListWrap--inset"
}.freeze
SCHEME_OPTIONS =
SCHEME_MAPPINGS.keys.freeze
DEFAULT_SELECT_VARIANT =
:none
SELECT_VARIANT_OPTIONS =
[
  :single,
  :multiple,
  :multiple_checkbox,
  DEFAULT_SELECT_VARIANT
].freeze
SELECT_VARIANT_ROLE_MAP =
{
  single: :menuitemradio,
  multiple: :menuitemcheckbox,
  multiple_checkbox: :menuitemcheckbox
}.freeze

Constants inherited from Component

Component::INVALID_ARIA_LABEL_TAGS

Constants included from Status::Dsl

Status::Dsl::STATUSES

Constants included from ViewHelper

ViewHelper::HELPERS

Constants included from TestSelectorHelper

TestSelectorHelper::TEST_SELECTOR_TAG

Constants included from FetchOrFallbackHelper

FetchOrFallbackHelper::InvalidValueError

Constants included from Primer::AttributesHelper

Primer::AttributesHelper::PLURAL_ARIA_ATTRIBUTES, Primer::AttributesHelper::PLURAL_DATA_ATTRIBUTES

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Component

deprecated?, generate_id

Methods included from JoinStyleArgumentsHelper

#join_style_arguments

Methods included from TestSelectorHelper

#add_test_selector

Methods included from FetchOrFallbackHelper

#fetch_or_fallback, #fetch_or_fallback_boolean, #silence_deprecations?

Methods included from ClassNameHelper

#class_names

Methods included from Primer::AttributesHelper

#aria, #data, #merge_aria, #merge_data, #merge_prefixed_attribute_hashes

Constructor Details

#initialize(id: self.class.generate_id, role: nil, item_classes: nil, scheme: DEFAULT_SCHEME, show_dividers: false, select_variant: DEFAULT_SELECT_VARIANT, form_arguments: {}, **system_arguments) ⇒ ActionList

Returns a new instance of ActionList.

Parameters:

  • id (String) (defaults to: self.class.generate_id)

    HTML ID value.

  • role (Boolean) (defaults to: nil)

    ARIA role describing the function of the list. listbox and menu are a common values.

  • item_classes (String) (defaults to: nil)

    Additional CSS classes to attach to items.

  • scheme (Symbol) (defaults to: DEFAULT_SCHEME)

    <%= one_of(Primer::Alpha::ActionList::SCHEME_OPTIONS) %> ‘inset` children are offset (vertically and horizontally) from list edges. `full` (default) children are flush (vertically and horizontally) with list edges.

  • show_dividers (Boolean) (defaults to: false)

    Display a divider above each item in the list when it does not follow a header or divider.

  • select_variant (Symbol) (defaults to: DEFAULT_SELECT_VARIANT)

    How items may be selected in the list. <%= one_of(Primer::Alpha::ActionList::SELECT_VARIANT_OPTIONS) %>

  • form_arguments (Hash) (defaults to: {})

    Allows an ‘ActionList` to act as a select list in multi- and single-select modes. Pass the `builder:` and `name:` options to this hash. `builder:` should be an instance of `ActionView::Helpers::FormBuilder`, which are created by the standard Rails `#form_with` and `#form_for` helpers. The `name:` option is the desired name of the field that will be included in the params sent to the server on form submission. NOTE: Consider using an <%= link_to_component(Primer::Alpha::ActionMenu) %> instead of using this feature directly.

  • system_arguments (Hash)

    <%= link_to_system_arguments_docs %>

Raises:

  • (ArgumentError)


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'app/components/primer/alpha/action_list.rb', line 127

def initialize(
  id: self.class.generate_id,
  role: nil,
  item_classes: nil,
  scheme: DEFAULT_SCHEME,
  show_dividers: false,
  select_variant: DEFAULT_SELECT_VARIANT,
  form_arguments: {},
  **system_arguments
)
  @system_arguments = system_arguments
  @id = id
  @system_arguments[:id] = @id
  @system_arguments[:tag] = :ul
  @item_classes = item_classes
  @scheme = fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)
  @show_dividers = show_dividers
  @select_variant = select_variant
  @system_arguments[:classes] = class_names(
    SCHEME_MAPPINGS[@scheme],
    system_arguments[:classes],
    "ActionListWrap",
    "ActionListWrap--divided" => @show_dividers
  )

  @role = role || (allows_selection? ? MENU_ROLE : DEFAULT_ROLE)
  @system_arguments[:role] = @role

  @list_wrapper_arguments = {}

  @form_builder = form_arguments[:builder]
  @input_name = form_arguments[:name]

  return unless required_form_arguments_given? && !allows_selection?

  raise ArgumentError, "lists/menus that act as form inputs must also allow item selection (please pass the `select_variant:` option)"
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



117
118
119
# File 'app/components/primer/alpha/action_list.rb', line 117

def id
  @id
end

#roleObject (readonly)

Returns the value of attribute role.



117
118
119
# File 'app/components/primer/alpha/action_list.rb', line 117

def role
  @role
end

#select_variantObject (readonly)

Returns the value of attribute select_variant.



117
118
119
# File 'app/components/primer/alpha/action_list.rb', line 117

def select_variant
  @select_variant
end

Class Method Details

.custom_element_nameObject

:nocov:



43
44
45
# File 'app/components/primer/alpha/action_list.rb', line 43

def self.custom_element_name
  @custom_element_name ||= name.split("::").last.underscore.dasherize
end

Instance Method Details

#acts_as_form_input?Boolean

Returns:

  • (Boolean)


239
240
241
# File 'app/components/primer/alpha/action_list.rb', line 239

def acts_as_form_input?
  required_form_arguments_given? && allows_selection?
end

#acts_as_menu?Boolean

Returns:

  • (Boolean)


231
232
233
# File 'app/components/primer/alpha/action_list.rb', line 231

def acts_as_menu?
  @system_arguments[:role] == :menu
end

#allows_selection?Boolean

Returns:

  • (Boolean)


227
228
229
# File 'app/components/primer/alpha/action_list.rb', line 227

def allows_selection?
  single_select? || multi_select?
end

#before_renderObject



166
167
168
169
170
171
# File 'app/components/primer/alpha/action_list.rb', line 166

def before_render
  return unless heading?

  @system_arguments[:"aria-labelledby"] = heading.title_id
  @system_arguments[:"aria-describedby"] = heading.subtitle_id if heading.subtitle?
end

#build_avatar_item(src:, username:, full_name: nil, full_name_scheme: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME, component_klass: ActionList::Item, avatar_arguments: {}, **system_arguments) ⇒ Object

Builds a new avatar item but does not add it to the list. Avatar items are a convenient way to accessibly add an item with a leading avatar image. Use this method instead of the ‘#with_avatar_item` slot if you need to render an avatar item outside the context of a list, eg. if rendering additional items to append to an existing list, perhaps via a separate HTTP request.

Parameters:

  • src (String)

    The source url of the avatar image.

  • username (String)

    The username associated with the avatar.

  • full_name (String) (defaults to: nil)

    Optional. The user’s full name.

  • full_name_scheme (Symbol) (defaults to: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME)

    Optional. How to display the user’s full name. <%= one_of(Primer::Alpha::ActionList::Item::DESCRIPTION_SCHEME_OPTIONS) %>

  • component_klass (Class) (defaults to: ActionList::Item)

    The class to use instead of the default <%= link_to_component(Primer::Alpha::ActionList::Item) %>

  • avatar_arguments (Hash) (defaults to: {})

    Optional. The arguments accepted by <%= link_to_component(Primer::Beta::Avatar) %>

  • system_arguments (Hash)

    These arguments are forwarded to <%= link_to_component(Primer::Alpha::ActionList::Item) %>, or whatever class is passed as the ‘component_klass` argument.



208
209
210
211
212
213
214
215
216
217
# File 'app/components/primer/alpha/action_list.rb', line 208

def build_avatar_item(src:, username:, full_name: nil, full_name_scheme: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME, component_klass: ActionList::Item, avatar_arguments: {}, **system_arguments)
  build_item(label: username, description_scheme: full_name_scheme, component_klass: component_klass, **system_arguments).tap do |item|
    item.with_leading_visual_raw_content do
      # no alt text necessary for presentational item
      item.render(Primer::Beta::Avatar.new(src: src, **avatar_arguments, role: :presentation, size: 16))
    end

    item.with_description_content(full_name) if full_name
  end
end

#build_item(component_klass: ActionList::Item, **system_arguments) ⇒ Object

Builds a new item but does not add it to the list. Use this method instead of the ‘#with_item` slot if you need to render an item outside the context of a list, eg. if rendering additional items to append to an existing list, perhaps via a separate HTTP request.

Parameters:

  • component_klass (Class) (defaults to: ActionList::Item)

    The class to use instead of the default <%= link_to_component(Primer::Alpha::ActionList::Item) %>

  • system_arguments (Hash)

    These arguments are forwarded to <%= link_to_component(Primer::Alpha::ActionList::Item) %>, or whatever class is passed as the ‘component_klass` argument.



180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'app/components/primer/alpha/action_list.rb', line 180

def build_item(component_klass: ActionList::Item, **system_arguments)
  if single_select? && system_arguments[:active] && items.count(&:active?).positive?
    raise ArgumentError, "only a single item may be active when select_variant is set to :single"
  end
  # rubocop:enable Style/IfUnlessModifier

  system_arguments[:classes] = class_names(
    @item_classes,
    system_arguments[:classes]
  )

  component_klass.new(list: self, **system_arguments)
end

#custom_element_nameObject



48
49
50
# File 'app/components/primer/alpha/action_list.rb', line 48

def custom_element_name
  self.class.custom_element_name
end

#multi_select?Boolean

Returns:

  • (Boolean)


223
224
225
# File 'app/components/primer/alpha/action_list.rb', line 223

def multi_select?
  select_variant == :multiple || select_variant == :multiple_checkbox
end

#required_form_arguments_given?Boolean

Returns:

  • (Boolean)


235
236
237
# File 'app/components/primer/alpha/action_list.rb', line 235

def required_form_arguments_given?
  @form_builder && @input_name
end

#single_select?Boolean

Returns:

  • (Boolean)


219
220
221
# File 'app/components/primer/alpha/action_list.rb', line 219

def single_select?
  select_variant == :single
end

#will_add_item(_item) ⇒ Object



244
# File 'app/components/primer/alpha/action_list.rb', line 244

def will_add_item(_item); end

#with_avatar_item(src:, username:, full_name: nil, full_name_scheme: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME, component_klass: ActionList::Item, avatar_arguments: {}, **system_arguments, &block) ⇒ Object

Adds an avatar item to the list. Avatar items are a convenient way to accessibly add an item with a leading avatar image.

Parameters:

  • src (String)

    The source url of the avatar image.

  • username (String)

    The username associated with the avatar.

  • full_name (String) (defaults to: nil)

    Optional. The user’s full name.

  • full_name_scheme (Symbol) (defaults to: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME)

    Optional. How to display the user’s full name. <%= one_of(Primer::Alpha::ActionList::Item::DESCRIPTION_SCHEME_OPTIONS) %>

  • component_klass (Class) (defaults to: ActionList::Item)

    The class to use instead of the default <%= link_to_component(Primer::Alpha::ActionList::Item) %>

  • avatar_arguments (Hash) (defaults to: {})

    Optional. The arguments accepted by <%= link_to_component(Primer::Beta::Avatar) %>

  • system_arguments (Hash)

    These arguments are forwarded to <%= link_to_component(Primer::Alpha::ActionList::Item) %>, or whatever class is passed as the ‘component_klass` argument.



10
11
# File 'app/components/primer/alpha/action_list.rb', line 10

def with_avatar_item(src:, username:, full_name: nil, full_name_scheme: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME, component_klass: ActionList::Item, avatar_arguments: {}, **system_arguments, &block)
end

#with_divider(**system_arguments, &block) ⇒ Object

Adds a divider to the list. Dividers visually separate items.

Parameters:

  • system_arguments (Hash)

    The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList::Divider) %>.



4
5
# File 'app/components/primer/alpha/action_list.rb', line 4

def with_divider(**system_arguments, &block)
end

#with_item(**system_arguments, &block) ⇒ Object

Adds an item to the list.

Parameters:

  • component_klass (Class)

    The class to use instead of the default <%= link_to_component(Primer::Alpha::ActionList::Item) %>

  • system_arguments (Hash)

    These arguments are forwarded to <%= link_to_component(Primer::Alpha::ActionList::Item) %>, or whatever class is passed as the ‘component_klass` argument.



5
6
# File 'app/components/primer/alpha/action_list.rb', line 5

def with_item(**system_arguments, &block)
end