ariadne_view_components 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/builds/ariadne_view_components.css +1874 -0
  4. data/app/assets/javascripts/ariadne.d.ts +1 -0
  5. data/app/assets/javascripts/ariadne_view_components.js +1 -1
  6. data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
  7. data/app/assets/javascripts/clipboard-copy-component.d.ts +4 -0
  8. data/app/assets/javascripts/slideover-component.d.ts +9 -0
  9. data/app/assets/javascripts/time_ago_component.d.ts +1 -0
  10. data/app/assets/javascripts/tooltip-component.d.ts +24 -0
  11. data/app/assets/stylesheets/application.ariadne_view_components.css +5 -3
  12. data/app/assets/stylesheets/tooltip-component.css +37 -0
  13. data/app/components/ariadne/ariadne.d.ts +1 -0
  14. data/app/components/ariadne/ariadne.js +9 -0
  15. data/app/components/ariadne/ariadne.ts +3 -0
  16. data/app/components/ariadne/base_button.rb +9 -8
  17. data/app/components/ariadne/blankslate_component.rb +1 -1
  18. data/app/components/ariadne/body_component.rb +30 -0
  19. data/app/components/ariadne/button_component.rb +5 -10
  20. data/app/components/ariadne/clipboard-copy-component.d.ts +4 -0
  21. data/app/components/ariadne/clipboard-copy-component.js +18 -0
  22. data/app/components/ariadne/clipboard_copy_component.d.ts +4 -0
  23. data/app/components/ariadne/clipboard_copy_component.html.erb +2 -2
  24. data/app/components/ariadne/clipboard_copy_component.js +18 -0
  25. data/app/components/ariadne/clipboard_copy_component.rb +41 -3
  26. data/app/components/ariadne/comment_component.html.erb +25 -0
  27. data/app/components/ariadne/comment_component.rb +45 -0
  28. data/app/components/ariadne/component.rb +2 -1
  29. data/app/components/ariadne/container_component.rb +1 -1
  30. data/app/components/ariadne/flash_component.rb +1 -1
  31. data/app/components/ariadne/flex_component.rb +51 -0
  32. data/app/components/ariadne/grid_component.html.erb +12 -3
  33. data/app/components/ariadne/grid_component.rb +18 -7
  34. data/app/components/ariadne/header_component.rb +1 -1
  35. data/app/components/ariadne/heading_component.rb +2 -2
  36. data/app/components/ariadne/heroicon_component.html.erb +4 -6
  37. data/app/components/ariadne/heroicon_component.rb +18 -7
  38. data/app/components/ariadne/inline_flex_component.rb +11 -9
  39. data/app/components/ariadne/link_component.rb +13 -8
  40. data/app/components/ariadne/list_component.html.erb +5 -7
  41. data/app/components/ariadne/list_component.rb +4 -34
  42. data/app/components/ariadne/main_component.rb +32 -0
  43. data/app/components/ariadne/slideover-component.d.ts +9 -0
  44. data/app/components/ariadne/slideover-component.js +20 -0
  45. data/app/components/ariadne/slideover_component.d.ts +9 -0
  46. data/app/components/ariadne/slideover_component.html.erb +1 -4
  47. data/app/components/ariadne/slideover_component.js +19 -0
  48. data/app/components/ariadne/slideover_component.rb +19 -15
  49. data/app/components/ariadne/time_ago_component.d.ts +1 -0
  50. data/app/components/ariadne/time_ago_component.js +1 -0
  51. data/app/components/ariadne/tooltip-component.d.ts +24 -0
  52. data/app/components/ariadne/tooltip-component.js +42 -0
  53. data/app/components/ariadne/tooltip-component.ts +57 -0
  54. data/app/components/ariadne/tooltip_component.html.erb +4 -0
  55. data/app/components/ariadne/tooltip_component.rb +34 -31
  56. data/app/lib/ariadne/form_builder.rb +14 -14
  57. data/lib/ariadne/classify.rb +4 -98
  58. data/lib/ariadne/view_components/version.rb +1 -1
  59. data/lib/ariadne/view_components.rb +31 -29
  60. data/lib/rubocop/cop/ariadne/ariadne_heroicon.rb +2 -2
  61. data/lib/tasks/docs.rake +4 -0
  62. data/static/arguments.yml +89 -13
  63. data/static/audited_at.json +4 -0
  64. data/static/classes.yml +40 -8
  65. data/static/constants.json +83 -101
  66. data/static/statuses.json +4 -0
  67. metadata +48 -6
