better_ui 0.3.0 → 0.5.1

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.

Potentially problematic release.


This version of better_ui might be problematic. Click here for more details.

Files changed (231) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +140 -230
  4. data/app/assets/stylesheets/better_ui/_base.scss +9 -0
  5. data/app/assets/stylesheets/better_ui/_components.scss +2 -0
  6. data/app/assets/stylesheets/better_ui/_utilities.scss +14 -0
  7. data/app/assets/stylesheets/better_ui/application.css +32 -0
  8. data/app/assets/stylesheets/better_ui/components/_avatar.scss +200 -0
  9. data/app/assets/stylesheets/better_ui/components/_badge.scss +154 -0
  10. data/app/assets/stylesheets/better_ui/components/_breadcrumb.scss +106 -0
  11. data/app/assets/stylesheets/better_ui/components/_button.scss +105 -0
  12. data/app/assets/stylesheets/better_ui/components/_card.scss +60 -0
  13. data/app/assets/stylesheets/better_ui/components/_heading.scss +81 -0
  14. data/app/assets/stylesheets/better_ui/components/_icon.scss +134 -0
  15. data/app/assets/stylesheets/better_ui/components/_index.scss +17 -0
  16. data/app/assets/stylesheets/better_ui/components/_link.scss +100 -0
  17. data/app/assets/stylesheets/better_ui/components/_panel.scss +104 -0
  18. data/app/assets/stylesheets/better_ui/components/_spinner.scss +129 -0
  19. data/app/assets/stylesheets/better_ui/components/_table.scss +156 -0
  20. data/app/assets/stylesheets/better_ui/components/_variables.scss +1 -0
  21. data/app/assets/stylesheets/better_ui.scss +4 -0
  22. data/app/components/better_ui/application/alert_component.html.erb +27 -0
  23. data/app/components/better_ui/application/alert_component.rb +202 -0
  24. data/app/components/better_ui/application/card_component.html.erb +24 -0
  25. data/app/components/better_ui/application/card_component.rb +53 -0
  26. data/app/components/better_ui/application/card_container_component.html.erb +8 -0
  27. data/app/components/better_ui/application/card_container_component.rb +14 -0
  28. data/app/components/better_ui/application/header_component.html.erb +88 -0
  29. data/app/components/better_ui/application/header_component.rb +188 -0
  30. data/app/components/better_ui/application/navbar_component.html.erb +294 -0
  31. data/app/components/better_ui/application/navbar_component.rb +249 -0
  32. data/app/components/better_ui/application/sidebar_component.html.erb +207 -0
  33. data/app/components/better_ui/application/sidebar_component.rb +318 -0
  34. data/app/components/better_ui/application/toast_component.html.erb +35 -0
  35. data/app/components/better_ui/application/toast_component.rb +223 -0
  36. data/app/components/better_ui/general/avatar_component.html.erb +19 -0
  37. data/app/components/better_ui/general/avatar_component.rb +171 -0
  38. data/app/components/better_ui/general/{badge/component.html.erb → badge_component.html.erb} +2 -6
  39. data/app/components/better_ui/general/badge_component.rb +135 -0
  40. data/app/components/better_ui/general/{breadcrumb/component.html.erb → breadcrumb_component.html.erb} +4 -4
  41. data/app/components/better_ui/general/breadcrumb_component.rb +130 -0
  42. data/app/components/better_ui/general/{button/component.html.erb → button_component.html.erb} +7 -7
  43. data/app/components/better_ui/general/button_component.rb +160 -0
  44. data/app/components/better_ui/general/heading_component.html.erb +1 -0
  45. data/app/components/better_ui/general/heading_component.rb +49 -0
  46. data/app/components/better_ui/general/icon_component.html.erb +2 -0
  47. data/app/components/better_ui/general/icon_component.rb +77 -0
  48. data/app/components/better_ui/general/link_component.html.erb +17 -0
  49. data/app/components/better_ui/general/link_component.rb +132 -0
  50. data/app/components/better_ui/general/panel_component.html.erb +27 -0
  51. data/app/components/better_ui/general/panel_component.rb +92 -0
  52. data/app/components/better_ui/general/spinner_component.html.erb +15 -0
  53. data/app/components/better_ui/general/spinner_component.rb +79 -0
  54. data/app/components/better_ui/general/table_component.html.erb +73 -0
  55. data/app/components/better_ui/general/table_component.rb +143 -0
  56. data/app/controllers/better_ui/application_controller.rb +1 -0
  57. data/app/helpers/better_ui/general/components/avatar_helper.rb +17 -0
  58. data/app/helpers/better_ui/general/components/badge_helper.rb +17 -0
  59. data/app/helpers/better_ui/general/components/breadcrumb_helper.rb +17 -0
  60. data/app/helpers/better_ui/general/components/button_helper.rb +17 -0
  61. data/app/helpers/better_ui/general/components/heading_helper.rb +17 -0
  62. data/app/helpers/better_ui/general/components/icon_helper.rb +17 -0
  63. data/app/helpers/better_ui/general/components/link_helper.rb +17 -0
  64. data/app/helpers/better_ui/general/components/panel_helper.rb +16 -0
  65. data/app/helpers/better_ui/general/components/spinner_helper.rb +17 -0
  66. data/app/helpers/better_ui/general/components/table_helper.rb +17 -0
  67. data/app/helpers/better_ui/general_helper.rb +15 -0
  68. data/app/helpers/better_ui_helper.rb +12 -0
  69. data/app/views/components/better_ui/general/table/_custom_body_row.html.erb +17 -0
  70. data/app/views/components/better_ui/general/table/_custom_footer_rows.html.erb +17 -0
  71. data/app/views/components/better_ui/general/table/_custom_header_rows.html.erb +12 -0
  72. data/app/views/layouts/component_preview.html.erb +32 -0
  73. data/config/initializers/lookbook.rb +12 -12
  74. data/config/routes.rb +2 -0
  75. data/lib/better_ui/engine.rb +92 -5
  76. data/lib/better_ui/version.rb +1 -1
  77. data/lib/better_ui.rb +32 -4
  78. data/lib/generators/better_ui/install_generator.rb +103 -0
  79. data/lib/generators/better_ui/stylesheet_generator.rb +159 -0
  80. data/lib/generators/better_ui/templates/README +125 -0
  81. data/lib/generators/better_ui/templates/components/_avatar.scss +200 -0
  82. data/lib/generators/better_ui/templates/components/_badge.scss +154 -0
  83. data/lib/generators/better_ui/templates/components/_breadcrumb.scss +106 -0
  84. data/lib/generators/better_ui/templates/components/_button.scss +109 -0
  85. data/lib/generators/better_ui/templates/components/_card.scss +60 -0
  86. data/lib/generators/better_ui/templates/components/_heading.scss +81 -0
  87. data/lib/generators/better_ui/templates/components/_icon.scss +134 -0
  88. data/lib/generators/better_ui/templates/components/_index.scss +17 -0
  89. data/lib/generators/better_ui/templates/components/_link.scss +100 -0
  90. data/lib/generators/better_ui/templates/components/_panel.scss +104 -0
  91. data/lib/generators/better_ui/templates/components/_spinner.scss +129 -0
  92. data/lib/generators/better_ui/templates/components/_table.scss +156 -0
  93. data/lib/generators/better_ui/templates/components/_variables.scss +0 -0
  94. data/lib/generators/better_ui/templates/components_stylesheet.scss +35 -0
  95. data/lib/generators/better_ui/templates/index.scss +18 -0
  96. data/lib/generators/better_ui/templates/initializer.rb +41 -0
  97. metadata +178 -147
  98. data/app/components/better_ui/application/card/component.html.erb +0 -20
  99. data/app/components/better_ui/application/card/component.rb +0 -214
  100. data/app/components/better_ui/application/main/component.html.erb +0 -9
  101. data/app/components/better_ui/application/main/component.rb +0 -123
  102. data/app/components/better_ui/application/navbar/component.html.erb +0 -92
  103. data/app/components/better_ui/application/navbar/component.rb +0 -136
  104. data/app/components/better_ui/application/sidebar/component.html.erb +0 -227
  105. data/app/components/better_ui/application/sidebar/component.rb +0 -130
  106. data/app/components/better_ui/general/accordion/component.html.erb +0 -5
  107. data/app/components/better_ui/general/accordion/component.rb +0 -92
  108. data/app/components/better_ui/general/accordion/item_component.html.erb +0 -12
  109. data/app/components/better_ui/general/accordion/item_component.rb +0 -176
  110. data/app/components/better_ui/general/alert/component.html.erb +0 -32
  111. data/app/components/better_ui/general/alert/component.rb +0 -242
  112. data/app/components/better_ui/general/avatar/component.html.erb +0 -20
  113. data/app/components/better_ui/general/avatar/component.rb +0 -301
  114. data/app/components/better_ui/general/badge/component.rb +0 -248
  115. data/app/components/better_ui/general/breadcrumb/component.rb +0 -187
  116. data/app/components/better_ui/general/button/component.rb +0 -214
  117. data/app/components/better_ui/general/divider/component.html.erb +0 -10
  118. data/app/components/better_ui/general/divider/component.rb +0 -226
  119. data/app/components/better_ui/general/dropdown/component.html.erb +0 -25
  120. data/app/components/better_ui/general/dropdown/component.rb +0 -170
  121. data/app/components/better_ui/general/dropdown/divider_component.html.erb +0 -1
  122. data/app/components/better_ui/general/dropdown/divider_component.rb +0 -41
  123. data/app/components/better_ui/general/dropdown/item_component.html.erb +0 -6
  124. data/app/components/better_ui/general/dropdown/item_component.rb +0 -119
  125. data/app/components/better_ui/general/field/component.html.erb +0 -27
  126. data/app/components/better_ui/general/field/component.rb +0 -37
  127. data/app/components/better_ui/general/heading/component.html.erb +0 -22
  128. data/app/components/better_ui/general/heading/component.rb +0 -257
  129. data/app/components/better_ui/general/icon/component.html.erb +0 -7
  130. data/app/components/better_ui/general/icon/component.rb +0 -239
  131. data/app/components/better_ui/general/input/checkbox/component.html.erb +0 -5
  132. data/app/components/better_ui/general/input/checkbox/component.rb +0 -238
  133. data/app/components/better_ui/general/input/datetime/component.html.erb +0 -5
  134. data/app/components/better_ui/general/input/datetime/component.rb +0 -223
  135. data/app/components/better_ui/general/input/radio/component.html.erb +0 -5
  136. data/app/components/better_ui/general/input/radio/component.rb +0 -230
  137. data/app/components/better_ui/general/input/select/component.html.erb +0 -16
  138. data/app/components/better_ui/general/input/select/component.rb +0 -184
  139. data/app/components/better_ui/general/input/select/select_component.html.erb +0 -5
  140. data/app/components/better_ui/general/input/select/select_component.rb +0 -37
  141. data/app/components/better_ui/general/input/text/component.html.erb +0 -5
  142. data/app/components/better_ui/general/input/text/component.rb +0 -171
  143. data/app/components/better_ui/general/input/textarea/component.html.erb +0 -5
  144. data/app/components/better_ui/general/input/textarea/component.rb +0 -166
  145. data/app/components/better_ui/general/link/component.html.erb +0 -18
  146. data/app/components/better_ui/general/link/component.rb +0 -258
  147. data/app/components/better_ui/general/modal/component.html.erb +0 -5
  148. data/app/components/better_ui/general/modal/component.rb +0 -47
  149. data/app/components/better_ui/general/modal/modal_component.html.erb +0 -52
  150. data/app/components/better_ui/general/modal/modal_component.rb +0 -160
  151. data/app/components/better_ui/general/pagination/component.html.erb +0 -85
  152. data/app/components/better_ui/general/pagination/component.rb +0 -216
  153. data/app/components/better_ui/general/panel/component.html.erb +0 -28
  154. data/app/components/better_ui/general/panel/component.rb +0 -249
  155. data/app/components/better_ui/general/progress/component.html.erb +0 -11
  156. data/app/components/better_ui/general/progress/component.rb +0 -160
  157. data/app/components/better_ui/general/spinner/component.html.erb +0 -35
  158. data/app/components/better_ui/general/spinner/component.rb +0 -93
  159. data/app/components/better_ui/general/table/component.html.erb +0 -5
  160. data/app/components/better_ui/general/table/component.rb +0 -217
  161. data/app/components/better_ui/general/table/tbody_component.html.erb +0 -3
  162. data/app/components/better_ui/general/table/tbody_component.rb +0 -30
  163. data/app/components/better_ui/general/table/td_component.html.erb +0 -3
  164. data/app/components/better_ui/general/table/td_component.rb +0 -44
  165. data/app/components/better_ui/general/table/tfoot_component.html.erb +0 -3
  166. data/app/components/better_ui/general/table/tfoot_component.rb +0 -28
  167. data/app/components/better_ui/general/table/th_component.html.erb +0 -6
  168. data/app/components/better_ui/general/table/th_component.rb +0 -51
  169. data/app/components/better_ui/general/table/thead_component.html.erb +0 -3
  170. data/app/components/better_ui/general/table/thead_component.rb +0 -28
  171. data/app/components/better_ui/general/table/tr_component.html.erb +0 -3
  172. data/app/components/better_ui/general/table/tr_component.rb +0 -30
  173. data/app/components/better_ui/general/tabs/component.html.erb +0 -11
  174. data/app/components/better_ui/general/tabs/component.rb +0 -120
  175. data/app/components/better_ui/general/tabs/panel_component.html.erb +0 -3
  176. data/app/components/better_ui/general/tabs/panel_component.rb +0 -37
  177. data/app/components/better_ui/general/tabs/tab_component.html.erb +0 -13
  178. data/app/components/better_ui/general/tabs/tab_component.rb +0 -111
  179. data/app/components/better_ui/general/tag/component.html.erb +0 -3
  180. data/app/components/better_ui/general/tag/component.rb +0 -104
  181. data/app/components/better_ui/general/tooltip/component.html.erb +0 -7
  182. data/app/components/better_ui/general/tooltip/component.rb +0 -239
  183. data/app/helpers/better_ui/application/components/card/card_helper.rb +0 -96
  184. data/app/helpers/better_ui/application/components/card.rb +0 -11
  185. data/app/helpers/better_ui/application/components/main/main_helper.rb +0 -64
  186. data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +0 -77
  187. data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +0 -51
  188. data/app/helpers/better_ui/application_helper.rb +0 -55
  189. data/app/helpers/better_ui/general/components/accordion/accordion_helper.rb +0 -73
  190. data/app/helpers/better_ui/general/components/accordion.rb +0 -11
  191. data/app/helpers/better_ui/general/components/alert/alert_helper.rb +0 -57
  192. data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +0 -29
  193. data/app/helpers/better_ui/general/components/badge/badge_helper.rb +0 -53
  194. data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +0 -37
  195. data/app/helpers/better_ui/general/components/button/button_helper.rb +0 -65
  196. data/app/helpers/better_ui/general/components/container/container_helper.rb +0 -60
  197. data/app/helpers/better_ui/general/components/divider/divider_helper.rb +0 -63
  198. data/app/helpers/better_ui/general/components/dropdown/divider_helper.rb +0 -32
  199. data/app/helpers/better_ui/general/components/dropdown/dropdown_helper.rb +0 -79
  200. data/app/helpers/better_ui/general/components/dropdown/item_helper.rb +0 -62
  201. data/app/helpers/better_ui/general/components/field/field_helper.rb +0 -26
  202. data/app/helpers/better_ui/general/components/heading/heading_helper.rb +0 -72
  203. data/app/helpers/better_ui/general/components/icon/icon_helper.rb +0 -16
  204. data/app/helpers/better_ui/general/components/input/checkbox/checkbox_helper.rb +0 -81
  205. data/app/helpers/better_ui/general/components/input/datetime/datetime_helper.rb +0 -91
  206. data/app/helpers/better_ui/general/components/input/radio/radio_helper.rb +0 -79
  207. data/app/helpers/better_ui/general/components/input/radio_group/radio_group_helper.rb +0 -124
  208. data/app/helpers/better_ui/general/components/input/select/select_helper.rb +0 -70
  209. data/app/helpers/better_ui/general/components/input/text/text_helper.rb +0 -138
  210. data/app/helpers/better_ui/general/components/input/textarea/textarea_helper.rb +0 -73
  211. data/app/helpers/better_ui/general/components/link/link_helper.rb +0 -89
  212. data/app/helpers/better_ui/general/components/modal/modal_helper.rb +0 -85
  213. data/app/helpers/better_ui/general/components/modal.rb +0 -11
  214. data/app/helpers/better_ui/general/components/pagination/pagination_helper.rb +0 -82
  215. data/app/helpers/better_ui/general/components/panel/panel_helper.rb +0 -83
  216. data/app/helpers/better_ui/general/components/progress/progress_helper.rb +0 -53
  217. data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +0 -19
  218. data/app/helpers/better_ui/general/components/table/table_helper.rb +0 -53
  219. data/app/helpers/better_ui/general/components/table/tbody_helper.rb +0 -13
  220. data/app/helpers/better_ui/general/components/table/td_helper.rb +0 -19
  221. data/app/helpers/better_ui/general/components/table/tfoot_helper.rb +0 -13
  222. data/app/helpers/better_ui/general/components/table/th_helper.rb +0 -19
  223. data/app/helpers/better_ui/general/components/table/thead_helper.rb +0 -13
  224. data/app/helpers/better_ui/general/components/table/tr_helper.rb +0 -13
  225. data/app/helpers/better_ui/general/components/tabs/panel_helper.rb +0 -62
  226. data/app/helpers/better_ui/general/components/tabs/tab_helper.rb +0 -55
  227. data/app/helpers/better_ui/general/components/tabs/tabs_helper.rb +0 -95
  228. data/app/helpers/better_ui/general/components/tag/tag_helper.rb +0 -26
  229. data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +0 -60
  230. data/app/views/layouts/better_ui/application.html.erb +0 -17
  231. data/lib/better_ui/railtie.rb +0 -20
