better_ui 0.4.0 → 0.5.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 +165 -105
- data/app/components/better_ui/application/alert_component.html.erb +1 -1
- data/app/components/better_ui/application/alert_component.rb +95 -89
- data/app/components/better_ui/application/card_component.html.erb +24 -0
- data/app/components/better_ui/application/card_component.rb +53 -0
- data/app/components/better_ui/application/card_container_component.html.erb +8 -0
- data/app/components/better_ui/application/card_container_component.rb +14 -0
- data/app/components/better_ui/application/toast_component.rb +92 -57
- data/app/components/better_ui/general/avatar_component.html.erb +19 -0
- data/app/components/better_ui/general/avatar_component.rb +171 -0
- data/app/components/better_ui/general/badge_component.html.erb +19 -0
- data/app/components/better_ui/general/badge_component.rb +123 -0
- data/app/components/better_ui/general/breadcrumb_component.html.erb +7 -31
- data/app/components/better_ui/general/breadcrumb_component.rb +64 -66
- data/app/components/better_ui/general/button_component.html.erb +4 -4
- data/app/components/better_ui/general/button_component.rb +64 -95
- data/app/components/better_ui/general/heading_component.html.erb +3 -3
- data/app/components/better_ui/general/heading_component.rb +76 -70
- data/app/components/better_ui/general/icon_component.html.erb +1 -1
- data/app/components/better_ui/general/icon_component.rb +22 -23
- data/app/components/better_ui/general/link_component.html.erb +17 -0
- data/app/components/better_ui/general/link_component.rb +132 -0
- data/app/components/better_ui/general/panel_component.rb +62 -56
- data/app/components/better_ui/general/spinner_component.html.erb +15 -0
- data/app/components/better_ui/general/spinner_component.rb +79 -0
- data/app/components/better_ui/general/table_component.html.erb +56 -20
- data/app/components/better_ui/general/table_component.rb +106 -80
- data/app/components/better_ui/theme_helper.rb +77 -75
- data/app/views/components/better_ui/general/table/_custom_body_row.html.erb +17 -0
- data/app/views/components/better_ui/general/table/_custom_footer_rows.html.erb +17 -0
- data/app/views/components/better_ui/general/table/_custom_header_rows.html.erb +12 -0
- data/lib/better_ui/engine.rb +4 -10
- data/lib/better_ui/version.rb +1 -1
- data/lib/better_ui.rb +4 -0
- data/lib/generators/better_ui/stylesheet_generator.rb +96 -0
- data/lib/generators/better_ui/templates/README +56 -0
- data/lib/generators/better_ui/templates/components/_avatar.scss +151 -0
- data/lib/generators/better_ui/templates/components/_badge.scss +142 -0
- data/lib/generators/better_ui/templates/components/_breadcrumb.scss +107 -0
- data/lib/generators/better_ui/templates/components/_button.scss +106 -0
- data/lib/generators/better_ui/templates/components/_card.scss +69 -0
- data/lib/generators/better_ui/templates/components/_heading.scss +180 -0
- data/lib/generators/better_ui/templates/components/_icon.scss +90 -0
- data/lib/generators/better_ui/templates/components/_link.scss +130 -0
- data/lib/generators/better_ui/templates/components/_panel.scss +144 -0
- data/lib/generators/better_ui/templates/components/_spinner.scss +132 -0
- data/lib/generators/better_ui/templates/components/_table.scss +105 -0
- data/lib/generators/better_ui/templates/components/_variables.scss +33 -0
- data/lib/generators/better_ui/templates/components_stylesheet.scss +66 -0
- metadata +51 -22
- data/app/helpers/better_ui_application_helper.rb +0 -99
@@ -0,0 +1,132 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
class LinkComponent < ViewComponent::Base
|
4
|
+
attr_reader :label, :href, :theme, :icon, :classes, :active, :data, :method, :target
|
5
|
+
|
6
|
+
# Temi di colore disponibili
|
7
|
+
LINK_THEME = {
|
8
|
+
default: {
|
9
|
+
link: "bui-link-default-link",
|
10
|
+
active: "bui-link-default-active",
|
11
|
+
text: "bui-link-default-text"
|
12
|
+
},
|
13
|
+
white: {
|
14
|
+
link: "bui-link-white-link",
|
15
|
+
active: "bui-link-white-active",
|
16
|
+
text: "bui-link-white-text"
|
17
|
+
},
|
18
|
+
red: {
|
19
|
+
link: "bui-link-red-link",
|
20
|
+
active: "bui-link-red-active",
|
21
|
+
text: "bui-link-red-text"
|
22
|
+
},
|
23
|
+
rose: {
|
24
|
+
link: "bui-link-rose-link",
|
25
|
+
active: "bui-link-rose-active",
|
26
|
+
text: "bui-link-rose-text"
|
27
|
+
},
|
28
|
+
orange: {
|
29
|
+
link: "bui-link-orange-link",
|
30
|
+
active: "bui-link-orange-active",
|
31
|
+
text: "bui-link-orange-text"
|
32
|
+
},
|
33
|
+
green: {
|
34
|
+
link: "bui-link-green-link",
|
35
|
+
active: "bui-link-green-active",
|
36
|
+
text: "bui-link-green-text"
|
37
|
+
},
|
38
|
+
blue: {
|
39
|
+
link: "bui-link-blue-link",
|
40
|
+
active: "bui-link-blue-active",
|
41
|
+
text: "bui-link-blue-text"
|
42
|
+
},
|
43
|
+
yellow: {
|
44
|
+
link: "bui-link-yellow-link",
|
45
|
+
active: "bui-link-yellow-active",
|
46
|
+
text: "bui-link-yellow-text"
|
47
|
+
},
|
48
|
+
violet: {
|
49
|
+
link: "bui-link-violet-link",
|
50
|
+
active: "bui-link-violet-active",
|
51
|
+
text: "bui-link-violet-text"
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
# Inizializzazione del componente
|
56
|
+
def initialize(
|
57
|
+
label:,
|
58
|
+
href: nil,
|
59
|
+
theme: :default,
|
60
|
+
icon: nil,
|
61
|
+
classes: nil,
|
62
|
+
active: false,
|
63
|
+
data: {},
|
64
|
+
method: nil,
|
65
|
+
target: nil
|
66
|
+
)
|
67
|
+
@label = label
|
68
|
+
@href = href
|
69
|
+
@theme = theme.to_sym
|
70
|
+
@icon = icon
|
71
|
+
@classes = classes
|
72
|
+
@active = active
|
73
|
+
@data = data || {}
|
74
|
+
@method = method
|
75
|
+
@target = target
|
76
|
+
end
|
77
|
+
|
78
|
+
# Determina se è un link attivo/corrente
|
79
|
+
def active?
|
80
|
+
@active
|
81
|
+
end
|
82
|
+
|
83
|
+
# Determina se è un link o solo testo
|
84
|
+
def link?
|
85
|
+
@href.present?
|
86
|
+
end
|
87
|
+
|
88
|
+
# Genera le classi per il componente
|
89
|
+
def component_classes
|
90
|
+
theme_classes = LINK_THEME.fetch(@theme, LINK_THEME[:default])
|
91
|
+
|
92
|
+
base_classes = ["bui-link-base"]
|
93
|
+
|
94
|
+
if active?
|
95
|
+
base_classes << theme_classes[:active]
|
96
|
+
elsif link?
|
97
|
+
base_classes << theme_classes[:link]
|
98
|
+
else
|
99
|
+
base_classes << theme_classes[:text]
|
100
|
+
end
|
101
|
+
|
102
|
+
base_classes << @classes if @classes.present?
|
103
|
+
|
104
|
+
base_classes.compact.join(" ")
|
105
|
+
end
|
106
|
+
|
107
|
+
# Restituisce gli attributi per il link
|
108
|
+
def link_attributes
|
109
|
+
attrs = {
|
110
|
+
class: component_classes
|
111
|
+
}
|
112
|
+
|
113
|
+
attrs[:data] = @data.merge(turbo_method: @method) if @method.present?
|
114
|
+
attrs[:data] = @data if @data.present? && !@method.present?
|
115
|
+
attrs[:target] = @target if @target.present?
|
116
|
+
|
117
|
+
attrs
|
118
|
+
end
|
119
|
+
|
120
|
+
# Renderizza l'icona
|
121
|
+
def render_icon
|
122
|
+
return nil unless @icon.present?
|
123
|
+
|
124
|
+
if @icon.is_a?(String)
|
125
|
+
render BetterUi::General::IconComponent.new(name: @icon)
|
126
|
+
else
|
127
|
+
@icon # Assumiamo che sia già un componente renderizzato
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -1,92 +1,98 @@
|
|
1
1
|
module BetterUi
|
2
2
|
module General
|
3
3
|
class PanelComponent < ViewComponent::Base
|
4
|
-
attr_reader :header, :footer, :body, :title, :padding, :variant
|
4
|
+
attr_reader :header, :footer, :body, :title, :padding, :variant, :rounded
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
# Opzioni di padding disponibili
|
7
|
+
PANEL_PADDING = {
|
8
|
+
none: 'bui-panel-padding-none',
|
9
|
+
small: 'bui-panel-padding-small',
|
10
|
+
medium: 'bui-panel-padding-medium',
|
11
|
+
large: 'bui-panel-padding-large'
|
11
12
|
}.freeze
|
12
13
|
|
13
|
-
|
14
|
+
# Temi di colore per l'header
|
15
|
+
PANEL_HEADER_THEME = {
|
16
|
+
default: 'bui-panel-default-header',
|
17
|
+
white: 'bui-panel-white-header',
|
18
|
+
red: 'bui-panel-red-header',
|
19
|
+
rose: 'bui-panel-rose-header',
|
20
|
+
orange: 'bui-panel-orange-header',
|
21
|
+
green: 'bui-panel-green-header',
|
22
|
+
blue: 'bui-panel-blue-header',
|
23
|
+
yellow: 'bui-panel-yellow-header',
|
24
|
+
violet: 'bui-panel-violet-header'
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
# Temi di colore per il footer
|
28
|
+
PANEL_FOOTER_THEME = {
|
29
|
+
default: 'bui-panel-default-footer',
|
30
|
+
white: 'bui-panel-white-footer',
|
31
|
+
red: 'bui-panel-red-footer',
|
32
|
+
rose: 'bui-panel-rose-footer',
|
33
|
+
orange: 'bui-panel-orange-footer',
|
34
|
+
green: 'bui-panel-green-footer',
|
35
|
+
blue: 'bui-panel-blue-footer',
|
36
|
+
yellow: 'bui-panel-yellow-footer',
|
37
|
+
violet: 'bui-panel-violet-footer'
|
38
|
+
}.freeze
|
39
|
+
|
40
|
+
# Opzioni di bordi arrotondati standardizzati
|
41
|
+
PANEL_RADIUS = {
|
42
|
+
none: 'bui-panel-radius-none',
|
43
|
+
small: 'bui-panel-radius-small',
|
44
|
+
medium: 'bui-panel-radius-medium',
|
45
|
+
large: 'bui-panel-radius-large',
|
46
|
+
full: 'bui-panel-radius-full'
|
47
|
+
}.freeze
|
48
|
+
|
49
|
+
def initialize(title: nil, body: nil, header: nil, footer: nil, padding: :medium, variant: :default, rounded: :small)
|
14
50
|
@title = title
|
15
51
|
@body = body
|
16
52
|
@header = header
|
17
53
|
@footer = footer
|
18
54
|
@padding = padding.to_sym
|
19
55
|
@variant = variant.to_sym
|
56
|
+
@rounded = rounded.to_sym
|
20
57
|
end
|
21
58
|
|
22
59
|
def panel_classes
|
23
|
-
|
60
|
+
[
|
61
|
+
'bui-panel-base',
|
62
|
+
get_border_radius_class
|
63
|
+
].compact.join(' ')
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_border_radius_class
|
67
|
+
PANEL_RADIUS[@rounded] || PANEL_RADIUS[:small]
|
24
68
|
end
|
25
69
|
|
26
70
|
def header_classes
|
27
71
|
[
|
28
|
-
'panel-header',
|
29
|
-
|
30
|
-
|
31
|
-
PADDING_OPTIONS.fetch(@padding, PADDING_OPTIONS[:medium])
|
72
|
+
'bui-panel-header',
|
73
|
+
PANEL_HEADER_THEME[@variant] || PANEL_HEADER_THEME[:default],
|
74
|
+
PANEL_PADDING.fetch(@padding, PANEL_PADDING[:medium])
|
32
75
|
].compact.join(' ')
|
33
76
|
end
|
34
77
|
|
35
78
|
def body_classes
|
36
79
|
[
|
37
|
-
'panel-body',
|
38
|
-
|
39
|
-
|
40
|
-
PADDING_OPTIONS.fetch(@padding, PADDING_OPTIONS[:medium])
|
80
|
+
'bui-panel-body',
|
81
|
+
'bui-panel-body-content',
|
82
|
+
PANEL_PADDING.fetch(@padding, PANEL_PADDING[:medium])
|
41
83
|
].compact.join(' ')
|
42
84
|
end
|
43
85
|
|
44
86
|
def footer_classes
|
45
87
|
[
|
46
|
-
'panel-footer',
|
47
|
-
|
48
|
-
|
49
|
-
'overflow-x-auto break-words',
|
50
|
-
PADDING_OPTIONS.fetch(@padding, PADDING_OPTIONS[:medium])
|
88
|
+
'bui-panel-footer',
|
89
|
+
PANEL_FOOTER_THEME[@variant] || PANEL_FOOTER_THEME[:default],
|
90
|
+
PANEL_PADDING.fetch(@padding, PANEL_PADDING[:medium])
|
51
91
|
].compact.join(' ')
|
52
92
|
end
|
53
93
|
|
54
94
|
def title_classes
|
55
|
-
'
|
56
|
-
end
|
57
|
-
|
58
|
-
def header_color_classes
|
59
|
-
case @variant
|
60
|
-
when :primary
|
61
|
-
'bg-orange-50 text-orange-700'
|
62
|
-
when :success
|
63
|
-
'bg-green-50 text-green-700'
|
64
|
-
when :warning
|
65
|
-
'bg-amber-50 text-amber-700'
|
66
|
-
when :danger
|
67
|
-
'bg-red-50 text-red-700'
|
68
|
-
when :info
|
69
|
-
'bg-blue-50 text-blue-700'
|
70
|
-
else
|
71
|
-
'bg-gray-50 text-gray-700'
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def footer_color_classes
|
76
|
-
case @variant
|
77
|
-
when :primary
|
78
|
-
'bg-orange-50 text-orange-600'
|
79
|
-
when :success
|
80
|
-
'bg-green-50 text-green-600'
|
81
|
-
when :warning
|
82
|
-
'bg-amber-50 text-amber-600'
|
83
|
-
when :danger
|
84
|
-
'bg-red-50 text-red-600'
|
85
|
-
when :info
|
86
|
-
'bg-blue-50 text-blue-600'
|
87
|
-
else
|
88
|
-
'bg-gray-50 text-gray-600'
|
89
|
-
end
|
95
|
+
'bui-panel-title'
|
90
96
|
end
|
91
97
|
|
92
98
|
def render?
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<div <%= spinner_attributes.to_s.html_safe %>>
|
2
|
+
<div class="bui-spinner-animation"></div>
|
3
|
+
|
4
|
+
<% if @label.present? %>
|
5
|
+
<div class="bui-spinner-label">
|
6
|
+
<%= @label %>
|
7
|
+
</div>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% if content.present? %>
|
11
|
+
<div class="bui-spinner-content">
|
12
|
+
<%= content %>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
class SpinnerComponent < ViewComponent::Base
|
4
|
+
attr_reader :size, :theme, :fullscreen, :label, :classes, :id
|
5
|
+
|
6
|
+
# Temi di colore disponibili
|
7
|
+
SPINNER_THEME = {
|
8
|
+
default: "bui-spinner-default",
|
9
|
+
white: "bui-spinner-white",
|
10
|
+
red: "bui-spinner-red",
|
11
|
+
rose: "bui-spinner-rose",
|
12
|
+
orange: "bui-spinner-orange",
|
13
|
+
green: "bui-spinner-green",
|
14
|
+
blue: "bui-spinner-blue",
|
15
|
+
yellow: "bui-spinner-yellow",
|
16
|
+
violet: "bui-spinner-violet"
|
17
|
+
}
|
18
|
+
|
19
|
+
# Dimensioni disponibili
|
20
|
+
SPINNER_SIZES = {
|
21
|
+
small: "bui-spinner-small",
|
22
|
+
medium: "bui-spinner-medium",
|
23
|
+
large: "bui-spinner-large"
|
24
|
+
}
|
25
|
+
|
26
|
+
# Stati e comportamenti dello spinner
|
27
|
+
SPINNER_STATES = {
|
28
|
+
fullscreen: "bui-spinner-fullscreen"
|
29
|
+
}
|
30
|
+
|
31
|
+
# Inizializzazione del componente
|
32
|
+
def initialize(
|
33
|
+
size: :medium,
|
34
|
+
theme: :default,
|
35
|
+
fullscreen: false,
|
36
|
+
label: nil,
|
37
|
+
classes: nil,
|
38
|
+
id: nil
|
39
|
+
)
|
40
|
+
@size = size.to_sym
|
41
|
+
@theme = theme.to_sym
|
42
|
+
@fullscreen = fullscreen
|
43
|
+
@label = label
|
44
|
+
@classes = classes
|
45
|
+
@id = id
|
46
|
+
end
|
47
|
+
|
48
|
+
# Combina tutte le classi
|
49
|
+
def combined_classes
|
50
|
+
[
|
51
|
+
"bui-spinner", # Classe base per tutti gli spinner
|
52
|
+
get_spinner_theme_class,
|
53
|
+
get_spinner_size_class,
|
54
|
+
@fullscreen ? SPINNER_STATES[:fullscreen] : "",
|
55
|
+
@classes
|
56
|
+
].compact.join(" ")
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_spinner_theme_class
|
60
|
+
SPINNER_THEME[@theme] || SPINNER_THEME[:default]
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_spinner_size_class
|
64
|
+
SPINNER_SIZES[@size] || SPINNER_SIZES[:medium]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Restituisce gli attributi per lo spinner
|
68
|
+
def spinner_attributes
|
69
|
+
attrs = {
|
70
|
+
class: combined_classes,
|
71
|
+
id: @id,
|
72
|
+
role: "status"
|
73
|
+
}
|
74
|
+
|
75
|
+
attrs
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -7,31 +7,67 @@
|
|
7
7
|
<% end %>
|
8
8
|
|
9
9
|
<thead class="<%= thead_classes %>">
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
<% if header_rows_partial.present? %>
|
11
|
+
<%= render partial: header_rows_partial, locals: {
|
12
|
+
component: self,
|
13
|
+
headers: headers_for_display
|
14
|
+
} %>
|
15
|
+
<% else %>
|
16
|
+
<tr>
|
17
|
+
<% headers_for_display.each do |header| %>
|
18
|
+
<th scope="col" class="<%= th_classes %>">
|
19
|
+
<%= header.to_s.humanize %>
|
20
|
+
</th>
|
21
|
+
<% end %>
|
22
|
+
</tr>
|
23
|
+
<% end %>
|
17
24
|
</thead>
|
18
25
|
|
19
26
|
<tbody class="<%= tbody_classes %>">
|
20
27
|
<% data.each_with_index do |row, index| %>
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
<% if body_row_partial.present? %>
|
29
|
+
<%= render partial: body_row_partial, locals: {
|
30
|
+
component: self,
|
31
|
+
row: row,
|
32
|
+
index: index,
|
33
|
+
headers: headers_for_display
|
34
|
+
} %>
|
35
|
+
<% else %>
|
36
|
+
<tr class="<%= tr_classes(index) %>">
|
37
|
+
<% headers_for_display.each do |header| %>
|
38
|
+
<td class="<%= td_classes %>">
|
39
|
+
<% if row.is_a?(Hash) %>
|
40
|
+
<%= row[header.to_s] || row[header.to_sym] %>
|
41
|
+
<% elsif row.respond_to?(header.to_sym) %>
|
42
|
+
<%= row.send(header.to_sym) %>
|
43
|
+
<% else %>
|
44
|
+
—
|
45
|
+
<% end %>
|
46
|
+
</td>
|
47
|
+
<% end %>
|
48
|
+
</tr>
|
49
|
+
<% end %>
|
34
50
|
<% end %>
|
35
51
|
</tbody>
|
52
|
+
|
53
|
+
<% if footer.present? %>
|
54
|
+
<tfoot class="<%= tfoot_classes %>">
|
55
|
+
<% if footer_rows_partial.present? %>
|
56
|
+
<%= render partial: footer_rows_partial, locals: {
|
57
|
+
component: self,
|
58
|
+
footer: footer,
|
59
|
+
headers: headers_for_display
|
60
|
+
} %>
|
61
|
+
<% else %>
|
62
|
+
<tr>
|
63
|
+
<% footer.each_with_index do |value, index| %>
|
64
|
+
<td class="<%= tf_classes %>">
|
65
|
+
<%= value || "—" %>
|
66
|
+
</td>
|
67
|
+
<% end %>
|
68
|
+
</tr>
|
69
|
+
<% end %>
|
70
|
+
</tfoot>
|
71
|
+
<% end %>
|
36
72
|
</table>
|
37
73
|
</div>
|