@@ -6,15 +6,19 @@ module Ariadne
6
6
  # `Heroicon` renders an <%= link_to_heroicons %> with <%= link_to_attributes_docs %>.
7
7
  # `Heroicon` can also be rendered with the `heroicon` helper.
8
8
  class HeroiconComponent < Ariadne::Component
9
+ DEFAULT_TEXT_CLASSES = "pl-2"
10
+
9
11
  include IconHelper
10
12
  include HeroiconsHelper
11
13
 
12
- SIZE_DEFAULT = :s
13
- SIZE_MEDIUM = :m
14
+ SIZE_DEFAULT = :sm
15
+ SIZE_MEDIUM = :md
16
+ SIZE_LARGE = :lg
14
17
 
15
18
  SIZE_MAPPINGS = {
16
19
  SIZE_DEFAULT => 16,
17
20
  SIZE_MEDIUM => 24,
21
+ SIZE_LARGE => 128,
18
22
  }.freeze
19
23
  SIZE_OPTIONS = SIZE_MAPPINGS.keys
20
24
 
@@ -62,7 +66,7 @@ module Ariadne
62
66
  # <%= render(Ariadne::HeroiconComponent.new(icon: :check, variant: HeroiconsHelper::Icon::VARIANT_SOLID)) %>
63
67
  #
64
68
  # @example Medium
65
- # <%= render(Ariadne::HeroiconComponent.new(icon: :"user-group", variant: HeroiconsHelper::Icon::VARIANT_OUTLINE, size: :m)) %>
69
+ # <%= render(Ariadne::HeroiconComponent.new(icon: :"user-group", variant: HeroiconsHelper::Icon::VARIANT_OUTLINE, size: :md)) %>
66
70
  #
67
71
  # @example Helper
68
72
  # <%= ariadne_heroicon(icon: :check, variant: HeroiconsHelper::Icon::VARIANT_OUTLINE) %>
@@ -73,7 +77,9 @@ module Ariadne
73
77
  # @param variant [String] <%= one_of(HeroiconsHelper::Icon::VARIANTS, sort: false) %>
74
78
  # @param size [Symbol] <%= one_of(Ariadne::HeroiconComponent::SIZE_MAPPINGS, sort: false) %>
75
79
  # @param attributes [Hash] <%= link_to_attributes_docs %>
76
- def initialize(tag: :svg, icon:, variant:, size: SIZE_DEFAULT, classes: "", attributes: {})
80
+ # @param text_classes [String] <%= link_to_classes_docs %>
81
+ # @param text_attributes [Hash] <%= link_to_attributes_docs %>
82
+ def initialize(tag: :svg, icon:, variant:, size: SIZE_DEFAULT, classes: "", attributes: {}, text_classes: "", text_attributes: {})
77
83
  @tag = check_incoming_tag(:svg, tag)
78
84
 
79
85
  check_icon_presence!(icon, variant)
@@ -107,11 +113,16 @@ module Ariadne
107
113
  classes
108
114
  )
109
115
  @attributes.merge!(@icon.attributes.except(:class, :"aria-hidden"))
116
+
117
+ @text_classes = class_names(DEFAULT_TEXT_CLASSES, text_classes)
118
+ @text_attributes = text_attributes
110
119
  end
111
120
 
112
- def self._after_compile
113
- HeroiconsHelper::Cache.preload!(PRELOADED_ICONS) do |found, icon|
114
- HeroiconComponent.new(icon: icon[:name], variant: icon[:variant]) unless found
121
+ class << self
122
+ def _after_compile
123
+ HeroiconsHelper::Cache.preload!(PRELOADED_ICONS) do |found, icon|
124
+ HeroiconComponent.new(icon: icon[:name], variant: icon[:variant]) unless found
125
+ end
115
126
  end
116
127
  end
117
128
  end
@@ -24,19 +24,21 @@ module Ariadne
24
24
  </svg>
25
25
  MSG
26
26
 
