better_ui 0.1.0 → 0.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +65 -1
  3. data/app/assets/javascripts/better_ui/controllers/navbar_controller.js +138 -0
  4. data/app/assets/javascripts/better_ui/controllers/sidebar_controller.js +211 -0
  5. data/app/assets/javascripts/better_ui/controllers/toast_controller.js +161 -0
  6. data/app/assets/javascripts/better_ui/index.js +159 -0
  7. data/app/assets/javascripts/better_ui/toast_manager.js +77 -0
  8. data/app/assets/stylesheets/better_ui/application.css +25 -351
  9. data/app/components/better_ui/application/alert_component.html.erb +27 -0
  10. data/app/components/better_ui/application/alert_component.rb +196 -0
  11. data/app/components/better_ui/application/header_component.html.erb +88 -0
  12. data/app/components/better_ui/application/header_component.rb +188 -0
  13. data/app/components/better_ui/application/navbar_component.html.erb +294 -0
  14. data/app/components/better_ui/application/navbar_component.rb +249 -0
  15. data/app/components/better_ui/application/sidebar_component.html.erb +207 -0
  16. data/app/components/better_ui/application/sidebar_component.rb +318 -0
  17. data/app/components/better_ui/application/toast_component.html.erb +35 -0
  18. data/app/components/better_ui/application/toast_component.rb +188 -0
  19. data/app/components/better_ui/general/breadcrumb_component.html.erb +39 -0
  20. data/app/components/better_ui/general/breadcrumb_component.rb +132 -0
  21. data/app/components/better_ui/general/button_component.html.erb +34 -0
  22. data/app/components/better_ui/general/button_component.rb +193 -0
  23. data/app/components/better_ui/general/heading_component.html.erb +25 -0
  24. data/app/components/better_ui/general/heading_component.rb +142 -0
  25. data/app/components/better_ui/general/icon_component.html.erb +2 -0
  26. data/app/components/better_ui/general/icon_component.rb +101 -0
  27. data/app/components/better_ui/general/panel_component.html.erb +27 -0
  28. data/app/components/better_ui/general/panel_component.rb +97 -0
  29. data/app/components/better_ui/general/table_component.html.erb +37 -0
  30. data/app/components/better_ui/general/table_component.rb +141 -0
  31. data/app/components/better_ui/theme_helper.rb +169 -0
  32. data/app/controllers/better_ui/application_controller.rb +1 -0
  33. data/app/controllers/better_ui/docs_controller.rb +18 -25
  34. data/app/helpers/better_ui_application_helper.rb +99 -0
  35. data/app/views/layouts/component_preview.html.erb +32 -0
  36. data/config/initializers/lookbook.rb +23 -0
  37. data/config/routes.rb +6 -1
  38. data/lib/better_ui/engine.rb +24 -1
  39. data/lib/better_ui/version.rb +1 -1
  40. metadata +103 -7
  41. data/app/helpers/better_ui/application_helper.rb +0 -183
  42. data/app/views/better_ui/docs/component.html.erb +0 -365
  43. data/app/views/better_ui/docs/index.html.erb +0 -100
  44. data/app/views/better_ui/docs/show.html.erb +0 -60
  45. data/app/views/layouts/better_ui/application.html.erb +0 -135
