matestack-ui-bootstrap 1.4.0

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.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +8 -0
  3. data/README.md +26 -0
  4. data/Rakefile +43 -0
  5. data/app/assets/images/avatar-placeholder.png +0 -0
  6. data/app/assets/images/icons/bootstrap-icons.svg +1 -0
  7. data/app/concepts/matestack/ui/bootstrap/apps/admin_template.rb +85 -0
  8. data/app/concepts/matestack/ui/bootstrap/components/accordion.rb +53 -0
  9. data/app/concepts/matestack/ui/bootstrap/components/alert.js +53 -0
  10. data/app/concepts/matestack/ui/bootstrap/components/alert.rb +34 -0
  11. data/app/concepts/matestack/ui/bootstrap/components/avatar.rb +27 -0
  12. data/app/concepts/matestack/ui/bootstrap/components/badge.rb +30 -0
  13. data/app/concepts/matestack/ui/bootstrap/components/breadcrumb.rb +46 -0
  14. data/app/concepts/matestack/ui/bootstrap/components/button.rb +54 -0
  15. data/app/concepts/matestack/ui/bootstrap/components/button_group.rb +36 -0
  16. data/app/concepts/matestack/ui/bootstrap/components/card.rb +100 -0
  17. data/app/concepts/matestack/ui/bootstrap/components/carousel.js +79 -0
  18. data/app/concepts/matestack/ui/bootstrap/components/carousel.rb +85 -0
  19. data/app/concepts/matestack/ui/bootstrap/components/chart.js +232 -0
  20. data/app/concepts/matestack/ui/bootstrap/components/chart.rb +71 -0
  21. data/app/concepts/matestack/ui/bootstrap/components/close.rb +30 -0
  22. data/app/concepts/matestack/ui/bootstrap/components/collapse.js +84 -0
  23. data/app/concepts/matestack/ui/bootstrap/components/collapse.rb +43 -0
  24. data/app/concepts/matestack/ui/bootstrap/components/dropdown.js +14 -0
  25. data/app/concepts/matestack/ui/bootstrap/components/dropdown.rb +116 -0
  26. data/app/concepts/matestack/ui/bootstrap/components/icon.rb +19 -0
  27. data/app/concepts/matestack/ui/bootstrap/components/list_group.rb +83 -0
  28. data/app/concepts/matestack/ui/bootstrap/components/modal.js +90 -0
  29. data/app/concepts/matestack/ui/bootstrap/components/modal.rb +106 -0
  30. data/app/concepts/matestack/ui/bootstrap/components/navbar.rb +120 -0
  31. data/app/concepts/matestack/ui/bootstrap/components/page_heading.rb +28 -0
  32. data/app/concepts/matestack/ui/bootstrap/components/pagination.rb +40 -0
  33. data/app/concepts/matestack/ui/bootstrap/components/popover.js +26 -0
  34. data/app/concepts/matestack/ui/bootstrap/components/popover.rb +92 -0
  35. data/app/concepts/matestack/ui/bootstrap/components/progress.rb +65 -0
  36. data/app/concepts/matestack/ui/bootstrap/components/scrollspy.rb +33 -0
  37. data/app/concepts/matestack/ui/bootstrap/components/section_card.rb +31 -0
  38. data/app/concepts/matestack/ui/bootstrap/components/spinner.rb +31 -0
  39. data/app/concepts/matestack/ui/bootstrap/components/tab_nav.rb +81 -0
  40. data/app/concepts/matestack/ui/bootstrap/components/tab_nav_content.rb +32 -0
  41. data/app/concepts/matestack/ui/bootstrap/components/toast.js +79 -0
  42. data/app/concepts/matestack/ui/bootstrap/components/toast.rb +99 -0
  43. data/app/concepts/matestack/ui/bootstrap/components/tooltip.js +26 -0
  44. data/app/concepts/matestack/ui/bootstrap/components/tooltip.rb +82 -0
  45. data/app/concepts/matestack/ui/bootstrap/content/collection/collection.rb +112 -0
  46. data/app/concepts/matestack/ui/bootstrap/content/collection/collection.scss +10 -0
  47. data/app/concepts/matestack/ui/bootstrap/content/collection/content.rb +101 -0
  48. data/app/concepts/matestack/ui/bootstrap/content/collection/filter.rb +33 -0
  49. data/app/concepts/matestack/ui/bootstrap/content/collection/paginate.rb +92 -0
  50. data/app/concepts/matestack/ui/bootstrap/content/figure.rb +7 -0
  51. data/app/concepts/matestack/ui/bootstrap/form/checkbox.rb +90 -0
  52. data/app/concepts/matestack/ui/bootstrap/form/date.js +38 -0
  53. data/app/concepts/matestack/ui/bootstrap/form/date.rb +98 -0
  54. data/app/concepts/matestack/ui/bootstrap/form/input.rb +123 -0
  55. data/app/concepts/matestack/ui/bootstrap/form/radio.rb +65 -0
  56. data/app/concepts/matestack/ui/bootstrap/form/select.haml +11 -0
  57. data/app/concepts/matestack/ui/bootstrap/form/select.rb +74 -0
  58. data/app/concepts/matestack/ui/bootstrap/form/submit.rb +20 -0
  59. data/app/concepts/matestack/ui/bootstrap/form/switch.rb +90 -0
  60. data/app/concepts/matestack/ui/bootstrap/layout/column.rb +47 -0
  61. data/app/concepts/matestack/ui/bootstrap/layout/container.rb +25 -0
  62. data/app/concepts/matestack/ui/bootstrap/layout/row.rb +15 -0
  63. data/app/concepts/matestack/ui/bootstrap/layout/sidebar.js +64 -0
  64. data/app/concepts/matestack/ui/bootstrap/layout/sidebar.rb +45 -0
  65. data/app/concepts/matestack/ui/bootstrap/layout/sidebar.scss +57 -0
  66. data/app/concepts/matestack/ui/bootstrap/pages/devise/sign_in.rb +40 -0
  67. data/app/concepts/matestack/ui/bootstrap/registry.rb +63 -0
  68. data/app/helpers/matestack/ui/bootstrap/application_helper.rb +13 -0
  69. data/app/javascript/matestack-ui-bootstrap/index.js +26 -0
  70. data/app/javascript/matestack-ui-bootstrap/stylesheets/matestack-ui-bootstrap.scss +65 -0
  71. data/app/javascript/packs/matestack-ui-bootstrap.js +2 -0
  72. data/config/routes.rb +2 -0
  73. data/config/webpack/development.js +5 -0
  74. data/config/webpack/environment.js +29 -0
  75. data/config/webpack/production.js +33 -0
  76. data/config/webpack/test.js +5 -0
  77. data/config/webpacker.yml +96 -0
  78. data/lib/matestack/ui/bootstrap.rb +27 -0
  79. data/lib/matestack/ui/bootstrap/engine.rb +26 -0
  80. data/lib/matestack/ui/bootstrap/version.rb +7 -0
  81. data/lib/tasks/matestack/ui/bootstrap_tasks.rake +66 -0
  82. metadata +137 -0
