better_ui_tmp 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.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +211 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/builds/application.js +1 -0
  6. data/app/assets/builds/better_ui.css +1 -0
  7. data/app/assets/stylesheets/better_ui.scss +3 -0
  8. data/app/components/better_ui/application/main/component.html.erb +5 -0
  9. data/app/components/better_ui/application/main/component.rb +99 -0
  10. data/app/components/better_ui/application/navbar/component.html.erb +219 -0
  11. data/app/components/better_ui/application/navbar/component.rb +148 -0
  12. data/app/components/better_ui/application/sidebar/component.html.erb +184 -0
  13. data/app/components/better_ui/application/sidebar/component.rb +129 -0
  14. data/app/components/better_ui/general/alert/component.html.erb +32 -0
  15. data/app/components/better_ui/general/alert/component.rb +242 -0
  16. data/app/components/better_ui/general/avatar/component.html.erb +20 -0
  17. data/app/components/better_ui/general/avatar/component.rb +301 -0
  18. data/app/components/better_ui/general/badge/component.html.erb +23 -0
  19. data/app/components/better_ui/general/badge/component.rb +248 -0
  20. data/app/components/better_ui/general/breadcrumb/component.html.erb +15 -0
  21. data/app/components/better_ui/general/breadcrumb/component.rb +186 -0
  22. data/app/components/better_ui/general/button/component.html.erb +34 -0
  23. data/app/components/better_ui/general/button/component.rb +214 -0
  24. data/app/components/better_ui/general/card/component.html.erb +21 -0
  25. data/app/components/better_ui/general/card/component.rb +37 -0
  26. data/app/components/better_ui/general/container/component.html.erb +8 -0
  27. data/app/components/better_ui/general/container/component.rb +158 -0
  28. data/app/components/better_ui/general/divider/component.html.erb +10 -0
  29. data/app/components/better_ui/general/divider/component.rb +226 -0
  30. data/app/components/better_ui/general/heading/component.html.erb +22 -0
  31. data/app/components/better_ui/general/heading/component.rb +257 -0
  32. data/app/components/better_ui/general/icon/component.html.erb +1 -0
  33. data/app/components/better_ui/general/icon/component.rb +222 -0
  34. data/app/components/better_ui/general/link/component.html.erb +18 -0
  35. data/app/components/better_ui/general/link/component.rb +255 -0
  36. data/app/components/better_ui/general/panel/component.html.erb +28 -0
  37. data/app/components/better_ui/general/panel/component.rb +249 -0
  38. data/app/components/better_ui/general/progress/component.html.erb +11 -0
  39. data/app/components/better_ui/general/progress/component.rb +160 -0
  40. data/app/components/better_ui/general/spinner/component.html.erb +35 -0
  41. data/app/components/better_ui/general/spinner/component.rb +93 -0
  42. data/app/components/better_ui/general/table/component.html.erb +5 -0
  43. data/app/components/better_ui/general/table/component.rb +217 -0
  44. data/app/components/better_ui/general/table/tbody_component.html.erb +3 -0
  45. data/app/components/better_ui/general/table/tbody_component.rb +30 -0
  46. data/app/components/better_ui/general/table/td_component.html.erb +3 -0
  47. data/app/components/better_ui/general/table/td_component.rb +44 -0
  48. data/app/components/better_ui/general/table/tfoot_component.html.erb +3 -0
  49. data/app/components/better_ui/general/table/tfoot_component.rb +28 -0
  50. data/app/components/better_ui/general/table/th_component.html.erb +6 -0
  51. data/app/components/better_ui/general/table/th_component.rb +51 -0
  52. data/app/components/better_ui/general/table/thead_component.html.erb +3 -0
  53. data/app/components/better_ui/general/table/thead_component.rb +28 -0
  54. data/app/components/better_ui/general/table/tr_component.html.erb +3 -0
  55. data/app/components/better_ui/general/table/tr_component.rb +30 -0
  56. data/app/components/better_ui/general/tag/component.html.erb +3 -0
  57. data/app/components/better_ui/general/tag/component.rb +104 -0
  58. data/app/components/better_ui/general/tooltip/component.html.erb +7 -0
  59. data/app/components/better_ui/general/tooltip/component.rb +239 -0
  60. data/app/controllers/better_ui/application_controller.rb +5 -0
  61. data/app/helpers/better_ui/application/components/main/main_helper.rb +42 -0
  62. data/app/helpers/better_ui/application/components/main.rb +13 -0
  63. data/app/helpers/better_ui/application/components/navbar/navbar_helper.rb +51 -0
  64. data/app/helpers/better_ui/application/components/navbar.rb +13 -0
  65. data/app/helpers/better_ui/application/components/sidebar/sidebar_helper.rb +51 -0
  66. data/app/helpers/better_ui/application/components/sidebar.rb +13 -0
  67. data/app/helpers/better_ui/application_helper.rb +10 -0
  68. data/app/helpers/better_ui/form_helper.rb +5 -0
  69. data/app/helpers/better_ui/general/components/alert/alert_helper.rb +29 -0
  70. data/app/helpers/better_ui/general/components/alert.rb +13 -0
  71. data/app/helpers/better_ui/general/components/avatar/avatar_helper.rb +29 -0
  72. data/app/helpers/better_ui/general/components/avatar.rb +13 -0
  73. data/app/helpers/better_ui/general/components/badge/badge_helper.rb +53 -0
  74. data/app/helpers/better_ui/general/components/badge.rb +13 -0
  75. data/app/helpers/better_ui/general/components/breadcrumb/breadcrumb_helper.rb +37 -0
  76. data/app/helpers/better_ui/general/components/breadcrumb.rb +13 -0
  77. data/app/helpers/better_ui/general/components/button/button_helper.rb +65 -0
  78. data/app/helpers/better_ui/general/components/button.rb +13 -0
  79. data/app/helpers/better_ui/general/components/card/card_helper.rb +37 -0
  80. data/app/helpers/better_ui/general/components/card.rb +13 -0
  81. data/app/helpers/better_ui/general/components/container/container_helper.rb +60 -0
  82. data/app/helpers/better_ui/general/components/container.rb +13 -0
  83. data/app/helpers/better_ui/general/components/divider/divider_helper.rb +63 -0
  84. data/app/helpers/better_ui/general/components/divider.rb +13 -0
  85. data/app/helpers/better_ui/general/components/heading/heading_helper.rb +72 -0
  86. data/app/helpers/better_ui/general/components/heading.rb +13 -0
  87. data/app/helpers/better_ui/general/components/icon/icon_helper.rb +16 -0
  88. data/app/helpers/better_ui/general/components/icon.rb +13 -0
  89. data/app/helpers/better_ui/general/components/link/link_helper.rb +89 -0
  90. data/app/helpers/better_ui/general/components/link.rb +13 -0
  91. data/app/helpers/better_ui/general/components/panel/panel_helper.rb +83 -0
  92. data/app/helpers/better_ui/general/components/panel.rb +13 -0
  93. data/app/helpers/better_ui/general/components/progress/progress_helper.rb +53 -0
  94. data/app/helpers/better_ui/general/components/progress.rb +11 -0
  95. data/app/helpers/better_ui/general/components/spinner/spinner_helper.rb +17 -0
  96. data/app/helpers/better_ui/general/components/spinner.rb +10 -0
  97. data/app/helpers/better_ui/general/components/table/table_helper.rb +13 -0
  98. data/app/helpers/better_ui/general/components/table/tbody_helper.rb +13 -0
  99. data/app/helpers/better_ui/general/components/table/td_helper.rb +19 -0
  100. data/app/helpers/better_ui/general/components/table/tfoot_helper.rb +13 -0
  101. data/app/helpers/better_ui/general/components/table/th_helper.rb +19 -0
  102. data/app/helpers/better_ui/general/components/table/thead_helper.rb +13 -0
  103. data/app/helpers/better_ui/general/components/table/tr_helper.rb +13 -0
  104. data/app/helpers/better_ui/general/components/table.rb +25 -0
  105. data/app/helpers/better_ui/general/components/tag/tag_helper.rb +26 -0
  106. data/app/helpers/better_ui/general/components/tag.rb +15 -0
  107. data/app/helpers/better_ui/general/components/tooltip/tooltip_helper.rb +60 -0
  108. data/app/helpers/better_ui/general/components/tooltip.rb +13 -0
  109. data/app/helpers/better_ui/general_helper.rb +24 -0
  110. data/app/helpers/better_ui_helper.rb +16 -0
  111. data/app/javascript/application.js +1 -0
  112. data/app/jobs/better_ui/application_job.rb +4 -0
  113. data/app/mailers/better_ui/application_mailer.rb +6 -0
  114. data/app/models/better_ui/application_record.rb +5 -0
  115. data/app/views/components/better_ui/general/table/_custom_body_row.html.erb +17 -0
  116. data/app/views/components/better_ui/general/table/_custom_footer_rows.html.erb +17 -0
  117. data/app/views/components/better_ui/general/table/_custom_header_rows.html.erb +12 -0
  118. data/app/views/layouts/component_preview.html.erb +32 -0
  119. data/config/initializers/lookbook.rb +23 -0
  120. data/config/routes.rb +3 -0
  121. data/lib/better_ui/engine.rb +109 -0
  122. data/lib/better_ui/version.rb +3 -0
  123. data/lib/better_ui.rb +37 -0
  124. data/lib/generators/better_ui/install_generator.rb +103 -0
  125. data/lib/generators/better_ui/stylesheet_generator.rb +159 -0
  126. data/lib/generators/better_ui/templates/components/_avatar.scss +200 -0
  127. data/lib/generators/better_ui/templates/components/_badge.scss +154 -0
  128. data/lib/generators/better_ui/templates/components/_breadcrumb.scss +106 -0
  129. data/lib/generators/better_ui/templates/components/_button.scss +109 -0
  130. data/lib/generators/better_ui/templates/components/_card.scss +60 -0
  131. data/lib/generators/better_ui/templates/components/_heading.scss +81 -0
  132. data/lib/generators/better_ui/templates/components/_icon.scss +134 -0
  133. data/lib/generators/better_ui/templates/components/_index.scss +17 -0
  134. data/lib/generators/better_ui/templates/components/_link.scss +100 -0
  135. data/lib/generators/better_ui/templates/components/_panel.scss +104 -0
  136. data/lib/generators/better_ui/templates/components/_spinner.scss +129 -0
  137. data/lib/generators/better_ui/templates/components/_table.scss +156 -0
  138. data/lib/generators/better_ui/templates/components/_variables.scss +0 -0
  139. data/lib/generators/better_ui/templates/components_stylesheet.scss +35 -0
  140. data/lib/generators/better_ui/templates/index.scss +18 -0
  141. data/lib/generators/better_ui/templates/initializer.rb +41 -0
  142. data/lib/tasks/better_ui_tasks.rake +4 -0
  143. metadata +260 -0
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Application
5
+ module Navbar
6
+ class Component < ViewComponent::Base
7
+ # Include degli helper per utilizzare bui_icon, bui_avatar e bui_breadcrumb
8
+ include BetterUi::General::Components::Icon::IconHelper
9
+ include BetterUi::General::Components::Avatar::AvatarHelper
10
+ include BetterUi::General::Components::Breadcrumb::BreadcrumbHelper
11
+ attr_reader :theme, :position, :height, :shadow, :border, :brand, :breadcrumb, :navigation_items, :actions, :classes
12
+
13
+ # Temi navbar con classi Tailwind dirette
14
+ NAVBAR_THEMES = {
15
+ default: "bg-white text-gray-900 border-gray-200",
16
+ dark: "bg-gray-900 text-white border-gray-700",
17
+ light: "bg-gray-50 text-gray-900 border-gray-100"
18
+ }
19
+
20
+ # Altezze navbar con classi Tailwind dirette
21
+ NAVBAR_HEIGHTS = {
22
+ sm: "h-12",
23
+ md: "h-16",
24
+ lg: "h-20"
25
+ }
26
+
27
+ # Posizioni navbar con classi Tailwind dirette
28
+ NAVBAR_POSITIONS = {
29
+ top: "",
30
+ fixed_top: "fixed top-0 left-0 right-0 z-50",
31
+ sticky_top: "sticky top-0 z-40"
32
+ }
33
+
34
+ # Ombre navbar con classi Tailwind dirette
35
+ NAVBAR_SHADOWS = {
36
+ none: "",
37
+ sm: "shadow-sm",
38
+ md: "shadow-md",
39
+ lg: "shadow-lg",
40
+ xl: "shadow-xl"
41
+ }
42
+
43
+ # @param theme [Symbol] Tema colori (:default, :dark, :light), default :default
44
+ # @param position [Symbol] Posizione della navbar (:top, :fixed_top, :sticky_top), default :top
45
+ # @param height [Symbol] Altezza della navbar (:sm, :md, :lg), default :md
46
+ # @param shadow [Symbol] Tipo di ombra (:none, :sm, :md, :lg, :xl), default :sm
47
+ # @param border [Boolean] Se mostrare il bordo inferiore, default true
48
+ # @param brand [Hash] Configurazione brand (logo, title, href)
49
+ # @param breadcrumb [Hash] Configurazione breadcrumb (items, separator, theme)
50
+ # @param navigation_items [Array] Array di elementi di navigazione centrali
51
+ # @param actions [Array] Array di azioni/pulsanti a destra
52
+ # @param classes [String] Classi CSS aggiuntive
53
+ def initialize(
54
+ theme: :default,
55
+ position: :top,
56
+ height: :md,
57
+ shadow: :sm,
58
+ border: true,
59
+ brand: {},
60
+ breadcrumb: {},
61
+ navigation_items: [],
62
+ actions: [],
63
+ classes: nil
64
+ )
65
+ @theme = theme.to_sym
66
+ @position = position.to_sym
67
+ @height = height.to_sym
68
+ @shadow = shadow.to_sym
69
+ @border = border
70
+ @brand = brand || {}
71
+ @breadcrumb = breadcrumb || {}
72
+ @navigation_items = navigation_items || []
73
+ @actions = actions || []
74
+ @classes = classes
75
+ end
76
+
77
+ def container_classes
78
+ base_classes = %w[w-full flex items-center justify-between px-4 sm:px-6 lg:px-8]
79
+
80
+ # Posizione
81
+ base_classes.concat(position_classes.split) if position != :top
82
+
83
+ # Altezza
84
+ base_classes << height_class
85
+
86
+ # Tema
87
+ base_classes.concat(theme_classes.split)
88
+
89
+ # Shadow
90
+ base_classes << shadow_class if shadow != :none
91
+
92
+ # Border
93
+ base_classes << "border-b" if border
94
+
95
+ # Classi aggiuntive
96
+ base_classes << classes if classes.present?
97
+
98
+ base_classes.compact.join(" ")
99
+ end
100
+
101
+ def has_brand?
102
+ brand.present? && (brand[:title].present? || brand[:logo].present?)
103
+ end
104
+
105
+ def has_breadcrumb?
106
+ breadcrumb.present? && breadcrumb[:items].present? && breadcrumb[:items].any?
107
+ end
108
+
109
+ def has_navigation?
110
+ navigation_items.present? && navigation_items.any?
111
+ end
112
+
113
+ def has_actions?
114
+ actions.present? && actions.any?
115
+ end
116
+
117
+ def render_breadcrumb
118
+ return unless has_breadcrumb?
119
+
120
+ bui_breadcrumb(
121
+ items: breadcrumb[:items],
122
+ separator: breadcrumb[:separator] || :chevron,
123
+ theme: breadcrumb[:theme] || theme,
124
+ size: :small
125
+ )
126
+ end
127
+
128
+ private
129
+
130
+ def position_classes
131
+ NAVBAR_POSITIONS[@position] || NAVBAR_POSITIONS[:top]
132
+ end
133
+
134
+ def height_class
135
+ NAVBAR_HEIGHTS[@height] || NAVBAR_HEIGHTS[:md]
136
+ end
137
+
138
+ def theme_classes
139
+ NAVBAR_THEMES[@theme] || NAVBAR_THEMES[:default]
140
+ end
141
+
142
+ def shadow_class
143
+ NAVBAR_SHADOWS[@shadow] || NAVBAR_SHADOWS[:sm]
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,184 @@
1
+ <aside class="<%= container_classes %>">
2
+ <!-- Header Section -->
3
+ <% if has_header? %>
4
+ <div class="px-6 py-4 border-b border-gray-200">
5
+ <% if header[:logo].present? %>
6
+ <div class="flex items-center">
7
+ <div class="flex-shrink-0">
8
+ <% if header[:logo].is_a?(Hash) %>
9
+ <%= bui_avatar(**header[:logo]) %>
10
+ <% else %>
11
+ <%= header[:logo].html_safe %>
12
+ <% end %>
13
+ </div>
14
+ <% if header[:title].present? %>
15
+ <div class="ml-3">
16
+ <h2 class="text-lg font-semibold text-gray-900"><%= header[:title] %></h2>
17
+ <% if header[:subtitle].present? %>
18
+ <p class="text-sm text-gray-500"><%= header[:subtitle] %></p>
19
+ <% end %>
20
+ </div>
21
+ <% end %>
22
+ </div>
23
+ <% elsif header[:title].present? %>
24
+ <div>
25
+ <h2 class="text-lg font-semibold text-gray-900"><%= header[:title] %></h2>
26
+ <% if header[:subtitle].present? %>
27
+ <p class="text-sm text-gray-500"><%= header[:subtitle] %></p>
28
+ <% end %>
29
+ </div>
30
+ <% end %>
31
+ </div>
32
+ <% end %>
33
+
34
+ <!-- Navigation Section -->
35
+ <nav class="flex-1 px-4 py-6 space-y-6">
36
+ <% navigation_sections.each do |section| %>
37
+ <div class="space-y-2">
38
+ <!-- Section Title -->
39
+ <% if section[:title].present? %>
40
+ <h3 class="px-3 text-xs font-semibold text-gray-500 uppercase tracking-wider">
41
+ <%= section[:title] %>
42
+ </h3>
43
+ <% end %>
44
+
45
+ <!-- Navigation Items -->
46
+ <div class="space-y-1">
47
+ <% (section[:items] || []).each do |item| %>
48
+ <% if item[:type] == :collapsible && collapsible %>
49
+ <!-- Collapsible Section -->
50
+ <div>
51
+ <button
52
+ type="button"
53
+ class="group flex items-center justify-between w-full px-3 py-2 text-sm font-medium text-gray-700 rounded-md hover:bg-gray-50 hover:text-gray-900 transition-colors duration-150"
54
+ data-collapse-target="#<%= item[:id] %>"
55
+ aria-expanded="<%= item[:expanded] || false %>"
56
+ >
57
+ <div class="flex items-center">
58
+ <% if item[:icon].present? %>
59
+ <span class="mr-3 text-gray-400 group-hover:text-gray-500">
60
+ <%= bui_icon(item[:icon], size: :medium) %>
61
+ </span>
62
+ <% end %>
63
+ <span><%= item[:label] %></span>
64
+ </div>
65
+ <span class="ml-3 transform transition-transform duration-150 <%= 'rotate-90' if item[:expanded] %>">
66
+ <%= bui_icon("chevron-right", size: :small) %>
67
+ </span>
68
+ </button>
69
+
70
+ <div
71
+ id="<%= item[:id] %>"
72
+ class="<%= item[:expanded] ? 'block' : 'hidden' %> mt-1 space-y-1"
73
+ >
74
+ <% (item[:children] || []).each do |child| %>
75
+ <% if child[:href].present? %>
76
+ <a
77
+ href="<%= child[:href] %>"
78
+ class="<%= (child[:active] || false) ? 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 bg-gray-100 text-gray-900' : 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 text-gray-700 hover:bg-gray-50 hover:text-gray-900' %> pl-11"
79
+ >
80
+ <% if child[:icon].present? %>
81
+ <span class="mr-3">
82
+ <%= bui_icon(child[:icon], size: :small) %>
83
+ </span>
84
+ <% end %>
85
+ <%= child[:label] %>
86
+ </a>
87
+ <% else %>
88
+ <div class="<%= (child[:active] || false) ? 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 bg-gray-100 text-gray-900' : 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 text-gray-700 hover:bg-gray-50 hover:text-gray-900' %> pl-11 cursor-default">
89
+ <% if child[:icon].present? %>
90
+ <span class="mr-3">
91
+ <%= bui_icon(child[:icon], size: :small) %>
92
+ </span>
93
+ <% end %>
94
+ <%= child[:label] %>
95
+ </div>
96
+ <% end %>
97
+ <% end %>
98
+ </div>
99
+ </div>
100
+ <% else %>
101
+ <!-- Regular Navigation Item -->
102
+ <% if item[:href].present? %>
103
+ <a
104
+ href="<%= item[:href] %>"
105
+ class="<%= (item[:active] || false) ? 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 bg-gray-100 text-gray-900' : 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 text-gray-700 hover:bg-gray-50 hover:text-gray-900' %>"
106
+ >
107
+ <% if item[:icon].present? %>
108
+ <span class="mr-3 text-gray-400 group-hover:text-gray-500">
109
+ <%= bui_icon(item[:icon], size: :medium) %>
110
+ </span>
111
+ <% end %>
112
+ <%= item[:label] %>
113
+ <% if item[:badge].present? %>
114
+ <span class="ml-auto inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
115
+ <%= item[:badge] %>
116
+ </span>
117
+ <% end %>
118
+ </a>
119
+ <% else %>
120
+ <div class="<%= (item[:active] || false) ? 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 bg-gray-100 text-gray-900' : 'group flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors duration-150 text-gray-700 hover:bg-gray-50 hover:text-gray-900' %> cursor-default">
121
+ <% if item[:icon].present? %>
122
+ <span class="mr-3 text-gray-400">
123
+ <%= bui_icon(item[:icon], size: :medium) %>
124
+ </span>
125
+ <% end %>
126
+ <%= item[:label] %>
127
+ <% if item[:badge].present? %>
128
+ <span class="ml-auto inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
129
+ <%= item[:badge] %>
130
+ </span>
131
+ <% end %>
132
+ </div>
133
+ <% end %>
134
+ <% end %>
135
+ <% end %>
136
+ </div>
137
+ </div>
138
+ <% end %>
139
+
140
+ <%= content if content.present? %>
141
+ </nav>
142
+
143
+ <!-- Footer Section -->
144
+ <% if has_footer? %>
145
+ <div class="px-6 py-4 border-t border-gray-200">
146
+ <% if footer[:user_info].present? %>
147
+ <div class="flex items-center">
148
+ <% if footer[:user_info][:avatar].present? %>
149
+ <div class="flex-shrink-0">
150
+ <% if footer[:user_info][:avatar].is_a?(Hash) %>
151
+ <%= bui_avatar(**footer[:user_info][:avatar]) %>
152
+ <% else %>
153
+ <%= footer[:user_info][:avatar].html_safe %>
154
+ <% end %>
155
+ </div>
156
+ <% end %>
157
+ <div class="<%= footer[:user_info][:avatar].present? ? 'ml-3' : '' %>">
158
+ <% if footer[:user_info][:name].present? %>
159
+ <p class="text-sm font-medium text-gray-700">
160
+ <%= footer[:user_info][:name] %>
161
+ </p>
162
+ <% end %>
163
+ <% if footer[:user_info][:email].present? %>
164
+ <p class="text-xs text-gray-500">
165
+ <%= footer[:user_info][:email] %>
166
+ </p>
167
+ <% end %>
168
+ </div>
169
+ <% if footer[:user_info][:menu_button].present? %>
170
+ <div class="ml-auto">
171
+ <%= footer[:user_info][:menu_button] %>
172
+ </div>
173
+ <% end %>
174
+ </div>
175
+ <% end %>
176
+
177
+ <% if footer[:content].present? %>
178
+ <div class="<%= footer[:user_info].present? ? 'mt-4' : '' %>">
179
+ <%= footer[:content] %>
180
+ </div>
181
+ <% end %>
182
+ </div>
183
+ <% end %>
184
+ </aside>
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterUi
4
+ module Application
5
+ module Sidebar
6
+ class Component < ViewComponent::Base
7
+ # Include degli helper per utilizzare bui_icon e bui_avatar
8
+ include BetterUi::General::Components::Icon::IconHelper
9
+ include BetterUi::General::Components::Avatar::AvatarHelper
10
+ attr_reader :width, :position, :theme, :shadow, :border, :header, :footer, :navigation_sections, :collapsible, :classes
11
+
12
+ # Larghezze sidebar con classi Tailwind dirette
13
+ SIDEBAR_WIDTHS = {
14
+ sm: "w-48",
15
+ md: "w-64",
16
+ lg: "w-72",
17
+ xl: "w-80"
18
+ }
19
+
20
+ # Temi sidebar con classi Tailwind dirette
21
+ SIDEBAR_THEMES = {
22
+ default: "bg-white text-gray-900",
23
+ dark: "bg-gray-900 text-white",
24
+ light: "bg-white text-gray-900"
25
+ }
26
+
27
+ # Ombre sidebar con classi Tailwind dirette
28
+ SIDEBAR_SHADOWS = {
29
+ none: "",
30
+ sm: "shadow-sm",
31
+ md: "shadow-md",
32
+ lg: "shadow-lg",
33
+ xl: "shadow-xl"
34
+ }
35
+
36
+ # Bordi sidebar con classi Tailwind dirette
37
+ SIDEBAR_BORDERS = {
38
+ left: "border-r border-gray-200",
39
+ right: "border-l border-gray-200"
40
+ }
41
+
42
+ # @param width [Symbol] Larghezza della sidebar (:sm, :md, :lg, :xl), default :md (w-64)
43
+ # @param position [Symbol] Posizione della sidebar (:left, :right), default :left
44
+ # @param theme [Symbol] Tema colori (:default, :dark, :light), default :default
45
+ # @param shadow [Symbol] Tipo di ombra (:none, :sm, :md, :lg), default :lg
46
+ # @param border [Boolean] Se mostrare il bordo destro/sinistro, default true
47
+ # @param header [Hash] Configurazione header (logo, title, subtitle)
48
+ # @param footer [Hash] Configurazione footer (content, user_info)
49
+ # @param navigation_sections [Array] Array di sezioni di navigazione
50
+ # @param collapsible [Boolean] Se abilitare sezioni collassabili, default true
51
+ # @param classes [String] Classi CSS aggiuntive
52
+ def initialize(
53
+ width: :md,
54
+ position: :left,
55
+ theme: :default,
56
+ shadow: :lg,
57
+ border: true,
58
+ header: {},
59
+ footer: {},
60
+ navigation_sections: [],
61
+ collapsible: true,
62
+ classes: nil
63
+ )
64
+ @width = width.to_sym
65
+ @position = position.to_sym
66
+ @theme = theme.to_sym
67
+ @shadow = shadow.to_sym
68
+ @border = border
69
+ @header = header || {}
70
+ @footer = footer || {}
71
+ @navigation_sections = navigation_sections || []
72
+ @collapsible = collapsible
73
+ @classes = classes
74
+ end
75
+
76
+ def container_classes
77
+ base_classes = %w[fixed inset-y-0 z-50 flex flex-col overflow-y-auto]
78
+
79
+ # Posizione
80
+ base_classes << (position == :right ? "right-0" : "left-0")
81
+
82
+ # Larghezza
83
+ base_classes << width_class
84
+
85
+ # Tema
86
+ base_classes.concat(theme_classes)
87
+
88
+ # Shadow
89
+ base_classes << shadow_class if shadow != :none
90
+
91
+ # Border
92
+ base_classes << border_class if border
93
+
94
+ # Classi aggiuntive
95
+ base_classes << classes if classes.present?
96
+
97
+ base_classes.compact.join(" ")
98
+ end
99
+
100
+
101
+ def has_header?
102
+ header.present? && (header[:title].present? || header[:logo].present?)
103
+ end
104
+
105
+ def has_footer?
106
+ footer.present? && (footer[:content].present? || footer[:user_info].present?)
107
+ end
108
+
109
+ private
110
+
111
+ def width_class
112
+ SIDEBAR_WIDTHS[@width] || SIDEBAR_WIDTHS[:md]
113
+ end
114
+
115
+ def theme_classes
116
+ (SIDEBAR_THEMES[@theme] || SIDEBAR_THEMES[:default]).split
117
+ end
118
+
119
+ def shadow_class
120
+ SIDEBAR_SHADOWS[@shadow] || SIDEBAR_SHADOWS[:none]
121
+ end
122
+
123
+ def border_class
124
+ SIDEBAR_BORDERS[@position] || SIDEBAR_BORDERS[:left]
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,32 @@
1
+ <div <%= tag.attributes(alert_attributes) %>>
2
+ <% if (@icon.blank? ? default_icon : @icon) && @icon_position == :left %>
3
+ <div class="<%= get_icon_classes %> <%= get_icon_theme_class %>">
4
+ <%= render BetterUi::General::Icon::Component.new(name: @icon.blank? ? default_icon : @icon) %>
5
+ </div>
6
+ <% end %>
7
+
8
+ <div class="<%= get_content_classes %>">
9
+ <% if @title.present? %>
10
+ <div class="<%= ALERT_TITLE_CLASSES %>"><%= @title %></div>
11
+ <% end %>
12
+ <div class="<%= ALERT_MESSAGE_CLASSES %>">
13
+ <% if @html_content %>
14
+ <%= raw @message %>
15
+ <% else %>
16
+ <%= @message %>
17
+ <% end %>
18
+ </div>
19
+ </div>
20
+
21
+ <% if (@icon.blank? ? default_icon : @icon) && @icon_position == :right %>
22
+ <div class="<%= get_icon_classes %> <%= get_icon_theme_class %>">
23
+ <%= render BetterUi::General::Icon::Component.new(name: @icon.blank? ? default_icon : @icon) %>
24
+ </div>
25
+ <% end %>
26
+
27
+ <% if @dismissible %>
28
+ <button type="button" class="<%= get_close_classes %>" aria-label="Chiudi">
29
+ <%= render BetterUi::General::Icon::Component.new(name: "x", size: :sm) %>
30
+ </button>
31
+ <% end %>
32
+ </div>