better_ui 0.1.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 +199 -75
- 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 +202 -0
- 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/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 +223 -0
- 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 +15 -0
- data/app/components/better_ui/general/breadcrumb_component.rb +130 -0
- data/app/components/better_ui/general/button_component.html.erb +34 -0
- data/app/components/better_ui/general/button_component.rb +162 -0
- data/app/components/better_ui/general/heading_component.html.erb +25 -0
- data/app/components/better_ui/general/heading_component.rb +148 -0
- data/app/components/better_ui/general/icon_component.html.erb +2 -0
- data/app/components/better_ui/general/icon_component.rb +100 -0
- 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.html.erb +27 -0
- data/app/components/better_ui/general/panel_component.rb +103 -0
- 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 +73 -0
- data/app/components/better_ui/general/table_component.rb +167 -0
- data/app/components/better_ui/theme_helper.rb +171 -0
- data/app/controllers/better_ui/application_controller.rb +1 -0
- data/app/controllers/better_ui/docs_controller.rb +18 -25
- 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/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 +18 -1
- 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 +135 -10
- 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,171 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
class AvatarComponent < ViewComponent::Base
|
4
|
+
attr_reader :name, :src, :size, :shape, :status, :status_position, :type, :classes, :id
|
5
|
+
|
6
|
+
# Temi di colore disponibili
|
7
|
+
AVATAR_THEME = {
|
8
|
+
default: "bui-avatar-default",
|
9
|
+
white: "bui-avatar-white",
|
10
|
+
red: "bui-avatar-red",
|
11
|
+
rose: "bui-avatar-rose",
|
12
|
+
orange: "bui-avatar-orange",
|
13
|
+
green: "bui-avatar-green",
|
14
|
+
blue: "bui-avatar-blue",
|
15
|
+
yellow: "bui-avatar-yellow",
|
16
|
+
violet: "bui-avatar-violet",
|
17
|
+
gray: "bui-avatar-gray"
|
18
|
+
}
|
19
|
+
|
20
|
+
# Dimensioni disponibili
|
21
|
+
AVATAR_SIZES = {
|
22
|
+
xxsmall: "bui-avatar-size-xxsmall",
|
23
|
+
xsmall: "bui-avatar-size-xsmall",
|
24
|
+
small: "bui-avatar-size-small",
|
25
|
+
medium: "bui-avatar-size-medium",
|
26
|
+
large: "bui-avatar-size-large",
|
27
|
+
xlarge: "bui-avatar-size-xlarge",
|
28
|
+
xxlarge: "bui-avatar-size-xxlarge"
|
29
|
+
}
|
30
|
+
|
31
|
+
# Forme disponibili
|
32
|
+
AVATAR_SHAPES = {
|
33
|
+
circle: "bui-avatar-shape-circle",
|
34
|
+
square: "bui-avatar-shape-square",
|
35
|
+
rounded: "bui-avatar-shape-rounded"
|
36
|
+
}
|
37
|
+
|
38
|
+
# Stati online disponibili
|
39
|
+
AVATAR_STATUS = {
|
40
|
+
online: "bui-avatar-status-online",
|
41
|
+
offline: "bui-avatar-status-offline",
|
42
|
+
busy: "bui-avatar-status-busy",
|
43
|
+
away: "bui-avatar-status-away"
|
44
|
+
}
|
45
|
+
|
46
|
+
# Posizioni dell'indicatore di stato
|
47
|
+
AVATAR_STATUS_POSITION = {
|
48
|
+
bottom_right: "bui-avatar-status-position-bottom-right",
|
49
|
+
bottom_left: "bui-avatar-status-position-bottom-left",
|
50
|
+
top_right: "bui-avatar-status-position-top-right",
|
51
|
+
top_left: "bui-avatar-status-position-top-left"
|
52
|
+
}
|
53
|
+
|
54
|
+
def initialize(
|
55
|
+
name: nil,
|
56
|
+
src: nil,
|
57
|
+
size: :medium,
|
58
|
+
shape: :circle,
|
59
|
+
status: nil,
|
60
|
+
status_position: :bottom_right,
|
61
|
+
type: :default,
|
62
|
+
classes: nil,
|
63
|
+
id: nil
|
64
|
+
)
|
65
|
+
@name = name
|
66
|
+
@src = src
|
67
|
+
@size = size.to_sym
|
68
|
+
@shape = shape.to_sym
|
69
|
+
@status = status&.to_sym
|
70
|
+
@status_position = status_position.to_sym
|
71
|
+
@type = type.to_sym
|
72
|
+
@classes = classes
|
73
|
+
@id = id
|
74
|
+
end
|
75
|
+
|
76
|
+
# Combina tutte le classi
|
77
|
+
def combined_classes
|
78
|
+
[
|
79
|
+
"bui-avatar", # Classe base per tutti gli avatar
|
80
|
+
get_avatar_theme_class,
|
81
|
+
get_avatar_size_class,
|
82
|
+
get_avatar_shape_class,
|
83
|
+
@classes
|
84
|
+
].compact.join(" ")
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_avatar_theme_class
|
88
|
+
AVATAR_THEME[@type] || AVATAR_THEME[:default]
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_avatar_size_class
|
92
|
+
AVATAR_SIZES[@size] || AVATAR_SIZES[:medium]
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_avatar_shape_class
|
96
|
+
AVATAR_SHAPES[@shape] || AVATAR_SHAPES[:circle]
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_avatar_status_class
|
100
|
+
AVATAR_STATUS[@status] || ""
|
101
|
+
end
|
102
|
+
|
103
|
+
def get_avatar_status_position_class
|
104
|
+
AVATAR_STATUS_POSITION[@status_position] || AVATAR_STATUS_POSITION[:bottom_right]
|
105
|
+
end
|
106
|
+
|
107
|
+
# Restituisce gli attributi per l'avatar
|
108
|
+
def avatar_attributes
|
109
|
+
attrs = {
|
110
|
+
class: combined_classes,
|
111
|
+
id: @id
|
112
|
+
}
|
113
|
+
|
114
|
+
attrs
|
115
|
+
end
|
116
|
+
|
117
|
+
# Restituisce le classi per l'indicatore di stato
|
118
|
+
def status_indicator_classes
|
119
|
+
[
|
120
|
+
"bui-avatar-status-indicator",
|
121
|
+
get_avatar_status_class,
|
122
|
+
get_avatar_status_position_class
|
123
|
+
].compact.join(" ")
|
124
|
+
end
|
125
|
+
|
126
|
+
# Determina se mostrare l'indicatore di stato
|
127
|
+
def show_status?
|
128
|
+
@status.present? && AVATAR_STATUS.key?(@status)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Ottiene le iniziali dal nome
|
132
|
+
def initials
|
133
|
+
return "" unless @name.present?
|
134
|
+
|
135
|
+
words = @name.strip.split(/\s+/)
|
136
|
+
if words.size >= 2
|
137
|
+
"#{words[0][0]}#{words[1][0]}".upcase
|
138
|
+
else
|
139
|
+
@name[0..1].upcase
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Determina se mostrare l'immagine
|
144
|
+
def show_image?
|
145
|
+
@src.present?
|
146
|
+
end
|
147
|
+
|
148
|
+
# Ottiene le dimensioni dell'avatar in pixel
|
149
|
+
def pixel_size
|
150
|
+
case @size
|
151
|
+
when :xxsmall
|
152
|
+
20
|
153
|
+
when :xsmall
|
154
|
+
24
|
155
|
+
when :small
|
156
|
+
32
|
157
|
+
when :medium
|
158
|
+
40
|
159
|
+
when :large
|
160
|
+
48
|
161
|
+
when :xlarge
|
162
|
+
64
|
163
|
+
when :xxlarge
|
164
|
+
96
|
165
|
+
else
|
166
|
+
40
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<span <%= badge_attributes.to_s.html_safe %>>
|
2
|
+
<% if @icon && @icon_position == :left %>
|
3
|
+
<span class="bui-badge-icon-left">
|
4
|
+
<%= render_icon(@icon) %>
|
5
|
+
</span>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<% if @label.present? %>
|
9
|
+
<span class="bui-badge-label"><%= @label %></span>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<% if @icon && @icon_position == :right %>
|
13
|
+
<span class="bui-badge-icon-right">
|
14
|
+
<%= render_icon(@icon) %>
|
15
|
+
</span>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<%= content %>
|
19
|
+
</span>
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
class BadgeComponent < ViewComponent::Base
|
4
|
+
attr_reader :label, :type, :size, :icon, :icon_position, :rounded, :notification, :outline, :classes, :id
|
5
|
+
|
6
|
+
# Temi di colore disponibili
|
7
|
+
BADGE_THEME = {
|
8
|
+
default: "bui-badge-default",
|
9
|
+
white: "bui-badge-white",
|
10
|
+
red: "bui-badge-red",
|
11
|
+
rose: "bui-badge-rose",
|
12
|
+
orange: "bui-badge-orange",
|
13
|
+
green: "bui-badge-green",
|
14
|
+
blue: "bui-badge-blue",
|
15
|
+
yellow: "bui-badge-yellow",
|
16
|
+
violet: "bui-badge-violet",
|
17
|
+
gray: "bui-badge-gray"
|
18
|
+
}
|
19
|
+
|
20
|
+
# Dimensioni disponibili
|
21
|
+
BADGE_SIZES = {
|
22
|
+
small: "bui-badge-size-small",
|
23
|
+
medium: "bui-badge-size-medium",
|
24
|
+
large: "bui-badge-size-large"
|
25
|
+
}
|
26
|
+
|
27
|
+
# Border radius disponibili
|
28
|
+
BADGE_RADIUS = {
|
29
|
+
none: "bui-badge-radius-none",
|
30
|
+
small: "bui-badge-radius-small",
|
31
|
+
medium: "bui-badge-radius-medium",
|
32
|
+
large: "bui-badge-radius-large",
|
33
|
+
full: "bui-badge-radius-full"
|
34
|
+
}
|
35
|
+
|
36
|
+
# Stati e varianti
|
37
|
+
BADGE_VARIANTS = {
|
38
|
+
outline: "bui-badge-outline",
|
39
|
+
notification: "bui-badge-notification"
|
40
|
+
}
|
41
|
+
|
42
|
+
# Inizializzazione del componente
|
43
|
+
def initialize(
|
44
|
+
label: nil,
|
45
|
+
type: :default,
|
46
|
+
size: :medium,
|
47
|
+
icon: nil,
|
48
|
+
icon_position: :left,
|
49
|
+
rounded: :medium,
|
50
|
+
notification: false,
|
51
|
+
outline: false,
|
52
|
+
classes: nil,
|
53
|
+
id: nil
|
54
|
+
)
|
55
|
+
@label = label
|
56
|
+
@type = type.to_sym
|
57
|
+
@size = size.to_sym
|
58
|
+
@icon = icon
|
59
|
+
@icon_position = icon_position.to_sym
|
60
|
+
@rounded = rounded.to_sym
|
61
|
+
@notification = notification
|
62
|
+
@outline = outline
|
63
|
+
@classes = classes
|
64
|
+
@id = id
|
65
|
+
end
|
66
|
+
|
67
|
+
# Combina tutte le classi
|
68
|
+
def combined_classes
|
69
|
+
[
|
70
|
+
"bui-badge", # Classe base per tutti i badge
|
71
|
+
get_badge_type_class,
|
72
|
+
get_badge_size_class,
|
73
|
+
get_border_radius_class,
|
74
|
+
@outline ? BADGE_VARIANTS[:outline] : "",
|
75
|
+
@notification ? BADGE_VARIANTS[:notification] : "",
|
76
|
+
@classes
|
77
|
+
].compact.join(" ")
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_badge_type_class
|
81
|
+
BADGE_THEME[@type] || BADGE_THEME[:default]
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_badge_size_class
|
85
|
+
BADGE_SIZES[@size] || BADGE_SIZES[:medium]
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_border_radius_class
|
89
|
+
BADGE_RADIUS[@rounded] || BADGE_RADIUS[:medium]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Restituisce gli attributi per il badge
|
93
|
+
def badge_attributes
|
94
|
+
attrs = {
|
95
|
+
class: combined_classes,
|
96
|
+
id: @id
|
97
|
+
}
|
98
|
+
|
99
|
+
attrs
|
100
|
+
end
|
101
|
+
|
102
|
+
# Helper per renderizzare le icone
|
103
|
+
def render_icon(icon_name)
|
104
|
+
# Mappa le dimensioni del badge alle dimensioni dell'icona
|
105
|
+
icon_size = case @size
|
106
|
+
when :large
|
107
|
+
:small
|
108
|
+
when :small
|
109
|
+
:tiny
|
110
|
+
else
|
111
|
+
:tiny
|
112
|
+
end
|
113
|
+
|
114
|
+
# Utilizziamo il componente Icon
|
115
|
+
render BetterUi::General::IconComponent.new(
|
116
|
+
name: icon_name,
|
117
|
+
size: icon_size,
|
118
|
+
fixed_width: true
|
119
|
+
)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<nav aria-label="Breadcrumb" class="<%= container_classes %>">
|
2
|
+
<ol class="bui-breadcrumb-list">
|
3
|
+
<% @items.each_with_index do |item, index| %>
|
4
|
+
<li class="bui-breadcrumb-item">
|
5
|
+
<%= render link_for_item(item, active: last_item?(index)) %>
|
6
|
+
|
7
|
+
<% unless last_item?(index) %>
|
8
|
+
<span class="<%= separator_classes %>" aria-hidden="true">
|
9
|
+
<%= separator_text %>
|
10
|
+
</span>
|
11
|
+
<% end %>
|
12
|
+
</li>
|
13
|
+
<% end %>
|
14
|
+
</ol>
|
15
|
+
</nav>
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
class BreadcrumbComponent < ViewComponent::Base
|
4
|
+
attr_reader :items, :separator, :size, :theme, :classes
|
5
|
+
|
6
|
+
# Temi di colore disponibili
|
7
|
+
BREADCRUMB_THEME = {
|
8
|
+
default: {
|
9
|
+
container: "bui-breadcrumb-default-container",
|
10
|
+
separator: "bui-breadcrumb-default-separator"
|
11
|
+
},
|
12
|
+
white: {
|
13
|
+
container: "bui-breadcrumb-white-container",
|
14
|
+
separator: "bui-breadcrumb-white-separator"
|
15
|
+
},
|
16
|
+
red: {
|
17
|
+
container: "bui-breadcrumb-red-container",
|
18
|
+
separator: "bui-breadcrumb-red-separator"
|
19
|
+
},
|
20
|
+
rose: {
|
21
|
+
container: "bui-breadcrumb-rose-container",
|
22
|
+
separator: "bui-breadcrumb-rose-separator"
|
23
|
+
},
|
24
|
+
orange: {
|
25
|
+
container: "bui-breadcrumb-orange-container",
|
26
|
+
separator: "bui-breadcrumb-orange-separator"
|
27
|
+
},
|
28
|
+
green: {
|
29
|
+
container: "bui-breadcrumb-green-container",
|
30
|
+
separator: "bui-breadcrumb-green-separator"
|
31
|
+
},
|
32
|
+
blue: {
|
33
|
+
container: "bui-breadcrumb-blue-container",
|
34
|
+
separator: "bui-breadcrumb-blue-separator"
|
35
|
+
},
|
36
|
+
yellow: {
|
37
|
+
container: "bui-breadcrumb-yellow-container",
|
38
|
+
separator: "bui-breadcrumb-yellow-separator"
|
39
|
+
},
|
40
|
+
violet: {
|
41
|
+
container: "bui-breadcrumb-violet-container",
|
42
|
+
separator: "bui-breadcrumb-violet-separator"
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
# Dimensioni disponibili
|
47
|
+
BREADCRUMB_SIZES = {
|
48
|
+
small: "bui-breadcrumb-small",
|
49
|
+
medium: "bui-breadcrumb-medium",
|
50
|
+
large: "bui-breadcrumb-large"
|
51
|
+
}
|
52
|
+
|
53
|
+
# Separatori predefiniti
|
54
|
+
BREADCRUMB_SEPARATORS = {
|
55
|
+
slash: "/",
|
56
|
+
chevron: "›",
|
57
|
+
arrow: "→",
|
58
|
+
dot: "•",
|
59
|
+
pipe: "|"
|
60
|
+
}
|
61
|
+
|
62
|
+
# Inizializzazione del componente
|
63
|
+
def initialize(
|
64
|
+
items: [],
|
65
|
+
separator: :chevron,
|
66
|
+
size: :medium,
|
67
|
+
theme: :default,
|
68
|
+
classes: nil
|
69
|
+
)
|
70
|
+
@items = items || []
|
71
|
+
@separator = separator.to_sym
|
72
|
+
@size = size.to_sym
|
73
|
+
@theme = theme.to_sym
|
74
|
+
@classes = classes
|
75
|
+
end
|
76
|
+
|
77
|
+
# Restituisce il separatore come stringa
|
78
|
+
def separator_text
|
79
|
+
if BREADCRUMB_SEPARATORS.key?(@separator)
|
80
|
+
BREADCRUMB_SEPARATORS[@separator]
|
81
|
+
else
|
82
|
+
@separator.to_s
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Genera le classi per il container
|
87
|
+
def container_classes
|
88
|
+
[
|
89
|
+
"bui-breadcrumb-container",
|
90
|
+
BREADCRUMB_SIZES.fetch(@size, BREADCRUMB_SIZES[:medium]),
|
91
|
+
BREADCRUMB_THEME.fetch(@theme, BREADCRUMB_THEME[:default])[:container],
|
92
|
+
@classes
|
93
|
+
].compact.join(" ")
|
94
|
+
end
|
95
|
+
|
96
|
+
# Genera le classi per il separatore
|
97
|
+
def separator_classes
|
98
|
+
[
|
99
|
+
"bui-breadcrumb-separator",
|
100
|
+
BREADCRUMB_THEME.fetch(@theme, BREADCRUMB_THEME[:default])[:separator]
|
101
|
+
].compact.join(" ")
|
102
|
+
end
|
103
|
+
|
104
|
+
# Verifica se un item è l'ultimo (attivo)
|
105
|
+
def last_item?(index)
|
106
|
+
index == @items.length - 1
|
107
|
+
end
|
108
|
+
|
109
|
+
# Crea un componente link per l'item
|
110
|
+
def link_for_item(item, active: false)
|
111
|
+
label = item.is_a?(Hash) ? item[:label] : item.to_s
|
112
|
+
href = item.is_a?(Hash) ? item[:url] : nil
|
113
|
+
icon = item.is_a?(Hash) ? item[:icon] : nil
|
114
|
+
|
115
|
+
BetterUi::General::LinkComponent.new(
|
116
|
+
label: label,
|
117
|
+
href: href,
|
118
|
+
theme: @theme,
|
119
|
+
icon: icon,
|
120
|
+
active: active
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Verifica se rendere il componente
|
125
|
+
def render?
|
126
|
+
@items.present? && @items.length > 0
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
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="bui-btn-icon-left"><%= 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="bui-btn-icon-right"><%= 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="bui-btn-icon-left"><%= 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="bui-btn-icon-right"><%= render_icon(@icon) %></span>
|
30
|
+
<% end %>
|
31
|
+
|
32
|
+
<%= content %>
|
33
|
+
<% end %>
|
34
|
+
<% end %>
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module BetterUi
|
2
|
+
module General
|
3
|
+
class ButtonComponent < ViewComponent::Base
|
4
|
+
attr_reader :label, :type, :size, :full_width, :disabled,
|
5
|
+
:icon, :icon_position, :href, :method, :data, :classes, :id, :rounded
|
6
|
+
|
7
|
+
# Temi di bottoni disponibili con classi CSS personalizzate
|
8
|
+
BUTTON_THEME = {
|
9
|
+
default: "bui-btn-default",
|
10
|
+
white: "bui-btn-white",
|
11
|
+
red: "bui-btn-red",
|
12
|
+
rose: "bui-btn-rose",
|
13
|
+
orange: "bui-btn-orange",
|
14
|
+
green: "bui-btn-green",
|
15
|
+
blue: "bui-btn-blue",
|
16
|
+
yellow: "bui-btn-yellow",
|
17
|
+
violet: "bui-btn-violet"
|
18
|
+
}
|
19
|
+
|
20
|
+
# Dimensioni disponibili con classi CSS personalizzate
|
21
|
+
BUTTON_SIZES = {
|
22
|
+
small: "bui-btn-size-small",
|
23
|
+
medium: "bui-btn-size-medium",
|
24
|
+
large: "bui-btn-size-large"
|
25
|
+
}
|
26
|
+
|
27
|
+
# Border radius disponibili con classi CSS personalizzate
|
28
|
+
BUTTON_RADIUS = {
|
29
|
+
none: "bui-btn-radius-none",
|
30
|
+
small: "bui-btn-radius-small",
|
31
|
+
medium: "bui-btn-radius-medium",
|
32
|
+
large: "bui-btn-radius-large",
|
33
|
+
full: "bui-btn-radius-full"
|
34
|
+
}
|
35
|
+
|
36
|
+
# Stati e comportamenti del bottone
|
37
|
+
BUTTON_STATES = {
|
38
|
+
disabled: "bui-btn-disabled",
|
39
|
+
full_width: "bui-btn-full-width"
|
40
|
+
}
|
41
|
+
|
42
|
+
# Layout e stili comuni
|
43
|
+
BUTTON_LAYOUT = {
|
44
|
+
default: "bui-btn-layout-default",
|
45
|
+
focus: "bui-btn-focus"
|
46
|
+
}
|
47
|
+
|
48
|
+
# Inizializzazione del componente
|
49
|
+
def initialize(
|
50
|
+
label: nil,
|
51
|
+
type: :default,
|
52
|
+
size: :medium,
|
53
|
+
full_width: false,
|
54
|
+
disabled: false,
|
55
|
+
icon: nil,
|
56
|
+
icon_position: :left,
|
57
|
+
href: nil,
|
58
|
+
method: nil,
|
59
|
+
data: {},
|
60
|
+
classes: nil,
|
61
|
+
id: nil,
|
62
|
+
rounded: :small
|
63
|
+
)
|
64
|
+
@label = label
|
65
|
+
@type = type.to_sym
|
66
|
+
@size = size.to_sym
|
67
|
+
@full_width = full_width
|
68
|
+
@disabled = disabled
|
69
|
+
@icon = icon
|
70
|
+
@icon_position = icon_position.to_sym
|
71
|
+
@href = href
|
72
|
+
@method = method
|
73
|
+
@data = data
|
74
|
+
@classes = classes
|
75
|
+
@id = id
|
76
|
+
@rounded = rounded.to_sym
|
77
|
+
end
|
78
|
+
|
79
|
+
# Determina se il bottone è un link o un button
|
80
|
+
def link?
|
81
|
+
@href.present?
|
82
|
+
end
|
83
|
+
|
84
|
+
# Combina tutte le classi
|
85
|
+
def combined_classes
|
86
|
+
[
|
87
|
+
"bui-btn", # Classe base per tutti i bottoni
|
88
|
+
BUTTON_LAYOUT[:default],
|
89
|
+
BUTTON_LAYOUT[:focus],
|
90
|
+
get_border_radius_class,
|
91
|
+
get_button_type_classes,
|
92
|
+
get_button_size_classes,
|
93
|
+
@full_width ? BUTTON_STATES[:full_width] : "",
|
94
|
+
@disabled ? BUTTON_STATES[:disabled] : "",
|
95
|
+
@classes
|
96
|
+
].compact.join(" ")
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_button_type_classes
|
100
|
+
BUTTON_THEME[@type] || BUTTON_THEME[:default]
|
101
|
+
end
|
102
|
+
|
103
|
+
def get_border_radius_class
|
104
|
+
BUTTON_RADIUS[@rounded] || BUTTON_RADIUS[:small]
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_button_size_classes
|
108
|
+
BUTTON_SIZES[@size] || BUTTON_SIZES[:medium]
|
109
|
+
end
|
110
|
+
|
111
|
+
# Restituisce gli attributi per il bottone
|
112
|
+
def button_attributes
|
113
|
+
attrs = {
|
114
|
+
class: combined_classes,
|
115
|
+
type: "button",
|
116
|
+
id: @id
|
117
|
+
}
|
118
|
+
|
119
|
+
attrs[:disabled] = true if @disabled
|
120
|
+
attrs[:data] = @data if @data.present?
|
121
|
+
attrs
|
122
|
+
end
|
123
|
+
|
124
|
+
# Restituisce gli attributi per il link
|
125
|
+
def link_attributes
|
126
|
+
attrs = {
|
127
|
+
class: combined_classes,
|
128
|
+
id: @id
|
129
|
+
}
|
130
|
+
|
131
|
+
attrs[:data] = @data.merge(turbo_method: @method) if @method.present?
|
132
|
+
attrs[:data] = @data if @data.present? && !@method.present?
|
133
|
+
attrs[:href] = @disabled ? nil : @href
|
134
|
+
attrs[:role] = "button"
|
135
|
+
attrs[:tabindex] = @disabled ? "-1" : "0"
|
136
|
+
attrs[:aria] = { disabled: @disabled } if @disabled
|
137
|
+
|
138
|
+
attrs
|
139
|
+
end
|
140
|
+
|
141
|
+
# Helper per renderizzare le icone
|
142
|
+
def render_icon(icon_name)
|
143
|
+
# Mappa le dimensioni del bottone alle dimensioni dell'icona
|
144
|
+
icon_size = case @size
|
145
|
+
when :large
|
146
|
+
:large
|
147
|
+
when :small
|
148
|
+
:small
|
149
|
+
else
|
150
|
+
:medium
|
151
|
+
end
|
152
|
+
|
153
|
+
# Utilizziamo il componente Icon
|
154
|
+
render BetterUi::General::IconComponent.new(
|
155
|
+
name: icon_name,
|
156
|
+
size: icon_size,
|
157
|
+
fixed_width: true
|
158
|
+
)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
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="bui-header-icon-container">
|
6
|
+
<span class="bui-header-icon-wrapper">
|
7
|
+
<%= render BetterUi::General::IconComponent.new(name: @icon, size: get_icon_size) %>
|
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>
|