Class: Daisy::Navigation::TabsComponent::TabComponent

Inherits:
LocoMotion::BasicComponent show all
Defined in:
app/components/daisy/navigation/tabs_component.rb

Overview

A tab within a TabsComponent that can be either a link or a radio button.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from LocoMotion::BasicComponent

name

Constructor Details

#initialize(*args, **kws, &block) ⇒ TabComponent

Create a new instance of the TabComponent.

Parameters:

  • args (Array) —

    Not used.

  • kws (Hash) —

    The keyword arguments for the component.

Options Hash (**kws):

  • title (String) —

    The text to display in the tab.

  • active (Boolean) —

    Whether this tab is active (default: false).

  • checked (Boolean) —

    Whether this tab is checked (default: false).

  • disabled (Boolean) —

    Whether this tab is disabled (default: false).

  • href (String) —

    The URL to visit when the tab is clicked. When omitted (and not using radio buttons), the tab renders as a <button> element so it stays keyboard-accessible.

  • target (String) —

    The target attribute for the tab (e.g., "_blank").

  • value (String) —

    The value attribute when using radio buttons.

  • name (String) —

    The radio input's name attribute, used to group tabs together when using radio buttons. Defaults to the parent Daisy::Navigation::TabsComponent's name; override to remove a tab from its group.

  • css (String) —

    Additional CSS classes for styling. Common options include:

    • Size: tab-lg, tab-md (default), tab-sm, tab-xs
    • Width: w-full, !w-14
    • Cursor: cursor-pointer, !cursor-auto


144
145
146
147
148
149
150
151
152
153
154
# File 'app/components/daisy/navigation/tabs_component.rb', line 144

def initialize(*args, **kws, &block)
  super

  @active       = config_option(:active, false)
  @checked      = config_option(:checked, false)
  @disabled     = config_option(:disabled, false)
  @href         = config_option(:href)
  @simple_title = config_option(:title)
  @target       = config_option(:target)
  @value        = config_option(:value)
end

Instance Attribute Details

#active ⇒ Object (readonly)

Returns the value of attribute active.



104
105
106
# File 'app/components/daisy/navigation/tabs_component.rb', line 104

def active
  @active
end

#simple_title ⇒ Object (readonly)

Returns the value of attribute simple_title.



104
105
106
# File 'app/components/daisy/navigation/tabs_component.rb', line 104

def simple_title
  @simple_title
end

Instance Method Details

#before_render ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
# File 'app/components/daisy/navigation/tabs_component.rb', line 156

def before_render
  # Reset the name to the config option or the parent name if available
  @name = config_option(:name, loco_parent.name)

  if loco_parent.radio?
    setup_radio_button
  else
    setup_component
  end

  setup_content_wrapper unless custom_content?
end

#call ⇒ Object



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'app/components/daisy/navigation/tabs_component.rb', line 235

def call
  # Not sure why we need these, but this forces the rendering below to
  # include the content blocks passed to each slot.
  # title.to_s if title?
  # custom_content.to_s if custom_content?

  capture do
    if loco_parent.radio?
      concat(part(:component))
    else
      concat(part(:component) { concat(title? ? title : @simple_title) })
    end

    concat(part(:content_wrapper) { content }) if content? && content
    concat(custom_content) if custom_content?
  end
end

#setup_component ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'app/components/daisy/navigation/tabs_component.rb', line 169

def setup_component
  # An anchor without an href is unfocusable and can't be activated
  # from the keyboard, so href-less tabs render as buttons instead.
  if @href
    set_tag_name(:component, :a)
    add_html(:component, { href: @href, target: @target })
  else
    set_tag_name(:component, :button)
    add_html(:component, { type: "button" })
  end

  add_css(:component, "tab")
  add_css(:component, "tab-active") if @active || @checked
  add_html(:component, { role: "tab" })
  add_aria(:component, label: @simple_title, selected: (@active || @checked).to_s)
  add_html(:component, { disabled: @disabled }) if @disabled

  setup_switching if switchable?
end

#setup_content_wrapper ⇒ Object



230
231
232
233
# File 'app/components/daisy/navigation/tabs_component.rb', line 230

def setup_content_wrapper
  add_css(:content_wrapper, "tab-content")
  add_html(:content_wrapper, { role: "tabpanel" })
end

#setup_radio_button ⇒ Object



216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'app/components/daisy/navigation/tabs_component.rb', line 216

def setup_radio_button
  set_tag_name(:component, :input)
  add_css(:component, "tab")
  add_html(:component, {
             type: "radio",
             role: "tab",
             name: @name,
             value: @value,
             checked: @active || @checked
           })
  add_aria(:component, label: @simple_title, selected: (@active || @checked).to_s)
  add_html(:component, { disabled: @disabled }) if @disabled
end

#setup_switching ⇒ Object

Wires the tab into the parent's loco-tabs Stimulus controller: arrow / Home / End keys move focus between tabs, and click (which Enter/Space fire natively on a button) activates the focused tab — the ARIA manual-activation pattern (see tabs_controller.js). Inert until the app registers the controller.



194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'app/components/daisy/navigation/tabs_component.rb', line 194

def setup_switching
  add_html(:component, {
             data: {
               "loco-tabs-target": "tab",
               action: [
                 "loco-tabs#activate",
                 "keydown.right->loco-tabs#focusNext",
                 "keydown.left->loco-tabs#focusPrevious",
                 "keydown.home->loco-tabs#focusFirst",
                 "keydown.end->loco-tabs#focusLast"
               ].join(" ")
             }
           })
end

#switchable? ⇒ Boolean

A tab participates in JS-driven switching only when it toggles a panel: it has content to show and no href (href tabs navigate, and content-less tabs are plain action or display tabs).

Returns:

  • (Boolean)


212
213
214
# File 'app/components/daisy/navigation/tabs_component.rb', line 212

def switchable?
  @href.nil? && (content? || custom_content?)
end