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.
- checksums.yaml +4 -4
- data/README.md +65 -1
- data/app/assets/javascripts/better_ui/controllers/navbar_controller.js +138 -0
- data/app/assets/javascripts/better_ui/controllers/sidebar_controller.js +211 -0
- data/app/assets/javascripts/better_ui/controllers/toast_controller.js +161 -0
- data/app/assets/javascripts/better_ui/index.js +159 -0
- data/app/assets/javascripts/better_ui/toast_manager.js +77 -0
- data/app/assets/stylesheets/better_ui/application.css +25 -351
- data/app/components/better_ui/application/alert_component.html.erb +27 -0
- data/app/components/better_ui/application/alert_component.rb +196 -0
- data/app/components/better_ui/application/header_component.html.erb +88 -0
- data/app/components/better_ui/application/header_component.rb +188 -0
- data/app/components/better_ui/application/navbar_component.html.erb +294 -0
- data/app/components/better_ui/application/navbar_component.rb +249 -0
- data/app/components/better_ui/application/sidebar_component.html.erb +207 -0
- data/app/components/better_ui/application/sidebar_component.rb +318 -0
- data/app/components/better_ui/application/toast_component.html.erb +35 -0
- data/app/components/better_ui/application/toast_component.rb +188 -0
- data/app/components/better_ui/general/breadcrumb_component.html.erb +39 -0
- data/app/components/better_ui/general/breadcrumb_component.rb +132 -0
- data/app/components/better_ui/general/button_component.html.erb +34 -0
- data/app/components/better_ui/general/button_component.rb +193 -0
- data/app/components/better_ui/general/heading_component.html.erb +25 -0
- data/app/components/better_ui/general/heading_component.rb +142 -0
- data/app/components/better_ui/general/icon_component.html.erb +2 -0
- data/app/components/better_ui/general/icon_component.rb +101 -0
- data/app/components/better_ui/general/panel_component.html.erb +27 -0
- data/app/components/better_ui/general/panel_component.rb +97 -0
- data/app/components/better_ui/general/table_component.html.erb +37 -0
- data/app/components/better_ui/general/table_component.rb +141 -0
- data/app/components/better_ui/theme_helper.rb +169 -0
- data/app/controllers/better_ui/application_controller.rb +1 -0
- data/app/controllers/better_ui/docs_controller.rb +18 -25
- data/app/helpers/better_ui_application_helper.rb +99 -0
- data/app/views/layouts/component_preview.html.erb +32 -0
- data/config/initializers/lookbook.rb +23 -0
- data/config/routes.rb +6 -1
- data/lib/better_ui/engine.rb +24 -1
- data/lib/better_ui/version.rb +1 -1
- metadata +103 -7
- data/app/helpers/better_ui/application_helper.rb +0 -183
- data/app/views/better_ui/docs/component.html.erb +0 -365
- data/app/views/better_ui/docs/index.html.erb +0 -100
- data/app/views/better_ui/docs/show.html.erb +0 -60
- 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>
|