27
- renders_one :icon, lambda { |icon, tag: :svg, variant:, size: Ariadne::HeroiconComponent::SIZE_DEFAULT, classes: "", attributes: {}|
28
- Ariadne::HeroiconComponent.new(tag: tag, icon: icon, variant: variant, size: size, classes: classes, attributes: attributes)
27
+ DEFAULT_TEXT_OPEN_CLASSES = "text-state-open"
28
+ DEFAULT_TEXT_CLOSED_CLASSES = "text-state-closed"
29
+ DEFAULT_TEXT_CLASSES = "pl-2 text-sm font-medium text-gray-900"
30
+ renders_one :icon, lambda { |tag: :svg, icon:, variant:, size: Ariadne::HeroiconComponent::SIZE_DEFAULT, classes: "", attributes: {}, text_classes: "", text_attributes: {}|
31
+ actual_text_classes = class_names(DEFAULT_TEXT_CLASSES, text_classes)
32
+ Ariadne::HeroiconComponent.new(tag: tag, icon: icon, variant: variant, size: size, classes: classes, attributes: attributes, text_classes: actual_text_classes, text_attributes: text_attributes) { content }
29
33
  }
30
34
 
31
- renders_one :item, lambda { |tag: :span, classes: "", attributes: {}|
32
- Ariadne::BaseComponent.new(tag: tag, classes: classes, attributes: attributes) { content }
35
+ renders_one :item, lambda { |classes: "", attributes: {}|
36
+ Ariadne::BaseComponent.new(tag: :span, classes: classes, attributes: attributes) { content }
33
37
  }
34
38
 
35
- DEFAULT_TEXT_OPEN_CLASSES = "text-state-open"
36
- DEFAULT_TEXT_CLOSED_CLASSES = "text-state-closed"
37
- DEFAULT_TEXT_CLASSES = "pl-2 text-sm font-medium text-gray-900 text-sm"
39
+ DEFAULT_LABEL_CLASSES = "pl-2 text-sm font-medium text-gray-900"
38
40
  renders_one :text, lambda { |classes: "", attributes: {}|
39
- actual_classes = class_names(DEFAULT_TEXT_CLASSES, classes)
41
+ actual_classes = class_names(DEFAULT_LABEL_CLASSES, classes)
40
42
  Ariadne::BaseComponent.new(tag: :span, classes: actual_classes, attributes: attributes) { content }
41
43
  }
42
44
 
@@ -47,7 +49,7 @@ module Ariadne
47
49
  # <% end %>
48
50
  #
49
51
  # <%= render(Ariadne::InlineFlexComponent.new) do |c| %>
50
- # <% c.icon(:check, size: :s, variant: HeroiconsHelper::Icon::VARIANT_SOLID) %>
52
+ # <% c.icon(icon: :check, size: :sm, variant: HeroiconsHelper::Icon::VARIANT_SOLID) %>
51
53
  # <% c.text { "Closed" } %>
52
54
  # <% end %>
53
55
  #
@@ -6,19 +6,22 @@ module Ariadne
6
6
  DEFAULT_TAG = :a
7
7
  TAG_OPTIONS = [DEFAULT_TAG, :span].freeze
8
8
 
9
- # `Tooltip` that appears on mouse hover or keyboard focus over the link. Use tooltips sparingly and as a last resort.
9
+ DEFAULT_CLASSES = "cursor-pointer"
10
+ DEFAULT_ACTIONABLE_CLASSES = " cursor-pointer underline decoration-double font-semibold hover:text-button-text-color focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
11
+
12
+ # `Tooltip` that appears on mouse hover or keyboard focus over the button. Use tooltips sparingly and as a last resort.
13
+ # **Important:** This tooltip defaults to `type: :description`. In a few scenarios, `type: :label` may be more appropriate.
10
14
  # Consult the <%= link_to_component(Ariadne::TooltipComponent) %> documentation for more information.
11
15
  #
12
16
  # @param tag [Symbol, String] The rendered tag name
13
17
  # @param text [String] The text content of the tooltip. This should be brief and no longer than a sentence.
18
+ # @param direction [Symbol] <%= one_of(Ariadne::TooltipComponent::VALID_PLACEMENTS) %>
14
19
  # @param classes [String] <%= link_to_classes_docs %>
15
- # @param attributes [Hash] <%= link_to_attributes_docs %>
16
- renders_one :tooltip, lambda { |tag: :"tool-tip", text:, classes: "", attributes: {}|
20
+ # @param attributes [Hash] Same arguments as <%= link_to_component(Ariadne::TooltipComponent) %>.
21
+ renders_one :tooltip, lambda { |tag: Ariadne::TooltipComponent::DEFAULT_TAG, text:, direction: Ariadne::TooltipComponent::DEFAULT_PLACEMENT, type: Ariadne::TooltipComponent::TYPE_DEFAULT, classes: "", attributes: {}|
17
22
  raise ArgumentError, "Links with a tooltip must have a unique `id` set on the `LinkComponent`." if @id.blank?
18
23
 
19
- actual_classes = class_names(classes)
20
-
21
- Ariadne::TooltipComponent.new(tag: tag, text: text, classes: actual_classes, attributes: attributes)
24
+ Ariadne::TooltipComponent.new(tag: tag, for_id: @id, text: text, direction: direction, type: type, classes: classes, attributes: attributes)
22
25
  }
23
26
 
24
27
  # @example Default
@@ -38,9 +41,10 @@ module Ariadne
38
41
  #
39
42
  # @param tag [String] <%= one_of(Ariadne::LinkComponent::TAG_OPTIONS) %>
40
43
  # @param href [String] URL to be used for the link.
44
+ # @param actionable [Boolean] If true, adds additional classes to the link to make it more aware.
41
45
  # @param classes [String] <%= link_to_classes_docs %>
42
46
  # @param attributes [Hash] <%= link_to_attributes_docs %>
43
- def initialize(tag: DEFAULT_TAG, href:, classes: "", attributes: {})
47
+ def initialize(tag: DEFAULT_TAG, href:, actionable: false, classes: "", attributes: {})
44
48
  @tag = check_incoming_tag(DEFAULT_TAG, tag)
45
49
 
46
50
  @attributes = attributes
@@ -48,7 +52,8 @@ module Ariadne
48
52
 
49
53
  @id = @attributes[:id]
50
54
 
51
- @classes = classes
55
+ @classes = class_names(DEFAULT_CLASSES, classes)
56
+ @classes << DEFAULT_ACTIONABLE_CLASSES if actionable
52
57
  end
53
58
 
54
59
  def call
@@ -1,17 +1,15 @@
1
1
  <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |list| %>
2
2
  <% items.each do |item| %>
3
3
  <% if item.linked? %>
4
- <li data-highlight-target="highlightable" class="relative <%= selected? ? 'bg-button-bg-color' : 'hover:bg-button-hover-color' %> focus:ring-2 focus:ring-offset-2 focus:ring-purple-500">
5
- <%= render(item.link) do %>
6
- <%= item.header %>
4
+ <%= render Ariadne::BaseComponent.new(tag: :li, classes: item.classes, attributes: item.attributes) do %>
5
+ <%= render Ariadne::LinkComponent.new(href: item.link[:href], classes: item.link[:classes], attributes: item.link[:attributes]) do %>
7
6
  <%= item.entry %>
8
7
  <% end %>
9
- </li>
8
+ <% end %>
10
9
  <% else %>
11
- <li data-highlight-target="highlightable" class="relative <%= selected? ? 'bg-button-bg-color' : 'hover:bg-button-hover-color' %> focus:ring-2 focus:ring-offset-2 focus:ring-purple-500">
12
- <%= item.header %>
10
+ <%= render Ariadne::BaseComponent.new(tag: :li, classes: item.classes, attributes: item.attributes) do %>
13
11
  <%= item.entry %>
14
- </li>
12
+ <% end %>
15
13
  <% end %>
16
14
  <% end %>
17
15
  <% end %>
@@ -17,16 +17,6 @@ module Ariadne
17
17
  # <% end %>
18
18
  # <% end %>
19
19
  #
20
- # @example With a header
21
- # <% numbers = [1, 2, 3] %>
22
- # <%= render(Ariadne::ListComponent.new) do |list| %>
23
- # <% numbers.each_with_index do |number, idx| %>
24
- # <%= list.item do |item| %>
25
- # <%= item.header { idx } %>
26
- # <%= item.entry { number } %>
27
- # <% end %>
28
- # <% end %>
29
- # <% end %>
30
20
  #
31
21
  # @param classes [String] <%= link_to_classes_docs %>
32
22
  # @param attributes [Hash] <%= link_to_attributes_docs %>
@@ -34,11 +24,6 @@ module Ariadne
34
24
  @tag = :ul
35
25
  @classes = class_names(DEFAULT_UL_CLASSES, classes)
36
26
  @attributes = attributes
37
- @attributes[:"data-controller"] = "highlight"
38
- end
39
-
40
- def selected?
41
- false
42
27
  end
43
28
 
44
29
  def render?
@@ -48,33 +33,22 @@ module Ariadne
48
33
  # This component is part of `ListComponent` and should not be
49
34
  # used as a standalone component.
50
35
  class Item < Ariadne::Component
51
- renders_one :header, lambda { |static_content = nil, &block|
52
- next static_content if static_content.present?
53
-
54
- render(Ariadne::BaseComponent.new(tag: :div, classes: "flex justify-between")) do
55
- view_context.capture { block&.call }
56
- end
57
- }
36
+ DEFAULT_ITEM_CLASSES = "relative p-1.5 focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 hover:bg-button-hover-color"
58
37
 
59
38
  renders_one :entry, lambda { |static_content = nil, &block|
60
39
  next static_content if static_content.present?
61
40
 
62
- render(Ariadne::BaseComponent.new(tag: :div, classes: "mt-1")) do
41
+ render(Ariadne::BaseComponent.new(tag: :div)) do
63
42
  view_context.capture { block&.call }
64
43
  end
65
44
  }
66
45
 
67
- attr_accessor :selected
68
46
  attr_reader :link, :classes, :attributes
69
47
 
70
48
  def initialize(link: {}, classes: "", attributes: {})
71
- if link.present?
72
- @link = Ariadne::LinkComponent.new(**link)
73
- end
74
-
75
- @classes = classes
49
+ @link = link
50
+ @classes = class_names(DEFAULT_ITEM_CLASSES, classes)
76
51
  @attributes = attributes
77
- @selected = false
78
52
  end
79
53
 
80
54
  def selected?
@@ -86,10 +60,6 @@ module Ariadne
86
60
  end
87
61
 
88
62
  def call
89
- if selected
90
- link_arguments[:"aria-current"] = "page"
91
- end
92
-
93
63
  Ariadne::BaseComponent.new(tag: :div, classes: @classes, attributes: @attributes)
94
64
  end
95
65
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Add a general description of component here
5
+ # Add additional usage considerations or best practices that may aid the user to use the component correctly.
6
+ # @accessibility Add any accessibility considerations
7
+ class MainComponent < Ariadne::Component
8
+ DEFAULT_CLASSES = "flex-auto"
9
+
10
+ # @example Default
11
+ #
12
+ # <%= render(Ariadne::MainComponent.new) { "Example" } %>
13
+ #
14
+ # @param classes [String] <%= link_to_classes_docs %>
15
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
16
+ def initialize(classes: "", attributes: {})
17
+ @tag = :main
18
+ @classes = class_names(
19
+ DEFAULT_CLASSES,
20
+ classes
21
+ )
22
+
23
+ @attributes = attributes
24
+ end
25
+
26
+ def call
27
+ render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) do
28
+ render(Ariadne::ContainerComponent.new) { content }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class SlideoverComponent extends Controller {
3
+ static targets: string[];
4
+ readonly expandableTarget: HTMLDivElement;
5
+ readonly expandWrapperTarget: HTMLDivElement;
6
+ readonly slidePanelTargets: [HTMLDivElement];
7
+ readonly buttonWrapperTarget: HTMLDivElement;
8
+ toggle(): void;
9
+ }
@@ -0,0 +1,20 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class SlideoverComponent extends Controller {
3
+ toggle() {
4
+ var _a;
5
+ this.expandableTarget.classList.toggle('hidden');
6
+ this.expandWrapperTarget.classList.toggle('bg-filter-panel');
7
+ for (const slidePanel of this.slidePanelTargets) {
8
+ slidePanel.classList.toggle('hidden');
9
+ }
10
+ this.buttonWrapperTarget.classList.toggle('bg-filter-panel');
11
+ if ((_a = document.getElementById('btnClose')) === null || _a === void 0 ? void 0 : _a.classList.contains('hidden')) {
12
+ const formID = this.buttonWrapperTarget.getAttribute('data-slideover-component-form-id');
13
+ if (formID) {
14
+ const form = document.getElementById(formID);
15
+ form === null || form === void 0 ? void 0 : form.submit();
16
+ }
17
+ }
18
+ }
19
+ }
20
+ SlideoverComponent.targets = ['expandable', 'expandWrapper', 'slidePanel', 'buttonWrapper'];
@@ -0,0 +1,9 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class SlideoverComponent extends Controller {
3
+ static targets: string[];
4
+ readonly expandableTarget: HTMLDivElement;
5
+ readonly expandWrapperTarget: HTMLDivElement;
6
+ readonly slidePanelTargets: [HTMLDivElement];
7
+ readonly buttonWrapperTarget: HTMLDivElement;
8
+ toggle(): void;
9
+ }
@@ -1,11 +1,8 @@
1
1
  <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |slideover| %>
2
- <div data-slideover-component-target="expandWrapper" class="flex flex-col">
2
+ <div data-slideover-component-target="expandWrapper" class="flex flex-col z-10">
3
3
  <div data-slideover-component-target="expandable" class="hidden bg-filter-panel px-3 pb-4">
4
4
  <%= content %>
5
5
  </div>
6
- <div class="relative top-4 inset-0 flex flex-row items-center bg-filter-panel" aria-hidden="true">
7
- <div class="w-full border-t border-billy-purple z-10"></div>
8
- </div>
9
6
  <div data-slideover-component-target="buttonWrapper" data-slideover-component-form-id="<%= @form_id %>" class="relative flex justify-center">
10
7
  <%= open_button %>
11
8
  <%= close_button %>
@@ -0,0 +1,19 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class SlideoverComponent extends Controller {
3
+ toggle() {
4
+ var _a;
5
+ // eslint-disable-next-line no-debugger
6
+ debugger;
7
+ this.expandableTarget.classList.toggle('hidden');
8
+ this.expandWrapperTarget.classList.toggle('bg-filter-panel');
9
+ for (const slidePanel of this.slidePanelTargets) {
10
+ slidePanel.classList.toggle('hidden');
11
+ }
12
+ this.buttonWrapperTarget.classList.toggle('bg-filter-panel');
13
+ if ((_a = document.getElementById('btnClose')) === null || _a === void 0 ? void 0 : _a.classList.contains('hidden')) {
14
+ const form = this.buttonWrapperTarget.closest('form');
15
+ form === null || form === void 0 ? void 0 : form.submit();
16
+ }
17
+ }
18
+ }
19
+ SlideoverComponent.targets = ['expandable', 'expandWrapper', 'slidePanel', 'buttonWrapper'];
@@ -8,14 +8,14 @@ module Ariadne
8
8
  DEFAULT_TAG = :div
9
9
  TAG_OPTIONS = [DEFAULT_TAG].freeze
10
10
 
11
- DIRECTION_Y = :y
12
- DIRECTION_X = :x
13
- VALID_DIRECTIONS = [DIRECTION_Y, DIRECTION_X].freeze
11
+ DIRECTION_Y_DOWN = :yd
12
+ DIRECTION_X_LEFT = :xl
13
+ VALID_DIRECTIONS = [DIRECTION_Y_DOWN, DIRECTION_X_LEFT].freeze
14
14
 
15
15
  DEFAULT_CLASSES = ""
16
16
 
17
- DEFAULT_BUTTON_CLASSES = "inline-flex items-center shadow-sm px-4 py-1.5 border border-our-purple-300 z-50 text-sm leading-5 font-medium rounded-full text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
18
- renders_one :open_button, lambda { |text:, classes: "", attributes: {}|
17
+ DEFAULT_BUTTON_CLASSES = "inline-flex items-center shadow-sm px-4 py-1.5 pb-2 text-sm leading-5 font-medium rounded-full " + Ariadne::ButtonComponent::SCHEME_CLASS_MAPPINGS[:default]
18
+ renders_one :open_button, lambda { |label:, classes: "", attributes: {}, text_classes: ""|
19
19
  actual_classes = class_names(DEFAULT_BUTTON_CLASSES, classes)
20
20
 
21
21
  attributes[:id] ||= "btnOpen"
@@ -23,15 +23,17 @@ module Ariadne
23
23
  attributes[:"data-action"] ||= "click->slideover-component#toggle"
24
24
  attributes[:type] ||= "submit"
25
25
 
26
+ icon = case @direction
27
+ when DIRECTION_Y_DOWN
28
+ :"chevron-double-down"
29
+ end
30
+
26
31
  render(Ariadne::BaseComponent.new(tag: :button, classes: actual_classes, attributes: attributes)) do
27
- render(Ariadne::InlineFlexComponent.new(attributes: { "data-slideover-component-target" => "slide-panel" })) do |flex|
28
- flex.icon(:"chevron-double-down", size: :s, variant: HeroiconsHelper::Icon::VARIANT_SOLID)
29
- flex.text { text }
30
- end
32
+ render(Ariadne::HeroiconComponent.new(icon: icon, size: :sm, variant: HeroiconsHelper::Icon::VARIANT_SOLID, attributes: { "data-slideover-component-target" => "slide-panel" }, text_classes: text_classes)) { label }
31
33
  end
32
34
  }
33
35
 
34
- renders_one :close_button, lambda { |text:, classes: "", attributes: {}|
36
+ renders_one :close_button, lambda { |label:, classes: "", attributes: {}, text_classes: ""|
35
37
  actual_classes = class_names(DEFAULT_BUTTON_CLASSES, classes)
36
38
 
37
39
  attributes[:id] ||= "btnClose"
@@ -39,17 +41,19 @@ module Ariadne
39
41
  attributes[:"data-action"] ||= "click->slideover-component#toggle"
40
42
  attributes[:type] ||= "submit"
41
43
 
44
+ icon = case @direction
45
+ when DIRECTION_Y_DOWN
46
+ :"chevron-double-up"
47
+ end
48
+
42
49
  render(Ariadne::BaseComponent.new(tag: :button, classes: actual_classes, attributes: attributes)) do
43
- render(Ariadne::InlineFlexComponent.new(attributes: { "data-slideover-component-target" => "slide-panel" })) do |flex|
44
- flex.icon(:"chevron-double-up", size: :s, variant: HeroiconsHelper::Icon::VARIANT_SOLID)
45
- flex.text { text }
46
- end
50
+ render(Ariadne::HeroiconComponent.new(icon: icon, size: :sm, variant: HeroiconsHelper::Icon::VARIANT_SOLID, attributes: { "data-slideover-component-target" => "slide-panel" }, text_classes: text_classes)) { label }
47
51
  end
48
52
  }
49
53
 
50
54
  # @example Default
51
55
  #
52
- # <%= render(Ariadne::SlideoverComponent.new(direction: Ariadne::SlideoverComponent::DIRECTION_Y)) { "Example" } %>
56
+ # <%= render(Ariadne::SlideoverComponent.new(direction: Ariadne::SlideoverComponent::DIRECTION_Y_DOWN)) { "Example" } %>
53
57
  #
54
58
  # @param tag [Symbol, String] The rendered tag name.
55
59
  # @param direction [Symbol] <%= one_of(Ariadne::SlideoverComponent::VALID_DIRECTIONS) %>
@@ -0,0 +1 @@
1
+ import '@github/time-elements';
@@ -0,0 +1 @@
1
+ import '@github/time-elements';
@@ -0,0 +1,24 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ import type { Instance, Placement } from '@popperjs/core';
3
+ export default class TooltipComponent extends Controller {
4
+ static targets: string[];
5
+ readonly triggerTarget: HTMLElement;
6
+ readonly tooltipTarget: HTMLElement;
7
+ static values: {
8
+ placement: {
9
+ type: StringConstructor;
10
+ default: string;
11
+ };
12
+ offset: {
13
+ type: ArrayConstructor;
14
+ default: number[];
15
+ };
16
+ };
17
+ readonly placementValue: Placement;
18
+ readonly offsetValue: Array<number>;
19
+ popperInstance: Instance;
20
+ connect(): void;
21
+ disconnect(): void;
22
+ show(): void;
23
+ hide(): void;
24
+ }
@@ -0,0 +1,42 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ import { createPopper } from '@popperjs/core';
3
+ export default class TooltipComponent extends Controller {
4
+ // Create a new Popper instance
5
+ connect() {
6
+ this.popperInstance = createPopper(this.triggerTarget, this.tooltipTarget, {
7
+ placement: this.placementValue,
8
+ modifiers: [
9
+ {
10
+ name: 'offset',
11
+ options: {
12
+ offset: this.offsetValue
13
+ }
14
+ }
15
+ ]
16
+ });
17
+ }
18
+ // Destroy the Popper instance
19
+ disconnect() {
20
+ if (this.popperInstance) {
21
+ this.popperInstance.destroy();
22
+ }
23
+ }
24
+ show() {
25
+ this.tooltipTarget.setAttribute('data-tooltip-show', '');
26
+ this.tooltipTarget.classList.remove('invisible');
27
+ // We need to tell Popper to update the tooltip position
28
+ // after we show the tooltip, otherwise it will be incorrect
29
+ this.popperInstance.update();
30
+ this.dispatch('shown', { detail: { trigger: this.triggerTarget, tooltip: this.tooltipTarget } });
31
+ }
32
+ hide() {
33
+ this.tooltipTarget.removeAttribute('data-tooltip-show');
34
+ this.tooltipTarget.classList.add('invisible');
35
+ this.dispatch('hidden', { detail: { trigger: this.triggerTarget, tooltip: this.tooltipTarget } });
36
+ }
37
+ }
38
+ TooltipComponent.targets = ['trigger', 'tooltip'];
39
+ TooltipComponent.values = {
40
+ placement: { type: String, default: 'top' },
41
+ offset: { type: Array, default: [0, 8] }
42
+ };
@@ -0,0 +1,57 @@
1
+ import {Controller} from '@hotwired/stimulus'
2
+ import {createPopper} from '@popperjs/core'
3
+ import type {Instance, Placement} from '@popperjs/core'
4
+
5
+ export default class TooltipComponent extends Controller {
6
+ static targets = ['trigger', 'tooltip']
7
+ declare readonly triggerTarget: HTMLElement
8
+ declare readonly tooltipTarget: HTMLElement
9
+
10
+ static values = {
11
+ placement: {type: String, default: 'top'},
12
+ offset: {type: Array, default: [0, 8]}
13
+ }
14
+ declare readonly placementValue: Placement
15
+ declare readonly offsetValue: Array<number>
16
+
17
+ popperInstance: Instance
18
+
19
+ // Create a new Popper instance
20
+ connect() {
21
+ this.popperInstance = createPopper(this.triggerTarget, this.tooltipTarget, {
22
+ placement: this.placementValue,
23
+ modifiers: [
24
+ {
25
+ name: 'offset',
26
+ options: {
27
+ offset: this.offsetValue
28
+ }
29
+ }
30
+ ]
31
+ })
32
+ }
33
+
34
+ // Destroy the Popper instance
35
+ disconnect() {
36
+ if (this.popperInstance) {
37
+ this.popperInstance.destroy()
38
+ }
39
+ }
40
+
41
+ show() {
42
+ this.tooltipTarget.setAttribute('data-tooltip-show', '')
43
+ this.tooltipTarget.classList.remove('invisible')
44
+
45
+ // We need to tell Popper to update the tooltip position
46
+ // after we show the tooltip, otherwise it will be incorrect
47
+ this.popperInstance.update()
48
+ this.dispatch('shown', {detail: {trigger: this.triggerTarget, tooltip: this.tooltipTarget}})
49
+ }
50
+
51
+ hide() {
52
+ this.tooltipTarget.removeAttribute('data-tooltip-show')
53
+ this.tooltipTarget.classList.add('invisible')
54
+
55
+ this.dispatch('hidden', {detail: {trigger: this.triggerTarget, tooltip: this.tooltipTarget}})
56
+ }
57
+ }
@@ -0,0 +1,4 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do %>
2
+ <span><%= @text %></span>
3
+ <span class="tooltip-arrow absolute block" data-popper-arrow></span>
4
+ <% end %>