@@ -0,0 +1,202 @@
1
+ module BetterUi
2
+ module Application
3
+ class AlertComponent < ViewComponent::Base
4
+ attr_reader :title, :message, :variant, :icon, :dismissible, :classes, :data, :icon_position, :outline, :rounded
5
+
6
+ # Varianti di colore disponibili
7
+ VARIANTS = {
8
+ default: {
9
+ bg: "bg-black",
10
+ border: "border-gray-900",
11
+ title: "text-white",
12
+ text: "text-white",
13
+ icon: "text-white",
14
+ close: "text-white hover:bg-gray-800"
15
+ },
16
+ white: {
17
+ bg: "bg-white",
18
+ border: "border-gray-200",
19
+ title: "text-black",
20
+ text: "text-black",
21
+ icon: "text-black",
22
+ close: "text-black hover:bg-gray-100"
23
+ },
24
+ red: {
25
+ bg: "bg-red-500",
26
+ border: "border-red-600",
27
+ title: "text-white",
28
+ text: "text-white",
29
+ icon: "text-white",
30
+ close: "text-white hover:bg-red-600"
31
+ },
32
+ rose: {
33
+ bg: "bg-rose-500",
34
+ border: "border-rose-600",
35
+ title: "text-white",
36
+ text: "text-white",
37
+ icon: "text-white",
38
+ close: "text-white hover:bg-rose-600"
39
+ },
40
+ orange: {
41
+ bg: "bg-orange-500",
42
+ border: "border-orange-600",
43
+ title: "text-white",
44
+ text: "text-white",
45
+ icon: "text-white",
46
+ close: "text-white hover:bg-orange-600"
47
+ },
48
+ green: {
49
+ bg: "bg-green-500",
50
+ border: "border-green-600",
51
+ title: "text-white",
52
+ text: "text-white",
53
+ icon: "text-white",
54
+ close: "text-white hover:bg-green-600"
55
+ },
56
+ blue: {
57
+ bg: "bg-blue-500",
58
+ border: "border-blue-600",
59
+ title: "text-white",
60
+ text: "text-white",
61
+ icon: "text-white",
62
+ close: "text-white hover:bg-blue-600"
63
+ },
64
+ yellow: {
65
+ bg: "bg-yellow-500",
66
+ border: "border-yellow-600",
67
+ title: "text-black",
68
+ text: "text-black",
69
+ icon: "text-black",
70
+ close: "text-black hover:bg-yellow-600"
71
+ },
72
+ violet: {
73
+ bg: "bg-violet-500",
74
+ border: "border-violet-600",
75
+ title: "text-white",
76
+ text: "text-white",
77
+ icon: "text-white",
78
+ close: "text-white hover:bg-violet-600"
79
+ }
80
+ }
81
+
82
+ # Icone predefinite per ciascuna variante
83
+ DEFAULT_ICONS = {
84
+ default: "bell",
85
+ white: "info-circle",
86
+ red: "exclamation-circle",
87
+ rose: "exclamation-circle",
88
+ orange: "bell",
89
+ green: "check-circle",
90
+ blue: "info-circle",
91
+ yellow: "exclamation-triangle",
92
+ violet: "shield-exclamation"
93
+ }
94
+
95
+ # Posizioni possibili per le icone
96
+ ICON_POSITIONS = [:left, :top]
97
+
98
+ # Inizializzazione del componente
99
+ def initialize(
100
+ title: nil,
101
+ message: nil,
102
+ variant: :default,
103
+ icon: nil,
104
+ dismissible: false,
105
+ classes: nil,
106
+ data: {},
107
+ icon_position: :left,
108
+ outline: false,
109
+ rounded: :sm
110
+ )
111
+ @title = title
112
+ @message = message
113
+ @variant = variant.to_sym
114
+ @icon = icon
115
+ @dismissible = dismissible
116
+ @classes = classes
117
+ @data = data
118
+ @icon_position = icon_position.to_sym
119
+ @outline = outline
120
+ @rounded = rounded.to_sym
121
+ end
122
+
123
+ # Genera l'icona in base alla variante se non specificata
124
+ def effective_icon
125
+ return @icon if @icon.present?
126
+ DEFAULT_ICONS[@variant] || DEFAULT_ICONS[:default]
127
+ end
128
+
129
+ # Genera le classi per il container
130
+ def container_classes
131
+ styles = VARIANTS.fetch(@variant, VARIANTS[:default])
132
+
133
+ base_classes = ["p-4 mb-4 flex border"]
134
+ base_classes << get_border_radius_class
135
+
136
+ [
137
+ *base_classes,
138
+ styles[:bg],
139
+ styles[:border],
140
+ @icon_position == :top ? "flex-col" : "items-start",
141
+ @classes
142
+ ].compact.join(" ")
143
+ end
144
+
145
+ # Genera il border-radius
146
+ def get_border_radius_class
147
+ ThemeHelper::BORDER_RADIUS[@rounded] || ThemeHelper::BORDER_RADIUS[:sm]
148
+ end
149
+
150
+ # Genera le classi per il titolo
151
+ def title_classes
152
+ styles = VARIANTS.fetch(@variant, VARIANTS[:default])
153
+
154
+ [
155
+ "font-medium",
156
+ styles[:title]
157
+ ].compact.join(" ")
158
+ end
159
+
160
+ # Genera le classi per il messaggio
161
+ def message_classes
162
+ styles = VARIANTS.fetch(@variant, VARIANTS[:default])
163
+
164
+ [
165
+ "mt-1",
166
+ styles[:text]
167
+ ].compact.join(" ")
168
+ end
169
+
170
+ # Genera le classi per l'icona
171
+ def icon_classes
172
+ styles = VARIANTS.fetch(@variant, VARIANTS[:default])
173
+
174
+ [
175
+ "flex-shrink-0",
176
+ @icon_position == :left ? "mr-3 mt-0.5" : "mb-3",
177
+ styles[:icon]
178
+ ].compact.join(" ")
179
+ end
180
+
181
+ # Genera le classi per il pulsante di chiusura
182
+ def close_button_classes
183
+ styles = VARIANTS.fetch(@variant, VARIANTS[:default])
184
+
185
+ [
186
+ "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",
187
+ styles[:close]
188
+ ].compact.join(" ")
189
+ end
190
+
191
+ # Genera le classi per il contenuto
192
+ def content_classes
193
+ "flex-1"
194
+ end
195
+
196
+ # Verifica se il componente deve essere reso
197
+ def render?
198
+ @title.present? || @message.present? || content.present?
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,24 @@
1
+ <div class="bui-card-base <%= get_border_radius_class %> px-4 py-5 sm:p-6">
2
+ <dt class="bui-card-title text-gray-900"><%= title %></dt>
3
+ <dd class="bui-card-body mt-1 flex items-baseline justify-between md:block lg:flex">
4
+ <div class="flex items-baseline">
5
+ <span class="bui-card-value text-indigo-600"><%= value %></span>
6
+ <span class="bui-card-value-from ml-2">from <%= value_from %></span>
7
+ </div>
8
+
9
+ <div class="bui-card-trend <%= trend_classes %>">
10
+ <% if trend_type == :up %>
11
+ <svg class="mr-0.5 -ml-1 size-5 shrink-0 self-center <%= trend_icon_classes %>" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
12
+ <path fill-rule="evenodd" d="M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z" clip-rule="evenodd" />
13
+ </svg>
14
+ <span class="sr-only">Incremento di</span>
15
+ <% else %>
16
+ <svg class="mr-0.5 -ml-1 size-5 shrink-0 self-center <%= trend_icon_classes %>" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
17
+ <path fill-rule="evenodd" d="M10 3a.75.75 0 0 1 .75.75v10.638l3.96-4.158a.75.75 0 1 1 1.08 1.04l-5.25 5.5a.75.75 0 0 1-1.08 0l-5.25-5.5a.75.75 0 1 1 1.08-1.04l3.96 4.158V3.75A.75.75 0 0 1 10 3Z" clip-rule="evenodd" />
18
+ </svg>
19
+ <span class="sr-only">Decremento di</span>
20
+ <% end %>
21
+ <%= trend_value %>
22
+ </div>
23
+ </dd>
24
+ </div>
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Application
5
+ class CardComponent < ViewComponent::Base
6
+ attr_reader :title, :value, :value_from, :trend_value, :trend_type, :rounded
7
+
8
+ # Opzioni di bordi arrotondati standardizzati
9
+ CARD_RADIUS = {
10
+ none: 'bui-card-radius-none',
11
+ small: 'bui-card-radius-small',
12
+ medium: 'bui-card-radius-medium',
13
+ large: 'bui-card-radius-large',
14
+ full: 'bui-card-radius-full'
15
+ }.freeze
16
+
17
+ # @param title [String] Titolo della card
18
+ # @param value [String] Valore principale da visualizzare
19
+ # @param value_from [String] Valore precedente di riferimento
20
+ # @param trend_value [String] Percentuale di variazione
21
+ # @param trend_type [Symbol] Tipo di variazione (:up o :down)
22
+ # @param rounded [Symbol] Tipo di border-radius (:none, :small, :medium, :large, :full), default :small
23
+ def initialize(title:, value:, value_from:, trend_value:, trend_type: :up, rounded: :small)
24
+ @title = title
25
+ @value = value
26
+ @value_from = value_from
27
+ @trend_value = trend_value
28
+ @trend_type = trend_type.to_sym
29
+ @rounded = rounded.to_sym
30
+ end
31
+
32
+ def trend_classes
33
+ if trend_type == :up
34
+ 'bg-green-500 text-white'
35
+ else
36
+ 'bg-black text-white'
37
+ end
38
+ end
39
+
40
+ def trend_icon_classes
41
+ if trend_type == :up
42
+ 'text-white'
43
+ else
44
+ 'text-white'
45
+ end
46
+ end
47
+
48
+ def get_border_radius_class
49
+ CARD_RADIUS[@rounded] || CARD_RADIUS[:small]
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,8 @@
1
+ <div>
2
+ <h3 class="text-base font-semibold text-gray-900"><%= @title %></h3>
3
+ <dl class="mt-5 grid grid-cols-1 divide-y divide-gray-200 overflow-hidden rounded-lg bg-white shadow-sm md:grid-cols-3 md:divide-x md:divide-y-0">
4
+ <% cards.each do |card| %>
5
+ <%= card %>
6
+ <% end %>
7
+ </dl>
8
+ </div>
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Application
5
+ class CardContainerComponent < ViewComponent::Base
6
+ renders_many :cards, CardComponent
7
+
8
+ # @param title [String] Titolo del container delle card
9
+ def initialize(title:)
10
+ @title = title
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,88 @@
1
+ <header class="<%= header_classes %>" <%= @data&.map { |k, v| "data-#{k}=\"#{v}\"" }&.join(' ')&.html_safe %>>
2
+ <div class="<%= container_class %>">
3
+ <div class="md:flex md:justify-between md:items-start">
4
+ <div class="min-w-0 flex-1">
5
+ <% if has_breadcrumbs? %>
6
+ <nav class="<%= breadcrumb_container_classes %>" aria-label="Breadcrumb">
7
+ <ol class="flex items-center">
8
+ <% @breadcrumbs.each_with_index do |breadcrumb, index| %>
9
+ <li class="flex items-center">
10
+ <% if index > 0 %>
11
+ <span class="<%= breadcrumb_divider_classes %>" aria-hidden="true">
12
+ <% if variant == :modern %>
13
+ <svg class="h-4 w-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
14
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
15
+ </svg>
16
+ <% else %>
17
+ /
18
+ <% end %>
19
+ </span>
20
+ <% end %>
21
+ <% is_last = index == @breadcrumbs.length - 1 %>
22
+ <% if is_last || !breadcrumb[:url].present? %>
23
+ <span class="<%= breadcrumb_link_classes(is_last) %>" <%= is_last ? 'aria-current="page"' : '' %>>
24
+ <%= breadcrumb[:text] %>
25
+ </span>
26
+ <% else %>
27
+ <a href="<%= breadcrumb[:url] %>" class="<%= breadcrumb_link_classes %>">
28
+ <%= breadcrumb[:text] %>
29
+ </a>
30
+ <% end %>
31
+ </li>
32
+ <% end %>
33
+ </ol>
34
+ </nav>
35
+ <% end %>
36
+
37
+ <div class="flex items-center">
38
+ <% if @title.is_a?(Hash) && @title[:icon].present? %>
39
+ <div class="mr-3 bg-gray-100 rounded-md p-2 flex-shrink-0">
40
+ <% if @title[:icon] == "document" %>
41
+ <svg class="h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
42
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
43
+ </svg>
44
+ <% elsif @title[:icon] == "users" %>
45
+ <svg class="h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
46
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
47
+ </svg>
48
+ <% elsif @title[:icon] == "settings" || @title[:icon] == "gear" %>
49
+ <svg class="h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
50
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
51
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
52
+ </svg>
53
+ <% elsif @title[:icon] == "dashboard" %>
54
+ <svg class="h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
55
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z" />
56
+ </svg>
57
+ <% else %>
58
+ <%= render BetterUi::General::IconComponent.new(name: @title[:icon], classes: "h-5 w-5 text-gray-500") %>
59
+ <% end %>
60
+ </div>
61
+ <h1 class="<%= title_classes %>"><%= @title[:text] %></h1>
62
+ <% else %>
63
+ <h1 class="<%= title_classes %>"><%= @title %></h1>
64
+ <% end %>
65
+ </div>
66
+ <% if @subtitle.present? %>
67
+ <p class="<%= subtitle_classes %>">
68
+ <%= @subtitle %>
69
+ </p>
70
+ <% end %>
71
+ </div>
72
+
73
+ <% if action_items.any? %>
74
+ <div class="<%= actions_container_classes %>">
75
+ <% action_items.each do |action| %>
76
+ <div class="ml-2">
77
+ <% if action.is_a?(Hash) && action[:content].present? %>
78
+ <%= action[:content].html_safe %>
79
+ <% elsif action.is_a?(String) %>
80
+ <%= action.html_safe %>
81
+ <% end %>
82
+ </div>
83
+ <% end %>
84
+ </div>
85
+ <% end %>
86
+ </div>
87
+ </div>
88
+ </header>
@@ -0,0 +1,188 @@
1
+ module BetterUi
2
+ module Application
3
+ class HeaderComponent < ViewComponent::Base
4
+ attr_reader :title, :subtitle, :breadcrumbs, :actions, :variant, :fixed, :container_class, :classes, :data, :show_breadcrumbs
5
+
6
+ # Varianti di colore disponibili
7
+ VARIANTS = {
8
+ light: {
9
+ bg: "bg-white border-gray-200",
10
+ text: "text-gray-700",
11
+ title: "text-gray-900",
12
+ subtitle: "text-gray-500",
13
+ border: "border-gray-200",
14
+ breadcrumb_text: "text-gray-500",
15
+ breadcrumb_hover: "hover:text-gray-700",
16
+ breadcrumb_active: "text-gray-900",
17
+ breadcrumb_divider: "text-gray-400"
18
+ },
19
+ dark: {
20
+ bg: "bg-gray-800 border-gray-700",
21
+ text: "text-gray-200",
22
+ title: "text-white",
23
+ subtitle: "text-gray-400",
24
+ border: "border-gray-700",
25
+ breadcrumb_text: "text-gray-400",
26
+ breadcrumb_hover: "hover:text-white",
27
+ breadcrumb_active: "text-white",
28
+ breadcrumb_divider: "text-gray-500"
29
+ },
30
+ primary: {
31
+ bg: "bg-orange-600",
32
+ text: "text-white",
33
+ title: "text-white",
34
+ subtitle: "text-orange-100",
35
+ border: "border-orange-500",
36
+ breadcrumb_text: "text-orange-200",
37
+ breadcrumb_hover: "hover:text-white",
38
+ breadcrumb_active: "text-white",
39
+ breadcrumb_divider: "text-orange-300"
40
+ },
41
+ transparent: {
42
+ bg: "bg-transparent",
43
+ text: "text-gray-700",
44
+ title: "text-gray-900",
45
+ subtitle: "text-gray-500",
46
+ border: "border-gray-200",
47
+ breadcrumb_text: "text-gray-500",
48
+ breadcrumb_hover: "hover:text-gray-700",
49
+ breadcrumb_active: "text-gray-900",
50
+ breadcrumb_divider: "text-gray-400"
51
+ },
52
+ modern: {
53
+ bg: "bg-white",
54
+ text: "text-gray-700",
55
+ title: "text-gray-900",
56
+ subtitle: "text-gray-500",
57
+ border: "border-gray-100",
58
+ breadcrumb_text: "text-gray-500",
59
+ breadcrumb_hover: "hover:text-gray-700",
60
+ breadcrumb_active: "text-gray-900",
61
+ breadcrumb_divider: "text-gray-400"
62
+ }
63
+ }
64
+
65
+ # Opzioni per la posizione fissa
66
+ FIXED_POSITIONS = {
67
+ top: "sticky top-0 z-40",
68
+ bottom: "sticky bottom-0 z-40"
69
+ }
70
+
71
+ # Inizializzazione del componente
72
+ def initialize(
73
+ title:,
74
+ subtitle: nil,
75
+ breadcrumbs: [],
76
+ actions: [],
77
+ variant: :modern,
78
+ fixed: nil,
79
+ container_class: "container mx-auto px-4",
80
+ classes: nil,
81
+ data: {},
82
+ show_breadcrumbs: true
83
+ )
84
+ @title = title
85
+ @subtitle = subtitle
86
+ @breadcrumbs = breadcrumbs || []
87
+ @actions = actions || []
88
+ @variant = variant.to_sym
89
+ @fixed = fixed.to_sym if fixed
90
+ @container_class = container_class
91
+ @classes = classes
92
+ @data = data || {}
93
+ @show_breadcrumbs = show_breadcrumbs
94
+ end
95
+
96
+ # Genera le classi per il container del header
97
+ def header_classes
98
+ styles = VARIANTS.fetch(@variant, VARIANTS[:modern])
99
+ position_class = @fixed.present? ? FIXED_POSITIONS[@fixed] : nil
100
+
101
+ cls = [
102
+ "w-full py-4",
103
+ styles[:bg],
104
+ position_class,
105
+ @classes
106
+ ]
107
+
108
+ # Aggiungi il bordo inferiore solo se non è trasparente
109
+ cls << "border-b" unless @variant == :transparent
110
+
111
+ cls.compact.join(" ")
112
+ end
113
+
114
+ # Genera classi per il titolo
115
+ def title_classes
116
+ styles = VARIANTS.fetch(@variant, VARIANTS[:modern])
117
+
118
+ [
119
+ "text-xl font-medium leading-6",
120
+ styles[:title]
121
+ ].join(" ")
122
+ end
123
+
124
+ # Genera classi per il sottotitolo
125
+ def subtitle_classes
126
+ styles = VARIANTS.fetch(@variant, VARIANTS[:modern])
127
+
128
+ [
129
+ "mt-1 text-sm",
130
+ styles[:subtitle]
131
+ ].join(" ")
132
+ end
133
+
134
+ # Genera classi per il breadcrumb
135
+ def breadcrumb_container_classes
136
+ "flex mb-3"
137
+ end
138
+
139
+ # Genera classi per i link del breadcrumb
140
+ def breadcrumb_link_classes(active = false)
141
+ styles = VARIANTS.fetch(@variant, VARIANTS[:modern])
142
+
143
+ if active
144
+ [
145
+ "text-sm font-medium",
146
+ styles[:breadcrumb_active]
147
+ ].join(" ")
148
+ else
149
+ [
150
+ "text-sm font-medium",
151
+ styles[:breadcrumb_text],
152
+ styles[:breadcrumb_hover]
153
+ ].join(" ")
154
+ end
155
+ end
156
+
157
+ # Genera classi per il divisore del breadcrumb
158
+ def breadcrumb_divider_classes
159
+ styles = VARIANTS.fetch(@variant, VARIANTS[:modern])
160
+
161
+ [
162
+ "mx-2 text-sm",
163
+ styles[:breadcrumb_divider]
164
+ ].join(" ")
165
+ end
166
+
167
+ # Genera classi per il contenitore delle azioni
168
+ def actions_container_classes
169
+ "mt-4 md:mt-0 flex flex-shrink-0 md:ml-4"
170
+ end
171
+
172
+ # Verifica se il componente deve essere reso
173
+ def render?
174
+ true
175
+ end
176
+
177
+ # Ritorna la lista delle azioni
178
+ def action_items
179
+ @actions
180
+ end
181
+
182
+ # Ritorna i breadcrumbs
183
+ def has_breadcrumbs?
184
+ @show_breadcrumbs && @breadcrumbs.present? && @breadcrumbs.any?
185
+ end
186
+ end
187
+ end
188
+ end