ariadne_view_components 0.0.11-arm64-darwin → 0.0.13-arm64-darwin
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/ariadne.d.ts +1 -0
- data/app/assets/javascripts/ariadne_view_components.js +2 -2
- data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
- data/app/assets/javascripts/tab-container-component.d.ts +1 -0
- data/app/assets/javascripts/tab-nav-component.d.ts +9 -0
- data/app/components/ariadne/ariadne.ts +3 -0
- data/app/components/ariadne/body_component.rb +1 -1
- data/app/components/ariadne/button_component.rb +2 -2
- data/app/components/ariadne/comment_component.html.erb +2 -6
- data/app/components/ariadne/comment_component.rb +1 -1
- data/app/components/ariadne/component.rb +3 -5
- data/app/components/ariadne/container_component.rb +1 -1
- data/app/components/ariadne/counter_component.rb +1 -1
- data/app/components/ariadne/flash_component.rb +1 -1
- data/app/components/ariadne/flex_component.rb +1 -1
- data/app/components/ariadne/footer_component.rb +1 -1
- data/app/components/ariadne/grid_component.html.erb +2 -2
- data/app/components/ariadne/grid_component.rb +10 -8
- data/app/components/ariadne/header_component.rb +1 -1
- data/app/components/ariadne/heroicon_component.html.erb +1 -1
- data/app/components/ariadne/heroicon_component.rb +1 -2
- data/app/components/ariadne/list_component.html.erb +3 -5
- data/app/components/ariadne/list_component.rb +5 -5
- data/app/components/ariadne/main_component.rb +1 -1
- data/app/components/ariadne/narrow_container_component.rb +1 -1
- data/app/components/ariadne/panel_bar_component.rb +2 -2
- data/app/components/ariadne/pill_component.rb +1 -1
- data/app/components/ariadne/rich_text_area_component.html.erb +1 -1
- data/app/components/ariadne/rich_text_area_component.rb +1 -1
- data/app/components/ariadne/slideover_component.rb +2 -2
- data/app/components/ariadne/tab-container-component.ts +24 -0
- data/app/components/ariadne/tab-nav-component.ts +34 -0
- data/app/components/ariadne/tab_component.html.erb +2 -6
- data/app/components/ariadne/tab_component.rb +77 -18
- data/app/components/ariadne/tab_container_component.erb +12 -0
- data/app/components/ariadne/tab_container_component.rb +61 -0
- data/app/components/ariadne/tab_nav_component.html.erb +7 -0
- data/app/components/ariadne/tab_nav_component.rb +72 -0
- data/app/components/ariadne/table_component.html.erb +17 -0
- data/app/components/ariadne/table_component.rb +281 -0
- data/app/components/ariadne/time_ago_component.rb +1 -1
- data/app/components/ariadne/timeline_component.rb +1 -1
- data/app/lib/ariadne/fetch_or_fallback_helper.rb +11 -3
- data/app/lib/ariadne/icon_helper.rb +17 -13
- data/lib/ariadne/view_components/commands.rb +1 -1
- data/lib/ariadne/view_components/constants.rb +2 -2
- data/lib/ariadne/view_components/statuses.rb +2 -2
- data/lib/ariadne/view_components/version.rb +1 -1
- data/lib/rubocop/config/default.yml +1 -1
- data/lib/tasks/docs.rake +5 -96
- data/static/arguments.yml +51 -15
- data/static/audited_at.json +9 -1
- data/static/classes.yml +157 -269
- data/static/constants.json +55 -15
- data/static/statuses.json +9 -1
- data/tailwind.config.js +11 -26
- metadata +13 -10
- data/app/components/ariadne/tab_bar_component.html.erb +0 -3
- data/app/components/ariadne/tab_bar_component.rb +0 -45
- data/app/lib/ariadne/join_style_arguments_helper.rb +0 -14
- data/app/lib/ariadne/tab_nav_helper.rb +0 -35
- data/app/lib/ariadne/tabbed_component_helper.rb +0 -39
- data/app/lib/ariadne/test_selector_helper.rb +0 -20
- data/app/lib/ariadne/underline_nav_helper.rb +0 -44
@@ -0,0 +1 @@
|
|
1
|
+
import '@github/tab-container-element';
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class TabNavComponent extends Controller {
|
3
|
+
static targets: string[];
|
4
|
+
readonly tabTargets: [HTMLAnchorElement];
|
5
|
+
SELECTED_CLASSES: string[];
|
6
|
+
UNSELECTED_CLASSES: string[];
|
7
|
+
connect(): void;
|
8
|
+
toggle(event: Event): void;
|
9
|
+
}
|
@@ -6,8 +6,10 @@ import ClipboardCopyComponent from './clipboard-copy-component'
|
|
6
6
|
import CommentComponent from './comment-component'
|
7
7
|
import RichTextAreaComponent from './rich-text-area-component'
|
8
8
|
import SlideoverComponent from './slideover-component'
|
9
|
+
import TabNavComponent from './tab-nav-component'
|
9
10
|
import TooltipComponent from './tooltip-component'
|
10
11
|
|
12
|
+
import './tab-container-component'
|
11
13
|
import './time-ago-component'
|
12
14
|
|
13
15
|
const application = Application.start()
|
@@ -17,4 +19,5 @@ application.register('ariadne-form', AriadneForm)
|
|
17
19
|
application.register('comment-component', CommentComponent)
|
18
20
|
application.register('rich-text-area-component', RichTextAreaComponent)
|
19
21
|
application.register('slideover-component', SlideoverComponent)
|
22
|
+
application.register('tab-nav-component', TabNavComponent)
|
20
23
|
application.register('tooltip-component', TooltipComponent)
|
@@ -82,7 +82,7 @@ module Ariadne
|
|
82
82
|
#
|
83
83
|
# @example With leading visual
|
84
84
|
# <%= render(Ariadne::ButtonComponent.new) do |c| %>
|
85
|
-
# <% c.icon(icon: :star, variant: HeroiconsHelper::Icon::VARIANT_OUTLINE, classes: "text-yellow-600") %>
|
85
|
+
# <% c.icon(icon: :star, variant: HeroiconsHelper::Icon::VARIANT_OUTLINE, classes: "ariadne-text-yellow-600") %>
|
86
86
|
# Button
|
87
87
|
# <% end %>
|
88
88
|
#
|
@@ -135,7 +135,7 @@ module Ariadne
|
|
135
135
|
|
136
136
|
@classes = class_names(
|
137
137
|
SCHEME_CLASS_MAPPINGS[@scheme],
|
138
|
-
classes
|
138
|
+
classes,
|
139
139
|
)
|
140
140
|
end
|
141
141
|
|
@@ -2,16 +2,12 @@
|
|
2
2
|
<div class="ariadne-bg-white" data-comment-component-target="commentComponent">
|
3
3
|
<div class="ariadne-hidden sm:ariadne-block">
|
4
4
|
<div class="ariadne-border-b ariadne-border-gray-200">
|
5
|
-
<%= render(Ariadne::TabBarComponent.new(sr_label: @sr_label, attributes: { :"data-comment-component-target" => "tabBarComponent" })) do |tab_bar| %>
|
6
|
-
<%= public_tab %>
|
7
|
-
<%= internal_tab %>
|
8
|
-
<% end %>
|
9
5
|
</div>
|
10
6
|
</div>
|
11
7
|
<%= ariadne_form_with(url: @url, method: @method, classes: @classes, attributes: @attributes) do |comment_box| %>
|
12
8
|
<div class="ariadne-overflow-hidden ariadne-border-x ariadne-border-b ariadne-border-gray-300 ariadne-shadow-sm focus-within:ariadne-border-indigo-500 focus-within:ariadne-ring-1 focus-within:ariadne-ring-indigo-500">
|
13
|
-
<%= hidden_field_tag 'message_public', true
|
14
|
-
<%= render(Ariadne::RichTextAreaComponent.new(name: :bodytext, sr_label: "Select reply type", attributes: { required: true}))
|
9
|
+
<%= hidden_field_tag 'message_public', true %>
|
10
|
+
<%= render(Ariadne::RichTextAreaComponent.new(name: :bodytext, sr_label: "Select reply type", attributes: { required: true})) %>
|
15
11
|
<% comment_box.submit { @submit } %>
|
16
12
|
</div>
|
17
13
|
<div class="ariadne-mt-2 ariadne-flex ariadne-justify-end">
|
@@ -10,15 +10,13 @@ module Ariadne
|
|
10
10
|
include ViewComponent::SlotableV2 unless ViewComponent::Base < ViewComponent::SlotableV2
|
11
11
|
include ClassNameHelper
|
12
12
|
include FetchOrFallbackHelper
|
13
|
-
include TestSelectorHelper
|
14
|
-
include JoinStyleArgumentsHelper
|
15
13
|
include ViewHelper
|
16
14
|
include Status::Dsl
|
17
15
|
include Audited::Dsl
|
18
16
|
include LoggerHelper
|
19
17
|
include Ariadne::ActionViewExtensions::FormHelper
|
20
18
|
|
21
|
-
BASE_HTML_CLASSES = "ariadne-h-full scroll-smooth ariadne-bg-white ariadne-antialiased"
|
19
|
+
BASE_HTML_CLASSES = "ariadne-h-full ariadne-scroll-smooth ariadne-bg-white ariadne-antialiased"
|
22
20
|
BASE_BODY_CLASSES = "ariadne-flex ariadne-h-full ariadne-flex-col"
|
23
21
|
BASE_WRAPPER_CLASSES = "ariadne-flex ariadne-flex-col ariadne-h-screen ariadne-justify-between"
|
24
22
|
BASE_MAIN_CLASSES = "ariadne-flex-auto"
|
@@ -84,7 +82,7 @@ module Ariadne
|
|
84
82
|
if (denylist = attributes[denylist_name])
|
85
83
|
check_denylist(denylist, attributes)
|
86
84
|
|
87
|
-
# Remove :attributes_denylist key and any denied keys from
|
85
|
+
# Remove :attributes_denylist key and any denied keys from attributes
|
88
86
|
attributes.except!(denylist_name)
|
89
87
|
attributes.except!(*denylist.keys.flatten)
|
90
88
|
end
|
@@ -109,7 +107,7 @@ module Ariadne
|
|
109
107
|
deny_aria_key(
|
110
108
|
:label,
|
111
109
|
"Don't use `aria-label` on `#{tag}` elements. See https://www.tpgi.com/short-note-on-aria-label-aria-labelledby-and-aria-describedby/",
|
112
|
-
attributes
|
110
|
+
attributes,
|
113
111
|
)
|
114
112
|
end
|
115
113
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<%= render Ariadne::BaseComponent.new(tag: :ul, classes: @classes, attributes: @attributes) do |grid| %>
|
2
2
|
<% items.each do |item| %>
|
3
|
-
<li class="<%= item.classes %>
|
3
|
+
<li class="<%= item.classes %>">
|
4
4
|
<% if item.has_href? %>
|
5
|
-
<%= render Ariadne::LinkComponent.new(href: item.href) do %>
|
5
|
+
<%= render Ariadne::LinkComponent.new(href: item.href, classes: Ariadne::GridComponent::GridItem::DEFAULT_ACTION_LINK_COLORS) do %>
|
6
6
|
<%= item.entry %>
|
7
7
|
<% end %>
|
8
8
|
<% if item.actions.any? %>
|
@@ -5,7 +5,7 @@ module Ariadne
|
|
5
5
|
class GridComponent < Ariadne::Component
|
6
6
|
DEFAULT_CLASSES = "ariadne-grid ariadne-gap-6 sm:ariadne-grid-cols-2 lg:ariadne-grid-cols-3"
|
7
7
|
|
8
|
-
DEFAULT_LINK_COLOR_CLASSES = "
|
8
|
+
DEFAULT_LINK_COLOR_CLASSES = "focus:ariadne-outline-none focus:ariadne-ring-2 focus:ariadne-ring-offset-2 focus:ariadne-ring-purple-500"
|
9
9
|
|
10
10
|
# The items to show in the ariadne-grid.
|
11
11
|
renders_many :items, "GridItem"
|
@@ -19,7 +19,7 @@ module Ariadne
|
|
19
19
|
def initialize(classes: "", attributes: {})
|
20
20
|
@classes = class_names(
|
21
21
|
DEFAULT_CLASSES,
|
22
|
-
classes
|
22
|
+
classes,
|
23
23
|
)
|
24
24
|
|
25
25
|
default_attributes = { role: "list" }
|
@@ -29,18 +29,20 @@ module Ariadne
|
|
29
29
|
# This component is part of `GridComponent` and should not be
|
30
30
|
# used as a standalone component.
|
31
31
|
class GridItem < Ariadne::Component
|
32
|
-
DEFAULT_ITEM_CLASSES = "ariadne-flex ariadne-flex-col ariadne-text-center ariadne-rounded-lg ariadne-shadow
|
32
|
+
DEFAULT_ITEM_CLASSES = "ariadne-flex ariadne-flex-col ariadne-text-center ariadne-rounded-lg ariadne-shadow text-black-700 ariadne-border-black"
|
33
33
|
|
34
|
-
DEFAULT_ENTRY_CLASSES = "group ariadne-flex-1 ariadne-flex ariadne-flex-col ariadne-p-8 hover:ariadne-
|
35
|
-
renders_one :entry, lambda { |classes: "", &block|
|
34
|
+
DEFAULT_ENTRY_CLASSES = "ariadne-group ariadne-flex-1 ariadne-flex ariadne-flex-col ariadne-p-8 hover:ariadne-text-gray-500"
|
35
|
+
renders_one :entry, lambda { |classes: "", attributes: {}, &block|
|
36
36
|
view_context.capture do
|
37
|
-
|
37
|
+
actual_classes = class_names(DEFAULT_ENTRY_CLASSES, classes)
|
38
|
+
render(Ariadne::BaseComponent.new(tag: :div, classes: actual_classes, attributes: attributes)) { block&.call }
|
38
39
|
end
|
39
40
|
}
|
40
41
|
|
41
|
-
DEFAULT_ACTION_LINK_CLASSES = "
|
42
|
+
DEFAULT_ACTION_LINK_CLASSES = "ariadne-relative ariadne--mr-px ariadne-w-0 ariadne-flex-1 ariadne-inline-flex ariadne-items-center ariadne-justify-center ariadne-py-4 ariadne-text-sm ariadne-font-medium ariadne-border ariadne-border-transparent"
|
43
|
+
DEFAULT_ACTION_LINK_COLORS = "hover:ariadne-text-gray-500"
|
42
44
|
renders_many :actions, lambda { |href:, icon:, label:, size: Ariadne::HeroiconComponent::SIZE_DEFAULT, variant: HeroiconsHelper::Icon::VARIANT_SOLID, classes: "", attributes: {}, text_classes: ""|
|
43
|
-
actual_classes = class_names(DEFAULT_ACTION_LINK_CLASSES, classes)
|
45
|
+
actual_classes = class_names(DEFAULT_ACTION_LINK_CLASSES, DEFAULT_ACTION_LINK_COLORS, classes)
|
44
46
|
render(Ariadne::LinkComponent.new(href: href, classes: actual_classes, attributes: attributes)) do
|
45
47
|
render(Ariadne::HeroiconComponent.new(icon: icon, size: size, variant: variant, text_classes: text_classes)) { label }
|
46
48
|
end
|
@@ -1,4 +1,4 @@
|
|
1
1
|
<%= render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) do %>
|
2
|
-
<%= @icon.path
|
2
|
+
<%= @icon.path %>
|
3
3
|
<% end %>
|
4
4
|
<%= render(Ariadne::BaseComponent.new(tag: :span, classes: @text_classes, attributes: @text_attributes)) { content } if content.present? %>
|
@@ -107,10 +107,9 @@ module Ariadne
|
|
107
107
|
}
|
108
108
|
|
109
109
|
@icon = heroicon(icon, variant: variant, **attributes)
|
110
|
-
|
111
110
|
@classes = class_names(
|
112
111
|
@icon.attributes[:class],
|
113
|
-
classes
|
112
|
+
classes,
|
114
113
|
)
|
115
114
|
@attributes.merge!(@icon.attributes.except(:class, :"aria-hidden"))
|
116
115
|
|
@@ -1,13 +1,11 @@
|
|
1
1
|
<%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |list| %>
|
2
2
|
<% items.each do |item| %>
|
3
|
-
|
4
|
-
|
3
|
+
<%= render Ariadne::BaseComponent.new(tag: :li, classes: item.classes, attributes: item.attributes) do %>
|
4
|
+
<% if item.linked? %>
|
5
5
|
<%= render Ariadne::LinkComponent.new(href: item.link[:href], classes: item.link[:classes], attributes: item.link[:attributes]) do %>
|
6
6
|
<%= item.entry %>
|
7
7
|
<% end %>
|
8
|
-
<%
|
9
|
-
<% else %>
|
10
|
-
<%= render Ariadne::BaseComponent.new(tag: :li, classes: item.classes, attributes: item.attributes) do %>
|
8
|
+
<% else %>
|
11
9
|
<%= item.entry %>
|
12
10
|
<% end %>
|
13
11
|
<% end %>
|
@@ -36,11 +36,11 @@ module Ariadne
|
|
36
36
|
class ListItem < Ariadne::Component
|
37
37
|
DEFAULT_ITEM_CLASSES = "ariadne-relative ariadne-p-1.5 focus:ariadne-ring-2 focus:ariadne-ring-offset-2 focus:ariadne-ring-purple-500 hover:ariadne-bg-button-hover-color"
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
DEFAULT_ENTRY_CLASSES = "hover:ariadne-text-gray-500"
|
40
|
+
renders_one :entry, lambda { |classes: "", attributes: {}, &block|
|
41
|
+
view_context.capture do
|
42
|
+
actual_classes = class_names(DEFAULT_ENTRY_CLASSES, classes)
|
43
|
+
render(Ariadne::BaseComponent.new(tag: :div, classes: actual_classes, attributes: attributes)) { block&.call }
|
44
44
|
end
|
45
45
|
}
|
46
46
|
|
@@ -23,7 +23,7 @@ module Ariadne
|
|
23
23
|
@tag = DEFAULT_TAG
|
24
24
|
@classes = class_names(
|
25
25
|
DEFAULT_CLASSES,
|
26
|
-
classes
|
26
|
+
classes,
|
27
27
|
)
|
28
28
|
|
29
29
|
@attributes = attributes
|
@@ -72,7 +72,7 @@ module Ariadne
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def call
|
75
|
-
Ariadne::BaseComponent.new(tag: :div, classes: @classes, attributes: @attributes)
|
75
|
+
render(Ariadne::BaseComponent.new(tag: :div, classes: @classes, attributes: @attributes))
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<%= render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) do %>
|
2
2
|
<% if @has_form %>
|
3
|
-
<input type="hidden" data-tiptap-value-container=true name="<%= @name %>" id="<%= @name %>"
|
3
|
+
<input type="hidden" data-tiptap-value-container=true name="<%= @name %>" id="<%= @name %>">
|
4
4
|
<% end %>
|
5
5
|
<textarea class="tiptap-editor"></textarea>
|
6
6
|
<% end %>
|
@@ -57,7 +57,7 @@ module Ariadne
|
|
57
57
|
#
|
58
58
|
# @param tag [Symbol, String] The rendered tag name.
|
59
59
|
# @param direction [Symbol] <%= one_of(Ariadne::SlideoverComponent::VALID_DIRECTIONS) %>
|
60
|
-
# @param form_id [String] The ID of any
|
60
|
+
# @param form_id [String] The ID of any `form` tag to submit when the button is clicked.
|
61
61
|
# @param open_text [String] The text to use to open the slideover.
|
62
62
|
# @param close_text [String] The text to use to close the slideover.
|
63
63
|
# @param classes [String] <%= link_to_classes_docs %>
|
@@ -66,7 +66,7 @@ module Ariadne
|
|
66
66
|
@tag = check_incoming_tag(DEFAULT_TAG, tag)
|
67
67
|
@classes = class_names(
|
68
68
|
DEFAULT_CLASSES,
|
69
|
-
classes
|
69
|
+
classes,
|
70
70
|
)
|
71
71
|
|
72
72
|
@direction = fetch_or_raise(VALID_DIRECTIONS, direction)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import '@github/tab-container-element'
|
2
|
+
|
3
|
+
// // keep in sync with tab_container_component.rb
|
4
|
+
// const DEFAULT_SELECTED_CLASSES: string[] = ['ariadne-border-indigo-500', 'ariadne-text-indigo-600']
|
5
|
+
// const DEFAULT_UNSELECTED_CLASSES: string[] = [
|
6
|
+
// 'ariadne-text-gray-500',
|
7
|
+
// 'hover:ariadne-text-gray-700',
|
8
|
+
// 'hover:ariadne-border-gray-300'
|
9
|
+
// ]
|
10
|
+
|
11
|
+
// for (const tabContainer of document.getElementsByTagName('tab-container')) {
|
12
|
+
// tabContainer.addEventListener('tab-container-change', function (event: Event) {
|
13
|
+
// const newPanel = (event as CustomEvent).detail.relatedTarget as HTMLElement
|
14
|
+
// const tabContainer = newPanel.closest('tab-container') as HTMLElement
|
15
|
+
// const tabList = tabContainer.firstElementChild as HTMLElement
|
16
|
+
// const currentTab = tabList.querySelector('[aria-selected="true"]') as HTMLElement
|
17
|
+
// const tabId = newPanel.getAttribute('id')?.split('-').slice(1).join('-')
|
18
|
+
// const newTab = tabList.querySelector(`#${tabId}`) as HTMLElement
|
19
|
+
// currentTab.classList.remove(...DEFAULT_SELECTED_CLASSES)
|
20
|
+
// currentTab.classList.add(...DEFAULT_UNSELECTED_CLASSES)
|
21
|
+
// newTab.classList.add(...DEFAULT_SELECTED_CLASSES)
|
22
|
+
// newTab.classList.remove(...DEFAULT_UNSELECTED_CLASSES)
|
23
|
+
// })
|
24
|
+
// }
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import {Controller} from '@hotwired/stimulus'
|
2
|
+
|
3
|
+
export default class TabNavComponent extends Controller {
|
4
|
+
static targets = ['tab']
|
5
|
+
|
6
|
+
declare readonly tabTargets: [HTMLAnchorElement]
|
7
|
+
|
8
|
+
// keep in synch with tab_nav_component
|
9
|
+
SELECTED_CLASSES = ['ariadne-border-indigo-500', 'ariadne-text-indigo-600']
|
10
|
+
UNSELECTED_CLASSES = ['ariadne-text-gray-500', 'hover:ariadne-text-gray-700', 'hover:ariadne-border-gray-300']
|
11
|
+
|
12
|
+
connect() {
|
13
|
+
for (const tab of this.tabTargets) {
|
14
|
+
if (tab.hasAttribute('aria-current')) {
|
15
|
+
tab.classList.add(...this.SELECTED_CLASSES)
|
16
|
+
tab.classList.remove(...this.UNSELECTED_CLASSES)
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
toggle(event: Event) {
|
22
|
+
for (const tab of this.tabTargets) {
|
23
|
+
if (tab === event.target) {
|
24
|
+
tab.setAttribute('aria-current', 'page')
|
25
|
+
tab.classList.add(...this.SELECTED_CLASSES)
|
26
|
+
tab.classList.remove(...this.UNSELECTED_CLASSES)
|
27
|
+
} else if (tab.hasAttribute('aria-current')) {
|
28
|
+
tab.removeAttribute('aria-current')
|
29
|
+
tab.classList.add(...this.UNSELECTED_CLASSES)
|
30
|
+
tab.classList.remove(...this.SELECTED_CLASSES)
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
@@ -1,7 +1,3 @@
|
|
1
|
-
<%= render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) do
|
2
|
-
|
3
|
-
<%= text %>
|
4
|
-
<% else %>
|
5
|
-
<%= content %>
|
6
|
-
<% end %>
|
1
|
+
<%= render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) do %>
|
2
|
+
<%= text || content %>
|
7
3
|
<% end %>
|
@@ -1,43 +1,102 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Ariadne
|
4
|
-
#
|
4
|
+
# This component is part of navigation components such as `Ariadne::TabContainerComponent`.
|
5
|
+
# and `Ariadne::TabNavComponent` and should not be used by itself.
|
6
|
+
#
|
7
|
+
# @accessibility
|
8
|
+
# `TabComponent` renders the selected anchor tab with `aria-current="page"` by default.
|
9
|
+
# When the selected tab does not correspond to the current page, such as in a nested inner tab, make sure to use aria-current="true"
|
5
10
|
class TabComponent < Ariadne::Component
|
6
|
-
|
7
|
-
|
11
|
+
DEFAULT_ARIA_CURRENT_FOR_ANCHOR = :page
|
12
|
+
ARIA_CURRENT_OPTIONS_FOR_ANCHOR = [true, DEFAULT_ARIA_CURRENT_FOR_ANCHOR].freeze
|
8
13
|
|
9
|
-
#
|
14
|
+
# Panel controlled by the Tab. This will not render anything in the tab itself.
|
15
|
+
# It will provide a accessor for the Tab's parent to call and render the panel
|
16
|
+
# content in the appropriate place.
|
17
|
+
#
|
18
|
+
# @param classes [String] <%= link_to_classes_docs %>
|
19
|
+
# @param attributes [Hash] <%= link_to_attributes_docs %>
|
20
|
+
renders_one :panel, lambda { |classes: "", attributes: {}|
|
21
|
+
attributes[:id] = @panel_id
|
22
|
+
tag = :div
|
23
|
+
attributes[:role] ||= :tabpanel
|
24
|
+
attributes[:tabindex] = 0
|
25
|
+
attributes[:hidden] = true unless @selected
|
26
|
+
|
27
|
+
label_present = aria("label", attributes) || aria("labelledby", attributes)
|
28
|
+
unless label_present
|
29
|
+
if @id.present?
|
30
|
+
attributes[:"aria-labelledby"] = @id
|
31
|
+
else
|
32
|
+
raise ArgumentError, "Panels must be labelled. Either set a unique `id` on the tab, or set an `aria-label` directly on the panel"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Ariadne::BaseComponent.new(tag: tag, classes: classes, attributes: attributes)
|
37
|
+
}
|
38
|
+
|
39
|
+
# The tab's text.
|
10
40
|
#
|
11
41
|
# @param kwargs [Hash] The same arguments as <%= link_to_component(Ariadne::Text) %>.
|
12
42
|
renders_one :text, Ariadne::Text
|
43
|
+
# TODO: test what hapenns with really long inbox names
|
13
44
|
|
14
45
|
attr_reader :selected
|
15
46
|
|
16
|
-
DEFAULT_CLASSES = "ariadne-border-gray-
|
17
|
-
|
18
|
-
BASE_TAB_CLASSES = "ariadne-whitespace-nowrap ariadne-py-4 ariadne-px-1 ariadne-border-b-2 ariadne-font-medium ariadne-text-sm"
|
47
|
+
DEFAULT_CLASSES = "ariadne-border-transparent ariadne-text-gray-500 hover:ariadne-text-gray-700 hover:ariadne-border-gray-300 ariadne-whitespace-nowrap ariadne-py-4 ariadne-px-1 ariadne-border-b-2 ariadne-font-medium ariadne-text-sm"
|
19
48
|
|
20
49
|
# @example Default
|
21
50
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
51
|
+
# <%= render(Ariadne::TabComponent.new(id: "pub-comment")) do |tab| %>
|
52
|
+
# <% tab.text { "Public comment" } %>
|
53
|
+
# <% tab.panel { "Public comment panel" } %>
|
54
|
+
# <% end %>
|
55
|
+
# @param id [String] The unique ID of the tab.
|
25
56
|
# @param selected [Boolean] Whether the tab is selected or not.
|
57
|
+
# @param with_panel [Boolean] Whether the Tab has an associated panel.
|
58
|
+
# @param href [String] The link to navigate to when the tab is clicked.
|
26
59
|
# @param classes [String] <%= link_to_classes_docs %>
|
27
60
|
# @param attributes [Hash] <%= link_to_attributes_docs %>
|
28
|
-
def initialize(
|
29
|
-
@
|
61
|
+
def initialize(id: nil, selected: false, with_panel: false, href: "", classes: "", attributes: {})
|
62
|
+
@id = id
|
63
|
+
|
64
|
+
@href = href
|
65
|
+
@selected = selected
|
66
|
+
|
30
67
|
@classes = class_names(
|
31
68
|
DEFAULT_CLASSES,
|
32
|
-
classes
|
69
|
+
classes,
|
33
70
|
)
|
34
71
|
|
35
72
|
@attributes = attributes
|
36
|
-
@attributes[:id] ||=
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
73
|
+
@attributes[:id] ||= @id
|
74
|
+
|
75
|
+
if with_panel # TODO: test
|
76
|
+
if @id.blank?
|
77
|
+
raise ArgumentError, "Tabs with panels must have a unique `id`"
|
78
|
+
end
|
79
|
+
|
80
|
+
@tag = :button
|
81
|
+
@system_arguments[:tag] = :button
|
82
|
+
@system_arguments[:type] = :button
|
83
|
+
@system_arguments[:role] = :tab
|
84
|
+
@panel_id = "panel-#{@id}"
|
85
|
+
@attributes[:"aria-controls"] = @panel_id
|
86
|
+
# https://www.w3.org/TR/wai-aria-practices/#presentation_role
|
87
|
+
@wrapper_arguments[:role] = :presentation
|
88
|
+
else
|
89
|
+
@tag = :a
|
90
|
+
end
|
91
|
+
|
92
|
+
return unless @selected
|
93
|
+
|
94
|
+
if @tag == :a
|
95
|
+
aria_current = aria("current", attributes) || DEFAULT_ARIA_CURRENT_FOR_ANCHOR
|
96
|
+
@attributes[:"aria-current"] = fetch_or_raise(ARIA_CURRENT_OPTIONS_FOR_ANCHOR, aria_current)
|
97
|
+
else
|
98
|
+
@attributes[:"aria-selected"] = true
|
99
|
+
end
|
41
100
|
end
|
42
101
|
end
|
43
102
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) do |component| %>
|
2
|
+
<div role="tablist">
|
3
|
+
<% tabs.each do |tab| %>
|
4
|
+
<%= tab %>
|
5
|
+
<% end %>
|
6
|
+
</div>
|
7
|
+
<% tabs.each do |tab| %>
|
8
|
+
<div class="ariadne-pt-2">
|
9
|
+
<%= tab.panel %>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
12
|
+
<% end %>
|