ariadne_view_components 0.0.13 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/ariadne_view_components.css +2355 -0
  3. data/app/assets/javascripts/ariadne_view_components.js +2 -2
  4. data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
  5. data/app/assets/javascripts/comment-component.d.ts +1 -2
  6. data/app/assets/stylesheets/ariadne_view_components.css +1 -0
  7. data/app/assets/stylesheets/dropdown.css +46 -0
  8. data/app/assets/stylesheets/tooltip-component.css +8 -8
  9. data/app/components/ariadne/ariadne-form-with.d.ts +20 -0
  10. data/app/components/ariadne/ariadne-form-with.js +85 -0
  11. data/app/components/ariadne/ariadne-form.d.ts +22 -0
  12. data/app/components/ariadne/ariadne-form.js +84 -0
  13. data/app/components/ariadne/ariadne.d.ts +2 -0
  14. data/app/components/ariadne/ariadne.js +16 -0
  15. data/app/components/ariadne/ariadne.ts +0 -2
  16. data/app/components/ariadne/avatar_component.rb +81 -0
  17. data/app/components/ariadne/avatar_stack_component.html.erb +12 -0
  18. data/app/components/ariadne/avatar_stack_component.rb +75 -0
  19. data/app/components/ariadne/base_button.rb +13 -4
  20. data/app/components/ariadne/blankslate_component.rb +4 -4
  21. data/app/components/ariadne/body_component.rb +1 -1
  22. data/app/components/ariadne/button_component.html.erb +1 -1
  23. data/app/components/ariadne/button_component.rb +9 -3
  24. data/app/components/ariadne/clipboard-copy-component.d.ts +4 -0
  25. data/app/components/ariadne/clipboard-copy-component.js +18 -0
  26. data/app/components/ariadne/clipboard_copy_component.d.ts +4 -0
  27. data/app/components/ariadne/clipboard_copy_component.js +18 -0
  28. data/app/components/ariadne/comment-component.d.ts +0 -0
  29. data/app/components/ariadne/comment-component.js +33 -0
  30. data/app/components/ariadne/comment-component.ts +32 -50
  31. data/app/components/ariadne/comment_component.html.erb +32 -10
  32. data/app/components/ariadne/comment_component.rb +17 -5
  33. data/app/components/ariadne/component.rb +0 -2
  34. data/app/components/ariadne/details_component.html.erb +4 -0
  35. data/app/components/ariadne/details_component.rb +80 -0
  36. data/app/components/ariadne/dropdown/menu_component.html.erb +20 -0
  37. data/app/components/ariadne/dropdown/menu_component.rb +101 -0
  38. data/app/components/ariadne/dropdown/menu_component.ts +1 -0
  39. data/app/components/ariadne/dropdown_component.html.erb +8 -0
  40. data/app/components/ariadne/dropdown_component.rb +172 -0
  41. data/app/components/ariadne/flex_component.rb +1 -1
  42. data/app/components/ariadne/footer_component.html.erb +1 -1
  43. data/app/components/ariadne/header_component.rb +3 -3
  44. data/app/components/ariadne/heroicon_component.rb +6 -4
  45. data/app/components/ariadne/inline_flex_component.html.erb +1 -0
  46. data/app/components/ariadne/inline_flex_component.rb +8 -1
  47. data/app/components/ariadne/link_component.rb +2 -2
  48. data/app/components/ariadne/list_component.html.erb +2 -9
  49. data/app/components/ariadne/list_component.rb +11 -15
  50. data/app/components/ariadne/pill_component.rb +19 -5
  51. data/app/components/ariadne/rich-text-area-component.d.ts +4 -0
  52. data/app/components/ariadne/rich-text-area-component.js +27 -0
  53. data/app/components/ariadne/rich-text-area-component.ts +4 -4
  54. data/app/components/ariadne/rich_text_area_component.html.erb +1 -1
  55. data/app/components/ariadne/rich_text_area_component.rb +1 -1
  56. data/app/components/ariadne/slideover-component.d.ts +9 -0
  57. data/app/components/ariadne/slideover-component.js +20 -0
  58. data/app/components/ariadne/slideover_component.d.ts +9 -0
  59. data/app/components/ariadne/slideover_component.html.erb +1 -1
  60. data/app/components/ariadne/slideover_component.js +19 -0
  61. data/app/components/ariadne/tab-component.js +1 -0
  62. data/app/components/ariadne/tab-container-component copy.d.ts +1 -0
  63. data/app/components/ariadne/tab-container-component copy.js +23 -0
  64. data/app/components/ariadne/tab-container-component.d.ts +1 -0
  65. data/app/components/ariadne/tab-container-component.js +23 -0
  66. data/app/components/ariadne/tab-container-component.ts +21 -21
  67. data/app/components/ariadne/tab-nav-component.d.ts +9 -0
  68. data/app/components/ariadne/tab-nav-component.js +32 -0
  69. data/app/components/ariadne/tab_component.rb +4 -7
  70. data/app/components/ariadne/tab_container_component.rb +8 -2
  71. data/app/components/ariadne/tab_nav_component.html.erb +1 -1
  72. data/app/components/ariadne/tab_nav_component.rb +1 -1
  73. data/app/components/ariadne/table_nav_component.html.erb +52 -0
  74. data/app/components/ariadne/table_nav_component.rb +338 -0
  75. data/app/components/ariadne/tabs-component.d.ts +0 -0
  76. data/app/components/ariadne/tabs-component.js +1 -0
  77. data/app/components/ariadne/time-ago-component.d.ts +1 -0
  78. data/app/components/ariadne/time-ago-component.js +1 -0
  79. data/app/components/ariadne/time_ago_component.d.ts +1 -0
  80. data/app/components/ariadne/time_ago_component.js +1 -0
  81. data/app/components/ariadne/tooltip-component.d.ts +24 -0
  82. data/app/components/ariadne/tooltip-component.js +42 -0
  83. data/app/components/ariadne/tooltip_component.html.erb +1 -1
  84. data/app/components/ariadne/tooltip_component.rb +4 -4
  85. data/app/lib/ariadne/action_view_extensions/form_helper.rb +21 -7
  86. data/app/lib/ariadne/form_builder.rb +4 -4
  87. data/lib/ariadne/view_components/version.rb +1 -1
  88. data/lib/tasks/docs.rake +19 -4
  89. data/static/arguments.yml +103 -22
  90. data/static/audited_at.json +15 -8
  91. data/static/classes.yml +51 -47
  92. data/static/constants.json +180 -55
  93. data/static/statuses.json +15 -8
  94. data/tailwind.config.js +25 -1
  95. metadata +53 -9
  96. data/app/components/ariadne/main_component.rb +0 -32
  97. data/app/components/ariadne/table_component.html.erb +0 -17
  98. data/app/components/ariadne/table_component.rb +0 -281