@@ -0,0 +1,188 @@
1
+ module BetterUi
2
+ module Application
3
+ class ToastComponent < ViewComponent::Base
4
+ attr_reader :title, :message, :variant, :icon, :dismissible, :classes, :data, :position, :duration, :auto_hide
5
+
6
+ # Varianti di colore disponibili
7
+ VARIANTS = {
8
+ primary: {
9
+ bg: "bg-orange-50",
10
+ border: "border-orange-300",
11
+ title: "text-orange-800",
12
+ text: "text-orange-700",
13
+ icon: "text-orange-500",
14
+ close: "text-orange-500 hover:bg-orange-100"
15
+ },
16
+ info: {
17
+ bg: "bg-blue-50",
18
+ border: "border-blue-300",
19
+ title: "text-blue-800",
20
+ text: "text-blue-700",
21
+ icon: "text-blue-500",
22
+ close: "text-blue-500 hover:bg-blue-100"
23
+ },
24
+ success: {
25
+ bg: "bg-green-50",
26
+ border: "border-green-300",
27
+ title: "text-green-800",
28
+ text: "text-green-700",
29
+ icon: "text-green-500",
30
+ close: "text-green-500 hover:bg-green-100"
31
+ },
32
+ warning: {
33
+ bg: "bg-yellow-50",
34
+ border: "border-yellow-300",
35
+ title: "text-yellow-800",
36
+ text: "text-yellow-700",
37
+ icon: "text-yellow-500",
38
+ close: "text-yellow-500 hover:bg-yellow-100"
39
+ },
40
+ danger: {
41
+ bg: "bg-red-50",
42
+ border: "border-red-300",
43
+ title: "text-red-800",
44
+ text: "text-red-700",
45
+ icon: "text-red-500",
46
+ close: "text-red-500 hover:bg-red-100"
47
+ },
48
+ dark: {
49
+ bg: "bg-gray-800",
50
+ border: "border-gray-700",
51
+ title: "text-white",
52
+ text: "text-gray-300",
53
+ icon: "text-gray-400",
54
+ close: "text-gray-400 hover:bg-gray-700"
55
+ }
56
+ }
57
+
58
+ # Icone predefinite per ciascuna variante
59
+ DEFAULT_ICONS = {
60
+ primary: "bell",
61
+ info: "info-circle",
62
+ success: "check-circle",
63
+ warning: "exclamation-triangle",
64
+ danger: "exclamation-circle",
65
+ dark: "shield-exclamation"
66
+ }
67
+
68
+ # Posizioni possibili per i toast
69
+ POSITIONS = {
70
+ "top-right": "top-right",
71
+ "top-left": "top-left",
72
+ "bottom-right": "bottom-right",
73
+ "bottom-left": "bottom-left",
74
+ "top-center": "top-center",
75
+ "bottom-center": "bottom-center"
76
+ }
77
+
78
+ # Inizializzazione del componente
79
+ def initialize(
80
+ title: nil,
81
+ message: nil,
82
+ variant: :info,
83
+ icon: nil,
84
+ dismissible: true,
85
+ classes: nil,
86
+ data: {},
87
+ position: :"top-right",
88
+ duration: 5000,
89
+ auto_hide: true
90
+ )
91
+ @title = title
92
+ @message = message
93
+ @variant = variant.to_sym
94
+ @icon = icon
95
+ @dismissible = dismissible
96
+ @classes = classes
97
+ @data = data || {}
98
+ @position = position.to_sym
99
+ @duration = duration
100
+ @auto_hide = auto_hide
101
+
102
+ # Aggiungiamo dati per il comportamento del toast
103
+ @data[:controller] = "toast" if @data[:controller].blank?
104
+ @data[:toast_duration_value] = @duration if @auto_hide
105
+ @data[:toast_auto_hide_value] = @auto_hide.to_s
106
+ @data[:toast_position_value] = @position.to_s
107
+ end
108
+
109
+ # Genera l'icona in base alla variante se non specificata
110
+ def effective_icon
111
+ return @icon if @icon.present?
112
+ DEFAULT_ICONS[@variant]
113
+ end
114
+
115
+ # Genera le classi per il container
116
+ def container_classes
117
+ styles = VARIANTS.fetch(@variant, VARIANTS[:info])
118
+ position_class = POSITIONS.fetch(@position, POSITIONS[:"top-right"])
119
+
120
+ [
121
+ "fixed z-50 rounded-lg p-4 border shadow-lg",
122
+ "transform transition-transform duration-300",
123
+ "data-toast-enter-from-class='translate-y-2 opacity-0'",
124
+ "data-toast-enter-to-class='translate-y-0 opacity-100'",
125
+ "data-toast-leave-from-class='translate-y-0 opacity-100'",
126
+ "data-toast-leave-to-class='translate-y-2 opacity-0'",
127
+ styles[:bg],
128
+ styles[:border],
129
+ position_class,
130
+ "min-w-[20rem] max-w-sm",
131
+ "flex items-start",
132
+ @classes
133
+ ].compact.join(" ")
134
+ end
135
+
136
+ # Genera le classi per il titolo
137
+ def title_classes
138
+ styles = VARIANTS.fetch(@variant, VARIANTS[:info])
139
+
140
+ [
141
+ "font-medium",
142
+ styles[:title]
143
+ ].compact.join(" ")
144
+ end
145
+
146
+ # Genera le classi per il messaggio
147
+ def message_classes
148
+ styles = VARIANTS.fetch(@variant, VARIANTS[:info])
149
+
150
+ [
151
+ "mt-1",
152
+ styles[:text]
153
+ ].compact.join(" ")
154
+ end
155
+
156
+ # Genera le classi per l'icona
157
+ def icon_classes
158
+ styles = VARIANTS.fetch(@variant, VARIANTS[:info])
159
+
160
+ [
161
+ "flex-shrink-0",
162
+ "mr-3 mt-0.5",
163
+ styles[:icon]
164
+ ].compact.join(" ")
165
+ end
166
+
167
+ # Genera le classi per il pulsante di chiusura
168
+ def close_button_classes
169
+ styles = VARIANTS.fetch(@variant, VARIANTS[:info])
170
+
171
+ [
172
+ "ml-auto -mr-1.5 -mt-1.5 inline-flex h-8 w-8 rounded-lg p-1.5 focus:ring-2 focus:ring-gray-400",
173
+ styles[:close]
174
+ ].compact.join(" ")
175
+ end
176
+
177
+ # Genera le classi per il contenuto
178
+ def content_classes
179
+ "flex-1"
180
+ end
181
+
182
+ # Verifica se il componente deve essere reso
183
+ def render?
184
+ @title.present? || @message.present? || content.present?
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,39 @@
1
+ <nav aria-label="Breadcrumb" class="<%= container_classes %>">
2
+ <ol class="flex flex-wrap items-center">
3
+ <% @items.each_with_index do |item, index| %>
4
+ <li class="flex items-center">
5
+ <% if last_item?(index) %>
6
+ <span class="<%= item_classes(true) %> flex items-center" aria-current="page">
7
+ <% if item_icon(item) %>
8
+ <span class="mr-1.5"><%= item_icon(item) %></span>
9
+ <% end %>
10
+ <%= item_text(item) %>
11
+ </span>
12
+ <% else %>
13
+ <% url = item_url(item) %>
14
+ <% if url.present? %>
15
+ <%= link_to url, class: "#{item_classes} flex items-center" do %>
16
+ <% if item_icon(item) %>
17
+ <span class="mr-1.5"><%= item_icon(item) %></span>
18
+ <% end %>
19
+ <%= item_text(item) %>
20
+ <% end %>
21
+ <% else %>
22
+ <span class="<%= item_classes %> flex items-center">
23
+ <% if item_icon(item) %>
24
+ <span class="mr-1.5"><%= item_icon(item) %></span>
25
+ <% end %>
26
+ <%= item_text(item) %>
27
+ </span>
28
+ <% end %>
29
+
30
+ <% unless last_item?(index) %>
31
+ <span class="<%= separator_classes %>" aria-hidden="true">
32
+ <%= separator_text %>
33
+ </span>
34
+ <% end %>
35
+ <% end %>
36
+ </li>
37
+ <% end %>
38
+ </ol>
39
+ </nav>
@@ -0,0 +1,132 @@
1
+ module BetterUi
2
+ module General
3
+ class BreadcrumbComponent < ViewComponent::Base
4
+ attr_reader :items, :separator, :size, :variant, :classes, :inverse
5
+
6
+ # Varianti di colore disponibili
7
+ VARIANTS = {
8
+ default: {
9
+ container: "text-gray-600",
10
+ item: "text-gray-500 hover:text-gray-700",
11
+ active: "text-gray-900 font-medium",
12
+ separator: "text-gray-400"
13
+ },
14
+ primary: {
15
+ container: "text-orange-600",
16
+ item: "text-orange-500 hover:text-orange-700",
17
+ active: "text-orange-800 font-medium",
18
+ separator: "text-orange-300"
19
+ },
20
+ light: {
21
+ container: "text-gray-100",
22
+ item: "text-gray-200 hover:text-white",
23
+ active: "text-white font-medium",
24
+ separator: "text-gray-300"
25
+ }
26
+ }
27
+
28
+ # Dimensioni disponibili
29
+ SIZES = {
30
+ sm: "text-xs",
31
+ md: "text-sm",
32
+ lg: "text-base"
33
+ }
34
+
35
+ # Separatori predefiniti
36
+ SEPARATORS = {
37
+ slash: "/",
38
+ chevron: "›",
39
+ arrow: "→",
40
+ dot: "•",
41
+ pipe: "|"
42
+ }
43
+
44
+ # Inizializzazione del componente
45
+ def initialize(
46
+ items: [],
47
+ separator: :chevron,
48
+ size: :md,
49
+ variant: :default,
50
+ classes: nil,
51
+ inverse: false
52
+ )
53
+ @items = items || []
54
+ @separator = separator.to_sym
55
+ @size = size.to_sym
56
+ @variant = variant.to_sym
57
+ @classes = classes
58
+ @inverse = inverse
59
+ end
60
+
61
+ # Restituisce il separatore come stringa
62
+ def separator_text
63
+ if SEPARATORS.key?(@separator)
64
+ SEPARATORS[@separator]
65
+ else
66
+ @separator.to_s
67
+ end
68
+ end
69
+
70
+ # Genera le classi per il container
71
+ def container_classes
72
+ [
73
+ "flex items-center flex-wrap",
74
+ SIZES.fetch(@size, SIZES[:md]),
75
+ VARIANTS.fetch(@variant, VARIANTS[:default])[:container],
76
+ @inverse ? "bg-gray-800 p-2 rounded" : "",
77
+ @classes
78
+ ].compact.join(" ")
79
+ end
80
+
81
+ # Genera le classi per un elemento
82
+ def item_classes(active = false)
83
+ variant_classes = VARIANTS.fetch(@variant, VARIANTS[:default])
84
+
85
+ if active
86
+ variant_classes[:active]
87
+ else
88
+ variant_classes[:item]
89
+ end
90
+ end
91
+
92
+ # Genera le classi per il separatore
93
+ def separator_classes
94
+ [
95
+ "mx-2",
96
+ VARIANTS.fetch(@variant, VARIANTS[:default])[:separator]
97
+ ].compact.join(" ")
98
+ end
99
+
100
+ # Verifica se un item è l'ultimo (attivo)
101
+ def last_item?(index)
102
+ index == @items.length - 1
103
+ end
104
+
105
+ # Formatta il testo dell'item
106
+ def item_text(item)
107
+ item.is_a?(Hash) ? item[:label] : item.to_s
108
+ end
109
+
110
+ # Restituisce l'URL dell'item
111
+ def item_url(item)
112
+ item.is_a?(Hash) ? item[:url] : nil
113
+ end
114
+
115
+ # Restituisce l'icona dell'item se presente
116
+ def item_icon(item)
117
+ return nil unless item.is_a?(Hash) && item[:icon].present?
118
+
119
+ if item[:icon].is_a?(String)
120
+ render BetterUi::General::IconComponent.new(name: item[:icon])
121
+ else
122
+ item[:icon] # Assumiamo che sia già un componente renderizzato
123
+ end
124
+ end
125
+
126
+ # Verifica se rendere il componente
127
+ def render?
128
+ @items.present? && @items.length > 0
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,34 @@
1
+ <%# Template per il bottone %>
2
+ <% if link? %>
3
+ <%= link_to @href, **link_attributes do %>
4
+ <% if @icon && @icon_position == :left %>
5
+ <span class="mr-2"><%= render_icon(@icon) %></span>
6
+ <% end %>
7
+
8
+ <% if @label %>
9
+ <span><%= @label %></span>
10
+ <% end %>
11
+
12
+ <% if @icon && @icon_position == :right %>
13
+ <span class="ml-2"><%= render_icon(@icon) %></span>
14
+ <% end %>
15
+
16
+ <%= content %>
17
+ <% end %>
18
+ <% else %>
19
+ <%= tag.button(**button_attributes) do %>
20
+ <% if @icon && @icon_position == :left %>
21
+ <span class="mr-2"><%= render_icon(@icon) %></span>
22
+ <% end %>
23
+
24
+ <% if @label %>
25
+ <span><%= @label %></span>
26
+ <% end %>
27
+
28
+ <% if @icon && @icon_position == :right %>
29
+ <span class="ml-2"><%= render_icon(@icon) %></span>
30
+ <% end %>
31
+
32
+ <%= content %>
33
+ <% end %>
34
+ <% end %>
@@ -0,0 +1,193 @@
1
+ module BetterUi
2
+ module General
3
+ class ButtonComponent < ViewComponent::Base
4
+ attr_reader :label, :type, :size, :outline, :full_width, :disabled,
5
+ :icon, :icon_position, :href, :method, :data, :classes, :id
6
+
7
+ # Tipi di bottoni disponibili con classi Tailwind staticamente definite
8
+ BUTTON_TYPES = {
9
+ primary: "bg-blue-600 hover:bg-blue-700 text-white",
10
+ secondary: "bg-gray-200 hover:bg-gray-300 text-gray-800",
11
+ success: "bg-green-600 hover:bg-green-700 text-white",
12
+ danger: "bg-red-600 hover:bg-red-700 text-white",
13
+ warning: "bg-yellow-500 hover:bg-yellow-600 text-white",
14
+ info: "bg-sky-500 hover:bg-sky-600 text-white",
15
+ light: "bg-white hover:bg-gray-100 text-gray-800 border border-gray-300",
16
+ dark: "bg-gray-800 hover:bg-gray-900 text-white"
17
+ }
18
+
19
+ # Classi per bottoni outline
20
+ OUTLINE_BUTTON_TYPES = {
21
+ primary: "bg-transparent text-blue-600 border-blue-600 border hover:text-white hover:bg-blue-600",
22
+ secondary: "bg-transparent text-gray-800 border-gray-200 border hover:text-white hover:bg-gray-200",
23
+ success: "bg-transparent text-green-600 border-green-600 border hover:text-white hover:bg-green-600",
24
+ danger: "bg-transparent text-red-600 border-red-600 border hover:text-white hover:bg-red-600",
25
+ warning: "bg-transparent text-yellow-500 border-yellow-500 border hover:text-white hover:bg-yellow-500",
26
+ info: "bg-transparent text-sky-500 border-sky-500 border hover:text-white hover:bg-sky-500",
27
+ light: "bg-transparent text-gray-800 border-gray-300 border hover:text-gray-900 hover:bg-gray-100",
28
+ dark: "bg-transparent text-gray-800 border-gray-800 border hover:text-white hover:bg-gray-800"
29
+ }
30
+
31
+ # Dimensioni disponibili
32
+ BUTTON_SIZES = {
33
+ sm: "py-1 px-2 text-sm",
34
+ md: "py-2 px-4 text-base",
35
+ lg: "py-3 px-6 text-lg"
36
+ }
37
+
38
+ # Inizializzazione del componente
39
+ def initialize(
40
+ label: nil,
41
+ type: :primary,
42
+ size: :md,
43
+ outline: false,
44
+ full_width: false,
45
+ disabled: false,
46
+ icon: nil,
47
+ icon_position: :left,
48
+ href: nil,
49
+ method: nil,
50
+ data: {},
51
+ classes: nil,
52
+ id: nil
53
+ )
54
+ @label = label
55
+ @type = type.to_sym
56
+ @size = size.to_sym
57
+ @outline = outline
58
+ @full_width = full_width
59
+ @disabled = disabled
60
+ @icon = icon
61
+ @icon_position = icon_position.to_sym
62
+ @href = href
63
+ @method = method
64
+ @data = data
65
+ @classes = classes
66
+ @id = id
67
+ end
68
+
69
+ # Determina se il bottone è un link o un button
70
+ def link?
71
+ @href.present?
72
+ end
73
+
74
+ # Combina tutte le classi
75
+ def combined_classes
76
+ [
77
+ "inline-flex items-center justify-center rounded-md font-medium",
78
+ "transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",
79
+ get_button_type_classes,
80
+ get_button_size_classes,
81
+ @full_width ? "w-full" : "",
82
+ @disabled ? "opacity-50 cursor-not-allowed" : "",
83
+ @classes
84
+ ].compact.join(" ")
85
+ end
86
+
87
+ def get_button_type_classes
88
+ if @outline
89
+ get_outline_button_classes
90
+ else
91
+ get_solid_button_classes
92
+ end
93
+ end
94
+
95
+ def get_solid_button_classes
96
+ case @type
97
+ when :primary
98
+ "bg-orange-500 text-white hover:bg-orange-600 focus:ring-orange-500"
99
+ when :secondary
100
+ "bg-gray-200 text-gray-800 hover:bg-gray-300 focus:ring-gray-300"
101
+ when :success
102
+ "bg-green-500 text-white hover:bg-green-600 focus:ring-green-500"
103
+ when :danger
104
+ "bg-red-500 text-white hover:bg-red-600 focus:ring-red-500"
105
+ when :warning
106
+ "bg-amber-500 text-white hover:bg-amber-600 focus:ring-amber-500"
107
+ when :info
108
+ "bg-blue-500 text-white hover:bg-blue-600 focus:ring-blue-500"
109
+ when :light
110
+ "bg-white text-gray-800 border border-gray-300 hover:bg-gray-100 focus:ring-gray-300"
111
+ when :dark
112
+ "bg-gray-800 text-white hover:bg-gray-900 focus:ring-gray-800"
113
+ else
114
+ "bg-orange-500 text-white hover:bg-orange-600 focus:ring-orange-500"
115
+ end
116
+ end
117
+
118
+ def get_outline_button_classes
119
+ case @type
120
+ when :primary
121
+ "bg-transparent text-orange-500 border-2 border-orange-500 hover:bg-orange-50 focus:ring-orange-500"
122
+ when :secondary
123
+ "bg-transparent text-gray-800 border-2 border-gray-300 hover:bg-gray-50 focus:ring-gray-300"
124
+ when :success
125
+ "bg-transparent text-green-500 border-2 border-green-500 hover:bg-green-50 focus:ring-green-500"
126
+ when :danger
127
+ "bg-transparent text-red-500 border-2 border-red-500 hover:bg-red-50 focus:ring-red-500"
128
+ when :warning
129
+ "bg-transparent text-amber-500 border-2 border-amber-500 hover:bg-amber-50 focus:ring-amber-500"
130
+ when :info
131
+ "bg-transparent text-blue-500 border-2 border-blue-500 hover:bg-blue-50 focus:ring-blue-500"
132
+ when :light
133
+ "bg-transparent text-gray-800 border-2 border-gray-300 hover:bg-gray-50 focus:ring-gray-300"
134
+ when :dark
135
+ "bg-transparent text-gray-800 border-2 border-gray-800 hover:bg-gray-50 focus:ring-gray-800"
136
+ else
137
+ "bg-transparent text-orange-500 border-2 border-orange-500 hover:bg-orange-50 focus:ring-orange-500"
138
+ end
139
+ end
140
+
141
+ def get_button_size_classes
142
+ case @size
143
+ when :sm
144
+ "py-1 px-2.5 text-xs"
145
+ when :lg
146
+ "py-2.5 px-6 text-base"
147
+ else # :md
148
+ "py-2 px-4 text-sm"
149
+ end
150
+ end
151
+
152
+ # Restituisce gli attributi per il bottone
153
+ def button_attributes
154
+ attrs = {
155
+ class: combined_classes,
156
+ type: "button",
157
+ id: @id
158
+ }
159
+
160
+ attrs[:disabled] = true if @disabled
161
+ attrs[:data] = @data if @data.present?
162
+ attrs
163
+ end
164
+
165
+ # Restituisce gli attributi per il link
166
+ def link_attributes
167
+ attrs = {
168
+ class: combined_classes,
169
+ id: @id
170
+ }
171
+
172
+ attrs[:data] = @data.merge(turbo_method: @method) if @method.present?
173
+ attrs[:data] = @data if @data.present? && !@method.present?
174
+ attrs[:href] = @disabled ? nil : @href
175
+ attrs[:role] = "button"
176
+ attrs[:tabindex] = @disabled ? "-1" : "0"
177
+ attrs[:aria] = { disabled: @disabled } if @disabled
178
+
179
+ attrs
180
+ end
181
+
182
+ # Helper per renderizzare le icone
183
+ def render_icon(icon_name)
184
+ # Utilizziamo il componente Icon
185
+ render BetterUi::General::IconComponent.new(
186
+ name: icon_name,
187
+ size: @size == :lg ? :lg : :md,
188
+ fixed_width: true
189
+ )
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,25 @@
1
+ <div class="<%= container_classes %>">
2
+ <%# Utilizzo di tag heading dinamico in base al livello specificato %>
3
+ <<%= "h#{@level}" %> class="<%= heading_classes %>">
4
+ <% if @icon.present? %>
5
+ <span class="inline-flex items-center">
6
+ <span class="mr-2">
7
+ <%= render BetterUi::General::IconComponent.new(name: @icon) %>
8
+ </span>
9
+ <%= @text || content %>
10
+ </span>
11
+ <% else %>
12
+ <%= @text || content %>
13
+ <% end %>
14
+ </<%= "h#{@level}" %>>
15
+
16
+ <% if @subtitle.present? %>
17
+ <div class="<%= subtitle_classes %>">
18
+ <%= @subtitle %>
19
+ </div>
20
+ <% end %>
21
+
22
+ <% if @with_divider %>
23
+ <div class="<%= divider_classes %>"></div>
24
+ <% end %>
25
+ </div>