@@ -0,0 +1,65 @@
1
+ class Matestack::Ui::Bootstrap::Components::Progress < Matestack::Ui::Component
2
+
3
+ optional class: { as: :bs_class }
4
+ optional :text, :valuemin, :valuemax
5
+ # progress expects a number or a list containing hashes with at least a :value
6
+ # other options are :text, :class, :variant, :striped, :animated, :aria_valuenow
7
+ optional :progress
8
+ # :value
9
+ optional :variant, :striped, :animated, :height
10
+
11
+ def response
12
+ div progress_attributes do
13
+ progress = self.progress.is_a?(Array) ? self.progress : [{ value: self.progress || value, text: self.text }]
14
+ progress.each do |prog|
15
+ progress_bar(prog[:value], valuemin, valuemax,
16
+ text: prog[:text], klass: prog[:class], variant: prog[:variant] || variant,
17
+ striped: prog[:striped] || striped, animated: prog[:animated] || animated,
18
+ aria_valuenow: prog[:aria_valuenow]
19
+ )
20
+ end
21
+ yield_components
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ def progress_attributes
28
+ attributes = {}.tap do |hash|
29
+ hash[:class] = "progress #{bs_class}".strip
30
+ hash[:attributes] = { style: "height: #{height}px;" } if height
31
+ end
32
+ html_attributes.merge(
33
+ attributes
34
+ )
35
+ end
36
+
37
+ def progress_bar(value, min, max, text: nil, klass: nil, variant: :primary, striped: false, animated: false, aria_valuenow: nil)
38
+ div progress_bar_attributes(value, klass, variant, striped, animated, aria_valuenow) do
39
+ plain text if text
40
+ end
41
+ end
42
+
43
+ def progress_bar_attributes(value, klass, variant, striped, animated, aria_valuenow)
44
+ {
45
+ class: progress_bar_classes(klass, variant, striped, animated),
46
+ attributes: {
47
+ role: :progressbar,
48
+ style: "width: #{value.to_i > 0 ? value : 0}%;",
49
+ 'aria-valuenow': aria_valuenow || value || 0,
50
+ 'aria-valuemin': valuemin || 0,
51
+ 'aria-valuemax': valuemax || 100
52
+ }
53
+ }
54
+ end
55
+
56
+ def progress_bar_classes(klass, variant, striped, animated)
57
+ [].tap do |classes|
58
+ classes << 'progress-bar'
59
+ classes << "bg-#{variant || :primary}"
60
+ classes << "progress-bar-striped" if striped
61
+ classes << "progress-bar-animated" if animated
62
+ classes << klass
63
+ end.join(' ').strip
64
+ end
65
+ end
@@ -0,0 +1,33 @@
1
+ class Matestack::Ui::Bootstrap::Components::Scrollspy < Matestack::Ui::Component
2
+
3
+ optional :offset # pixel to offset from top, by default 10
4
+ optional method: { as: :bs_method} # find which section, by default auto
5
+ optional :target # scroll target id
6
+ optional class: { as: :bs_class} # adding custom class to scrollspy
7
+
8
+ def response
9
+ div scrollspy_attributes do
10
+ yield_components
11
+ end
12
+ end
13
+
14
+ protected
15
+
16
+ def scrollspy_attributes
17
+ attributes = {}.tap do |hash|
18
+ hash[:class] = scrollspy_classes
19
+ hash[:data] = { "bs-spy": "scroll", "bs-target": "#{target}" }
20
+ hash[:data].merge!("bs-offset": offset) if offset.present?
21
+ hash[:data].merge!("bs-method": :"#{bs_method}") if bs_method.present?
22
+ end
23
+ html_attributes.merge(
24
+ attributes
25
+ )
26
+ end
27
+
28
+ def scrollspy_classes
29
+ [].tap do |classes|
30
+ classes << bs_class
31
+ end.join(' ').strip
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ class Matestack::Ui::Bootstrap::Components::SectionCard < Matestack::Ui::Component
2
+
3
+ optional :id, :title, :subtitle, :icon, :slots, :content_padding
4
+
5
+ def response
6
+ section id: :id, class: "section-card rounded shadow-sm mb-4 bg-white" do
7
+ div class: "d-flex flex-row justify-content-between" do
8
+ if title.present? || subtitle.present?
9
+ div class: "section-card-heading p-4" do
10
+ heading size: 5, class: "mb-0" do
11
+ bs_icon name: icon, size: "35" if icon.present?
12
+ plain title
13
+ end
14
+ small class: "text-muted" do
15
+ plain subtitle
16
+ end
17
+ end
18
+ end
19
+ if slots.present? && slots[:actions].present?
20
+ div class: "section-card-actions p-4" do
21
+ slot slots[:actions]
22
+ end
23
+ end
24
+ end
25
+ div class: "section-card-content #{'p-4' unless content_padding == false} #{'pt-1' if title || subtitle}" do
26
+ yield_components
27
+ end
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,31 @@
1
+ class Matestack::Ui::Bootstrap::Components::Spinner < Matestack::Ui::Component
2
+
3
+ optional class: { as: :bs_class }
4
+ optional :kind, :variant, :size, :sr_only
5
+
6
+ def response
7
+ div spinner_attributes do
8
+ span class: "sr-only", text: sr_only
9
+ end
10
+ end
11
+
12
+ protected
13
+
14
+ def spinner_attributes
15
+ html_attributes.merge(
16
+ class: spinner_class,
17
+ attributes: { 'role': "status" }
18
+ )
19
+ end
20
+
21
+ def spinner_class
22
+ [].tap do |classes|
23
+ spinner_kind = kind || :border
24
+ classes << "spinner-#{spinner_kind}"
25
+ classes << "text-#{variant || 'primary'}"
26
+ classes << "spinner-#{spinner_kind}-sm" if size
27
+ #optional classes
28
+ classes << bs_class
29
+ end.join(' ').strip
30
+ end
31
+ end
@@ -0,0 +1,81 @@
1
+ class Matestack::Ui::Bootstrap::Components::TabNav < Matestack::Ui::Component
2
+
3
+ requires :id
4
+
5
+ optional :items, :variant, :fill, :justified, :vertical, :vertical_up_to_sm,
6
+ :vertical_up_to_md, :vertical_up_to_xl, :horizontal,
7
+ class: { as: :bs_class }, attributes: { as: :bs_attrs}
8
+
9
+ def response
10
+ ul nav_attributes do
11
+ nav_items_partial if items.present?
12
+ end
13
+ div class: "tab-content", id: "#{id}Content" do
14
+ yield_components
15
+ end
16
+ end
17
+
18
+ protected
19
+
20
+ def nav_items_partial
21
+ items.each do |item|
22
+ li class: "nav-item", attributes: { role: "presentation" } do
23
+ # '<a class="nav-link active" id="pills-home-tab" data-toggle="pill" href="#pills-home" role="tab" aria-controls="pills-home" aria-selected="true">Home</a>'
24
+ link class: "nav-link #{'active' if item[:active]}",
25
+ id: "tab-#{item[:id]}",
26
+ path: "#tab-#{item[:id]}-content",
27
+ attributes: {
28
+ role: "tab",
29
+ "aria-controls": "tab-#{item[:id]}",
30
+ "aria-selected": "#{'true' if item[:active]}",
31
+ "data-bs-toggle": "tab"
32
+ } do
33
+ bs_icon name: item[:icon], size: 20 if item[:icon]
34
+ span class: "#{'ps-3' if item[:icon]}", text: item[:text] if item[:text]
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def link_attrs path, active, disabled, delay=nil
41
+ {}.tap do |hash|
42
+ hash[:class] = "nav-link #{'active' if path == request.fullpath } #{'disabled' if disabled}"
43
+
44
+ hash[:attributes] = {}.tap do |hash|
45
+ hash[:'aria-selected'] = path == request.fullpath ? 'true' : 'false'
46
+ hash[:'aria-current'] = 'page' if active == true
47
+ hash[:'aria-disabled'] = 'true' if disabled
48
+ hash[:role] = "tab" if toggle.present?
49
+ hash[:'aria-controls'] = "#{path.gsub('#','')}" if toggle.present?
50
+ end
51
+
52
+ hash[:data] = { "bs-toggle": "pill" } if pills
53
+ hash[:data] = { "bs-toggle": "tab" } if tabs
54
+ hash[:path] = path
55
+ end
56
+ end
57
+
58
+ def nav_attributes
59
+ html_attributes.merge(
60
+ id: id,
61
+ class: nav_classes,
62
+ attributes: { role: "tablist"}
63
+ )
64
+ end
65
+
66
+ def nav_classes
67
+ [].tap do |classes|
68
+ classes << 'nav'
69
+ classes << 'nav-tabs' if variant == :tabs || variant.nil?
70
+ classes << 'nav-pills' if variant == :pills
71
+ classes << 'nav-fill' if fill
72
+ classes << 'nav-justified' if justified
73
+ classes << 'flex-column' if vertical
74
+ classes << 'flex-column flex-sm-column flex-md-row' if vertical_up_to_sm
75
+ classes << 'flex-column flex-sm-column flex-md-column flex-lg-row' if vertical_up_to_md
76
+ classes << 'flex-column flex-sm-column flex-md-column flex-lg-column flex-xl-row' if vertical_up_to_xl
77
+ classes << "justify-content-#{horizontal}" if horizontal.present?
78
+ classes << bs_class
79
+ end.join(' ').strip
80
+ end
81
+ end
@@ -0,0 +1,32 @@
1
+ class Matestack::Ui::Bootstrap::Components::TabNavContent < Matestack::Ui::Component
2
+
3
+ requires :id
4
+
5
+ optional :tabs, :pills, :active, class: { as: :bs_class }, attributes: { as: :bs_attrs}
6
+
7
+ def response
8
+ div tab_content_attributes do
9
+ yield_components
10
+ end
11
+ end
12
+
13
+ protected
14
+
15
+ def tab_content_attributes
16
+ html_attributes.merge(
17
+ id: "tab-#{id}-content",
18
+ class: tab_content_classes,
19
+ attributes: { role: "tabpanel", "aria-labelledby": "tab-#{id}" }
20
+ )
21
+ end
22
+
23
+ def tab_content_classes
24
+ [].tap do |classes|
25
+ classes << 'tab-pane'
26
+ classes << 'fade'
27
+ classes << 'show ' if active
28
+ classes << 'active' if active
29
+ classes << bs_class
30
+ end.join(' ').strip
31
+ end
32
+ end
@@ -0,0 +1,79 @@
1
+ import * as bootstrap from 'bootstrap'
2
+
3
+ MatestackUiCore.Vue.component('matestack-ui-bootstrap-toast', {
4
+
5
+ mixins: [MatestackUiCore.componentMixin],
6
+ data() {
7
+ return {
8
+ toastsInstance: undefined,
9
+ eventData: {},
10
+ showing: false,
11
+ };
12
+ },
13
+ methods: {
14
+ show: function(event){
15
+ const self = this;
16
+ if(this.componentConfig["autohide"]){
17
+ setTimeout(function () {
18
+ self.showing = false;
19
+ }, 5000);
20
+ }
21
+ this.showing = true
22
+ this.eventData = event
23
+ },
24
+ hide: function(event){
25
+ const self = this;
26
+ this.showing = false
27
+ setTimeout(function () {
28
+ self.eventData = false;
29
+ }, 500);
30
+ },
31
+ dispose: function(){
32
+ const self = this;
33
+ self.toastsInstance.dispose()
34
+ self.toastsInstance = new bootstrap.Toast(self.$el)
35
+ }
36
+ },
37
+ mounted: function() {
38
+ const self = this;
39
+ var myToasts = self.$el
40
+ self.toastsInstance = new bootstrap.Toast(myToasts)
41
+ },
42
+ created: function() {
43
+ const self = this
44
+
45
+ if(this.componentConfig["show_on"] != undefined){
46
+ var show_events = this.componentConfig["show_on"].split(",")
47
+ show_events.forEach(show_event => MatestackUiCore.matestackEventHub.$on(show_event.trim(), self.show));
48
+ }
49
+
50
+ if(this.componentConfig["hide_on"] != undefined){
51
+ var show_events = this.componentConfig["hide_on"].split(",")
52
+ show_events.forEach(show_event => MatestackUiCore.matestackEventHub.$on(show_event.trim(), self.hide));
53
+ }
54
+
55
+ if(this.componentConfig["dispose_on"] != undefined){
56
+ var show_events = this.componentConfig["dispose_on"].split(",")
57
+ show_events.forEach(show_event => MatestackUiCore.matestackEventHub.$on(show_event.trim(), self.dispose));
58
+ }
59
+ },
60
+
61
+ beforeDestroy: function() {
62
+ const self = this
63
+ MatestackUiCore.matestackEventHub.$off(this.componentConfig["show_on"], self.show);
64
+ MatestackUiCore.matestackEventHub.$off(this.componentConfig["hide_on"], self.hide);
65
+ MatestackUiCore.matestackEventHub.$off(this.componentConfig["dispose_on"], self.hide);
66
+ if(this.componentConfig["show_on"] != undefined){
67
+ var shown_events = this.componentConfig["show_on"].split(",")
68
+ shown_events.forEach(show_event => MatestackUiCore.matestackEventHub.$off(show_event.trim(), self.show));
69
+ }
70
+ if(this.componentConfig["hide_on"] != undefined){
71
+ var hiden_events = this.componentConfig["hide_on"].split(",")
72
+ hiden_events.forEach(hide_event => MatestackUiCore.matestackEventHub.$off(hide_event.trim(), self.hide));
73
+ }
74
+ if(this.componentConfig["dispose_on"] != undefined){
75
+ var hiden_events = this.componentConfig["dispose_on"].split(",")
76
+ hiden_events.forEach(hide_event => MatestackUiCore.matestackEventHub.$off(hide_event.trim(), self.dispose));
77
+ }
78
+ },
79
+ });
@@ -0,0 +1,99 @@
1
+ class Matestack::Ui::Bootstrap::Components::Toast < Matestack::Ui::VueJsComponent
2
+ vue_js_component_name "matestack-ui-bootstrap-toast"
3
+
4
+ # header attributes, expects a hash or string
5
+ # possible keys `:icon_class, :icon, :title, :subtitle`
6
+ optional :header
7
+ # body expects a string as message inside toast
8
+ optional :body
9
+ # placement attributes, expects a hash wiht possible keys: position, min-height
10
+ optional :placement # for adding custom css style
11
+ optional :important, :delay, :autohide, :animation
12
+ optional class: { as: :bs_class }, attributes: { as: :bs_attrs }, data: { as: :bs_data }
13
+ optional :slots
14
+
15
+ def response
16
+ standard_placement_partial
17
+ # standard_placement_partial unless placement.present?
18
+ # custom_placement_partial if placement.present?
19
+ end
20
+
21
+ protected
22
+
23
+ def custom_placement_partial
24
+ div attributes: placement_attrs do
25
+ standard_placement_partial
26
+ end
27
+ end
28
+
29
+ def standard_placement_partial
30
+ div toast_attributes do
31
+ header_partial if header || slots && slots[:header]
32
+ body_partial
33
+ end
34
+ end
35
+
36
+ def header_partial
37
+ header = self.header.is_a?(Hash) ? self.header : { title: self.header }
38
+ div class: "toast-header" do
39
+ img class: "#{'rounded me-2' || header[:icon_class]}", path: header[:icon] if header[:icon].present?
40
+ strong class: "me-auto", text: header[:title] if header[:title].present?
41
+ small text: header[:subtitle] if header[:subtitle].present?
42
+
43
+ slot slots[:header] if slots && slots[:header]
44
+ bs_close dismiss: 'toast', class: "ms-2 mb-1", attributes: { "@click": "hide()"}
45
+ end
46
+
47
+ end
48
+
49
+ def body_partial
50
+ div class: "toast-body" do
51
+ plain body if body
52
+ end
53
+ unless header || slots && slots[:header]
54
+ bs_close dismiss: 'toast', class: "ms-auto me-2 btn-close-white", attributes: { "@click": "hide()"}
55
+ end
56
+ end
57
+
58
+ def toast_attributes
59
+ html_attributes.merge(
60
+ class: toast_classes,
61
+ attributes: toast_attrs,
62
+ data: toast_data
63
+ )
64
+ end
65
+
66
+ def toast_data
67
+ (bs_data || {}).tap do |hash|
68
+ hash["bs-delay"] = delay.nil? ? 5000 : delay
69
+ hash["bs-autohide"] = autohide.nil? ? "true" : "#{autohide}"
70
+ hash["bs-animation"] = animation.nil? ? "true" : "#{animation}"
71
+ end
72
+ end
73
+
74
+ def toast_attrs
75
+ (bs_attrs || {}).tap do |hash|
76
+ hash[:role] = (important == false ? 'status' : 'alert')
77
+ hash[:'aria-live'] = (important ? 'assertive' : 'polite') if important.present? && !placement.present?
78
+ hash[:'aria-live'] = 'assertive' unless important.present?
79
+ hash[:'aria-atomic'] = 'true' unless placement.present?
80
+ hash[:style] = "z-index: 10000; position: fixed; #{placement[:position] || 'top: 0; right: 0;' }" if placement.present?
81
+ hash["v-bind:class"] = "{'show' : showing }"
82
+ end
83
+ end
84
+
85
+ def toast_classes
86
+ [].tap do |classes|
87
+ classes << 'toast p-0 fade d-flex align-items-center border-0'
88
+ classes << bs_class
89
+ end.join(' ').strip
90
+ end
91
+
92
+ def placement_attrs
93
+ {}.tap do |hash|
94
+ hash[:'aria-live'] = (important ? 'assertive' : 'polite') if important.present?
95
+ hash[:'aria-atomic'] = 'true'
96
+ hash[:style] = "position: relative; min-height: #{placement[:height]};"
97
+ end
98
+ end
99
+ end