@@ -9,6 +9,7 @@ module Ariadne
9
9
  LINK_SCHEME = :link
10
10
 
11
11
  SCHEME_CLASS_MAPPINGS = {
12
+ link: Ariadne::LinkComponent::DEFAULT_ACTIONABLE_CLASSES,
12
13
  none: "",
13
14
  default: "ariadne-text-purple-800 ariadne-bg-purple-50 hover:ariadne-bg-purple-100 ariadne-border-purple-300 focus:ariadne-ring-offset-purple-50 focus:ariadne-ring-purple-600",
14
15
  info: "ariadne-text-blue-800 ariadne-bg-blue-50 hover:ariadne-bg-blue-100 ariadne-border-blue-300 focus:ariadne-ring-offset-blue-50 focus:ariadne-ring-blue-600",
@@ -109,10 +110,10 @@ module Ariadne
109
110
  # <% end %>
110
111
  #
111
112
  # @param tag [Symbol] <%= one_of(Ariadne::BaseButton::TAG_OPTIONS) %>
112
- # @param type [Symbol] <%= one_of(Ariadne::BaseButton::TYPE_OPTIONS) %>
113
+ # @param type [Symbol] <%= one_of(Ariadne::BaseButton::VALID_TYPES) %>
113
114
  # @param scheme [Symbol] <%= one_of(Ariadne::ButtonComponent::VALID_SCHEMES) %>
114
115
  # @param size [Symbol] <%= one_of(Ariadne::BaseButton::VALID_SIZES) %>
115
- # @param type [Symbol] <%= one_of(Ariadne::BaseButton::TYPE_OPTIONS) %>
116
+ # @param dropdown [Boolean] Whether or not to render a dropdown caret.
116
117
  # @param classes [String] <%= link_to_classes_docs %>
117
118
  # @param attributes [Hash] <%= link_to_attributes_docs %>
118
119
  def initialize(
@@ -120,18 +121,19 @@ module Ariadne
120
121
  type: Ariadne::BaseButton::DEFAULT_TYPE,
121
122
  scheme: DEFAULT_SCHEME,
122
123
  size: BaseButton::DEFAULT_SIZE,
124
+ dropdown: false,
123
125
  classes: "",
124
126
  attributes: {}
125
127
  )
126
128
  @tag = tag
127
129
  @type = type
128
- @scheme = scheme
129
130
 
130
131
  @attributes = attributes
131
132
  @id = @attributes[:id]
132
133
 
133
134
  @size = fetch_or_raise(Ariadne::BaseButton::VALID_SIZES, size)
134
135
  @scheme = fetch_or_raise(VALID_SCHEMES, scheme)
136
+ @scheme = LINK_SCHEME if @tag == :a
135
137
 
136
138
  @classes = class_names(
137
139
  SCHEME_CLASS_MAPPINGS[@scheme],
@@ -139,6 +141,10 @@ module Ariadne
139
141
  )
140
142
  end
141
143
 
144
+ private def dropdown?
145
+ @dropdown
146
+ end
147
+
142
148
  private def trimmed_content
143
149
  return if content.blank?
144
150
 
@@ -0,0 +1,4 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class ClipboardCopyComponent extends Controller {
3
+ copy(): void;
4
+ }
@@ -0,0 +1,18 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class ClipboardCopyComponent extends Controller {
3
+ copy() {
4
+ const value = this.element.attributes.getNamedItem('value');
5
+ const forNode = this.element.attributes.getNamedItem('for');
6
+ if (value) {
7
+ navigator.clipboard.writeText(value.value);
8
+ }
9
+ else if (forNode) {
10
+ const node = document.getElementById(forNode.value);
11
+ navigator.clipboard.writeText((node === null || node === void 0 ? void 0 : node.textContent) || '');
12
+ }
13
+ else {
14
+ // just copy inner text
15
+ navigator.clipboard.writeText(this.element.textContent || '');
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,4 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class ClipboardCopyComponent extends Controller {
3
+ copy(): void;
4
+ }
@@ -0,0 +1,18 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class ClipboardCopyComponent extends Controller {
3
+ copy() {
4
+ const value = this.element.attributes.getNamedItem('value');
5
+ const forNode = this.element.attributes.getNamedItem('for');
6
+ if (value) {
7
+ navigator.clipboard.writeText(value.value);
8
+ }
9
+ else if (forNode) {
10
+ const node = document.getElementById(forNode.value);
11
+ navigator.clipboard.writeText((node === null || node === void 0 ? void 0 : node.textContent) || '');
12
+ }
13
+ else {
14
+ // just copy inner text
15
+ navigator.clipboard.writeText(this.element.textContent || '');
16
+ }
17
+ }
18
+ }
File without changes
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ // import {Controller} from '@hotwired/stimulus'
3
+ // export default class CommentComponent extends Controller {
4
+ // static targets = ['tab', 'tabBarComponent']
5
+ // declare readonly commentComponentTarget: HTMLDivElement
6
+ // declare readonly tabBarComponentTarget: HTMLElement // technically a `nav but typescript can't find it?
7
+ // declare readonly tabTargets: [HTMLButtonElement]
8
+ // // keep in sync with comment_component.rb
9
+ // SELECTED_TAB_CLASSES = ['ariadne-border-indigo-500', 'ariadne-text-indigo-600']
10
+ // PUBLIC_BACKGROUND_COLOR = 'ariadne-bg-white'
11
+ // INTERNAL_BACKGROUND_COLOR = 'ariadne-bg-internal-message'
12
+ // toggleTab() {
13
+ // for (const tab of this.tabTargets) {
14
+ // if (tab.hasAttribute('aria-selected')) {
15
+ // tab.classList.remove(...this.SELECTED_TAB_CLASSES)
16
+ // this.toggleBackgrounds(tab, false)
17
+ // tab.removeAttribute('aria-selected')
18
+ // } else {
19
+ // tab.setAttribute('aria-selected', 'true')
20
+ // tab.classList.add(...this.SELECTED_TAB_CLASSES)
21
+ // this.toggleBackgrounds(tab, true)
22
+ // }
23
+ // }
24
+ // }
25
+ // toggleBackgrounds(tab: HTMLButtonElement, publicComment: boolean) {
26
+ // if (publicComment) {
27
+ // this.tabBarComponentTarget.classList.add(this.PUBLIC_BACKGROUND_COLOR)
28
+ // this.tabBarComponentTarget.classList.remove(this.INTERNAL_BACKGROUND_COLOR)
29
+ // this.tabBarComponentTarget.classList.remove(this.PUBLIC_BACKGROUND_COLOR)
30
+ // this.tabBarComponentTarget.classList.add(this.INTERNAL_BACKGROUND_COLOR)
31
+ // }
32
+ // }
33
+ // }
@@ -1,55 +1,37 @@
1
- import {Controller} from '@hotwired/stimulus'
1
+ // import {Controller} from '@hotwired/stimulus'
2
2
 
3
- export default class CommentComponent extends Controller {
4
- static targets = ['tab', 'tabBarComponent']
3
+ // export default class CommentComponent extends Controller {
4
+ // static targets = ['tab', 'tabBarComponent']
5
5
 
6
- declare readonly commentComponentTarget: HTMLDivElement
7
- declare readonly tabBarComponentTarget: HTMLElement // technically a `nav but typescript can't find it?
8
- declare readonly tabTargets: [HTMLButtonElement]
6
+ // declare readonly commentComponentTarget: HTMLDivElement
7
+ // declare readonly tabBarComponentTarget: HTMLElement // technically a `nav but typescript can't find it?
8
+ // declare readonly tabTargets: [HTMLButtonElement]
9
9
 
10
- SELECTED_TAB_CLASSES = ['ariadne-border-indigo-500', 'ariadne-text-indigo-600']
11
- PUBLIC_BACKGROUND_COLOR = 'ariadne-bg-white'
12
- INTERNAL_BACKGROUND_COLOR = 'ariadne-bg-internal-message'
10
+ // // keep in sync with comment_component.rb
11
+ // SELECTED_TAB_CLASSES = ['ariadne-border-indigo-500', 'ariadne-text-indigo-600']
12
+ // PUBLIC_BACKGROUND_COLOR = 'ariadne-bg-white'
13
+ // INTERNAL_BACKGROUND_COLOR = 'ariadne-bg-internal-message'
13
14
 
14
- connect() {
15
- for (const tab of this.tabTargets) {
16
- if (tab.hasAttribute('selected')) {
17
- tab.classList.add(...this.SELECTED_TAB_CLASSES)
18
- }
19
- }
20
- }
15
+ // toggleTab() {
16
+ // for (const tab of this.tabTargets) {
17
+ // if (tab.hasAttribute('aria-selected')) {
18
+ // tab.classList.remove(...this.SELECTED_TAB_CLASSES)
19
+ // this.toggleBackgrounds(tab, false)
20
+ // tab.removeAttribute('aria-selected')
21
+ // } else {
22
+ // tab.setAttribute('aria-selected', 'true')
23
+ // tab.classList.add(...this.SELECTED_TAB_CLASSES)
24
+ // this.toggleBackgrounds(tab, true)
25
+ // }
26
+ // }
27
+ // }
28
+ // toggleBackgrounds(tab: HTMLButtonElement, publicComment: boolean) {
29
+ // if (publicComment) {
30
+ // this.tabBarComponentTarget.classList.add(this.PUBLIC_BACKGROUND_COLOR)
31
+ // this.tabBarComponentTarget.classList.remove(this.INTERNAL_BACKGROUND_COLOR)
21
32
 
22
- toggleTab() {
23
- for (const tab of this.tabTargets) {
24
- if (tab.hasAttribute('selected')) {
25
- tab.removeAttribute('selected')
26
- tab.classList.remove(...this.SELECTED_TAB_CLASSES)
27
- this.toggleBackgrounds(tab)
28
- } else {
29
- tab.setAttribute('selected', 'true')
30
- tab.classList.add(...this.SELECTED_TAB_CLASSES)
31
- this.toggleBackgrounds(tab)
32
- if (tab.hasAttribute('data-public')) {
33
- document.getElementById('message_public')?.setAttribute('value', 'true')
34
- } else {
35
- document.getElementById('message_public')?.setAttribute('value', 'false')
36
- }
37
- }
38
- }
39
- }
40
- toggleBackgrounds(tab: HTMLButtonElement) {
41
- if (tab.hasAttribute('selected')) {
42
- if (tab.hasAttribute('data-public')) {
43
- // this.commentComponentTarget.classList.add(this.PUBLIC_BACKGROUND_COLOR)
44
- // this.commentComponentTarget.classList.remove(this.INTERNAL_BACKGROUND_COLOR)
45
- this.tabBarComponentTarget.classList.add(this.PUBLIC_BACKGROUND_COLOR)
46
- this.tabBarComponentTarget.classList.remove(this.INTERNAL_BACKGROUND_COLOR)
47
- } else {
48
- // this.commentComponentTarget.classList.remove(this.PUBLIC_BACKGROUND_COLOR)
49
- // this.commentComponentTarget.classList.add(this.INTERNAL_BACKGROUND_COLOR)
50
- this.tabBarComponentTarget.classList.remove(this.PUBLIC_BACKGROUND_COLOR)
51
- this.tabBarComponentTarget.classList.add(this.INTERNAL_BACKGROUND_COLOR)
52
- }
53
- }
54
- }
55
- }
33
+ // this.tabBarComponentTarget.classList.remove(this.PUBLIC_BACKGROUND_COLOR)
34
+ // this.tabBarComponentTarget.classList.add(this.INTERNAL_BACKGROUND_COLOR)
35
+ // }
36
+ // }
37
+ // }
@@ -2,17 +2,39 @@
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::TabContainerComponent.new(sr_label: @sr_label)) do |tab_container| %>
6
+ <%= tab_container.tab(id: public_tab.id, selected: public_tab.selected, classes: public_tab.classes, attributes: public_tab.attributes) do |tab| %>
7
+ <% tab.text { @public_tab_text } %>
8
+ <% tab.panel do %>
9
+ <%= ariadne_form_with(url: @url, method: @method, classes: @classes, attributes: @attributes) do |comment_box| %>
10
+ <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">
11
+ <%= hidden_field_tag 'message_public', true %>
12
+ <%= render(Ariadne::RichTextAreaComponent.new(name: :bodytext, sr_label: "Select reply type", attributes: { required: true})) %>
13
+ <% comment_box.submit { @submit } %>
14
+ </div>
15
+ <div class="ariadne-mt-2 ariadne-flex ariadne-justify-end">
16
+ <%= submit %>
17
+ </div>
18
+ <% end %>
19
+ <% end %>
20
+ <% end %>
21
+ <%= tab_container.tab(id: internal_tab.id, selected: internal_tab.selected, classes: internal_tab.classes, attributes: internal_tab.attributes) do |tab| %>
22
+ <% tab.text { @internal_tab_text } %>
23
+ <% tab.panel do %>
24
+ <%= ariadne_form_with(url: @url, method: @method, classes: @classes, attributes: @attributes) do |comment_box| %>
25
+ <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">
26
+ <%= hidden_field_tag 'message_public', false %>
27
+ <%= render(Ariadne::RichTextAreaComponent.new(name: :bodytext, sr_label: "Select reply type", attributes: { required: true})) %>
28
+ <% comment_box.submit { @submit } %>
29
+ </div>
30
+ <div class="ariadne-mt-2 ariadne-flex ariadne-justify-end">
31
+ <%= submit %>
32
+ </div>
33
+ <% end %>
34
+ <% end %>
35
+ <% end %>
36
+ <% end %>
5
37
  </div>
6
38
  </div>
7
- <%= ariadne_form_with(url: @url, method: @method, classes: @classes, attributes: @attributes) do |comment_box| %>
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">
9
- <%= hidden_field_tag 'message_public', true %>
10
- <%= render(Ariadne::RichTextAreaComponent.new(name: :bodytext, sr_label: "Select reply type", attributes: { required: true})) %>
11
- <% comment_box.submit { @submit } %>
12
- </div>
13
- <div class="ariadne-mt-2 ariadne-flex ariadne-justify-end">
14
- <%= submit %>
15
- </div>
16
- <% end %>
17
39
  </div>
18
40
  <% end %>
@@ -2,6 +2,10 @@
2
2
 
3
3
  module Ariadne
4
4
  # Defines a submittable form for adding comments to a conversation.
5
+ #
6
+ #
7
+ # Requires JavaScript. Set `data-comment-component-selected-class` to the class name that will be applied to the
8
+ # selected tab.
5
9
  # @accessibility This component requires you to pass in a `sr_label`
6
10
  # attribute, which will be used to label the tabs for screen readers.
7
11
  class CommentComponent < Ariadne::Component
@@ -12,17 +16,21 @@ module Ariadne
12
16
 
13
17
  renders_one :public_tab, lambda { |selected: false, text:, classes: "", attributes: {}|
14
18
  attributes[:"data-comment-component-target"] ||= "tab"
15
- attributes[:"data-action"] ||= "click->comment-component#toggleTab"
16
19
  attributes[:"data-public"] = true
17
20
  @tab_idx += 1
18
- render(Ariadne::TabComponent.new(selected: selected, classes: classes, attributes: attributes)) { text }
21
+ id = attributes.fetch(:id, "public-tab-#{@tab_idx}")
22
+ @public_tab_text = text
23
+
24
+ Ariadne::TabComponent.new(selected: selected, classes: classes, id: id, with_panel: true, attributes: attributes)
19
25
  }
20
26
 
21
27
  renders_one :internal_tab, lambda { |selected: false, text:, classes: "", attributes: {}|
22
28
  attributes[:"data-comment-component-target"] ||= "tab"
23
- attributes[:"data-action"] ||= "click->comment-component#toggleTab"
24
29
  @tab_idx += 1
25
- render(Ariadne::TabComponent.new(selected: selected, classes: classes, attributes: attributes)) { text }
30
+ id = attributes.fetch(:id, "internal-tab-#{@tab_idx}")
31
+ @internal_tab_text = text
32
+
33
+ Ariadne::TabComponent.new(selected: selected, classes: classes, id: id, with_panel: true, attributes: attributes)
26
34
  }
27
35
 
28
36
  renders_one :submit, lambda { |classes: "", attributes: {}|
@@ -31,7 +39,11 @@ module Ariadne
31
39
 
32
40
  # @example Default
33
41
  #
34
- # <%= render(Ariadne::CommentComponent.new(url: "/messages", method: :post, sr_label: "Select delivery time")) { "Example" } %>
42
+ # <%= render(Ariadne::CommentComponent.new(url: "/messages", method: :post, sr_label: "Select delivery time")) do |comment| %>
43
+ # <% comment.public_tab(selected: true, text: "Reply to sender") %>
44
+ # <% comment.internal_tab(text: "Internal comment") %>
45
+ # <% comment.submit { "Send" } %>
46
+ # <% end %>
35
47
  #
36
48
  # @param url [String] The URL to take action against.
37
49
  # @param method [String] The method to use when submitting the form.
@@ -16,8 +16,6 @@ module Ariadne
16
16
  include LoggerHelper
17
17
  include Ariadne::ActionViewExtensions::FormHelper
18
18
 
19
- BASE_HTML_CLASSES = "ariadne-h-full ariadne-scroll-smooth ariadne-bg-white ariadne-antialiased"
20
- BASE_BODY_CLASSES = "ariadne-flex ariadne-h-full ariadne-flex-col"
21
19
  BASE_WRAPPER_CLASSES = "ariadne-flex ariadne-flex-col ariadne-h-screen ariadne-justify-between"
22
20
  BASE_MAIN_CLASSES = "ariadne-flex-auto"
23
21
 
@@ -0,0 +1,4 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |component| %>
2
+ <%= summary %>
3
+ <%= body %>
4
+ <% end %>
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Use `DetailsComponent` to reveal content after clicking a button.
5
+ class DetailsComponent < Ariadne::Component
6
+ DEFAULT_TAG = :details
7
+ DEFAULT_BODY_TAG = :div
8
+
9
+ VALID_BODY_TAGS = [:ul, :"details-menu", :"details-dialog", DEFAULT_BODY_TAG].freeze
10
+
11
+ NO_OVERLAY = :none
12
+ OVERLAY_MAPPINGS = {
13
+ NO_OVERLAY => "",
14
+ :default => "",
15
+ }.freeze
16
+
17
+ # Use the Summary as a trigger to reveal the content.
18
+ #
19
+ # @param button [Boolean] (true) Whether to render the Summary as a button or not.
20
+ # @param classes [String] <%= link_to_classes_docs %>
21
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
22
+ renders_one :summary, lambda { |button: true, classes: "", attributes: {}|
23
+ tag = :summary
24
+ attributes[:role] = "button"
25
+
26
+ return Ariadne::BaseComponent.new(tag: tag, classes: classes, attributes: attributes) unless button
27
+
28
+ Ariadne::Content.new
29
+ }
30
+
31
+ DEFAULT_BODY_CLASSES = "ariadne-absolute ariadne-right-0 ariadne-z-10 ariadne-mt-2 ariadne-w-56 ariadne-origin-top-right ariadne-divide-y ariadne-divide-gray-100 ariadne-rounded-md ariadne-bg-white ariadne-shadow-lg ariadne-ring-1 ariadne-ring-black ariadne-ring-opacity-5 focus:ariadne-outline-none"
32
+ # Use the Body slot as the main content to be shown when triggered by the Summary.
33
+ #
34
+ # @param tag [Symbol] The tag to use for the body/ <%= one_of(Ariadne::DetailsComponent::VALID_BODY_TAGS) %>
35
+ # @param classes [String] <%= link_to_classes_docs %>
36
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
37
+ renders_one :body, lambda { |tag: DEFAULT_BODY_TAG, classes: "", attributes: {}|
38
+ tag = fetch_or_raise(VALID_BODY_TAGS, tag)
39
+ actual_classes = class_names(DEFAULT_BODY_CLASSES, classes)
40
+
41
+ Ariadne::BaseComponent.new(tag: tag, classes: actual_classes, attributes: attributes)
42
+ }
43
+
44
+ DEFAULT_CLASSES = ""
45
+
46
+ # @example Default
47
+ #
48
+ # <%= render Ariadne::DetailsComponent.new do |c| %>
49
+ # <% c.summary do %>
50
+ # Summary
51
+ # <% end %>
52
+ # <% c.body do %>
53
+ # Body
54
+ # <% end %>
55
+ # <% end %>
56
+ #
57
+ # @param overlay [Symbol] Dictates the type of overlay to render with. <%= one_of(Ariadne::DetailsComponent::OVERLAY_MAPPINGS.keys) %>
58
+ # @param reset [Boolean] If set to true, it will remove the default caret and remove style from the summary element
59
+ # @param classes [String] <%= link_to_classes_docs %>
60
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
61
+ def initialize(overlay: NO_OVERLAY, reset: false, classes: "", attributes: {})
62
+ @tag = DEFAULT_TAG
63
+ @reset = reset
64
+
65
+ @classes = class_names(
66
+ DEFAULT_CLASSES,
67
+ classes,
68
+ @reset ? "ariadne__details-reset" : "",
69
+ )
70
+
71
+ @attributes = attributes
72
+
73
+ @overlay = fetch_or_raise(OVERLAY_MAPPINGS.keys, overlay)
74
+ end
75
+
76
+ def render?
77
+ true # summary.present? && body.present?
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,20 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |component| %>
2
+ <%= header %>
3
+ <% if list? %>
4
+ <ul>
5
+ <% items.each do |item| %>
6
+ <% if item.divider? %>
7
+ <%= item %>
8
+ <% else %>
9
+ <li>
10
+ <%= item %>
11
+ </li>
12
+ <% end %>
13
+ <% end %>
14
+ </ul>
15
+ <% else %>
16
+ <% items.each do |item| %>
17
+ <%= item %>
18
+ <% end %>
19
+ <% end %>
20
+ <% end %>
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ module Dropdown
5
+ # This component is part of `DropdownComponent` and should not be
6
+ # used as a standalone component.
7
+ class MenuComponent < Ariadne::Component
8
+ DEFAULT_AS_OPTION = :default
9
+ VALID_AS_OPTIONS = [DEFAULT_AS_OPTION, :list].freeze
10
+
11
+ DEFAULT_DIRECTION = :se
12
+ VALID_DIRECTIONS = [DEFAULT_DIRECTION, :sw, :w, :e, :ne, :s].freeze
13
+
14
+ DEFAULT_HEADER_CLASSES = "ariadne-text-sm ariadne-font-medium ariadne-text-gray-900"
15
+ # @param classes [String] <%= link_to_classes_docs %>
16
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
17
+ renders_one :header, lambda { |classes: "", attributes: {}|
18
+ actual_classes = class_names(DEFAULT_HEADER_CLASSES, classes)
19
+ Ariadne::BaseComponent.new(tag: :span, classes: actual_classes, attributes: attributes)
20
+ }
21
+
22
+ # @param tag [Boolean] <%= one_of(Ariadne::Dropdown::MenuComponent::Item::VALID_TAGS) %>.
23
+ # @param divider [Boolean] Whether the item is a divider without any function.
24
+ # @param classes [String] <%= link_to_classes_docs %>
25
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
26
+ renders_many :items, lambda { |tag: Ariadne::Dropdown::MenuComponent::Item::DEFAULT_TAG, divider: false, classes: "", attributes: {}|
27
+ Ariadne::Dropdown::MenuComponent::Item.new(tag: tag, as: @as, divider: divider, classes: classes, attributes: attributes)
28
+ }
29
+
30
+ DEFAULT_TAG = :"details-menu"
31
+ TAG_OPTIONS = [DEFAULT_TAG].freeze
32
+
33
+ DEFAULT_CLASSES = ""
34
+
35
+ # @param as [Symbol] When `as` is `:list`, wraps the menu in a `<ul>` with a `<li>` for each item.
36
+ # @param direction [Symbol] <%= one_of(Ariadne::Dropdown::MenuComponent::VALID_DIRECTIONS) %>.
37
+ # @param classes [String] <%= link_to_classes_docs %>
38
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
39
+ def initialize(as: DEFAULT_AS_OPTION, direction: VALID_DIRECTIONS, classes: "", attributes: {})
40
+ @tag = DEFAULT_TAG
41
+ @classes = class_names(
42
+ DEFAULT_CLASSES,
43
+ classes,
44
+ )
45
+
46
+ @attributes = attributes
47
+
48
+ @direction = direction
49
+ @as = fetch_or_raise(VALID_AS_OPTIONS, as)
50
+
51
+ @attributes[:role] = "menu"
52
+ end
53
+
54
+ private def list?
55
+ @as == :list
56
+ end
57
+
58
+ # Items to be rendered in the `Dropdown` menu.
59
+ class Item < Ariadne::Component
60
+ DEFAULT_TAG = :a
61
+ BUTTON_TAGS = [:button, :summary].freeze
62
+ VALID_TAGS = [DEFAULT_TAG, *BUTTON_TAGS].freeze
63
+
64
+ DEFAULT_ITEM_CLASSES = "ariadne-block ariadne-px-4 ariadne-py-2 ariadne-text-sm ariadne-text-gray-700"
65
+
66
+ def initialize(as:, tag: DEFAULT_TAG, divider: false, classes: "", attributes: {})
67
+ @divider = divider
68
+ @as = as
69
+
70
+ @classes = class_names(DEFAULT_ITEM_CLASSES, classes)
71
+ @attributes = attributes
72
+ @tag = fetch_or_raise(VALID_TAGS, tag)
73
+ @tag = :li if list? && divider?
74
+ @attributes[:role] ||= :menuitem
75
+ @attributes[:role] = :separator if @divider
76
+ end
77
+
78
+ def call
79
+ component = if BUTTON_TAGS.include?(@tag)
80
+ Ariadne::ButtonComponent.new(scheme: Ariadne::ButtonComponent::LINK_SCHEME, classes: @classes, attributes: @attributes)
81
+ else
82
+ Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)
83
+ end
84
+
85
+ # divider has no content
86
+ render(component) if divider?
87
+
88
+ render(component) { content }
89
+ end
90
+
91
+ def divider?
92
+ @divider
93
+ end
94
+
95
+ def list?
96
+ @as == :list
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1 @@
1
+ import '@github/details-menu-element'
@@ -0,0 +1,8 @@
1
+ <%= render(Ariadne::DetailsComponent.new(classes: @classes, attributes: @attributes)) do |c| %>
2
+ <% c.summary(classes: @button_classes, attributes: @button_attributes) do %>
3
+ <%= button %>
4
+ <% end %>
5
+ <% c.body do %>
6
+ <%= menu %>
7
+ <% end %>
8
+ <% end %>